package org.estgroup.phphub.common.transformer; import android.accounts.Account; import android.accounts.AccountManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import org.estgroup.phphub.api.entity.element.Token; import org.estgroup.phphub.common.util.Utils; import org.estgroup.phphub.model.TokenModel; import eu.unicate.retroauth.AuthAccountManager; import eu.unicate.retroauth.exceptions.AuthenticationCanceledException; import rx.Notification; import rx.Observable; import rx.functions.Action1; import rx.functions.Func1; import rx.functions.Func2; import static org.estgroup.phphub.common.qualifier.AuthType.AUTH_TYPE_REFRESH; public class RefreshTokenTransformer<T> extends RetryTransformer implements Observable.Transformer<T, T> { private TokenModel tokenModel; private AuthAccountManager authAccountManager; private AccountManager accountManager; private Account account; private String accountType, tokenType; public RefreshTokenTransformer(@NonNull TokenModel tokenModel, AuthAccountManager authAccountManager, AccountManager accountManager, @Nullable Account account, String accountType, String tokenType) { this.tokenModel = tokenModel; this.authAccountManager = authAccountManager; this.accountManager = accountManager; this.account = account; this.accountType = accountType; this.tokenType = tokenType; } private boolean hasAuthentication(Throwable throwable) { return (throwable instanceof AuthenticationCanceledException || Utils.hasUnauthorized(throwable)); } @Override public Observable<T> call(Observable<T> observable) { return observable.retry(new Func2<Integer, Throwable, Boolean>() { @Override public Boolean call(Integer retryCount, Throwable throwable) { final boolean[] needRetry = {false}; if (retryCount <= RETRY_COUNT && hasAuthentication(throwable) && account != null) { tokenModel.refreshToken(authAccountManager.getUserData(accountType, AUTH_TYPE_REFRESH)) .materialize() .filter(new Func1<Notification<Token>, Boolean>() { @Override public Boolean call(Notification<Token> notification) { return !notification.isOnCompleted(); } }) .filter(new Func1<Notification<Token>, Boolean>() { @Override public Boolean call(Notification<Token> notification) { Token token = notification.getValue(); return (token != null && !TextUtils.isEmpty(token.getToken())); } }) .doOnNext(new Action1<Notification<Token>>() { @Override public void call(Notification<Token> notification) { Token token = notification.getValue(); accountManager.setAuthToken(account, tokenType, token.getToken()); accountManager.setUserData(account, AUTH_TYPE_REFRESH, token.getRefreshToken()); } }) .toBlocking() .forEach(new Action1<Notification<Token>>() { @Override public void call(Notification<Token> notification) { needRetry[0] = true; } }); } return needRetry[0]; } }); } }