diff --git a/README.md b/README.md index 4356da5475d0..dfa96fbf28cb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,22 @@ -# autorest-clientruntime-for-java +[![Build Status](https://travis-ci.org/Azure/autorest-clientruntime-for-java.svg?branch=javavnext)](https://travis-ci.org/Azure/autorest-clientruntime-for-java) + +# AutoRest Client Runtimes for Java The runtime libraries for AutoRest generated Java clients. + +## Repository structure + +### client-runtime +This is the generic runtime. You will need this for AutoRest generated library using Java code generator. + +### azure-client-runtime +This is the runtime with Azure specific customizations. You will need this for AutoRest generated library using Azure.Java code generator. + +### azure-client-authentication +This package provides access to Active Directory authentication on JDK using OrgId or application ID / secret combinations. Multi-factor-auth is currently not supported. + +### azure-android-client-authentication +This package provides access to Active Directory authentication on Android. You can login with Microsoft accounts, OrgId, with or without multi-factor-auth. + +## Build +To build this repository, you will need maven 2.0+ and gradle 1.6+. +Maven is used for [Java SDK](https://github.com/Azure/azure-sdk-for-java) when it's used as a submodule in there. Gradle is used for [AutoRest](https://github.com/Azure/autorest) when it's used as a submodule in there. diff --git a/azure-android-client-authentication/build.gradle b/azure-android-client-authentication/build.gradle index 753fd4b7114e..df85a81cc546 100644 --- a/azure-android-client-authentication/build.gradle +++ b/azure-android-client-authentication/build.gradle @@ -95,16 +95,6 @@ uploadArchives { } } -task versionInfo(type:Exec){ - commandLine 'git rev-parse HEAD'.split() - ext.versionfile = new File("${projectDir}/.gitrevision") - standardOutput = new ByteArrayOutputStream() - - doLast { - versionfile.text = "Azure/autorest#" + standardOutput.toString() - } -} - task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' @@ -116,7 +106,7 @@ task javadoc(type: Javadoc) { options.encoding = 'UTF-8' } -task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { +task javadocJar(type: Jar, dependsOn: [javadoc]) { classifier = 'javadoc' from javadoc.destinationDir } @@ -124,5 +114,4 @@ task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { artifacts { archives sourcesJar archives javadocJar - archives file: file("${projectDir}/.gitrevision") } \ No newline at end of file diff --git a/azure-client-authentication/build.gradle b/azure-client-authentication/build.gradle index a04020e1fd37..5f2010826478 100644 --- a/azure-client-authentication/build.gradle +++ b/azure-client-authentication/build.gradle @@ -70,16 +70,6 @@ test { } } -task versionInfo(type:Exec){ - commandLine 'git rev-parse HEAD'.split() - ext.versionfile = new File("${projectDir}/.gitrevision") - standardOutput = new ByteArrayOutputStream() - - doLast { - versionfile.text = "Azure/autorest#" + standardOutput.toString() - } -} - javadoc { options.encoding = 'UTF-8' } @@ -89,7 +79,7 @@ task sourcesJar(type: Jar, dependsOn:classes) { from sourceSets.main.allSource } -task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { +task javadocJar(type: Jar, dependsOn: [javadoc]) { classifier = 'javadoc' from javadoc.destinationDir } @@ -97,7 +87,6 @@ task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { artifacts { archives sourcesJar archives javadocJar - archives file: file("${projectDir}/.gitrevision") } test { diff --git a/azure-client-runtime/build.gradle b/azure-client-runtime/build.gradle index dcdaddcea285..e8a50ca11242 100644 --- a/azure-client-runtime/build.gradle +++ b/azure-client-runtime/build.gradle @@ -69,16 +69,6 @@ test { } } -task versionInfo(type:Exec){ - commandLine 'git rev-parse HEAD'.split() - ext.versionfile = new File("${projectDir}/.gitrevision") - standardOutput = new ByteArrayOutputStream() - - doLast { - versionfile.text = "Azure/autorest#" + standardOutput.toString() - } -} - javadoc { options.encoding = 'UTF-8' } @@ -88,7 +78,7 @@ task sourcesJar(type: Jar, dependsOn:classes) { from sourceSets.main.allSource } -task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { +task javadocJar(type: Jar, dependsOn: [javadoc]) { classifier = 'javadoc' from javadoc.destinationDir } @@ -96,7 +86,6 @@ task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { artifacts { archives sourcesJar archives javadocJar - archives file: file("${projectDir}/.gitrevision") } test { diff --git a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java index 2f3569fc51c5..d8389869810f 100644 --- a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java @@ -7,14 +7,13 @@ package com.microsoft.azure; +import com.microsoft.rest.RestClient; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceException; import com.microsoft.rest.ServiceResponse; import com.microsoft.rest.ServiceResponseCallback; import com.microsoft.rest.ServiceResponseWithHeaders; -import com.microsoft.rest.credentials.ServiceClientCredentials; -import com.microsoft.rest.serializer.JacksonMapperAdapter; import java.io.IOException; import java.lang.reflect.Type; @@ -24,11 +23,9 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import okhttp3.OkHttpClient; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Response; -import retrofit2.Retrofit; import retrofit2.http.GET; import retrofit2.http.Url; @@ -42,32 +39,18 @@ public class AzureClient extends AzureServiceClient { * used if null. */ private Integer longRunningOperationRetryTimeout; - /** - * The credentials to use for authentication for long running operations. - */ - private ServiceClientCredentials credentials; /** * The executor for asynchronous requests. */ private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - /** - * Initializes an instance of this class. - */ - public AzureClient() { - super(); - } - /** * Initializes an instance of this class with customized client metadata. * - * @param clientBuilder customized http client. - * @param retrofitBuilder customized retrofit builder - * @param mapperAdapter the adapter for the Jackson object mapper + * @param restClient the REST client to connect to Azure */ - public AzureClient(OkHttpClient.Builder clientBuilder, Retrofit.Builder retrofitBuilder, JacksonMapperAdapter mapperAdapter) { - super(clientBuilder, retrofitBuilder); - this.mapperAdapter = mapperAdapter; + public AzureClient(RestClient restClient) { + super(restClient); } /** @@ -98,13 +81,13 @@ public ServiceResponse getPutOrPatchResult(Response respons CloudException exception = new CloudException(statusCode + " is not a valid polling status code"); exception.setResponse(response); if (responseBody != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(responseBody.string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(responseBody.string(), CloudError.class)); responseBody.close(); } throw exception; } - PollingState pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, mapperAdapter); + PollingState pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, restClient().mapperAdapter()); String url = response.raw().request().url().toString(); // Check provisioning state @@ -151,7 +134,7 @@ public ServiceResponseWithHeaders getPutOrPatchResultWi ServiceResponse bodyResponse = getPutOrPatchResult(response, resourceType); return new ServiceResponseWithHeaders<>( bodyResponse.getBody(), - mapperAdapter.deserialize(mapperAdapter.serialize(bodyResponse.getResponse().headers()), headerType), + restClient().mapperAdapter().deserialize(restClient().mapperAdapter().serialize(bodyResponse.getResponse().headers()), headerType), bodyResponse.getResponse() ); } @@ -186,7 +169,7 @@ public AsyncPollingTask getPutOrPatchResultAsync(Response r exception.setResponse(response); try { if (responseBody != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(responseBody.string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(responseBody.string(), CloudError.class)); responseBody.close(); } } catch (Exception e) { /* ignore serialization errors on top of service errors */ } @@ -196,7 +179,7 @@ public AsyncPollingTask getPutOrPatchResultAsync(Response r PollingState pollingState; try { - pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, mapperAdapter); + pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, restClient().mapperAdapter()); } catch (IOException e) { callback.failure(e); return null; @@ -235,7 +218,7 @@ public void success(ServiceResponse result) { try { callback.success(new ServiceResponseWithHeaders<>( result.getBody(), - mapperAdapter.deserialize(mapperAdapter.serialize(result.getResponse().headers()), headerType), + restClient().mapperAdapter().deserialize(restClient().mapperAdapter().serialize(result.getResponse().headers()), headerType), result.getResponse() )); } catch (IOException e) { @@ -273,13 +256,13 @@ public ServiceResponse getPostOrDeleteResult(Response respo CloudException exception = new CloudException(statusCode + " is not a valid polling status code"); exception.setResponse(response); if (responseBody != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(responseBody.string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(responseBody.string(), CloudError.class)); responseBody.close(); } throw exception; } - PollingState pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, mapperAdapter); + PollingState pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, restClient().mapperAdapter()); // Check provisioning state while (!AzureAsyncOperation.getTerminalStatuses().contains(pollingState.getStatus())) { @@ -325,7 +308,7 @@ public ServiceResponseWithHeaders getPostOrDeleteResult ServiceResponse bodyResponse = getPostOrDeleteResult(response, resourceType); return new ServiceResponseWithHeaders<>( bodyResponse.getBody(), - mapperAdapter.deserialize(mapperAdapter.serialize(bodyResponse.getResponse().headers()), headerType), + restClient().mapperAdapter().deserialize(restClient().mapperAdapter().serialize(bodyResponse.getResponse().headers()), headerType), bodyResponse.getResponse() ); } @@ -360,7 +343,7 @@ public AsyncPollingTask getPostOrDeleteResultAsync(Response exception.setResponse(response); try { if (responseBody != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(responseBody.string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(responseBody.string(), CloudError.class)); responseBody.close(); } } catch (Exception e) { /* ignore serialization errors on top of service errors */ } @@ -370,7 +353,7 @@ public AsyncPollingTask getPostOrDeleteResultAsync(Response PollingState pollingState; try { - pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, mapperAdapter); + pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, restClient().mapperAdapter()); } catch (IOException e) { callback.failure(e); return null; @@ -408,7 +391,7 @@ public void success(ServiceResponse result) { try { callback.success(new ServiceResponseWithHeaders<>( result.getBody(), - mapperAdapter.deserialize(mapperAdapter.serialize(result.getResponse().headers()), headerType), + restClient().mapperAdapter().deserialize(restClient().mapperAdapter().serialize(result.getResponse().headers()), headerType), result.getResponse() )); } catch (IOException e) { @@ -584,7 +567,7 @@ private void updateStateFromAzureAsyncOperationHeader(PollingState pollin AzureAsyncOperation body = null; if (response.body() != null) { - body = mapperAdapter.deserialize(response.body().string(), AzureAsyncOperation.class); + body = restClient().mapperAdapter().deserialize(response.body().string(), AzureAsyncOperation.class); response.body().close(); } @@ -592,7 +575,7 @@ private void updateStateFromAzureAsyncOperationHeader(PollingState pollin CloudException exception = new CloudException("no body"); exception.setResponse(response); if (response.errorBody() != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(response.errorBody().string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(response.errorBody().string(), CloudError.class)); response.errorBody().close(); } throw exception; @@ -624,14 +607,14 @@ public void success(ServiceResponse result) { try { AzureAsyncOperation body = null; if (result.getBody() != null) { - body = mapperAdapter.deserialize(result.getBody().string(), AzureAsyncOperation.class); + body = restClient().mapperAdapter().deserialize(result.getBody().string(), AzureAsyncOperation.class); result.getBody().close(); } if (body == null || body.getStatus() == null) { CloudException exception = new CloudException("no body"); exception.setResponse(result.getResponse()); if (result.getResponse().errorBody() != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(result.getResponse().errorBody().string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(result.getResponse().errorBody().string(), CloudError.class)); result.getResponse().errorBody().close(); } failure(exception); @@ -663,18 +646,17 @@ private Response poll(String url) throws CloudException, IOExcepti if (port == -1) { port = endpoint.getDefaultPort(); } - AsyncService service = this.retrofitBuilder - .baseUrl(endpoint.getProtocol() + "://" + endpoint.getHost() + ":" + port).build().create(AsyncService.class); + AsyncService service = restClient().retrofit().create(AsyncService.class); Response response = service.get(endpoint.getFile()).execute(); int statusCode = response.code(); if (statusCode != 200 && statusCode != 201 && statusCode != 202 && statusCode != 204) { CloudException exception = new CloudException(statusCode + " is not a valid polling status code"); exception.setResponse(response); if (response.body() != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(response.body().string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(response.body().string(), CloudError.class)); response.body().close(); } else if (response.errorBody() != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(response.errorBody().string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(response.errorBody().string(), CloudError.class)); response.errorBody().close(); } throw exception; @@ -701,8 +683,7 @@ private Call pollAsync(String url, final ServiceCallback call = service.get(endpoint.getFile()); call.enqueue(new ServiceResponseCallback(callback) { @Override @@ -713,10 +694,10 @@ public void onResponse(Call call, Response response) CloudException exception = new CloudException(statusCode + " is not a valid polling status code"); exception.setResponse(response); if (response.body() != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(response.body().string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(response.body().string(), CloudError.class)); response.body().close(); } else if (response.errorBody() != null) { - exception.setBody((CloudError) mapperAdapter.deserialize(response.errorBody().string(), CloudError.class)); + exception.setBody((CloudError) restClient().mapperAdapter().deserialize(response.errorBody().string(), CloudError.class)); response.errorBody().close(); } callback.failure(exception); @@ -749,24 +730,6 @@ public void setLongRunningOperationRetryTimeout(Integer longRunningOperationRetr this.longRunningOperationRetryTimeout = longRunningOperationRetryTimeout; } - /** - * Gets the credentials used for authentication. - * - * @return the credentials. - */ - public ServiceClientCredentials getCredentials() { - return credentials; - } - - /** - * Sets the credentials used for authentication. - * - * @param credentials the credentials. - */ - public void setCredentials(ServiceClientCredentials credentials) { - this.credentials = credentials; - } - /** * The Retrofit service used for polling. */ 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 5feea13fa74d..94142029cfc6 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 @@ -8,57 +8,24 @@ package com.microsoft.azure; import com.microsoft.azure.serializer.AzureJacksonMapperAdapter; +import com.microsoft.rest.RestClient; import com.microsoft.rest.ServiceClient; -import com.microsoft.rest.UserAgentInterceptor; -import com.microsoft.rest.retry.RetryHandler; - -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 AzureServiceClient extends ServiceClient { - /** - * Initializes a new instance of the ServiceClient class. - */ - protected AzureServiceClient() { - super(); + protected AzureServiceClient(String baseUrl) { + this(new RestClient.Builder(baseUrl) + .withMapperAdapter(new AzureJacksonMapperAdapter()).build()); } /** * Initializes a new instance of the ServiceClient class. * - * @param clientBuilder the builder to build up an OkHttp client - * @param retrofitBuilder the builder to build up a rest adapter + * @param restClient the REST client */ - protected AzureServiceClient(OkHttpClient.Builder clientBuilder, Retrofit.Builder retrofitBuilder) { - super(clientBuilder, retrofitBuilder); - } - - /** - * This method initializes the builders for Http client and Retrofit with common - * behaviors for all service clients. - */ - @Override - protected void initialize() { - // Add retry handler - CookieManager cookieManager = new CookieManager(); - cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); - - // Set up OkHttp client - this.clientBuilder = clientBuilder - .cookieJar(new JavaNetCookieJar(cookieManager)) - .addInterceptor(new RetryHandler()) - .addInterceptor(new UserAgentInterceptor()); - // Set up rest adapter - this.mapperAdapter = new AzureJacksonMapperAdapter(); - this.retrofitBuilder = retrofitBuilder - .client(clientBuilder.build()) - .addConverterFactory(mapperAdapter.getConverterFactory()); + protected AzureServiceClient(RestClient restClient) { + super(restClient); } } diff --git a/client-runtime/build.gradle b/client-runtime/build.gradle index b734d33608ea..2558fc5055f9 100644 --- a/client-runtime/build.gradle +++ b/client-runtime/build.gradle @@ -80,16 +80,6 @@ test { } } -task versionInfo(type:Exec){ - commandLine 'git rev-parse HEAD'.split() - ext.versionfile = new File("${projectDir}/.gitrevision") - standardOutput = new ByteArrayOutputStream() - - doLast { - versionfile.text = "Azure/autorest#" + standardOutput.toString() - } -} - javadoc { options.encoding = 'UTF-8' } @@ -99,7 +89,7 @@ task sourcesJar(type: Jar, dependsOn:classes) { from sourceSets.main.allSource } -task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { +task javadocJar(type: Jar, dependsOn: [javadoc]) { classifier = 'javadoc' from javadoc.destinationDir } @@ -107,7 +97,6 @@ task javadocJar(type: Jar, dependsOn: [javadoc, versionInfo]) { artifacts { archives sourcesJar archives javadocJar - archives file: file("${projectDir}/.gitrevision") } test { diff --git a/client-runtime/src/main/java/com/microsoft/rest/BaseUrlHandler.java b/client-runtime/src/main/java/com/microsoft/rest/BaseUrlHandler.java new file mode 100644 index 000000000000..f04cbc17edd8 --- /dev/null +++ b/client-runtime/src/main/java/com/microsoft/rest/BaseUrlHandler.java @@ -0,0 +1,83 @@ +/** + * + * 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 java.io.IOException; + +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +/** + * An instance of class handles dynamic base URLs in the HTTP pipeline. + */ +public class BaseUrlHandler implements Interceptor { + /** The URL template for the dynamic URL. */ + private final String rawUrl; + /** The base URL after applying the variable replacements. */ + private String baseUrl; + + /** + * Creates an instance of this class with a URL template. + * + * @param rawUrl the URL template with variables wrapped in "{" and "}". + */ + public BaseUrlHandler(String rawUrl) { + this.rawUrl = rawUrl; + this.baseUrl = null; + } + + /** + * Gets the base URL. + * + * @return the URL template if it's not a dynamic URL or variables in a + * dynamic URL haven't been set. The compiled URL otherwise. + */ + public String baseUrl() { + if (this.baseUrl == null) { + return rawUrl; + } + return this.baseUrl; + } + + /** + * Handles dynamic replacements on base URL. The arguments must be in pairs + * with the string in raw URL to replace as replacements[i] and the dynamic + * part as replacements[i+1]. E.g. {subdomain}.microsoft.com can be set + * dynamically by calling setBaseUrl("{subdomain}", "azure"). + * + * @param replacements the string replacements in pairs. + */ + public void setBaseUrl(String... replacements) { + if (replacements.length % 2 != 0) { + throw new IllegalArgumentException("Must provide a replacement value for each pattern"); + } + baseUrl = rawUrl; + for (int i = 0; i < replacements.length; i += 2) { + baseUrl = baseUrl.replace(replacements[i], replacements[i + 1]); + } + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + if (baseUrl != null) { + HttpUrl baseHttpUrl = HttpUrl.parse(baseUrl); + HttpUrl newUrl = request.url().newBuilder() + .host(baseHttpUrl.host()) + .scheme(baseHttpUrl.scheme()) + .port(baseHttpUrl.port()) + .build(); + request = request.newBuilder() + .url(newUrl) + .build(); + } + return chain.proceed(request); + } +} diff --git a/client-runtime/src/main/java/com/microsoft/rest/CustomHeadersInterceptor.java b/client-runtime/src/main/java/com/microsoft/rest/CustomHeadersInterceptor.java new file mode 100644 index 000000000000..00903b93a9e0 --- /dev/null +++ b/client-runtime/src/main/java/com/microsoft/rest/CustomHeadersInterceptor.java @@ -0,0 +1,136 @@ +/** + * + * 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 okhttp3.Headers; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * An instance of this class enables adding custom headers in client requests + * when added to the {@link okhttp3.OkHttpClient} interceptors. + */ +public class CustomHeadersInterceptor implements Interceptor { + /** + * A mapping of custom headers. + */ + private Map> headers; + + /** + * Initialize an instance of {@link CustomHeadersInterceptor} class. + */ + public CustomHeadersInterceptor() { + headers = new HashMap>(); + } + + /** + * Initialize an instance of {@link CustomHeadersInterceptor} class. + * + * @param key the key for the header + * @param value the value of the header + */ + public CustomHeadersInterceptor(String key, String value) { + this(); + addHeader(key, value); + } + + /** + * Add a single header key-value pair. If one with the name already exists, + * it gets replaced. + * + * @param name the name of the header. + * @param value the value of the header. + * @return the interceptor instance itself. + */ + public CustomHeadersInterceptor replaceHeader(String name, String value) { + this.headers.put(name, new ArrayList()); + this.headers.get(name).add(value); + return this; + } + + /** + * Add a single header key-value pair. If one with the name already exists, + * both stay in the header map. + * + * @param name the name of the header. + * @param value the value of the header. + * @return the interceptor instance itself. + */ + public CustomHeadersInterceptor addHeader(String name, String value) { + if (!this.headers.containsKey(name)) { + this.headers.put(name, new ArrayList()); + } + this.headers.get(name).add(value); + return this; + } + + /** + * Add all headers in a {@link Headers} object. + * + * @param headers an OkHttp {@link Headers} object. + * @return the interceptor instance itself. + */ + public CustomHeadersInterceptor addHeaders(Headers headers) { + this.headers.putAll(headers.toMultimap()); + return this; + } + + /** + * Add all headers in a header map. + * + * @param headers a map of headers. + * @return the interceptor instance itself. + */ + public CustomHeadersInterceptor addHeaderMap(Map headers) { + for (Map.Entry header : headers.entrySet()) { + this.headers.put(header.getKey(), Collections.singletonList(header.getValue())); + } + return this; + } + + /** + * Add all headers in a header multimap. + * + * @param headers a multimap of headers. + * @return the interceptor instance itself. + */ + public CustomHeadersInterceptor addHeaderMultimap(Map> headers) { + this.headers.putAll(headers); + return this; + } + + /** + * Remove a header. + * + * @param name the name of the header to remove. + * @return the interceptor instance itself. + */ + public CustomHeadersInterceptor removeHeader(String name) { + this.headers.remove(name); + return this; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request.Builder builder = chain.request().newBuilder(); + for (Map.Entry> header : headers.entrySet()) { + for (String value : header.getValue()) { + builder = builder.header(header.getKey(), value); + } + } + return chain.proceed(builder.build()); + } +} diff --git a/client-runtime/src/main/java/com/microsoft/rest/RestClient.java b/client-runtime/src/main/java/com/microsoft/rest/RestClient.java new file mode 100644 index 000000000000..ffc52643040d --- /dev/null +++ b/client-runtime/src/main/java/com/microsoft/rest/RestClient.java @@ -0,0 +1,269 @@ +/** + * + * 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; + + private RestClient(OkHttpClient httpClient, + Retrofit retrofit, + ServiceClientCredentials credentials, + CustomHeadersInterceptor customHeadersInterceptor, + BaseUrlHandler baseUrlHandler, + JacksonMapperAdapter mapperAdapter) { + this.httpClient = httpClient; + this.retrofit = retrofit; + this.credentials = credentials; + this.customHeadersInterceptor = customHeadersInterceptor; + 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 base URL currently set. If it's a customizable URL, the updated + * URL instead of the raw one might be returned. + * + * @return the base URL. + * @see {@link RestClient#setBaseUrl(String...)} + */ + public String baseUrl() { + return baseUrlHandler.baseUrl(); + } + + /** + * Handles dynamic replacements on base URL. The arguments must be in pairs + * with the string in raw URL to replace as replacements[i] and the dynamic + * part as replacements[i+1]. E.g. {subdomain}.microsoft.com can be set + * dynamically by calling setBaseUrl("{subdomain}", "azure"). + * + * @param replacements the string replacements in pairs. + */ + public void setBaseUrl(String... replacements) { + baseUrlHandler.setBaseUrl(replacements); + } + + /** + * 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; + + /** + * Creates an instance of the builder with a base URL to the service. + * + * @param baseUrl the dynamic base URL with varialbes 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 varialbes 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(baseUrl); + // Set up OkHttp client + this.httpClientBuilder = httpClientBuilder + .cookieJar(new JavaNetCookieJar(cookieManager)) + .addInterceptor(new RetryHandler()) + .addInterceptor(new UserAgentInterceptor()); + // Set up rest adapter + this.retrofitBuilder = retrofitBuilder.baseUrl(baseUrl); + } + + /** + * Sets the base URL. + * + * @param baseUrl the dynamic base URL. + * @return the builder itself for chaining. + */ + public Builder withBaseUrl(String baseUrl) { + this.retrofitBuilder.baseUrl(baseUrl); + this.baseUrlHandler = new BaseUrlHandler(baseUrl); + return this; + } + + /** + * Sets the user agent header. + * + * @param userAgent the user agent header. + * @return the builder itself for chaining. + */ + public Builder withUserAgent(String userAgent) { + this.httpClientBuilder.addInterceptor(new UserAgentInterceptor(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) { + if (mapperAdapter != null) { + this.mapperAdapter = mapperAdapter; + this.retrofitBuilder = retrofitBuilder.addConverterFactory(mapperAdapter.getConverterFactory()); + } + 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() { + OkHttpClient httpClient = httpClientBuilder + .addInterceptor(baseUrlHandler) + .addInterceptor(customHeadersInterceptor) + .build(); + return new RestClient(httpClient, + retrofitBuilder.client(httpClient).build(), + credentials, + customHeadersInterceptor, + 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 a0655bc3ab79..ef2f8cae9cfe 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java +++ b/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java @@ -7,20 +7,8 @@ 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 java.util.List; - -import okhttp3.Interceptor; -import okhttp3.JavaNetCookieJar; -import okhttp3.OkHttpClient; -import okhttp3.logging.HttpLoggingInterceptor; -import okhttp3.logging.HttpLoggingInterceptor.Level; -import retrofit2.Retrofit; - /** * ServiceClient is the abstraction for accessing REST operations and their payload data types. */ @@ -28,90 +16,33 @@ public abstract class ServiceClient { /** * The builder for building the OkHttp client. */ - protected OkHttpClient.Builder clientBuilder; - - /** - * The builder for building Retrofit services. - */ - protected Retrofit.Builder retrofitBuilder; - - /** - * The adapter for {@link com.fasterxml.jackson.databind.ObjectMapper} for serialization - * and deserialization operations. - */ - protected JacksonMapperAdapter mapperAdapter; + private RestClient restClient; /** * Initializes a new instance of the ServiceClient class. */ - protected ServiceClient() { - this(new OkHttpClient.Builder(), new Retrofit.Builder()); + protected ServiceClient(String baseUrl) { + this(new RestClient.Builder(baseUrl) + .withMapperAdapter(new JacksonMapperAdapter()).build()); } /** * Initializes a new instance of the ServiceClient class. * - * @param clientBuilder the builder to build up an OkHttp client - * @param retrofitBuilder the builder to build up a rest adapter + * @param restClient the builder to build up an REST client */ - protected ServiceClient(OkHttpClient.Builder clientBuilder, Retrofit.Builder retrofitBuilder) { - if (clientBuilder == null) { - throw new IllegalArgumentException("clientBuilder == null"); - } - if (retrofitBuilder == null) { - throw new IllegalArgumentException("retrofitBuilder == null"); + protected ServiceClient(RestClient restClient) { + if (restClient == null) { + throw new IllegalArgumentException("restClient == null"); } - - this.clientBuilder = clientBuilder; - this.retrofitBuilder = retrofitBuilder; + this.restClient = restClient; } /** * Get the list of interceptors the OkHttp client will execute. * @return the list of interceptors */ - public List getClientInterceptors() { - return this.clientBuilder.interceptors(); - } - - /** - * Sets the logging level for OkHttp client. - * - * @param logLevel the logging level enum - */ - public void setLogLevel(Level logLevel) { - HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); - loggingInterceptor.setLevel(logLevel); - this.getClientInterceptors().add(loggingInterceptor); - } - - /** - * Gets the adapter for {@link com.fasterxml.jackson.databind.ObjectMapper} for serialization - * and deserialization operations.. - * - * @return the adapter. - */ - public JacksonMapperAdapter getMapperAdapter() { - return this.mapperAdapter; - } - - /** - * This method initializes the builders for Http client and Retrofit with common - * behaviors for all service clients. - */ - protected void initialize() { - // Add retry handler - CookieManager cookieManager = new CookieManager(); - cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); - - // Set up OkHttp client - this.clientBuilder = clientBuilder - .cookieJar(new JavaNetCookieJar(cookieManager)) - .addInterceptor(new RetryHandler()) - .addInterceptor(new UserAgentInterceptor()); - // Set up rest adapter - this.mapperAdapter = new JacksonMapperAdapter(); - this.retrofitBuilder = retrofitBuilder - .addConverterFactory(mapperAdapter.getConverterFactory()); + public RestClient restClient() { + return this.restClient; } } 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 296c7c910095..19b7a8ca2a4f 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java @@ -9,44 +9,32 @@ import com.microsoft.rest.credentials.BasicAuthenticationCredentials; import com.microsoft.rest.credentials.TokenCredentials; -import okhttp3.Interceptor; -import okhttp3.Protocol; -import okhttp3.Response; + 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 CredentialsTests { @Test public void basicCredentialsTest() throws Exception { - ServiceClient serviceClient = new ServiceClient() { }; + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); BasicAuthenticationCredentials credentials = new BasicAuthenticationCredentials("user", "pass"); - credentials.applyCredentialsFilter(serviceClient.clientBuilder); - serviceClient.getClientInterceptors().add(new Interceptor() { + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder) + .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(); - } - }); - } - - @Test - public void tokenCredentialsTest() throws Exception { - ServiceClient serviceClient = new ServiceClient() { }; - TokenCredentials credentials = new TokenCredentials(null, "this_is_a_token"); - credentials.applyCredentialsFilter(serviceClient.clientBuilder); - serviceClient.getClientInterceptors().add(new Interceptor() { - @Override - public Response intercept(Chain chain) throws IOException { - String header = chain.request().header("Authorization"); - Assert.assertEquals("Bearer this_is_a_token", header); return new Response.Builder() .request(chain.request()) .code(200) @@ -54,5 +42,32 @@ 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(); + 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) + .withCredentials(credentials) + .withInterceptor(new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { + String header = chain.request().header("Authorization"); + Assert.assertEquals("Bearer this_is_a_token", 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(); + 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 4291450c27d1..050e7374aba1 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java @@ -10,9 +10,12 @@ import com.microsoft.rest.retry.RetryHandler; import okhttp3.Interceptor; +import okhttp3.OkHttpClient; import okhttp3.Protocol; import okhttp3.Request; import okhttp3.Response; +import retrofit2.Retrofit; + import org.junit.Assert; import org.junit.Test; @@ -21,9 +24,10 @@ public class RetryHandlerTests { @Test public void exponentialRetryEndOn501() throws Exception { - ServiceClient serviceClient = new ServiceClient() { }; - serviceClient.getClientInterceptors().add(new RetryHandler()); - serviceClient.getClientInterceptors().add(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); + clientBuilder.addInterceptor(new RetryHandler()); + clientBuilder.addInterceptor(new Interceptor() { // Send 408, 500, 502, all retried, with a 501 ending private int[] codes = new int[]{408, 500, 502, 501}; private int count = 0; @@ -37,18 +41,22 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - Response response = serviceClient.clientBuilder.build().newCall( + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; + Response response = serviceClient.restClient().httpClient().newCall( new Request.Builder().url("http://localhost").get().build()).execute(); Assert.assertEquals(501, response.code()); } @Test public void exponentialRetryMax() throws Exception { - ServiceClient serviceClient = new ServiceClient() { }; - serviceClient.getClientInterceptors().add(new RetryHandler()); - serviceClient.getClientInterceptors().add(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); + clientBuilder.addInterceptor(new RetryHandler()); + clientBuilder.addInterceptor(new Interceptor() { // Send 500 until max retry is hit private int count = 0; + @Override public Response intercept(Chain chain) throws IOException { Assert.assertTrue(count++ < 5); @@ -59,7 +67,9 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - Response response = serviceClient.clientBuilder.build().newCall( + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; + Response response = serviceClient.restClient().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 f30127974005..5497d607549d 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java @@ -7,27 +7,41 @@ package com.microsoft.rest; -import okhttp3.Interceptor; -import okhttp3.Response; 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 ServiceClientTests { @Test public void filterTests() throws Exception { - ServiceClient serviceClient = new ServiceClient() { }; - serviceClient.getClientInterceptors().add(0, new FirstFilter()); - serviceClient.getClientInterceptors().add(1, new SecondFilter()); - serviceClient.getClientInterceptors().add(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); + clientBuilder.interceptors().add(0, new FirstFilter()); + clientBuilder.interceptors().add(1, new SecondFilter()); + clientBuilder.interceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Assert.assertEquals("1", chain.request().header("filter1")); Assert.assertEquals("2", chain.request().header("filter2")); - return chain.proceed(chain.request()); + return new Response.Builder() + .request(chain.request()) + .code(200) + .protocol(Protocol.HTTP_1_1) + .build(); } }); + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; + Response response = serviceClient.restClient().httpClient().newCall(new Request.Builder().url("http://localhost").build()).execute(); + Assert.assertEquals(200, response.code()); } public class FirstFilter implements Interceptor { 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 ce06a25b8869..e6b938f93368 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java @@ -8,8 +8,11 @@ package com.microsoft.rest; import okhttp3.Interceptor; +import okhttp3.OkHttpClient; import okhttp3.Protocol; import okhttp3.Response; +import retrofit2.Retrofit; + import org.junit.Assert; import org.junit.Test; @@ -18,36 +21,42 @@ public class UserAgentTests { @Test public void defaultUserAgentTests() throws Exception { - ServiceClient serviceClient = new ServiceClient() { }; - serviceClient.getClientInterceptors().add(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); + clientBuilder.addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { String header = chain.request().header("User-Agent"); Assert.assertEquals("AutoRest-Java", header); return new Response.Builder() - .request(chain.request()) - .code(200) - .protocol(Protocol.HTTP_1_1) - .build(); + .request(chain.request()) + .code(200) + .protocol(Protocol.HTTP_1_1) + .build(); } }); + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; } @Test public void customUserAgentTests() throws Exception { - ServiceClient serviceClient = new ServiceClient() { }; - serviceClient.getClientInterceptors().add(new UserAgentInterceptor("Awesome")); - serviceClient.getClientInterceptors().add(new Interceptor() { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + Retrofit.Builder retrofitBuilder = new Retrofit.Builder(); + clientBuilder.addInterceptor(new UserAgentInterceptor("Awesome")); + clientBuilder.addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { String header = chain.request().header("User-Agent"); Assert.assertEquals("Awesome", header); return new Response.Builder() - .request(chain.request()) - .code(200) - .protocol(Protocol.HTTP_1_1) - .build(); + .request(chain.request()) + .code(200) + .protocol(Protocol.HTTP_1_1) + .build(); } }); + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; } } diff --git a/pom.xml b/pom.xml index ae5dc28eaff4..98b38905b457 100644 --- a/pom.xml +++ b/pom.xml @@ -244,29 +244,6 @@ maven-release-plugin 2.5.2 - - - org.codehaus.mojo - build-helper-maven-plugin - 1.10 - - - attach-artifacts - package - - attach-artifact - - - - - target/.gitrevision - gitrevision - - - - - -