From 486acdc633c498d4335711e30817cc70faacc487 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Thu, 16 Jun 2016 15:48:48 -0700 Subject: [PATCH] Squashed 'runtimes/' changes from 1ae4191..04af976 04af976 Regenerate azure & azure.fluent fecda5c Move RestClient into azure runtime 05105b4 Remove rest client from generic codegen 1773d49 Add stage for base url 4a7b25e Remove required mapper adapter 6196ce0 Merge pull request #20 from jianghaolu/master 06f30cf Checkstyle passes everywhere 2bf6b8b Merge pull request #783 from jianghaolu/javadocs b14cc72 Merge pull request #779 from jianghaolu/paramhostfix 546e068 Network passes checkstyle 14b071c Merge commit '4aa3dd4b847e747387475e9249c4aba97b6ef8ac' into paramhostfix 95fa032 Done storage usages git-subtree-dir: runtimes git-subtree-split: 04af9766d691bd19eb137f9f6cc27fab9c572cc0 --- .../com/microsoft/azure/AzureEnvironment.java | 11 +- .../microsoft/azure/AzureServiceClient.java | 49 ++- .../java/com/microsoft/azure/RestClient.java | 290 ++++++++++++++++++ .../java/com/microsoft/azure/DAGraphTest.java | 145 +++++++++ .../RequestIdHeaderInterceptorTests.java | 21 +- build-tools/src/main/resources/checkstyle.xml | 1 - .../src/main/resources/suppressions.xml | 4 +- .../java/com/microsoft/rest/RestClient.java | 245 --------------- .../com/microsoft/rest/ServiceClient.java | 68 +++- .../microsoft/rest/UserAgentInterceptor.java | 8 +- .../com/microsoft/rest/CredentialsTests.java | 51 ++- .../com/microsoft/rest/RetryHandlerTests.java | 23 +- .../microsoft/rest/ServiceClientTests.java | 9 +- .../com/microsoft/rest/UserAgentTests.java | 30 +- 14 files changed, 602 insertions(+), 353 deletions(-) create mode 100644 azure-client-runtime/src/main/java/com/microsoft/azure/RestClient.java create mode 100644 azure-client-runtime/src/test/java/com/microsoft/azure/DAGraphTest.java delete mode 100644 client-runtime/src/main/java/com/microsoft/rest/RestClient.java diff --git a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureEnvironment.java b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureEnvironment.java index 1721e2ff97bb8..517a2c3205ac1 100644 --- a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureEnvironment.java +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureEnvironment.java @@ -7,9 +7,6 @@ package com.microsoft.azure; -import com.microsoft.azure.serializer.AzureJacksonMapperAdapter; -import com.microsoft.rest.RestClient; - /** * An instance of this class describes an environment in Azure. */ @@ -87,10 +84,10 @@ public String getBaseUrl() { * * @return a builder for the rest client. */ - public RestClient.Builder newRestClientBuilder() { - return new RestClient.Builder(baseURL) - .withInterceptor(new RequestIdHeaderInterceptor()) - .withMapperAdapter(new AzureJacksonMapperAdapter()); + public RestClient.Builder.Buildable newRestClientBuilder() { + return new RestClient.Builder() + .withDefaultBaseUrl(this) + .withInterceptor(new RequestIdHeaderInterceptor()); } /** diff --git a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureServiceClient.java b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureServiceClient.java index 08094b67d5071..09c8c28fbd536 100644 --- a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureServiceClient.java +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureServiceClient.java @@ -7,18 +7,23 @@ package com.microsoft.azure; -import com.microsoft.azure.serializer.AzureJacksonMapperAdapter; -import com.microsoft.rest.RestClient; -import com.microsoft.rest.ServiceClient; +import com.microsoft.rest.serializer.JacksonMapperAdapter; + +import okhttp3.OkHttpClient; +import retrofit2.Retrofit; /** * ServiceClient is the abstraction for accessing REST operations and their payload data types. */ -public abstract class AzureServiceClient extends ServiceClient { +public abstract class AzureServiceClient { + /** + * The RestClient instance storing all information needed for making REST calls. + */ + private RestClient restClient; + protected AzureServiceClient(String baseUrl) { - this(new RestClient.Builder(baseUrl) - .withInterceptor(new RequestIdHeaderInterceptor()) - .withMapperAdapter(new AzureJacksonMapperAdapter()).build()); + this(new RestClient.Builder().withBaseUrl(baseUrl) + .withInterceptor(new RequestIdHeaderInterceptor()).build()); } /** @@ -27,7 +32,7 @@ protected AzureServiceClient(String baseUrl) { * @param restClient the REST client */ protected AzureServiceClient(RestClient restClient) { - super(restClient); + this.restClient = restClient; } /** @@ -38,4 +43,32 @@ protected AzureServiceClient(RestClient restClient) { public String userAgent() { return "Azure-SDK-For-Java/" + getClass().getPackage().getImplementationVersion(); } + + /** + * @return the {@link RestClient} instance. + */ + public RestClient restClient() { + return restClient; + } + + /** + * @return the Retrofit instance. + */ + public Retrofit retrofit() { + return restClient().retrofit(); + } + + /** + * @return the HTTP client. + */ + public OkHttpClient httpClient() { + return restClient().httpClient(); + } + + /** + * @return the adapter to a Jackson {@link com.fasterxml.jackson.databind.ObjectMapper}. + */ + public JacksonMapperAdapter mapperAdapter() { + return restClient().mapperAdapter(); + } } diff --git a/azure-client-runtime/src/main/java/com/microsoft/azure/RestClient.java b/azure-client-runtime/src/main/java/com/microsoft/azure/RestClient.java new file mode 100644 index 0000000000000..2517f890a52ca --- /dev/null +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/RestClient.java @@ -0,0 +1,290 @@ +/** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * + */ + +package com.microsoft.azure; + +import com.microsoft.azure.serializer.AzureJacksonMapperAdapter; +import com.microsoft.rest.BaseUrlHandler; +import com.microsoft.rest.CustomHeadersInterceptor; +import com.microsoft.rest.UserAgentInterceptor; +import com.microsoft.rest.credentials.ServiceClientCredentials; +import com.microsoft.rest.retry.RetryHandler; +import com.microsoft.rest.serializer.JacksonMapperAdapter; + +import java.lang.reflect.Field; +import java.net.CookieManager; +import java.net.CookiePolicy; + +import okhttp3.Interceptor; +import okhttp3.JavaNetCookieJar; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.Retrofit; + +/** + * An instance of this class stores the client information for making REST calls. + */ +public class RestClient { + /** The {@link okhttp3.OkHttpClient} object. */ + private OkHttpClient httpClient; + /** The {@link retrofit2.Retrofit} object. */ + private Retrofit retrofit; + /** The credentials to authenticate. */ + private ServiceClientCredentials credentials; + /** The interceptor to handle custom headers. */ + private CustomHeadersInterceptor customHeadersInterceptor; + /** The interceptor to handle base URL. */ + private BaseUrlHandler baseUrlHandler; + /** The adapter to a Jackson {@link com.fasterxml.jackson.databind.ObjectMapper}. */ + private JacksonMapperAdapter mapperAdapter; + /** The interceptor to set 'User-Agent' header. */ + private UserAgentInterceptor userAgentInterceptor; + + protected RestClient(OkHttpClient httpClient, + Retrofit retrofit, + ServiceClientCredentials credentials, + CustomHeadersInterceptor customHeadersInterceptor, + UserAgentInterceptor userAgentInterceptor, + BaseUrlHandler baseUrlHandler, + JacksonMapperAdapter mapperAdapter) { + this.httpClient = httpClient; + this.retrofit = retrofit; + this.credentials = credentials; + this.customHeadersInterceptor = customHeadersInterceptor; + this.userAgentInterceptor = userAgentInterceptor; + this.baseUrlHandler = baseUrlHandler; + this.mapperAdapter = mapperAdapter; + } + + /** + * Get the headers interceptor. + * + * @return the headers interceptor. + */ + public CustomHeadersInterceptor headers() { + return customHeadersInterceptor; + } + + /** + * Get the adapter to {@link com.fasterxml.jackson.databind.ObjectMapper}. + * + * @return the Jackson mapper adapter. + */ + public JacksonMapperAdapter mapperAdapter() { + return mapperAdapter; + } + + /** + * Sets the mapper adapter. + * + * @param mapperAdapter an adapter to a Jackson mapper. + * @return the builder itself for chaining. + */ + public RestClient withMapperAdapater(JacksonMapperAdapter mapperAdapter) { + this.mapperAdapter = mapperAdapter; + return this; + } + + /** + * Get the http client. + * + * @return the {@link OkHttpClient} object. + */ + public OkHttpClient httpClient() { + return httpClient; + } + + /** + * Get the retrofit instance. + * + * @return the {@link Retrofit} object. + */ + public Retrofit retrofit() { + return retrofit; + } + + /** + * Get the credentials attached to this REST client. + * + * @return the credentials. + */ + public ServiceClientCredentials credentials() { + return this.credentials; + } + + /** + * The builder class for building a REST client. + */ + public static class Builder { + /** The dynamic base URL with variables wrapped in "{" and "}". */ + protected String baseUrl; + /** The builder to build an {@link OkHttpClient}. */ + protected OkHttpClient.Builder httpClientBuilder; + /** The builder to build a {@link Retrofit}. */ + protected Retrofit.Builder retrofitBuilder; + /** The credentials to authenticate. */ + protected ServiceClientCredentials credentials; + /** The interceptor to handle custom headers. */ + protected CustomHeadersInterceptor customHeadersInterceptor; + /** The interceptor to handle base URL. */ + protected BaseUrlHandler baseUrlHandler; + /** The interceptor to set 'User-Agent' header. */ + protected UserAgentInterceptor userAgentInterceptor; + /** The inner Builder instance. */ + protected Buildable buildable; + + /** + * Creates an instance of the builder with a base URL to the service. + */ + public Builder() { + this(new OkHttpClient.Builder(), new Retrofit.Builder()); + } + + /** + * Creates an instance of the builder with a base URL and 2 custom builders. + * + * @param httpClientBuilder the builder to build an {@link OkHttpClient}. + * @param retrofitBuilder the builder to build a {@link Retrofit}. + */ + public Builder(OkHttpClient.Builder httpClientBuilder, Retrofit.Builder retrofitBuilder) { + if (httpClientBuilder == null) { + throw new IllegalArgumentException("httpClientBuilder == null"); + } + if (retrofitBuilder == null) { + throw new IllegalArgumentException("retrofitBuilder == null"); + } + CookieManager cookieManager = new CookieManager(); + cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); + customHeadersInterceptor = new CustomHeadersInterceptor(); + baseUrlHandler = new BaseUrlHandler(); + userAgentInterceptor = new UserAgentInterceptor(); + // Set up OkHttp client + this.httpClientBuilder = httpClientBuilder + .cookieJar(new JavaNetCookieJar(cookieManager)) + .addInterceptor(userAgentInterceptor); + this.retrofitBuilder = retrofitBuilder; + this.buildable = new Buildable(); + } + + /** + * Sets the dynamic base URL. + * + * @param baseUrl the base URL to use. + * @return the builder itself for chaining. + */ + public Buildable withBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return buildable; + } + + /** + * Sets the base URL with the default from the service client. + * + * @param serviceClientClass the service client class containing a default base URL. + * @return the builder itself for chaining. + */ + public Buildable withDefaultBaseUrl(Class serviceClientClass) { + try { + Field field = serviceClientClass.getDeclaredField("DEFAULT_BASE_URL"); + field.setAccessible(true); + baseUrl = (String) field.get(null); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new UnsupportedOperationException("Cannot read static field DEFAULT_BASE_URL", e); + } + return buildable; + } + + /** + * Sets the base URL with the default from the Azure Environment. + * + * @param environment the environment the application is running in + * @return the builder itself for chaining + */ + public RestClient.Builder.Buildable withDefaultBaseUrl(AzureEnvironment environment) { + withBaseUrl(environment.getBaseUrl()); + return buildable; + } + + /** + * The inner class from which a Rest Client can be built. + */ + public class Buildable { + /** + * Sets the user agent header. + * + * @param userAgent the user agent header. + * @return the builder itself for chaining. + */ + public Buildable withUserAgent(String userAgent) { + userAgentInterceptor.withUserAgent(userAgent); + return this; + } + + /** + * Sets the credentials. + * + * @param credentials the credentials object. + * @return the builder itself for chaining. + */ + public Buildable withCredentials(ServiceClientCredentials credentials) { + Builder.this.credentials = credentials; + if (credentials != null) { + credentials.applyCredentialsFilter(httpClientBuilder); + } + return this; + } + + /** + * Sets the log level. + * + * @param logLevel the {@link okhttp3.logging.HttpLoggingInterceptor.Level} enum. + * @return the builder itself for chaining. + */ + public Buildable withLogLevel(HttpLoggingInterceptor.Level logLevel) { + httpClientBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(logLevel)); + return this; + } + + /** + * Add an interceptor the Http client pipeline. + * + * @param interceptor the interceptor to add. + * @return the builder itself for chaining. + */ + public Buildable withInterceptor(Interceptor interceptor) { + httpClientBuilder.addInterceptor(interceptor); + return this; + } + + /** + * Build a RestClient with all the current configurations. + * + * @return a {@link RestClient}. + */ + public RestClient build() { + AzureJacksonMapperAdapter mapperAdapter = new AzureJacksonMapperAdapter(); + OkHttpClient httpClient = httpClientBuilder + .addInterceptor(baseUrlHandler) + .addInterceptor(customHeadersInterceptor) + .addInterceptor(new RetryHandler()) + .build(); + return new RestClient(httpClient, + retrofitBuilder + .baseUrl(baseUrl) + .client(httpClient) + .addConverterFactory(mapperAdapter.getConverterFactory()) + .build(), + credentials, + customHeadersInterceptor, + userAgentInterceptor, + baseUrlHandler, + mapperAdapter); + } + + } + } +} diff --git a/azure-client-runtime/src/test/java/com/microsoft/azure/DAGraphTest.java b/azure-client-runtime/src/test/java/com/microsoft/azure/DAGraphTest.java new file mode 100644 index 0000000000000..8c1e12dd7011d --- /dev/null +++ b/azure-client-runtime/src/test/java/com/microsoft/azure/DAGraphTest.java @@ -0,0 +1,145 @@ +package com.microsoft.azure; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class DAGraphTest { + @Test + public void testDAGraphGetNext() { + /** + * |-------->[D]------>[B]-----------[A] + * | ^ ^ + * | | | + * [F]------->[E]-------| | + * | | | + * | |------->[G]----->[C]---- + * | + * |-------->[H]-------------------->[I] + */ + List expectedOrder = new ArrayList<>(); + expectedOrder.add("A"); expectedOrder.add("I"); + expectedOrder.add("B"); expectedOrder.add("C"); expectedOrder.add("H"); + expectedOrder.add("D"); expectedOrder.add("G"); + expectedOrder.add("E"); + expectedOrder.add("F"); + + DAGNode nodeA = new DAGNode<>("A", "dataA"); + DAGNode nodeI = new DAGNode<>("I", "dataI"); + + DAGNode nodeB = new DAGNode<>("B", "dataB"); + nodeB.addDependency(nodeA.key()); + + DAGNode nodeC = new DAGNode<>("C", "dataC"); + nodeC.addDependency(nodeA.key()); + + DAGNode nodeH = new DAGNode<>("H", "dataH"); + nodeH.addDependency(nodeI.key()); + + DAGNode nodeG = new DAGNode<>("G", "dataG"); + nodeG.addDependency(nodeC.key()); + + DAGNode nodeE = new DAGNode<>("E", "dataE"); + nodeE.addDependency(nodeB.key()); + nodeE.addDependency(nodeG.key()); + + DAGNode nodeD = new DAGNode<>("D", "dataD"); + nodeD.addDependency(nodeB.key()); + + + DAGNode nodeF = new DAGNode<>("F", "dataF"); + nodeF.addDependency(nodeD.key()); + nodeF.addDependency(nodeE.key()); + nodeF.addDependency(nodeH.key()); + + DAGraph> dag = new DAGraph<>(nodeF); + dag.addNode(nodeA); + dag.addNode(nodeB); + dag.addNode(nodeC); + dag.addNode(nodeD); + dag.addNode(nodeE); + dag.addNode(nodeG); + dag.addNode(nodeH); + dag.addNode(nodeI); + + dag.populateDependentKeys(); + DAGNode nextNode = dag.getNext(); + int i = 0; + while (nextNode != null) { + Assert.assertEquals(nextNode.key(), expectedOrder.get(i)); + dag.reportedCompleted(nextNode); + nextNode = dag.getNext(); + i++; + } + + System.out.println("done"); + } + + @Test + public void testGraphMerge() { + /** + * |-------->[D]------>[B]-----------[A] + * | ^ ^ + * | | | + * [F]------->[E]-------| | + * | | | + * | |------->[G]----->[C]---- + * | + * |-------->[H]-------------------->[I] + */ + List expectedOrder = new ArrayList<>(); + expectedOrder.add("A"); expectedOrder.add("I"); + expectedOrder.add("B"); expectedOrder.add("C"); expectedOrder.add("H"); + expectedOrder.add("D"); expectedOrder.add("G"); + expectedOrder.add("E"); + expectedOrder.add("F"); + + DAGraph> graphA = createGraph("A"); + DAGraph> graphI = createGraph("I"); + + DAGraph> graphB = createGraph("B"); + graphA.merge(graphB); + + DAGraph> graphC = createGraph("C"); + graphA.merge(graphC); + + DAGraph> graphH = createGraph("H"); + graphI.merge(graphH); + + DAGraph> graphG = createGraph("G"); + graphC.merge(graphG); + + DAGraph> graphE = createGraph("E"); + graphB.merge(graphE); + graphG.merge(graphE); + + DAGraph> graphD = createGraph("D"); + graphB.merge(graphD); + + DAGraph> graphF = createGraph("F"); + graphD.merge(graphF); + graphE.merge(graphF); + graphH.merge(graphF); + + DAGraph> dag = graphF; + dag.prepare(); + + DAGNode nextNode = dag.getNext(); + int i = 0; + while (nextNode != null) { + Assert.assertEquals(expectedOrder.get(i), nextNode.key()); + // Process the node + dag.reportedCompleted(nextNode); + nextNode = dag.getNext(); + i++; + } + } + + private DAGraph> createGraph(String resourceName) { + DAGNode node = new DAGNode<>(resourceName, "data" + resourceName); + DAGraph> graph = new DAGraph<>(node); + return graph; + } +} diff --git a/azure-client-runtime/src/test/java/com/microsoft/azure/RequestIdHeaderInterceptorTests.java b/azure-client-runtime/src/test/java/com/microsoft/azure/RequestIdHeaderInterceptorTests.java index e8cce598b05f4..060336cd23d29 100644 --- a/azure-client-runtime/src/test/java/com/microsoft/azure/RequestIdHeaderInterceptorTests.java +++ b/azure-client-runtime/src/test/java/com/microsoft/azure/RequestIdHeaderInterceptorTests.java @@ -7,24 +7,25 @@ package com.microsoft.azure; -import com.microsoft.azure.serializer.AzureJacksonMapperAdapter; -import com.microsoft.rest.RestClient; import com.microsoft.rest.retry.RetryHandler; -import okhttp3.Interceptor; -import okhttp3.Protocol; -import okhttp3.Request; -import okhttp3.Response; + import org.junit.Assert; import org.junit.Test; import java.io.IOException; +import okhttp3.Interceptor; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; + public class RequestIdHeaderInterceptorTests { private static final String REQUEST_ID_HEADER = "x-ms-client-request-id"; @Test public void newRequestIdForEachCall() throws Exception { - RestClient restClient = new RestClient.Builder("http://localhost") + RestClient restClient = new RestClient.Builder() + .withBaseUrl("http://localhost") .withInterceptor(new RequestIdHeaderInterceptor()) .withInterceptor(new Interceptor() { private String firstRequestId = null; @@ -45,7 +46,6 @@ public Response intercept(Chain chain) throws IOException { .protocol(Protocol.HTTP_1_1).build(); } }) - .withMapperAdapter(new AzureJacksonMapperAdapter()) .build(); AzureServiceClient serviceClient = new AzureServiceClient(restClient) { }; Response response = serviceClient.restClient().httpClient() @@ -58,11 +58,13 @@ public Response intercept(Chain chain) throws IOException { @Test public void sameRequestIdForRetry() throws Exception { - RestClient restClient = new RestClient.Builder("http://localhost") + RestClient restClient = new RestClient.Builder() + .withBaseUrl("http://localhost") .withInterceptor(new RequestIdHeaderInterceptor()) .withInterceptor(new RetryHandler()) .withInterceptor(new Interceptor() { private String firstRequestId = null; + @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); @@ -80,7 +82,6 @@ public Response intercept(Chain chain) throws IOException { .protocol(Protocol.HTTP_1_1).build(); } }) - .withMapperAdapter(new AzureJacksonMapperAdapter()) .build(); AzureServiceClient serviceClient = new AzureServiceClient(restClient) { }; Response response = serviceClient.restClient().httpClient() diff --git a/build-tools/src/main/resources/checkstyle.xml b/build-tools/src/main/resources/checkstyle.xml index d156ff63e65f6..1875d6f100cab 100644 --- a/build-tools/src/main/resources/checkstyle.xml +++ b/build-tools/src/main/resources/checkstyle.xml @@ -248,7 +248,6 @@ --> - diff --git a/build-tools/src/main/resources/suppressions.xml b/build-tools/src/main/resources/suppressions.xml index 690bb7a9fc35f..29e5bd66eefb5 100644 --- a/build-tools/src/main/resources/suppressions.xml +++ b/build-tools/src/main/resources/suppressions.xml @@ -31,6 +31,8 @@ --> - + + + \ No newline at end of file diff --git a/client-runtime/src/main/java/com/microsoft/rest/RestClient.java b/client-runtime/src/main/java/com/microsoft/rest/RestClient.java deleted file mode 100644 index 254639642345a..0000000000000 --- a/client-runtime/src/main/java/com/microsoft/rest/RestClient.java +++ /dev/null @@ -1,245 +0,0 @@ -/** - * - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * - */ - -package com.microsoft.rest; - -import com.microsoft.rest.credentials.ServiceClientCredentials; -import com.microsoft.rest.retry.RetryHandler; -import com.microsoft.rest.serializer.JacksonMapperAdapter; - -import java.net.CookieManager; -import java.net.CookiePolicy; - -import okhttp3.Interceptor; -import okhttp3.JavaNetCookieJar; -import okhttp3.OkHttpClient; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Retrofit; - -/** - * An instance of this class stores the client information for making REST calls. - */ -public final class RestClient { - /** The {@link okhttp3.OkHttpClient} object. */ - private OkHttpClient httpClient; - /** The {@link retrofit2.Retrofit} object. */ - private Retrofit retrofit; - /** The credentials to authenticate. */ - private ServiceClientCredentials credentials; - /** The interceptor to handle custom headers. */ - private CustomHeadersInterceptor customHeadersInterceptor; - /** The interceptor to handle base URL. */ - private BaseUrlHandler baseUrlHandler; - /** The adapter to a Jackson {@link com.fasterxml.jackson.databind.ObjectMapper}. */ - private JacksonMapperAdapter mapperAdapter; - /** The interceptor to set 'User-Agent' header. */ - private UserAgentInterceptor userAgentInterceptor; - - private RestClient(OkHttpClient httpClient, - Retrofit retrofit, - ServiceClientCredentials credentials, - CustomHeadersInterceptor customHeadersInterceptor, - UserAgentInterceptor userAgentInterceptor, - BaseUrlHandler baseUrlHandler, - JacksonMapperAdapter mapperAdapter) { - this.httpClient = httpClient; - this.retrofit = retrofit; - this.credentials = credentials; - this.customHeadersInterceptor = customHeadersInterceptor; - this.userAgentInterceptor = userAgentInterceptor; - this.baseUrlHandler = baseUrlHandler; - this.mapperAdapter = mapperAdapter; - } - - /** - * Get the headers interceptor. - * - * @return the headers interceptor. - */ - public CustomHeadersInterceptor headers() { - return customHeadersInterceptor; - } - - /** - * Get the adapter to {@link com.fasterxml.jackson.databind.ObjectMapper}. - * - * @return the Jackson mapper adapter. - */ - public JacksonMapperAdapter mapperAdapter() { - return mapperAdapter; - } - - /** - * Get the http client. - * - * @return the {@link OkHttpClient} object. - */ - public OkHttpClient httpClient() { - return httpClient; - } - - /** - * Get the retrofit instance. - * - * @return the {@link Retrofit} object. - */ - public Retrofit retrofit() { - return retrofit; - } - - /** - * Get the credentials attached to this REST client. - * - * @return the credentials. - */ - public ServiceClientCredentials credentials() { - return this.credentials; - } - - /** - * The builder class for building a REST client. - */ - public static class Builder { - /** The builder to build an {@link OkHttpClient}. */ - private OkHttpClient.Builder httpClientBuilder; - /** The builder to build a {@link Retrofit}. */ - private Retrofit.Builder retrofitBuilder; - /** The credentials to authenticate. */ - private ServiceClientCredentials credentials; - /** The interceptor to handle custom headers. */ - private CustomHeadersInterceptor customHeadersInterceptor; - /** The interceptor to handle base URL. */ - private BaseUrlHandler baseUrlHandler; - /** The adapter to a Jackson {@link com.fasterxml.jackson.databind.ObjectMapper}. */ - private JacksonMapperAdapter mapperAdapter; - /** The interceptor to set 'User-Agent' header. */ - private UserAgentInterceptor userAgentInterceptor; - - /** - * Creates an instance of the builder with a base URL to the service. - * - * @param baseUrl the dynamic base URL with variables wrapped in "{" and "}". - */ - public Builder(String baseUrl) { - this(baseUrl, new OkHttpClient.Builder(), new Retrofit.Builder()); - } - - /** - * Creates an instance of the builder with a base URL and 2 custom builders. - * - * @param baseUrl the dynamic base URL with variables wrapped in "{" and "}". - * @param httpClientBuilder the builder to build an {@link OkHttpClient}. - * @param retrofitBuilder the builder to build a {@link Retrofit}. - */ - public Builder(String baseUrl, OkHttpClient.Builder httpClientBuilder, Retrofit.Builder retrofitBuilder) { - if (baseUrl == null) { - throw new IllegalArgumentException("baseUrl == null"); - } - if (httpClientBuilder == null) { - throw new IllegalArgumentException("httpClientBuilder == null"); - } - if (retrofitBuilder == null) { - throw new IllegalArgumentException("retrofitBuilder == null"); - } - CookieManager cookieManager = new CookieManager(); - cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); - customHeadersInterceptor = new CustomHeadersInterceptor(); - baseUrlHandler = new BaseUrlHandler(); - userAgentInterceptor = new UserAgentInterceptor(); - // Set up OkHttp client - this.httpClientBuilder = httpClientBuilder - .cookieJar(new JavaNetCookieJar(cookieManager)) - .addInterceptor(userAgentInterceptor); - // Set up rest adapter - this.retrofitBuilder = retrofitBuilder.baseUrl(baseUrl); - } - - /** - * Sets the user agent header. - * - * @param userAgent the user agent header. - * @return the builder itself for chaining. - */ - public Builder withUserAgent(String userAgent) { - this.userAgentInterceptor.setUserAgent(userAgent); - return this; - } - - /** - * Sets the mapper adapter. - * - * @param mapperAdapter an adapter to a Jackson mapper. - * @return the builder itself for chaining. - */ - public Builder withMapperAdapter(JacksonMapperAdapter mapperAdapter) { - this.mapperAdapter = mapperAdapter; - return this; - } - - /** - * Sets the credentials. - * - * @param credentials the credentials object. - * @return the builder itself for chaining. - */ - public Builder withCredentials(ServiceClientCredentials credentials) { - this.credentials = credentials; - if (credentials != null) { - credentials.applyCredentialsFilter(httpClientBuilder); - } - return this; - } - - /** - * Sets the log level. - * - * @param logLevel the {@link okhttp3.logging.HttpLoggingInterceptor.Level} enum. - * @return the builder itself for chaining. - */ - public Builder withLogLevel(HttpLoggingInterceptor.Level logLevel) { - this.httpClientBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(logLevel)); - return this; - } - - /** - * Add an interceptor the Http client pipeline. - * - * @param interceptor the interceptor to add. - * @return the builder itself for chaining. - */ - public Builder withInterceptor(Interceptor interceptor) { - this.httpClientBuilder.addInterceptor(interceptor); - return this; - } - - /** - * Build a RestClient with all the current configurations. - * - * @return a {@link RestClient}. - */ - public RestClient build() { - if (mapperAdapter == null) { - throw new IllegalArgumentException("Please set mapper adapter."); - } - OkHttpClient httpClient = httpClientBuilder - .addInterceptor(baseUrlHandler) - .addInterceptor(customHeadersInterceptor) - .addInterceptor(new RetryHandler()) - .build(); - return new RestClient(httpClient, - retrofitBuilder - .client(httpClient) - .addConverterFactory(mapperAdapter.getConverterFactory()) - .build(), - credentials, - customHeadersInterceptor, - userAgentInterceptor, - baseUrlHandler, - mapperAdapter); - } - } -} diff --git a/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java b/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java index 674b6a1bc6253..8311a243de139 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java +++ b/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java @@ -7,16 +7,26 @@ package com.microsoft.rest; +import com.microsoft.rest.retry.RetryHandler; import com.microsoft.rest.serializer.JacksonMapperAdapter; +import java.net.CookieManager; +import java.net.CookiePolicy; + +import okhttp3.JavaNetCookieJar; +import okhttp3.OkHttpClient; +import retrofit2.Retrofit; + /** * ServiceClient is the abstraction for accessing REST operations and their payload data types. */ public abstract class ServiceClient { - /** - * The builder for building the OkHttp client. - */ - private RestClient restClient; + /** The HTTP client. */ + private OkHttpClient httpClient; + /** The Retrofit instance. */ + private Retrofit retrofit; + /** The adapter to a Jackson {@link com.fasterxml.jackson.databind.ObjectMapper}. */ + private JacksonMapperAdapter mapperAdapter; /** * Initializes a new instance of the ServiceClient class. @@ -24,27 +34,55 @@ public abstract class ServiceClient { * @param baseUrl the service endpoint */ protected ServiceClient(String baseUrl) { - this(new RestClient.Builder(baseUrl) - .withMapperAdapter(new JacksonMapperAdapter()).build()); + this(baseUrl, new OkHttpClient.Builder(), new Retrofit.Builder()); } /** * Initializes a new instance of the ServiceClient class. * - * @param restClient the builder to build up an REST client */ - protected ServiceClient(RestClient restClient) { - if (restClient == null) { - throw new IllegalArgumentException("restClient == null"); + protected ServiceClient(String baseUrl, OkHttpClient.Builder clientBuilder, Retrofit.Builder restBuilder) { + if (clientBuilder == null) { + throw new IllegalArgumentException("clientBuilder == null"); } - this.restClient = restClient; + if (restBuilder == null) { + throw new IllegalArgumentException("restBuilder == null"); + } + this.mapperAdapter = new JacksonMapperAdapter(); + CookieManager cookieManager = new CookieManager(); + cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); + this.httpClient = clientBuilder + .cookieJar(new JavaNetCookieJar(cookieManager)) + .addInterceptor(new UserAgentInterceptor()) + .addInterceptor(new BaseUrlHandler()) + .addInterceptor(new CustomHeadersInterceptor()) + .addInterceptor(new RetryHandler()) + .build(); + this.retrofit = restBuilder + .baseUrl(baseUrl) + .client(httpClient) + .addConverterFactory(mapperAdapter.getConverterFactory()) + .build(); + } + + /** + * @return the Retrofit instance. + */ + public Retrofit retrofit() { + return this.retrofit; + } + + /** + * @return the HTTP client. + */ + public OkHttpClient httpClient() { + return this.httpClient; } /** - * Get the list of interceptors the OkHttp client will execute. - * @return the list of interceptors + * @return the adapter to a Jackson {@link com.fasterxml.jackson.databind.ObjectMapper}. */ - public RestClient restClient() { - return this.restClient; + public JacksonMapperAdapter mapperAdapter() { + return this.mapperAdapter; } } diff --git a/client-runtime/src/main/java/com/microsoft/rest/UserAgentInterceptor.java b/client-runtime/src/main/java/com/microsoft/rest/UserAgentInterceptor.java index ac4a5ec5a73c4..7b822078d79ab 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/UserAgentInterceptor.java +++ b/client-runtime/src/main/java/com/microsoft/rest/UserAgentInterceptor.java @@ -39,18 +39,22 @@ public UserAgentInterceptor() { * Overwrite the User-Agent header. * * @param userAgent the new user agent value. + * @return the user agent interceptor itself */ - public void setUserAgent(String userAgent) { + public UserAgentInterceptor withUserAgent(String userAgent) { this.userAgent = userAgent; + return this; } /** * Append a text to the User-Agent header. * * @param userAgent the user agent value to append. + * @return the user agent interceptor itself */ - public void appendUserAgent(String userAgent) { + public UserAgentInterceptor appendUserAgent(String userAgent) { this.userAgent += " " + userAgent; + return this; } @Override diff --git a/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java b/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java index 3e05c5d723fdb..d21de3ef9bd1e 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java @@ -9,7 +9,6 @@ import com.microsoft.rest.credentials.BasicAuthenticationCredentials; import com.microsoft.rest.credentials.TokenCredentials; -import com.microsoft.rest.serializer.JacksonMapperAdapter; import org.junit.Assert; import org.junit.Test; @@ -26,38 +25,34 @@ public class CredentialsTests { @Test public void basicCredentialsTest() throws Exception { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); - Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); BasicAuthenticationCredentials credentials = new BasicAuthenticationCredentials("user", "pass"); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder) - .withMapperAdapter(new JacksonMapperAdapter()) - .withCredentials(credentials) - .withInterceptor(new Interceptor() { - @Override - public Response intercept(Chain chain) throws IOException { - String header = chain.request().header("Authorization"); - Assert.assertEquals("Basic dXNlcjpwYXNz", header); - return new Response.Builder() - .request(chain.request()) - .code(200) - .protocol(Protocol.HTTP_1_1) - .build(); - } - }); - ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; - Response response = serviceClient.restClient().httpClient().newCall(new Request.Builder().url("http://localhost").build()).execute(); + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + credentials.applyCredentialsFilter(clientBuilder); + clientBuilder.addInterceptor( + new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { + String header = chain.request().header("Authorization"); + Assert.assertEquals("Basic dXNlcjpwYXNz", header); + return new Response.Builder() + .request(chain.request()) + .code(200) + .protocol(Protocol.HTTP_1_1) + .build(); + } + }); + ServiceClient serviceClient = new ServiceClient("http://localhost", clientBuilder, new Retrofit.Builder()) { }; + Response response = serviceClient.httpClient().newCall(new Request.Builder().url("http://localhost").build()).execute(); Assert.assertEquals(200, response.code()); } @Test public void tokenCredentialsTest() throws Exception { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); - Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); TokenCredentials credentials = new TokenCredentials(null, "this_is_a_token"); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder) - .withMapperAdapter(new JacksonMapperAdapter()) - .withCredentials(credentials) - .withInterceptor(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + credentials.applyCredentialsFilter(clientBuilder); + clientBuilder.addInterceptor( + new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { String header = chain.request().header("Authorization"); @@ -69,8 +64,8 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; - Response response = serviceClient.restClient().httpClient().newCall(new Request.Builder().url("http://localhost").build()).execute(); + ServiceClient serviceClient = new ServiceClient("http://localhost", clientBuilder, new Retrofit.Builder()) { }; + Response response = serviceClient.httpClient().newCall(new Request.Builder().url("http://localhost").build()).execute(); Assert.assertEquals(200, response.code()); } } diff --git a/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java b/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java index 97c46f6fe4fc3..068e57b214323 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java @@ -9,7 +9,11 @@ import com.microsoft.rest.retry.RetryHandler; -import com.microsoft.rest.serializer.JacksonMapperAdapter; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Protocol; @@ -17,11 +21,6 @@ import okhttp3.Response; import retrofit2.Retrofit; -import org.junit.Assert; -import org.junit.Test; - -import java.io.IOException; - public class RetryHandlerTests { @Test public void exponentialRetryEndOn501() throws Exception { @@ -42,10 +41,8 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder) - .withMapperAdapter(new JacksonMapperAdapter()); - ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; - Response response = serviceClient.restClient().httpClient().newCall( + ServiceClient serviceClient = new ServiceClient("http://localhost", clientBuilder, retrofitBuilder) { }; + Response response = serviceClient.httpClient().newCall( new Request.Builder().url("http://localhost").get().build()).execute(); Assert.assertEquals(501, response.code()); } @@ -69,10 +66,8 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder) - .withMapperAdapter(new JacksonMapperAdapter()); - ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; - Response response = serviceClient.restClient().httpClient().newCall( + ServiceClient serviceClient = new ServiceClient("http://localhost", clientBuilder, retrofitBuilder) { }; + Response response = serviceClient.httpClient().newCall( new Request.Builder().url("http://localhost").get().build()).execute(); Assert.assertEquals(500, response.code()); } diff --git a/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java b/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java index 6423ef23d8081..9d76292d20a03 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java @@ -7,10 +7,8 @@ package com.microsoft.rest; -import com.microsoft.rest.serializer.JacksonMapperAdapter; import org.junit.Assert; import org.junit.Test; -import retrofit2.Retrofit; import java.io.IOException; @@ -19,6 +17,7 @@ import okhttp3.Protocol; import okhttp3.Request; import okhttp3.Response; +import retrofit2.Retrofit; public class ServiceClientTests { @Test @@ -39,10 +38,8 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder) - .withMapperAdapter(new JacksonMapperAdapter()); - ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; - Response response = serviceClient.restClient().httpClient().newCall(new Request.Builder().url("http://localhost").build()).execute(); + ServiceClient serviceClient = new ServiceClient("http://localhost", clientBuilder, retrofitBuilder) { }; + Response response = serviceClient.httpClient().newCall(new Request.Builder().url("http://localhost").build()).execute(); Assert.assertEquals(200, response.code()); } diff --git a/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java b/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java index 35970714e3a83..9aa60e5b26313 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java @@ -7,23 +7,24 @@ package com.microsoft.rest; -import com.microsoft.rest.serializer.JacksonMapperAdapter; - import org.junit.Assert; import org.junit.Test; import java.io.IOException; import okhttp3.Interceptor; +import okhttp3.OkHttpClient; import okhttp3.Protocol; import okhttp3.Request; import okhttp3.Response; +import retrofit2.Retrofit; public class UserAgentTests { @Test public void defaultUserAgentTests() throws Exception { - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost") - .withInterceptor(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() + .addInterceptor(new UserAgentInterceptor()) + .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { String header = chain.request().header("User-Agent"); @@ -34,20 +35,18 @@ public Response intercept(Chain chain) throws IOException { .protocol(Protocol.HTTP_1_1) .build(); } - }) - .withMapperAdapter(new JacksonMapperAdapter()); - ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; - Response response = serviceClient.restClient().httpClient() + }); + ServiceClient serviceClient = new ServiceClient("http://localhost", clientBuilder, new Retrofit.Builder()) { }; + Response response = serviceClient.httpClient() .newCall(new Request.Builder().get().url("http://localhost").build()).execute(); Assert.assertEquals(200, response.code()); } @Test public void customUserAgentTests() throws Exception { - - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost") - .withUserAgent("Awesome") - .withInterceptor(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() + .addInterceptor(new UserAgentInterceptor().withUserAgent("Awesome")) + .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { String header = chain.request().header("User-Agent"); @@ -58,10 +57,9 @@ public Response intercept(Chain chain) throws IOException { .protocol(Protocol.HTTP_1_1) .build(); } - }) - .withMapperAdapter(new JacksonMapperAdapter()); - ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; - Response response = serviceClient.restClient().httpClient() + }); + ServiceClient serviceClient = new ServiceClient("http://localhost", clientBuilder, new Retrofit.Builder()) { }; + Response response = serviceClient.httpClient() .newCall(new Request.Builder().get().url("http://localhost").build()).execute(); Assert.assertEquals(200, response.code()); }