From 91f86cb70fea7e5cfa1c2f53bde80845f926d243 Mon Sep 17 00:00:00 2001 From: Phil Adams Date: Fri, 1 Apr 2022 13:54:26 -0500 Subject: [PATCH] feat: allow user-specified default OkHttpClient instance This commit modifies the java core so that users can now specify a fully-configured OkHttpClient instance to be used by service and authenticator instances: 1. The HttpClientSingleton class now has methods setHttpClient() and getHttpClient(). These methods can be used to set and get the default client configuration from which other OkHttpClient instances are created. 2. The TokenRequestBasedAuthenticator base class now has methods setClient() and getClient(). These methods can be used to set and get the specific OkHttpClient instance that should be used by an authenticator when interacting with the token service. These new methods are inherited by each of the request-based authenticator implementation classes: ContainerAuthenticator, CloudPakForDataAuthenticator, CloudPakForDataServiceAuthenticator, CloudPakForDataServiceInstanceAuthenticator, IamAuthenticator, and VpcInstanceAuthenticator. --- .../sdk/core/http/HttpClientSingleton.java | 22 +++++- .../TokenRequestBasedAuthenticator.java | 68 ++++++++++++++----- .../VpcInstanceAuthenticatorTest.java | 19 ++++++ .../test/http/HttpClientSingletonTest.java | 44 ++++++++++++ .../security/ContainerAuthenticatorTest.java | 19 ++++++ .../test/security/Cp4dAuthenticatorTest.java | 22 +++++- .../Cp4dServiceAuthenticatorTest.java | 22 +++++- .../Cp4dServiceInstanceAuthenticatorTest.java | 22 +++++- .../test/security/IamAuthenticatorTest.java | 19 ++++++ 9 files changed, 232 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/ibm/cloud/sdk/core/http/HttpClientSingleton.java b/src/main/java/com/ibm/cloud/sdk/core/http/HttpClientSingleton.java index 0245555f7..778d8a86a 100644 --- a/src/main/java/com/ibm/cloud/sdk/core/http/HttpClientSingleton.java +++ b/src/main/java/com/ibm/cloud/sdk/core/http/HttpClientSingleton.java @@ -153,7 +153,25 @@ protected HttpClientSingleton() { } /** - * Configures the HTTP client. + * Returns the current {@link OkHttpClient} instance held by this singleton. + * This is the client instance that is used as a default configuration from which other client instances are built. + * @return the current OkHttpClient instance + */ + public OkHttpClient getHttpClient() { + return this.okHttpClient; + } + + /** + * Sets the current {@link OkHttpClient} instance held by this singleton. + * This is the client instance that is used as a default configuration from which other client instances are built. + * @param client the new OkHttpClient instance to use as a default client configuration + */ + public void setHttpClient(OkHttpClient client) { + this.okHttpClient = client; + } + + /** + * Configures a new HTTP client instance. * * @return the HTTP client */ @@ -290,7 +308,7 @@ private OkHttpClient setLoggingLevel(OkHttpClient client, LoggingLevel loggingLe * * @param builder the {@link OkHttpClient} builder. */ - private void setupTLSProtocol(final OkHttpClient.Builder builder) { + public static void setupTLSProtocol(final OkHttpClient.Builder builder) { try { TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); diff --git a/src/main/java/com/ibm/cloud/sdk/core/security/TokenRequestBasedAuthenticator.java b/src/main/java/com/ibm/cloud/sdk/core/security/TokenRequestBasedAuthenticator.java index 5c8b95f24..e59092a19 100644 --- a/src/main/java/com/ibm/cloud/sdk/core/security/TokenRequestBasedAuthenticator.java +++ b/src/main/java/com/ibm/cloud/sdk/core/security/TokenRequestBasedAuthenticator.java @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2019, 2021. + * (C) Copyright IBM Corp. 2019, 2022. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at @@ -40,9 +40,11 @@ * */ public abstract class TokenRequestBasedAuthenticator @@ -50,6 +52,8 @@ public abstract class TokenRequestBasedAuthenticator headers; @@ -67,6 +71,47 @@ private void setTokenData(T tokenData) { this.tokenData = tokenData; } + /** + * Sets the OkHttpClient instance to be used when interacting with the token service. + * @param client the OkHttpClient instance to use + */ + public void setClient(OkHttpClient client) { + this.client = client; + } + + /** + * Returns the OkHttpClient instance to be used when interacting with the token service. + * @return the client instance or null if a client insance has not yet been set + */ + public OkHttpClient getClient() { + return this.client; + } + + /** + * Returns a properly-configured OkHttpClient instance to use when interacting with the token service. + * This function is different from "getClient()" in that it will configure and save + * a client instance if one has not yet been setup for "this". + * @return a non-null, configured OkHttpClient instance + */ + protected synchronized OkHttpClient getConfiguredClient() { + if (this.client == null) { + OkHttpClient defaultClient = HttpClientSingleton.getInstance().getHttpClient(); + + HttpConfigOptions.Builder clientOptions = new HttpConfigOptions.Builder() + .disableSslVerification(this.disableSSLVerification) + .proxy(this.proxy) + .proxyAuthenticator(this.proxyAuthenticator); + + if (logger.isLoggable(Level.FINE)) { + clientOptions.loggingLevel(LoggingLevel.BODY); + } + + this.client = HttpClientSingleton.getInstance().configureClient(defaultClient, clientOptions.build()); + } + + return this.client; + } + /** * Validates the configuration properties associated with the Authenticator. * Each concrete subclass must implement this method. @@ -136,7 +181,7 @@ public Proxy getProxy() { /** * Sets a Proxy object on this Authenticator. - * @param proxy the proxy object to be associated with the Client used to interact wth the token service. + * @param proxy the proxy object to be associated with the Client used to interact with the token service. */ public void setProxy(Proxy proxy) { this.proxy = proxy; @@ -256,18 +301,7 @@ protected R invokeRequest(final RequestBuilder requestBuilder, final Class