diff --git a/build.gradle b/build.gradle index c1b1c921..ac9c3760 100644 --- a/build.gradle +++ b/build.gradle @@ -71,8 +71,8 @@ test.finalizedBy jacocoTestReport test { useJUnitPlatform() reports { - junitXml.enabled = false - html.enabled = true + junitXml.required.set(false) + html.required.set(true) } } diff --git a/src/main/java/com/amadeus/client/AccessToken.java b/src/main/java/com/amadeus/client/AccessToken.java index 27debdcf..a539a532 100644 --- a/src/main/java/com/amadeus/client/AccessToken.java +++ b/src/main/java/com/amadeus/client/AccessToken.java @@ -1,85 +1,23 @@ package com.amadeus.client; -import com.amadeus.Configuration; -import com.amadeus.Constants; import com.amadeus.HTTPClient; -import com.amadeus.HttpVerbs; -import com.amadeus.Params; -import com.amadeus.Response; import com.amadeus.exceptions.ResponseException; -import com.google.gson.JsonObject; /** * A memoized Access Token, with the ability to auto-refresh when needed. * @hide as only used internally */ public class AccessToken { - // Renew the token 10 seconds earlier than required, - // just to account for system lag - private static final long TOKEN_BUFFER = 10000L; - // An instance of the API client private final HTTPClient client; - // The access token value - private String accessToken = null; - // The (UNIX) expiry time of this token - private long expiresAt; + private final TokenManager tokenManager; - /** - * Constructor. - * @hides as only used internally - */ public AccessToken(HTTPClient client) { this.client = client; + this.tokenManager = new TokenManager(client); } - /** - * Creates a Bearer header using the cached Access Token. - * @hides as only used internally - */ public String getBearerToken() throws ResponseException { - lazyUpdateAccessToken(); - return String.format("Bearer %s", accessToken); - } - - // Loads the access token if it's still null - // or has expired. - private void lazyUpdateAccessToken() throws ResponseException { - if (needsRefresh()) { - updateAccessToken(); - } - } - - // Fetches the access token and then parses the resuling values. - private void updateAccessToken() throws ResponseException { - Response response = fetchAccessToken(); - storeAccessToken(response.getResult()); - } - - // Checks if this access token needs a refresh. - private boolean needsRefresh() { - boolean isNull = accessToken == null; - boolean expired = (System.currentTimeMillis() + TOKEN_BUFFER) > expiresAt; - return isNull || expired; - } - - // Fetches a new Access Token using the credentials from the client - private Response fetchAccessToken() throws ResponseException { - Configuration config = client.getConfiguration(); - return client.unauthenticatedRequest( - HttpVerbs.POST, - Constants.AUTH_URL, - Params.with(Constants.GRANT_TYPE, Constants.CLIENT_CREDENTIALS) - .and(Constants.CLIENT_ID, config.getClientId()) - .and(Constants.CLIENT_SECRET, config.getClientSecret()), - null, - null - ); - } - - // Store the fetched access token and expiry date - private void storeAccessToken(JsonObject result) { - this.accessToken = result.get(Constants.ACCESS_TOKEN).getAsString(); - int expiresIn = result.get(Constants.EXPIRES_IN).getAsInt(); - this.expiresAt = System.currentTimeMillis() + expiresIn * 1000L; + tokenManager.lazyUpdateAccessToken(); + return String.format("Bearer %s", tokenManager.getTokenValue()); } } diff --git a/src/main/java/com/amadeus/client/AuthUtils.java b/src/main/java/com/amadeus/client/AuthUtils.java new file mode 100644 index 00000000..93d7f33d --- /dev/null +++ b/src/main/java/com/amadeus/client/AuthUtils.java @@ -0,0 +1,36 @@ +package com.amadeus.client; + +import com.amadeus.Configuration; +import com.amadeus.Constants; +import com.amadeus.HTTPClient; +import com.amadeus.HttpVerbs; +import com.amadeus.Params; +import com.amadeus.Response; +import com.amadeus.exceptions.ResponseException; + +/** + * Utility class for authentication-related operations. + */ +public class AuthUtils { + + private AuthUtils() { + // Prevent instantiation + } + + public static Params createAuthRequestParams(Configuration config) { + return Params.with(Constants.GRANT_TYPE, Constants.CLIENT_CREDENTIALS) + .and(Constants.CLIENT_ID, config.getClientId()) + .and(Constants.CLIENT_SECRET, config.getClientSecret()); + } + + public static Response executeUnauthenticatedRequest(HTTPClient client, Params params) + throws ResponseException { + return client.unauthenticatedRequest( + HttpVerbs.POST, + Constants.AUTH_URL, + params, + null, + null + ); + } +} diff --git a/src/main/java/com/amadeus/client/TokenManager.java b/src/main/java/com/amadeus/client/TokenManager.java new file mode 100644 index 00000000..c065a864 --- /dev/null +++ b/src/main/java/com/amadeus/client/TokenManager.java @@ -0,0 +1,62 @@ +package com.amadeus.client; + +import com.amadeus.Configuration; +import com.amadeus.Constants; +import com.amadeus.HTTPClient; +import com.amadeus.Params; +import com.amadeus.Response; +import com.amadeus.exceptions.ResponseException; +import com.google.gson.JsonObject; +import lombok.Getter; + +/** + * Handles token-related functionality, including fetching and refreshing tokens. + */ +public class TokenManager { + private static final long TOKEN_BUFFER = 10000L; + private static final long MILLISECONDS_IN_SECOND = 1000L; + + private final HTTPClient client; + @Getter + private String tokenValue = null; + private long expiresAt; + + public TokenManager(HTTPClient client) { + this.client = client; + } + + public void lazyUpdateAccessToken() throws ResponseException { + if (isTokenExpiredOrNull()) { + updateAccessToken(); + } + } + + private boolean isTokenExpiredOrNull() { + return isTokenNull() || isTokenExpired(); + } + + private boolean isTokenNull() { + return tokenValue == null; + } + + private boolean isTokenExpired() { + return (System.currentTimeMillis() + TOKEN_BUFFER) > expiresAt; + } + + private void updateAccessToken() throws ResponseException { + Configuration config = client.getConfiguration(); + Params requestParams = AuthUtils.createAuthRequestParams(config); + Response response = AuthUtils.executeUnauthenticatedRequest(client, requestParams); + storeAccessTokenDetails(response.getResult()); + } + + private void storeAccessTokenDetails(JsonObject result) { + this.tokenValue = result.get(Constants.ACCESS_TOKEN).getAsString(); + int expiresIn = result.get(Constants.EXPIRES_IN).getAsInt(); + this.expiresAt = calculateExpiryTime(expiresIn); + } + + private long calculateExpiryTime(int expiresIn) { + return System.currentTimeMillis() + expiresIn * MILLISECONDS_IN_SECOND; + } +}