155 lines
4.5 KiB
Java
155 lines
4.5 KiB
Java
package sh.ftp.rocketninelabs.meditationassistant;
|
|
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
import androidx.annotation.AnyThread;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import android.util.Log;
|
|
|
|
import net.openid.appauth.AuthState;
|
|
import net.openid.appauth.AuthorizationException;
|
|
import net.openid.appauth.AuthorizationResponse;
|
|
import net.openid.appauth.RegistrationResponse;
|
|
import net.openid.appauth.TokenResponse;
|
|
|
|
import org.json.JSONException;
|
|
|
|
import java.lang.ref.WeakReference;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
/**
|
|
* An example persistence mechanism for an {@link AuthState} instance.
|
|
* This stores the instance in a shared preferences file, and provides thread-safe access and
|
|
* mutation.
|
|
*/
|
|
public class AuthStateManager {
|
|
|
|
private static final AtomicReference<WeakReference<AuthStateManager>> INSTANCE_REF =
|
|
new AtomicReference<>(new WeakReference<>(null));
|
|
|
|
private static final String TAG = "AuthStateManager";
|
|
|
|
private static final String STORE_NAME = "AuthState";
|
|
private static final String KEY_STATE = "state";
|
|
|
|
private final SharedPreferences mPrefs;
|
|
private final ReentrantLock mPrefsLock;
|
|
private final AtomicReference<AuthState> mCurrentAuthState;
|
|
|
|
@AnyThread
|
|
public static AuthStateManager getInstance(@NonNull Context context) {
|
|
AuthStateManager manager = INSTANCE_REF.get().get();
|
|
if (manager == null) {
|
|
manager = new AuthStateManager(context.getApplicationContext());
|
|
INSTANCE_REF.set(new WeakReference<>(manager));
|
|
}
|
|
|
|
return manager;
|
|
}
|
|
|
|
private AuthStateManager(Context context) {
|
|
mPrefs = context.getSharedPreferences(STORE_NAME, Context.MODE_PRIVATE);
|
|
mPrefsLock = new ReentrantLock();
|
|
mCurrentAuthState = new AtomicReference<>();
|
|
}
|
|
|
|
@AnyThread
|
|
@NonNull
|
|
public AuthState getCurrent() {
|
|
if (mCurrentAuthState.get() != null) {
|
|
return mCurrentAuthState.get();
|
|
}
|
|
|
|
AuthState state = readState();
|
|
if (mCurrentAuthState.compareAndSet(null, state)) {
|
|
return state;
|
|
} else {
|
|
return mCurrentAuthState.get();
|
|
}
|
|
}
|
|
|
|
@AnyThread
|
|
@NonNull
|
|
public AuthState replace(@NonNull AuthState state) {
|
|
writeState(state);
|
|
mCurrentAuthState.set(state);
|
|
return state;
|
|
}
|
|
|
|
@AnyThread
|
|
@NonNull
|
|
public AuthState updateAfterAuthorization(
|
|
@Nullable AuthorizationResponse response,
|
|
@Nullable AuthorizationException ex) {
|
|
AuthState current = getCurrent();
|
|
current.update(response, ex);
|
|
return replace(current);
|
|
}
|
|
|
|
@AnyThread
|
|
@NonNull
|
|
public AuthState updateAfterTokenResponse(
|
|
@Nullable TokenResponse response,
|
|
@Nullable AuthorizationException ex) {
|
|
AuthState current = getCurrent();
|
|
current.update(response, ex);
|
|
return replace(current);
|
|
}
|
|
|
|
@AnyThread
|
|
@NonNull
|
|
public AuthState updateAfterRegistration(
|
|
RegistrationResponse response,
|
|
AuthorizationException ex) {
|
|
AuthState current = getCurrent();
|
|
if (ex != null) {
|
|
return current;
|
|
}
|
|
|
|
current.update(response);
|
|
return replace(current);
|
|
}
|
|
|
|
@AnyThread
|
|
@NonNull
|
|
private AuthState readState() {
|
|
mPrefsLock.lock();
|
|
try {
|
|
String currentState = mPrefs.getString(KEY_STATE, null);
|
|
if (currentState == null) {
|
|
return new AuthState();
|
|
}
|
|
|
|
try {
|
|
return AuthState.jsonDeserialize(currentState);
|
|
} catch (JSONException ex) {
|
|
Log.w(TAG, "Failed to deserialize stored auth state - discarding");
|
|
return new AuthState();
|
|
}
|
|
} finally {
|
|
mPrefsLock.unlock();
|
|
}
|
|
}
|
|
|
|
@AnyThread
|
|
private void writeState(@Nullable AuthState state) {
|
|
mPrefsLock.lock();
|
|
try {
|
|
SharedPreferences.Editor editor = mPrefs.edit();
|
|
if (state == null) {
|
|
editor.remove(KEY_STATE);
|
|
} else {
|
|
editor.putString(KEY_STATE, state.jsonSerializeString());
|
|
}
|
|
|
|
if (!editor.commit()) {
|
|
throw new IllegalStateException("Failed to write state to shared prefs");
|
|
}
|
|
} finally {
|
|
mPrefsLock.unlock();
|
|
}
|
|
}
|
|
}
|