JAMES-1718 AccessToken API should be asynchronous
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7e39d441 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7e39d441 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7e39d441 Branch: refs/heads/master Commit: 7e39d44192c85068143767b42c838f0921d994f2 Parents: 231beb5 Author: Benoit Tellier <[email protected]> Authored: Tue Apr 12 10:23:47 2016 +0700 Committer: Benoit Tellier <[email protected]> Committed: Fri Apr 15 15:50:29 2016 +0700 ---------------------------------------------------------------------- .../access/CassandraAccessTokenRepository.java | 19 ++++++++++++------- server/data/data-jmap/pom.xml | 4 ++++ .../jmap/api/access/AccessTokenRepository.java | 10 +++++++--- .../access/MemoryAccessTokenRepository.java | 15 +++++++++------ .../AbstractAccessTokenRepositoryTest.java | 10 +++++----- server/pom.xml | 5 +++++ .../jmap/crypto/AccessTokenManagerImpl.java | 11 +++++++++-- .../jmap/crypto/AccessTokenManagerImplTest.java | 2 +- 8 files changed, 52 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/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 0dd51a7..4ddbc1c 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,6 +19,8 @@ package org.apache.james.jmap.cassandra.access; +import java.util.concurrent.CompletableFuture; + import javax.inject.Inject; import javax.inject.Named; @@ -28,6 +30,7 @@ import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken; import com.datastax.driver.core.Session; import com.google.common.base.Preconditions; +import com.jasongoodwin.monads.Try; public class CassandraAccessTokenRepository implements AccessTokenRepository { @@ -39,27 +42,29 @@ public class CassandraAccessTokenRepository implements AccessTokenRepository { } @Override - public void addToken(String username, AccessToken accessToken) { + public CompletableFuture<Void> addToken(String username, AccessToken accessToken) { Preconditions.checkNotNull(username); Preconditions.checkArgument(! username.isEmpty(), "Username should not be empty"); Preconditions.checkNotNull(accessToken); - cassandraAccessTokenDAO.addToken(username, accessToken).join(); + return cassandraAccessTokenDAO.addToken(username, accessToken); } @Override - public void removeToken(AccessToken accessToken) { + public CompletableFuture<Void> removeToken(AccessToken accessToken) { Preconditions.checkNotNull(accessToken); - cassandraAccessTokenDAO.removeToken(accessToken).join(); + return cassandraAccessTokenDAO.removeToken(accessToken); } @Override - public String getUsernameFromToken(AccessToken accessToken) throws InvalidAccessToken { + public CompletableFuture<Try<String>> getUsernameFromToken(AccessToken accessToken) throws InvalidAccessToken { Preconditions.checkNotNull(accessToken); return cassandraAccessTokenDAO.getUsernameFromToken(accessToken) - .join() - .orElseThrow(() -> new InvalidAccessToken(accessToken)); + .thenApply( + optional -> Try.ofFailable( + () -> optional.orElseThrow( + () -> new InvalidAccessToken(accessToken)))); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/server/data/data-jmap/pom.xml ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/pom.xml b/server/data/data-jmap/pom.xml index 48b55ff..4166b7e 100644 --- a/server/data/data-jmap/pom.xml +++ b/server/data/data-jmap/pom.xml @@ -182,6 +182,10 @@ <artifactId>guava</artifactId> </dependency> <dependency> + <groupId>com.jason-goodwin</groupId> + <artifactId>better-monads</artifactId> + </dependency> + <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java index 6fb3ae0..a2a7e2f 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java @@ -19,16 +19,20 @@ package org.apache.james.jmap.api.access; +import java.util.concurrent.CompletableFuture; + import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken; +import com.jasongoodwin.monads.Try; + public interface AccessTokenRepository { String TOKEN_EXPIRATION_IN_MS = "tokenExpirationInMs"; - void addToken(String username, AccessToken accessToken); + CompletableFuture<Void> addToken(String username, AccessToken accessToken); - void removeToken(AccessToken accessToken); + CompletableFuture<Void> removeToken(AccessToken accessToken); - String getUsernameFromToken(AccessToken accessToken) throws InvalidAccessToken; + CompletableFuture<Try<String>> getUsernameFromToken(AccessToken accessToken) throws InvalidAccessToken; } http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java index 2c16fc2..0a67751 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java @@ -20,6 +20,7 @@ package org.apache.james.jmap.memory.access; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import javax.inject.Inject; import javax.inject.Named; @@ -31,6 +32,7 @@ import org.apache.james.jmap.api.access.AccessTokenRepository; import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken; import com.google.common.base.Preconditions; +import com.jasongoodwin.monads.Try; @Singleton public class MemoryAccessTokenRepository implements AccessTokenRepository { @@ -43,30 +45,31 @@ public class MemoryAccessTokenRepository implements AccessTokenRepository { } @Override - public void addToken(String username, AccessToken accessToken) { + public CompletableFuture<Void> addToken(String username, AccessToken accessToken) { Preconditions.checkNotNull(username); Preconditions.checkArgument(! username.isEmpty(), "Username should not be empty"); Preconditions.checkNotNull(accessToken); synchronized (tokensExpirationDates) { tokensExpirationDates.put(accessToken, username); } + return CompletableFuture.completedFuture(null); } @Override - public void removeToken(AccessToken accessToken) { + public CompletableFuture<Void> removeToken(AccessToken accessToken) { Preconditions.checkNotNull(accessToken); synchronized (tokensExpirationDates) { tokensExpirationDates.remove(accessToken); } + return CompletableFuture.completedFuture(null); } @Override - public String getUsernameFromToken(AccessToken accessToken) throws InvalidAccessToken { + public CompletableFuture<Try<String>> getUsernameFromToken(AccessToken accessToken) throws InvalidAccessToken { Preconditions.checkNotNull(accessToken); synchronized (tokensExpirationDates) { - return Optional - .ofNullable(tokensExpirationDates.get(accessToken)) - .orElseThrow(() -> new InvalidAccessToken(accessToken)); + return CompletableFuture.completedFuture( + Try.ofFailable(() -> Optional.ofNullable(tokensExpirationDates.get(accessToken)).orElseThrow(() -> new InvalidAccessToken(accessToken)))); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/access/AbstractAccessTokenRepositoryTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/access/AbstractAccessTokenRepositoryTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/access/AbstractAccessTokenRepositoryTest.java index 04482be..95953ec 100644 --- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/access/AbstractAccessTokenRepositoryTest.java +++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/access/AbstractAccessTokenRepositoryTest.java @@ -42,28 +42,28 @@ public abstract class AbstractAccessTokenRepositoryTest { protected abstract AccessTokenRepository createAccessTokenRepository(); @Test - public void validTokenMustBeRetrieved() throws Exception { + public void validTokenMustBeRetrieved() throws Throwable { accessTokenRepository.addToken(USERNAME, TOKEN); - assertThat(accessTokenRepository.getUsernameFromToken(TOKEN)).isEqualTo(USERNAME); + assertThat(accessTokenRepository.getUsernameFromToken(TOKEN).join().get()).isEqualTo(USERNAME); } @Test public void absentTokensMustBeInvalid() throws Exception { - assertThatThrownBy(() -> accessTokenRepository.getUsernameFromToken(TOKEN)).isInstanceOf(InvalidAccessToken.class); + assertThatThrownBy(() -> accessTokenRepository.getUsernameFromToken(TOKEN).join().get()).isInstanceOf(InvalidAccessToken.class); } @Test public void removedTokensMustBeInvalid() throws Exception { accessTokenRepository.addToken(USERNAME, TOKEN); accessTokenRepository.removeToken(TOKEN); - assertThatThrownBy(() -> accessTokenRepository.getUsernameFromToken(TOKEN)).isInstanceOf(InvalidAccessToken.class); + assertThatThrownBy(() -> accessTokenRepository.getUsernameFromToken(TOKEN).join().get()).isInstanceOf(InvalidAccessToken.class); } @Test public void outDatedTokenMustBeInvalid() throws Exception { accessTokenRepository.addToken(USERNAME, TOKEN); Thread.sleep(2 * TTL_IN_MS); - assertThatThrownBy(() -> accessTokenRepository.getUsernameFromToken(TOKEN)).isInstanceOf(InvalidAccessToken.class); + assertThatThrownBy(() -> accessTokenRepository.getUsernameFromToken(TOKEN).join().get()).isInstanceOf(InvalidAccessToken.class); } @Test(expected = NullPointerException.class) http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/server/pom.xml ---------------------------------------------------------------------- diff --git a/server/pom.xml b/server/pom.xml index 47399c4..7f9fb5e 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -891,6 +891,11 @@ <version>${geronimo-activation-spec.version}</version> </dependency> <dependency> + <groupId>com.jason-goodwin</groupId> + <artifactId>better-monads</artifactId> + <version>0.4.0</version> + </dependency> + <dependency> <groupId>commons-daemon</groupId> <artifactId>commons-daemon</artifactId> <version>${commons-daemon.version}</version> http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java index 4fce6c4..0131071 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java @@ -28,6 +28,7 @@ import org.apache.james.jmap.api.access.AccessTokenRepository; import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken; import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; @Singleton public class AccessTokenManagerImpl implements AccessTokenManager { @@ -49,7 +50,13 @@ public class AccessTokenManagerImpl implements AccessTokenManager { @Override public String getUsernameFromToken(AccessToken token) throws InvalidAccessToken { - return accessTokenRepository.getUsernameFromToken(token); + try { + return accessTokenRepository.getUsernameFromToken(token).join().get(); + } catch (InvalidAccessToken invalidAccessToken) { + throw invalidAccessToken; + } catch (Throwable throwable) { + throw Throwables.propagate(throwable); + } } @Override @@ -64,7 +71,7 @@ public class AccessTokenManagerImpl implements AccessTokenManager { @Override public void revoke(AccessToken token) { - accessTokenRepository.removeToken(token); + accessTokenRepository.removeToken(token).join(); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/7e39d441/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java index eba0dcc..fb3716a 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java @@ -52,7 +52,7 @@ public class AccessTokenManagerImplTest { @Test public void grantShouldStoreATokenOnUsername() throws Exception { AccessToken token = accessTokenManager.grantAccessToken("username"); - assertThat(accessTokenRepository.getUsernameFromToken(token)).isEqualTo("username"); + assertThat(accessTokenRepository.getUsernameFromToken(token).join().get()).isEqualTo("username"); } @Test(expected=NullPointerException.class) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
