JAMES-1925 Adapt slightly ACLs - Read should use future - Only rely on mailboxId
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7b85c970 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7b85c970 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7b85c970 Branch: refs/heads/master Commit: 7b85c97040ebda3301dc0ef5e38cdf7516a5966a Parents: 7c223af Author: Benoit Tellier <[email protected]> Authored: Tue Feb 14 11:01:53 2017 +0700 Committer: Antoine Duprat <[email protected]> Committed: Wed Feb 15 13:12:37 2017 +0100 ---------------------------------------------------------------------- .../cassandra/mail/CassandraACLMapper.java | 55 ++++++++++---------- .../cassandra/mail/CassandraMailboxMapper.java | 8 +-- .../cassandra/mail/CassandraACLMapperTest.java | 52 +++++++----------- 3 files changed, 52 insertions(+), 63 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/7b85c970/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java index 378b48b..18b406a 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java @@ -27,7 +27,9 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.update; import java.io.IOException; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor; import org.apache.james.backends.cassandra.utils.CassandraConstants; import org.apache.james.backends.cassandra.utils.FunctionRunnerWithRetry; import org.apache.james.backends.cassandra.utils.LightweightTransactionException; @@ -39,7 +41,6 @@ import org.apache.james.mailbox.exception.UnsupportedRightException; import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.SimpleMailboxACL; import org.apache.james.mailbox.store.json.SimpleMailboxACLJsonConverter; -import org.apache.james.mailbox.store.mail.model.Mailbox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,33 +58,36 @@ public class CassandraACLMapper { void inject(); } - private final Mailbox mailbox; + private final CassandraId cassandraId; + private final CassandraAsyncExecutor executor; private final Session session; private final int maxRetry; private final CodeInjector codeInjector; private static final Logger LOG = LoggerFactory.getLogger(CassandraACLMapper.class); - public CassandraACLMapper(Mailbox mailbox, Session session, int maxRetry) { - this(mailbox, session, maxRetry, () -> {}); + public CassandraACLMapper(CassandraId cassandraId, Session session, int maxRetry) { + this(cassandraId, session, maxRetry, () -> {}); } - public CassandraACLMapper(Mailbox mailbox, Session session, int maxRetry, CodeInjector codeInjector) { + public CassandraACLMapper(CassandraId cassandraId, Session session, int maxRetry, CodeInjector codeInjector) { Preconditions.checkArgument(maxRetry > 0); - Preconditions.checkArgument(mailbox.getMailboxId() != null); - this.mailbox = mailbox; + Preconditions.checkArgument(cassandraId != null); + this.cassandraId = cassandraId; this.session = session; + this.executor = new CassandraAsyncExecutor(session); this.maxRetry = maxRetry; this.codeInjector = codeInjector; } - public MailboxACL getACL() { - ResultSet resultSet = getStoredACLRow(); - if (resultSet.isExhausted()) { - return SimpleMailboxACL.EMPTY; - } - String serializedACL = resultSet.one().getString(CassandraACLTable.ACL); - return deserializeACL(serializedACL); + public CompletableFuture<MailboxACL> getACL() { + return getStoredACLRow().thenApply(resultSet -> { + if (resultSet.isExhausted()) { + return SimpleMailboxACL.EMPTY; + } + String serializedACL = resultSet.one().getString(CassandraACLTable.ACL); + return deserializeACL(serializedACL); + }); } public void updateACL(MailboxACL.MailboxACLCommand command) throws MailboxException { @@ -111,23 +115,19 @@ public class CassandraACLMapper { } } - private ResultSet getStoredACLRow() { - CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); - return session.execute( - select(CassandraACLTable.ACL, CassandraACLTable.VERSION) - .from(CassandraACLTable.TABLE_NAME) - .where(eq(CassandraMailboxTable.ID, mailboxId.asUuid())) - ); + private CompletableFuture<ResultSet> getStoredACLRow() { + return executor.execute(select(CassandraACLTable.ACL, CassandraACLTable.VERSION) + .from(CassandraACLTable.TABLE_NAME) + .where(eq(CassandraMailboxTable.ID, cassandraId.asUuid()))); } private ResultSet updateStoredACL(ACLWithVersion aclWithVersion) { try { - CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); return session.execute( update(CassandraACLTable.TABLE_NAME) .with(set(CassandraACLTable.ACL, SimpleMailboxACLJsonConverter.toJson(aclWithVersion.mailboxACL))) .and(set(CassandraACLTable.VERSION, aclWithVersion.version + 1)) - .where(eq(CassandraACLTable.ID, mailboxId.asUuid())) + .where(eq(CassandraACLTable.ID, cassandraId.asUuid())) .onlyIf(eq(CassandraACLTable.VERSION, aclWithVersion.version)) ); } catch (JsonProcessingException exception) { @@ -137,10 +137,9 @@ public class CassandraACLMapper { private ResultSet insertACL(MailboxACL acl) { try { - CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); return session.execute( insertInto(CassandraACLTable.TABLE_NAME) - .value(CassandraACLTable.ID, mailboxId.asUuid()) + .value(CassandraACLTable.ID, cassandraId.asUuid()) .value(CassandraACLTable.ACL, SimpleMailboxACLJsonConverter.toJson(acl)) .value(CassandraACLTable.VERSION, 0) .ifNotExists() @@ -151,7 +150,7 @@ public class CassandraACLMapper { } private Optional<ACLWithVersion> getAclWithVersion() { - ResultSet resultSet = getStoredACLRow(); + ResultSet resultSet = getStoredACLRow().join(); if (resultSet.isExhausted()) { return Optional.empty(); } @@ -165,8 +164,8 @@ public class CassandraACLMapper { } catch(IOException exception) { LOG.error("Unable to read stored ACL. " + "We will use empty ACL instead." + - "Mailbox is {}:{}:{} ." + - "ACL is {}", mailbox.getNamespace(), mailbox.getUser(), mailbox.getName(), serializedACL, exception); + "Mailbox is {} ." + + "ACL is {}", cassandraId, serializedACL, exception); return SimpleMailboxACL.EMPTY; } } http://git-wip-us.apache.org/repos/asf/james-project/blob/7b85c970/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java index c2f824e..4314148 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java @@ -158,7 +158,8 @@ public class CassandraMailboxMapper implements MailboxMapper { @Override public void updateACL(Mailbox mailbox, MailboxACL.MailboxACLCommand mailboxACLCommand) throws MailboxException { - new CassandraACLMapper(mailbox, session, maxRetry).updateACL(mailboxACLCommand); + CassandraId cassandraId = (CassandraId) mailbox.getMailboxId(); + new CassandraACLMapper(cassandraId, session, maxRetry).updateACL(mailboxACLCommand); } @Override @@ -173,8 +174,9 @@ public class CassandraMailboxMapper implements MailboxMapper { row.getUDTValue(MAILBOX_BASE).getString(MailboxBase.USER), row.getString(NAME)), row.getLong(UIDVALIDITY)); - mailbox.setMailboxId(CassandraId.of(row.getUUID(ID))); - mailbox.setACL(new CassandraACLMapper(mailbox, session, maxRetry).getACL()); + CassandraId mailboxId = CassandraId.of(row.getUUID(ID)); + mailbox.setMailboxId(mailboxId); + mailbox.setACL(new CassandraACLMapper(mailboxId, session, maxRetry).getACL().join()); return mailbox; } http://git-wip-us.apache.org/repos/asf/james-project/blob/7b85c970/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperTest.java index 008bcdf..ebff807 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperTest.java @@ -36,9 +36,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.table.CassandraACLTable; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.model.MailboxACL; -import org.apache.james.mailbox.model.MailboxPath; import org.apache.james.mailbox.model.SimpleMailboxACL; -import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -47,22 +45,17 @@ import com.google.common.base.Throwables; public class CassandraACLMapperTest { + public static final CassandraId MAILBOX_ID = CassandraId.of(UUID.fromString("464765a0-e4e7-11e4-aba4-710c1de3782b")); + public static final int MAX_RETRY = 100; private CassandraACLMapper cassandraACLMapper; private CassandraCluster cassandra; - private SimpleMailbox mailbox; - private int uidValidity; - private int maxRetry; private ExecutorService executor; @Before public void setUp() { cassandra = CassandraCluster.create(new CassandraAclModule()); cassandra.ensureAllTables(); - uidValidity = 10; - mailbox = new SimpleMailbox(new MailboxPath("#private", "[email protected]", "INBOX"), uidValidity); - mailbox.setMailboxId(CassandraId.of(UUID.fromString("464765a0-e4e7-11e4-aba4-710c1de3782b"))); - maxRetry = 100; - cassandraACLMapper = new CassandraACLMapper(mailbox, cassandra.getConf(), maxRetry); + cassandraACLMapper = new CassandraACLMapper(MAILBOX_ID, cassandra.getConf(), MAX_RETRY); executor = Executors.newFixedThreadPool(2); } @@ -74,28 +67,23 @@ public class CassandraACLMapperTest { @Test(expected = IllegalArgumentException.class) public void creatingACLMapperWithNegativeMaxRetryShouldFail() { - new CassandraACLMapper(mailbox, cassandra.getConf(), -1); + new CassandraACLMapper(MAILBOX_ID, cassandra.getConf(), -1); } @Test(expected = IllegalArgumentException.class) public void creatingACLMapperWithNullMaxRetryShouldFail() { - new CassandraACLMapper(mailbox, cassandra.getConf(), 0); - } - - @Test(expected = IllegalArgumentException.class) - public void creatingACLMapperWithNoMailboxIdShouldFail() { - new CassandraACLMapper(new SimpleMailbox(new MailboxPath("#private", "user", "name"), uidValidity), cassandra.getConf(), maxRetry); + new CassandraACLMapper(MAILBOX_ID, cassandra.getConf(), 0); } @Test public void retrieveACLWhenPresentInBaseShouldReturnCorrespondingACL() throws Exception { cassandra.getConf().execute( insertInto(CassandraACLTable.TABLE_NAME) - .value(CassandraACLTable.ID, ((CassandraId) mailbox.getMailboxId()).asUuid()) + .value(CassandraACLTable.ID, MAILBOX_ID.asUuid()) .value(CassandraACLTable.ACL, "{\"entries\":{\"bob\":64}}") .value(CassandraACLTable.VERSION, 1) ); - assertThat(cassandraACLMapper.getACL()) + assertThat(cassandraACLMapper.getACL().join()) .isEqualTo( SimpleMailboxACL.EMPTY.union( new SimpleMailboxACL.SimpleMailboxACLEntryKey("bob", MailboxACL.NameType.user, false), @@ -107,16 +95,16 @@ public class CassandraACLMapperTest { public void retrieveACLWhenInvalidInBaseShouldReturnEmptyACL() throws Exception { cassandra.getConf().execute( insertInto(CassandraACLTable.TABLE_NAME) - .value(CassandraACLTable.ID, ((CassandraId) mailbox.getMailboxId()).asUuid()) + .value(CassandraACLTable.ID, MAILBOX_ID.asUuid()) .value(CassandraACLTable.ACL, "{\"entries\":{\"bob\":invalid}}") .value(CassandraACLTable.VERSION, 1) ); - assertThat(cassandraACLMapper.getACL()).isEqualTo(SimpleMailboxACL.EMPTY); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(SimpleMailboxACL.EMPTY); } @Test public void retrieveACLWhenNoACLStoredShouldReturnEmptyACL() { - assertThat(cassandraACLMapper.getACL()).isEqualTo(SimpleMailboxACL.EMPTY); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(SimpleMailboxACL.EMPTY); } @Test @@ -124,7 +112,7 @@ public class CassandraACLMapperTest { SimpleMailboxACL.SimpleMailboxACLEntryKey key = new SimpleMailboxACL.SimpleMailboxACLEntryKey("bob", MailboxACL.NameType.user, false); SimpleMailboxACL.Rfc4314Rights rights = new SimpleMailboxACL.Rfc4314Rights(new SimpleMailboxACL.SimpleMailboxACLRight('r')); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.ADD, rights)); - assertThat(cassandraACLMapper.getACL()).isEqualTo(new SimpleMailboxACL().union(key, rights)); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(new SimpleMailboxACL().union(key, rights)); } @Test @@ -134,7 +122,7 @@ public class CassandraACLMapperTest { cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(keyBob, MailboxACL.EditMode.ADD, rights)); SimpleMailboxACL.SimpleMailboxACLEntryKey keyAlice = new SimpleMailboxACL.SimpleMailboxACLEntryKey("alice", MailboxACL.NameType.user, false); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(keyAlice, MailboxACL.EditMode.ADD, rights)); - assertThat(cassandraACLMapper.getACL()).isEqualTo(new SimpleMailboxACL().union(keyBob, rights).union(keyAlice, rights)); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(new SimpleMailboxACL().union(keyBob, rights).union(keyAlice, rights)); } @Test @@ -143,7 +131,7 @@ public class CassandraACLMapperTest { SimpleMailboxACL.Rfc4314Rights rights = new SimpleMailboxACL.Rfc4314Rights(new SimpleMailboxACL.SimpleMailboxACLRight('r')); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.ADD, rights)); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.REMOVE, rights)); - assertThat(cassandraACLMapper.getACL()).isEqualTo(SimpleMailboxACL.EMPTY); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(SimpleMailboxACL.EMPTY); } @Test @@ -152,7 +140,7 @@ public class CassandraACLMapperTest { SimpleMailboxACL.Rfc4314Rights rights = new SimpleMailboxACL.Rfc4314Rights(new SimpleMailboxACL.SimpleMailboxACLRight('r')); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.ADD, rights)); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.REPLACE, null)); - assertThat(cassandraACLMapper.getACL()).isEqualTo(SimpleMailboxACL.EMPTY); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(SimpleMailboxACL.EMPTY); } @Test @@ -160,21 +148,21 @@ public class CassandraACLMapperTest { SimpleMailboxACL.SimpleMailboxACLEntryKey key = new SimpleMailboxACL.SimpleMailboxACLEntryKey("bob", MailboxACL.NameType.user, false); SimpleMailboxACL.Rfc4314Rights rights = new SimpleMailboxACL.Rfc4314Rights(new SimpleMailboxACL.SimpleMailboxACLRight('r')); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.REPLACE, rights)); - assertThat(cassandraACLMapper.getACL()).isEqualTo(new SimpleMailboxACL().union(key, rights)); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(new SimpleMailboxACL().union(key, rights)); } @Test public void updateInvalidACLShouldBeBasedOnEmptyACL() throws Exception { cassandra.getConf().execute( insertInto(CassandraACLTable.TABLE_NAME) - .value(CassandraACLTable.ID, ((CassandraId) mailbox.getMailboxId()).asUuid()) + .value(CassandraACLTable.ID, MAILBOX_ID.asUuid()) .value(CassandraACLTable.ACL, "{\"entries\":{\"bob\":invalid}}") .value(CassandraACLTable.VERSION, 1) ); SimpleMailboxACL.SimpleMailboxACLEntryKey key = new SimpleMailboxACL.SimpleMailboxACLEntryKey("bob", MailboxACL.NameType.user, false); SimpleMailboxACL.Rfc4314Rights rights = new SimpleMailboxACL.Rfc4314Rights(new SimpleMailboxACL.SimpleMailboxACLRight('r')); cassandraACLMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.ADD, rights)); - assertThat(cassandraACLMapper.getACL()).isEqualTo(new SimpleMailboxACL().union(key, rights)); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(new SimpleMailboxACL().union(key, rights)); } @Test @@ -186,7 +174,7 @@ public class CassandraACLMapperTest { Future<Boolean> future1 = performACLUpdateInExecutor(executor, keyBob, rights, countDownLatch::countDown); Future<Boolean> future2 = performACLUpdateInExecutor(executor, keyAlice, rights, countDownLatch::countDown); awaitAll(future1, future2); - assertThat(cassandraACLMapper.getACL()).isEqualTo(new SimpleMailboxACL().union(keyBob, rights).union(keyAlice, rights)); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(new SimpleMailboxACL().union(keyBob, rights).union(keyAlice, rights)); } @Test @@ -200,7 +188,7 @@ public class CassandraACLMapperTest { Future<Boolean> future1 = performACLUpdateInExecutor(executor, keyBob, rights, countDownLatch::countDown); Future<Boolean> future2 = performACLUpdateInExecutor(executor, keyAlice, rights, countDownLatch::countDown); awaitAll(future1, future2); - assertThat(cassandraACLMapper.getACL()).isEqualTo(new SimpleMailboxACL().union(keyBob, rights).union(keyAlice, rights).union(keyBenwa, rights)); + assertThat(cassandraACLMapper.getACL().join()).isEqualTo(new SimpleMailboxACL().union(keyBob, rights).union(keyAlice, rights).union(keyBenwa, rights)); } private void awaitAll(Future<?>... futures) @@ -212,7 +200,7 @@ public class CassandraACLMapperTest { private Future<Boolean> performACLUpdateInExecutor(ExecutorService executor, SimpleMailboxACL.SimpleMailboxACLEntryKey key, SimpleMailboxACL.Rfc4314Rights rights, CassandraACLMapper.CodeInjector runnable) { return executor.submit(() -> { - CassandraACLMapper aclMapper = new CassandraACLMapper(mailbox, cassandra.getConf(), maxRetry, runnable); + CassandraACLMapper aclMapper = new CassandraACLMapper(MAILBOX_ID, cassandra.getConf(), MAX_RETRY, runnable); try { aclMapper.updateACL(new SimpleMailboxACL.SimpleMailboxACLCommand(key, MailboxACL.EditMode.ADD, rights)); } catch (MailboxException exception) { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
