package co.smartreceipts.android.aws.s3;
import android.content.Context;
import android.support.annotation.NonNull;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.google.common.base.Preconditions;
import com.hadisatrio.optional.Optional;
import co.smartreceipts.android.aws.cognito.CognitoManager;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.ReplaySubject;
class S3ClientFactory {
private final Context context;
private final CognitoManager cognitoManager;
private ReplaySubject<Optional<AmazonS3Client>> amazonS3ReplaySubject;
private Disposable amazonS3Disposable;
public S3ClientFactory(@NonNull Context context, @NonNull CognitoManager cognitoManager) {
this.context = Preconditions.checkNotNull(context.getApplicationContext());
this.cognitoManager = Preconditions.checkNotNull(cognitoManager);
}
/**
* @return an {@link Optional} instance of the {@link AmazonS3} client. Once we fetch a valid
* entry, this should be treated as a singleton for the lifetime of the parent
* {@link S3ClientFactory} object, since we use a replay subject
*/
@NonNull
public synchronized Observable<Optional<AmazonS3Client>> getAmazonS3() {
if (amazonS3ReplaySubject == null) {
amazonS3ReplaySubject = ReplaySubject.createWithSize(1);
amazonS3Disposable = cognitoManager.getCognitoCachingCredentialsProvider()
.<Optional<AmazonS3Client>>map(cognitoCachingCredentialsProvider -> {
if (cognitoCachingCredentialsProvider.isPresent()) {
return Optional.of(new AmazonS3Client(cognitoCachingCredentialsProvider.get()));
} else {
return Optional.absent();
}
})
.subscribe(amazonS3ClientOptional -> {
amazonS3ReplaySubject.onNext(amazonS3ClientOptional);
if (amazonS3ClientOptional.isPresent()) {
amazonS3ReplaySubject.onComplete();
if (amazonS3Disposable != null) {
amazonS3Disposable.dispose();
}
}
}, throwable -> amazonS3ReplaySubject.onError(throwable),
() -> amazonS3ReplaySubject.onComplete());
}
return amazonS3ReplaySubject;
}
}