diff --git a/.travis.yml b/.travis.yml index f17a99d..1f42d35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,15 +5,17 @@ jdk: oraclejdk8 env: global: - MALLOC_ARENA_MAX=2 + - ADB_INSTALL_TIMEOUT=10 matrix: - ANDROID_TARGET=android-22 ANDROID_ABI=armeabi-v7a android: components: - tools - - build-tools-23.0.2 - - android-23 + - build-tools-23.0.3 + - android-24 - android-22 + - android-23 - sys-img-armeabi-v7a-android-22 - extra-google-m2repository - extra-android-m2repository diff --git a/library/build.gradle b/library/build.gradle index a8a78da..cc2cce5 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -10,7 +10,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' + classpath 'com.android.tools.build:gradle:2.1.3' classpath 'me.tatarka:gradle-retrolambda:2.5.0' classpath 'org.codehaus.groovy:gradle-groovy-android-plugin:0.3.6' classpath 'com.github.dcendents:android-maven-plugin:1.2' @@ -20,8 +20,8 @@ buildscript { group = 'com.github.rheinfabrik' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 24 + buildToolsVersion "23.0.3" compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -37,8 +37,8 @@ android { defaultConfig { minSdkVersion 9 targetSdkVersion 23 - versionCode 104 - versionName "1.0.4" + versionCode 105 + versionName "1.0.5" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/library/src/androidTest/groovy/de/rheinfabrik/heimdall/OAuth2AccessTokenManagerSpecs.groovy b/library/src/androidTest/groovy/de/rheinfabrik/heimdall/OAuth2AccessTokenManagerSpecs.groovy index e570264..5e86dac 100644 --- a/library/src/androidTest/groovy/de/rheinfabrik/heimdall/OAuth2AccessTokenManagerSpecs.groovy +++ b/library/src/androidTest/groovy/de/rheinfabrik/heimdall/OAuth2AccessTokenManagerSpecs.groovy @@ -5,6 +5,8 @@ import de.rheinfabrik.heimdall.grants.OAuth2Grant import de.rheinfabrik.heimdall.grants.OAuth2RefreshAccessTokenGrant import spock.lang.Title +import java.util.concurrent.TimeUnit + import static rx.Single.just @Title("Tests for the constructor of the OAuth2AccessTokenManager class") @@ -138,6 +140,39 @@ class OAuth2AccessTokenManagerGetValidAccessTokenSpecs extends AndroidSpecificat // Scenarios + def "it should only request a new valid token ONCE"() { + + given: "An expired OAuth2AccessToken" + OAuth2AccessToken accessToken = Mock(OAuth2AccessToken) + accessToken.refreshToken = "rt" + accessToken.isExpired() >> true + + and: "A mock storage emitting that token" + OAuth2AccessTokenStorage storage = Mock(OAuth2AccessTokenStorage) + storage.getStoredAccessToken() >> just(accessToken).delay(1, TimeUnit.SECONDS) + + and: "An OAuth2AccessTokenManager with that storage" + OAuth2AccessTokenManager tokenManager = new OAuth2AccessTokenManager(storage) + + and: "A mock grant" + OAuth2RefreshAccessTokenGrant grant = Mock(OAuth2RefreshAccessTokenGrant) + + when: "I ask for a valid access token" + tokenManager.getValidAccessToken(grant).subscribe() + + and: "I ask again" + tokenManager.getValidAccessToken(grant).subscribe() + + and: "I wait 2 seconds" + sleep(2000) + + and: "I ask again" + tokenManager.getValidAccessToken(grant).subscribe() + + then: "The refresh grant is asked for a new token TWICE" + 2 * grant.grantNewAccessToken() >> just(accessToken) >> just(accessToken) + } + def "it should throw an IllegalArgumentException when the refreshAccessTokenGrant parameter is null"() { given: "A null grant" diff --git a/library/src/main/java/de/rheinfabrik/heimdall/OAuth2AccessTokenManager.java b/library/src/main/java/de/rheinfabrik/heimdall/OAuth2AccessTokenManager.java index f772ace..9e16867 100644 --- a/library/src/main/java/de/rheinfabrik/heimdall/OAuth2AccessTokenManager.java +++ b/library/src/main/java/de/rheinfabrik/heimdall/OAuth2AccessTokenManager.java @@ -4,8 +4,8 @@ import de.rheinfabrik.heimdall.grants.OAuth2Grant; import de.rheinfabrik.heimdall.grants.OAuth2RefreshAccessTokenGrant; +import rx.Observable; import rx.Single; -import rx.functions.Func1; import static rx.Single.error; @@ -20,6 +20,7 @@ public class OAuth2AccessTokenManager { // Members private final OAuth2AccessTokenStorage mStorage; + private Single mTokenSingle; // Constructor @@ -71,17 +72,23 @@ public Single grantNewAccessToken(OAuth2Grant grant, throw new IllegalArgumentException("Grant MUST NOT be null."); } - return grant - .grantNewAccessToken() - .doOnSuccess(accessToken -> { - if (accessToken.expiresIn != null) { - Calendar expirationDate = (Calendar) calendar.clone(); - expirationDate.add(Calendar.SECOND, accessToken.expiresIn); - accessToken.expirationDate = expirationDate; - } + if (mTokenSingle == null) { + mTokenSingle = grant + .grantNewAccessToken() + .doOnSuccess(accessToken -> { + if (accessToken.expiresIn != null) { + Calendar expirationDate = (Calendar) calendar.clone(); + expirationDate.add(Calendar.SECOND, accessToken.expiresIn); + accessToken.expirationDate = expirationDate; + } - mStorage.storeAccessToken(accessToken); - }); + mStorage.storeAccessToken(accessToken); + + mTokenSingle = null; + }); + } + + return mTokenSingle; } /** diff --git a/sample/build.gradle b/sample/build.gradle index 0d4860e..3c0b9bb 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -12,13 +12,13 @@ buildscript { } android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 24 + buildToolsVersion "23.0.3" defaultConfig { applicationId "de.rheinfabrik.heimdall" minSdkVersion 15 - targetSdkVersion 23 + targetSdkVersion 24 versionCode 1 versionName "1.0" }