JAMES-1718 Separate logic from data access in CassandraAccessTokenRepository
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7a59d2da Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7a59d2da Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7a59d2da Branch: refs/heads/master Commit: 7a59d2da353f2844ed74478f5c28ae1236139c57 Parents: 86ba885 Author: Benoit Tellier <[email protected]> Authored: Mon Apr 11 16:43:42 2016 +0700 Committer: Benoit Tellier <[email protected]> Committed: Fri Apr 15 15:49:52 2016 +0700 ---------------------------------------------------------------------- .../access/CassandraAccessTokenDAO.java | 85 ++++++++++++++++++++ .../access/CassandraAccessTokenRepository.java | 57 ++----------- 2 files changed, 91 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/7a59d2da/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenDAO.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenDAO.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenDAO.java new file mode 100644 index 0000000..1dcd903 --- /dev/null +++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenDAO.java @@ -0,0 +1,85 @@ +/**************************************************************** + * 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.jmap.cassandra.access; + +import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker; +import static com.datastax.driver.core.querybuilder.QueryBuilder.delete; +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 com.datastax.driver.core.querybuilder.QueryBuilder.ttl; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor; +import org.apache.james.jmap.api.access.AccessToken; +import org.apache.james.jmap.cassandra.access.table.CassandraAccessTokenTable; + +import com.datastax.driver.core.PreparedStatement; +import com.datastax.driver.core.Session; + +public class CassandraAccessTokenDAO { + + private static final String TTL = "ttl"; + + private final CassandraAsyncExecutor cassandraAsyncExecutor; + private final PreparedStatement removeStatement; + private final PreparedStatement insertStatement; + private final PreparedStatement selectStatement; + private final int durationInSeconds; + + public CassandraAccessTokenDAO(Session session, long durationInMilliseconds) { + this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session); + this.durationInSeconds = (int) (durationInMilliseconds / 1000); + + this.removeStatement = session.prepare(delete() + .from(CassandraAccessTokenTable.TABLE_NAME) + .where(eq(CassandraAccessTokenTable.TOKEN, bindMarker(CassandraAccessTokenTable.TOKEN)))); + + this.insertStatement = session.prepare(insertInto(CassandraAccessTokenTable.TABLE_NAME) + .ifNotExists() + .value(CassandraAccessTokenTable.TOKEN, bindMarker(CassandraAccessTokenTable.TOKEN)) + .value(CassandraAccessTokenTable.USERNAME, bindMarker(CassandraAccessTokenTable.USERNAME)) + .using(ttl(bindMarker(TTL)))); + + this.selectStatement = session.prepare(select() + .from(CassandraAccessTokenTable.TABLE_NAME) + .where(eq(CassandraAccessTokenTable.TOKEN, bindMarker(CassandraAccessTokenTable.TOKEN)))); + } + + public CompletableFuture<Boolean> addToken(String username, AccessToken accessToken) { + return cassandraAsyncExecutor.executeReturnApplied(insertStatement.bind() + .setUUID(CassandraAccessTokenTable.TOKEN, accessToken.getToken()) + .setString(CassandraAccessTokenTable.USERNAME, username) + .setInt(TTL, durationInSeconds)); + } + + public CompletableFuture<Void> removeToken(AccessToken accessToken) { + return cassandraAsyncExecutor.executeVoid(removeStatement.bind() + .setUUID(CassandraAccessTokenTable.TOKEN, accessToken.getToken())); + } + + public CompletableFuture<Optional<String>> getUsernameFromToken(AccessToken accessToken) { + return cassandraAsyncExecutor.executeSingleRow(selectStatement.bind() + .setUUID(CassandraAccessTokenTable.TOKEN, accessToken.getToken())) + .thenApply(optional -> optional.map(row -> row.getString(CassandraAccessTokenTable.USERNAME))); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/7a59d2da/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepository.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepository.java index 9683503..2afd24d 100644 --- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepository.java +++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepository.java @@ -19,57 +19,24 @@ package org.apache.james.jmap.cassandra.access; -import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker; -import static com.datastax.driver.core.querybuilder.QueryBuilder.delete; -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 com.datastax.driver.core.querybuilder.QueryBuilder.ttl; - -import java.util.Optional; - import javax.inject.Inject; import javax.inject.Named; -import org.apache.james.backends.cassandra.utils.CassandraConstants; -import org.apache.james.jmap.cassandra.access.table.CassandraAccessTokenTable; import org.apache.james.jmap.api.access.AccessToken; import org.apache.james.jmap.api.access.AccessTokenRepository; import org.apache.james.jmap.api.access.exceptions.AccessTokenAlreadyStored; import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken; -import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.Session; import com.google.common.base.Preconditions; public class CassandraAccessTokenRepository implements AccessTokenRepository { - private static final String TTL = "ttl"; - - private final Session session; - private final PreparedStatement removeStatement; - private final PreparedStatement insertStatement; - private final PreparedStatement selectStatement; - private final int durationInSeconds; + private final CassandraAccessTokenDAO cassandraAccessTokenDAO; @Inject public CassandraAccessTokenRepository(Session session, @Named(TOKEN_EXPIRATION_IN_MS) long durationInMilliseconds) { - this.session = session; - this.durationInSeconds = (int) (durationInMilliseconds / 1000); - - this.removeStatement = this.session.prepare(delete() - .from(CassandraAccessTokenTable.TABLE_NAME) - .where(eq(CassandraAccessTokenTable.TOKEN, bindMarker(CassandraAccessTokenTable.TOKEN)))); - - this.insertStatement = this.session.prepare(insertInto(CassandraAccessTokenTable.TABLE_NAME) - .ifNotExists() - .value(CassandraAccessTokenTable.TOKEN, bindMarker(CassandraAccessTokenTable.TOKEN)) - .value(CassandraAccessTokenTable.USERNAME, bindMarker(CassandraAccessTokenTable.USERNAME)) - .using(ttl(bindMarker(TTL)))); - - this.selectStatement = this.session.prepare(select() - .from(CassandraAccessTokenTable.TABLE_NAME) - .where(eq(CassandraAccessTokenTable.TOKEN, bindMarker(CassandraAccessTokenTable.TOKEN)))); + this.cassandraAccessTokenDAO = new CassandraAccessTokenDAO(session, durationInMilliseconds); } @Override @@ -78,14 +45,7 @@ public class CassandraAccessTokenRepository implements AccessTokenRepository { Preconditions.checkArgument(! username.isEmpty(), "Username should not be empty"); Preconditions.checkNotNull(accessToken); - boolean applied = session.execute(insertStatement.bind() - .setUUID(CassandraAccessTokenTable.TOKEN, accessToken.getToken()) - .setString(CassandraAccessTokenTable.USERNAME, username) - .setInt(TTL, durationInSeconds)) - .one() - .getBool(CassandraConstants.LIGHTWEIGHT_TRANSACTION_APPLIED); - - if (!applied) { + if (!cassandraAccessTokenDAO.addToken(username, accessToken).join()) { throw new AccessTokenAlreadyStored(accessToken); } } @@ -94,20 +54,15 @@ public class CassandraAccessTokenRepository implements AccessTokenRepository { public void removeToken(AccessToken accessToken) { Preconditions.checkNotNull(accessToken); - session.execute(removeStatement.bind() - .setUUID(CassandraAccessTokenTable.TOKEN, accessToken.getToken())); + cassandraAccessTokenDAO.removeToken(accessToken).join(); } @Override public String getUsernameFromToken(AccessToken accessToken) throws InvalidAccessToken { Preconditions.checkNotNull(accessToken); - return Optional.ofNullable( - session.execute( - selectStatement.bind() - .setUUID(CassandraAccessTokenTable.TOKEN, accessToken.getToken())) - .one()) - .map(row -> row.getString(CassandraAccessTokenTable.USERNAME)) + return cassandraAccessTokenDAO.getUsernameFromToken(accessToken) + .join() .orElseThrow(() -> new InvalidAccessToken(accessToken)); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
