001 002package io.vrap.rmf.base.client.oauth2; 003 004import java.time.Duration; 005import java.util.concurrent.CompletableFuture; 006import java.util.concurrent.ExecutorService; 007import java.util.concurrent.ScheduledExecutorService; 008 009import io.vrap.rmf.base.client.AuthenticationToken; 010import io.vrap.rmf.base.client.AutoCloseableService; 011 012import dev.failsafe.Failsafe; 013import dev.failsafe.FailsafeExecutor; 014import dev.failsafe.Timeout; 015import dev.failsafe.spi.Scheduler; 016 017public class InMemoryTokenSupplier extends AutoCloseableService implements RefreshableTokenSupplier { 018 private final TokenSupplier supplier; 019 private final Object lock = new Object(); 020 private volatile CompletableFuture<AuthenticationToken> tokenFuture; 021 022 private final FailsafeExecutor<AuthenticationToken> failsafeExecutor; 023 024 public InMemoryTokenSupplier(TokenSupplier tokenSupplier) { 025 this(Scheduler.DEFAULT, tokenSupplier); 026 } 027 028 public InMemoryTokenSupplier(ScheduledExecutorService executorService, TokenSupplier tokenSupplier) { 029 this(Scheduler.of(executorService), tokenSupplier); 030 } 031 032 public InMemoryTokenSupplier(ExecutorService executorService, TokenSupplier tokenSupplier) { 033 this(Scheduler.of(executorService), tokenSupplier); 034 } 035 036 public InMemoryTokenSupplier(Scheduler scheduler, TokenSupplier tokenSupplier) { 037 this.supplier = tokenSupplier; 038 this.failsafeExecutor = Failsafe.with(Timeout.<AuthenticationToken> of(Duration.ofSeconds(10))).with(scheduler); 039 } 040 041 public CompletableFuture<AuthenticationToken> getToken() { 042 if (tokenFuture == null) 043 synchronized (lock) { 044 if (tokenFuture == null) { 045 failsafeExecutor 046 .run(() -> tokenFuture = CompletableFuture.completedFuture(supplier.getToken().join())); 047 } 048 } 049 return tokenFuture; 050 } 051 052 public CompletableFuture<AuthenticationToken> refreshToken() { 053 synchronized (lock) { 054 tokenFuture = null; 055 } 056 return getToken(); 057 } 058 059 @Override 060 protected void internalClose() { 061 if (supplier instanceof AutoCloseable) 062 closeQuietly((AutoCloseable) supplier); 063 } 064}