diff --git a/azure-android-client-authentication/build.gradle b/azure-android-client-authentication/build.gradle index 753fd4b7114e0..24d3409361216 100644 --- a/azure-android-client-authentication/build.gradle +++ b/azure-android-client-authentication/build.gradle @@ -51,7 +51,7 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.microsoft.aad:adal:1.1.11' - compile 'com.microsoft.rest:client-runtime:1.0.0-beta1' + compile 'com.microsoft.azure:azure-client-runtime:1.0.0-SNAPSHOT' testCompile 'junit:junit:4.12' testCompile 'junit:junit-dep:4.11' deployerJars "org.apache.maven.wagon:wagon-ftp:2.10" @@ -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 a04020e1fd378..b56a80eeb3065 100644 --- a/azure-client-authentication/build.gradle +++ b/azure-client-authentication/build.gradle @@ -20,7 +20,7 @@ checkstyle { dependencies { compile 'com.microsoft.azure:adal4j:1.1.2' - compile 'com.microsoft.rest:client-runtime:1.0.0-beta1' + compile 'com.microsoft.azure:azure-client-runtime:1.0.0-SNAPSHOT' testCompile 'junit:junit:4.12' testCompile 'junit:junit-dep:4.11' deployerJars "org.apache.maven.wagon:wagon-ftp:2.10" @@ -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-authentication/pom.xml b/azure-client-authentication/pom.xml index 4dc317b73c131..47582ca1eaa87 100644 --- a/azure-client-authentication/pom.xml +++ b/azure-client-authentication/pom.xml @@ -47,9 +47,9 @@ - com.microsoft.rest - client-runtime - ${parent.version} + com.microsoft.azure + azure-client-runtime + 1.0.0-SNAPSHOT com.microsoft.azure diff --git a/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/ApplicationTokenCredentials.java b/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/ApplicationTokenCredentials.java index 3e995fb06a087..163d10f60a1d5 100644 --- a/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/ApplicationTokenCredentials.java +++ b/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/ApplicationTokenCredentials.java @@ -10,9 +10,13 @@ import com.microsoft.aad.adal4j.AuthenticationContext; import com.microsoft.aad.adal4j.AuthenticationResult; import com.microsoft.aad.adal4j.ClientCredential; +import com.microsoft.azure.AzureEnvironment; import com.microsoft.rest.credentials.TokenCredentials; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -30,6 +34,8 @@ public class ApplicationTokenCredentials extends TokenCredentials { private AzureEnvironment environment; /** The current authentication result. */ private AuthenticationResult authenticationResult; + /** The default subscription to use, if any. */ + private String defaultSubscription; /** * Initializes a new instance of the UserTokenCredentials. @@ -52,6 +58,103 @@ public ApplicationTokenCredentials(String clientId, String domain, String secret } } + /** + * Contains the keys of the settings in a Properties file to read credentials from. + */ + private enum CredentialSettings { + /** The subscription GUID. */ + SUBSCRIPTION_ID("subscription"), + /** The tenant GUID or domain. */ + TENANT_ID("tenant"), + /** The client id for the client application. */ + CLIENT_ID("client"), + /** The client secret for the service principal. */ + CLIENT_KEY("key"), + /** The management endpoint. */ + MANAGEMENT_URI("managementURI"), + /** The base URL to the current Azure environment. */ + BASE_URL("baseURL"), + /** The URL to Active Directory authentication. */ + AUTH_URL("authURL"); + + /** The name of the key in the properties file. */ + private final String name; + + CredentialSettings(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } + } + + /** + * @return The default subscription ID, if any + */ + public String defaultSubscriptionId() { + return defaultSubscription; + } + + /** + * Set default subscription ID. + * + * @param subscriptionId the default subscription ID. + * @return the credentials object itself. + */ + public ApplicationTokenCredentials withDefaultSubscriptionId(String subscriptionId) { + this.defaultSubscription = subscriptionId; + return this; + } + + /** + * Initializes the credentials based on the provided credentials file. + * + * @param credentialsFile A file with credentials, using the standard Java properties format. + * and the following keys: + * subscription= + * tenant= + * client= + * key= + * managementURI= + * baseURL= + * authURL= + * @return The credentials based on the file. + * @throws IOException exception thrown from file access errors. + */ + public static ApplicationTokenCredentials fromFile(File credentialsFile) throws IOException { + // Set defaults + Properties authSettings = new Properties(); + authSettings.put(CredentialSettings.AUTH_URL.toString(), AzureEnvironment.AZURE.getAuthenticationEndpoint()); + authSettings.put(CredentialSettings.BASE_URL.toString(), AzureEnvironment.AZURE.getBaseUrl()); + authSettings.put(CredentialSettings.MANAGEMENT_URI.toString(), AzureEnvironment.AZURE.getTokenAudience()); + + // Load the credentials from the file + FileInputStream credentialsFileStream = new FileInputStream(credentialsFile); + authSettings.load(credentialsFileStream); + credentialsFileStream.close(); + + final String clientId = authSettings.getProperty(CredentialSettings.CLIENT_ID.toString()); + final String tenantId = authSettings.getProperty(CredentialSettings.TENANT_ID.toString()); + final String clientKey = authSettings.getProperty(CredentialSettings.CLIENT_KEY.toString()); + final String mgmtUri = authSettings.getProperty(CredentialSettings.MANAGEMENT_URI.toString()); + final String authUrl = authSettings.getProperty(CredentialSettings.AUTH_URL.toString()); + final String baseUrl = authSettings.getProperty(CredentialSettings.BASE_URL.toString()); + final String defaultSubscriptionId = authSettings.getProperty(CredentialSettings.SUBSCRIPTION_ID.toString()); + + return new ApplicationTokenCredentials( + clientId, + tenantId, + clientKey, + new AzureEnvironment( + authUrl, + mgmtUri, + true, + baseUrl) + ).withDefaultSubscriptionId(defaultSubscriptionId); + } + /** * Gets the active directory application client id. * diff --git a/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/UserTokenCredentials.java b/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/UserTokenCredentials.java index af02c07507b74..60d6bdb3c0a58 100644 --- a/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/UserTokenCredentials.java +++ b/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/UserTokenCredentials.java @@ -9,6 +9,7 @@ import com.microsoft.aad.adal4j.AuthenticationContext; import com.microsoft.aad.adal4j.AuthenticationResult; +import com.microsoft.azure.AzureEnvironment; import com.microsoft.rest.credentials.TokenCredentials; import java.io.IOException; diff --git a/azure-client-authentication/src/test/java/com/microsoft/azure/credentials/UserTokenCredentialsTests.java b/azure-client-authentication/src/test/java/com/microsoft/azure/credentials/UserTokenCredentialsTests.java index afce04b56ecdf..7905ba7e7b21e 100644 --- a/azure-client-authentication/src/test/java/com/microsoft/azure/credentials/UserTokenCredentialsTests.java +++ b/azure-client-authentication/src/test/java/com/microsoft/azure/credentials/UserTokenCredentialsTests.java @@ -8,9 +8,8 @@ package com.microsoft.azure.credentials; import com.microsoft.aad.adal4j.AuthenticationResult; - +import com.microsoft.azure.AzureEnvironment; import org.junit.Assert; - import org.junit.Test; import java.io.IOException; diff --git a/azure-client-runtime/build.gradle b/azure-client-runtime/build.gradle index dcdaddcea285b..e8a50ca112428 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 d8389869810f4..56f377008512e 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,7 +7,6 @@ package com.microsoft.azure; -import com.microsoft.rest.RestClient; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceException; @@ -27,6 +26,7 @@ import retrofit2.Call; import retrofit2.Response; import retrofit2.http.GET; +import retrofit2.http.Header; import retrofit2.http.Url; /** @@ -44,13 +44,19 @@ public class AzureClient extends AzureServiceClient { */ private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + /** + * The user agent from the service client that owns this Azure Client. + */ + private final String serviceClientUserAgent; + /** * Initializes an instance of this class with customized client metadata. * - * @param restClient the REST client to connect to Azure + * @param serviceClient the caller client that initiates the asynchronous request. */ - public AzureClient(RestClient restClient) { - super(restClient); + public AzureClient(AzureServiceClient serviceClient) { + super(serviceClient.restClient()); + this.serviceClientUserAgent = serviceClient.userAgent(); } /** @@ -647,7 +653,7 @@ private Response poll(String url) throws CloudException, IOExcepti port = endpoint.getDefaultPort(); } AsyncService service = restClient().retrofit().create(AsyncService.class); - Response response = service.get(endpoint.getFile()).execute(); + Response response = service.get(endpoint.getFile(), serviceClientUserAgent).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"); @@ -684,7 +690,7 @@ private Call pollAsync(String url, final ServiceCallback call = service.get(endpoint.getFile()); + Call call = service.get(endpoint.getFile(), serviceClientUserAgent); call.enqueue(new ServiceResponseCallback(callback) { @Override public void onResponse(Call call, Response response) { @@ -735,7 +741,7 @@ public void setLongRunningOperationRetryTimeout(Integer longRunningOperationRetr */ private interface AsyncService { @GET - Call get(@Url String url); + Call get(@Url String url, @Header("User-Agent") String userAgent); } /** diff --git a/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/AzureEnvironment.java b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureEnvironment.java similarity index 67% rename from azure-client-authentication/src/main/java/com/microsoft/azure/credentials/AzureEnvironment.java rename to azure-client-runtime/src/main/java/com/microsoft/azure/AzureEnvironment.java index dd8a1a2dc9de9..1721e2ff97bb8 100644 --- a/azure-client-authentication/src/main/java/com/microsoft/azure/credentials/AzureEnvironment.java +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureEnvironment.java @@ -5,20 +5,30 @@ * */ -package com.microsoft.azure.credentials; +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. */ public final class AzureEnvironment { + /** + * Base URL for calls to Azure management API. + */ + private final String baseURL; + /** * ActiveDirectory Endpoint for the Azure Environment. */ private String authenticationEndpoint; + /** * Token audience for an endpoint. */ private String tokenAudience; + /** * Determines whether the authentication endpoint should * be validated with Azure AD. Default value is true. @@ -32,11 +42,17 @@ public final class AzureEnvironment { * @param tokenAudience token audience for an endpoint. * @param validateAuthority whether the authentication endpoint should * be validated with Azure AD. + * @param baseUrl the base URL for the current environment. */ - public AzureEnvironment(String authenticationEndpoint, String tokenAudience, boolean validateAuthority) { + public AzureEnvironment( + String authenticationEndpoint, + String tokenAudience, + boolean validateAuthority, + String baseUrl) { this.authenticationEndpoint = authenticationEndpoint; this.tokenAudience = tokenAudience; this.validateAuthority = validateAuthority; + this.baseURL = baseUrl; } /** @@ -45,7 +61,8 @@ public AzureEnvironment(String authenticationEndpoint, String tokenAudience, boo public static final AzureEnvironment AZURE = new AzureEnvironment( "https://login.windows.net/", "https://management.core.windows.net/", - true); + true, + "https://management.azure.com/"); /** * Provides the settings for authentication with Azure China. @@ -53,7 +70,28 @@ public AzureEnvironment(String authenticationEndpoint, String tokenAudience, boo public static final AzureEnvironment AZURE_CHINA = new AzureEnvironment( "https://login.chinacloudapi.cn/", "https://management.core.chinacloudapi.cn/", - true); + true, + "https://management.chinacloudapi.cn"); + + /** + * Gets the base URL of the management service. + * + * @return the Base URL for the management service. + */ + public String getBaseUrl() { + return this.baseURL; + } + + /** + * Gets a builder for {@link RestClient}. + * + * @return a builder for the rest client. + */ + public RestClient.Builder newRestClientBuilder() { + return new RestClient.Builder(baseURL) + .withInterceptor(new RequestIdHeaderInterceptor()) + .withMapperAdapter(new AzureJacksonMapperAdapter()); + } /** * Gets the ActiveDirectory Endpoint for the Azure Environment. 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 94142029cfc67..08094b67d5071 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 @@ -17,6 +17,7 @@ public abstract class AzureServiceClient extends ServiceClient { protected AzureServiceClient(String baseUrl) { this(new RestClient.Builder(baseUrl) + .withInterceptor(new RequestIdHeaderInterceptor()) .withMapperAdapter(new AzureJacksonMapperAdapter()).build()); } @@ -28,4 +29,13 @@ protected AzureServiceClient(String baseUrl) { protected AzureServiceClient(RestClient restClient) { super(restClient); } + + /** + * The default User-Agent header. Override this method to override the user agent. + * + * @return the user agent string. + */ + public String userAgent() { + return "Azure-SDK-For-Java/" + getClass().getPackage().getImplementationVersion(); + } } diff --git a/azure-client-runtime/src/main/java/com/microsoft/azure/PagedList.java b/azure-client-runtime/src/main/java/com/microsoft/azure/PagedList.java index f13aca518532e..f501163ff03e0 100644 --- a/azure-client-runtime/src/main/java/com/microsoft/azure/PagedList.java +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/PagedList.java @@ -47,7 +47,8 @@ public PagedList() { * @param page the {@link Page} object. */ public PagedList(Page page) { - items = page.getItems(); + this(); + items.addAll(page.getItems()); nextPageLink = page.getNextPageLink(); currentPage = page; } diff --git a/azure-client-runtime/src/main/java/com/microsoft/azure/RequestIdHeaderInterceptor.java b/azure-client-runtime/src/main/java/com/microsoft/azure/RequestIdHeaderInterceptor.java new file mode 100644 index 0000000000000..ddbe0db30ec0b --- /dev/null +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/RequestIdHeaderInterceptor.java @@ -0,0 +1,29 @@ +/** + * + * 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 okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; +import java.util.UUID; + +/** + * An instance of this class puts an UUID in the request header. Azure uses + * the request id as the unique identifier for + */ +public class RequestIdHeaderInterceptor implements Interceptor { + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request().newBuilder() + .header("x-ms-client-request-id", UUID.randomUUID().toString()) + .build(); + return chain.proceed(request); + } +} 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 new file mode 100644 index 0000000000000..e8cce598b05f4 --- /dev/null +++ b/azure-client-runtime/src/test/java/com/microsoft/azure/RequestIdHeaderInterceptorTests.java @@ -0,0 +1,90 @@ +/** + * + * 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.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; + +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") + .withInterceptor(new RequestIdHeaderInterceptor()) + .withInterceptor(new Interceptor() { + private String firstRequestId = null; + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + if (request.header(REQUEST_ID_HEADER) != null) { + if (firstRequestId == null) { + firstRequestId = request.header(REQUEST_ID_HEADER); + return new Response.Builder().code(200).request(request) + .protocol(Protocol.HTTP_1_1).build(); + } else if (!request.header(REQUEST_ID_HEADER).equals(firstRequestId)) { + return new Response.Builder().code(200).request(request) + .protocol(Protocol.HTTP_1_1).build(); + } + } + return new Response.Builder().code(400).request(request) + .protocol(Protocol.HTTP_1_1).build(); + } + }) + .withMapperAdapter(new AzureJacksonMapperAdapter()) + .build(); + AzureServiceClient serviceClient = new AzureServiceClient(restClient) { }; + Response response = serviceClient.restClient().httpClient() + .newCall(new Request.Builder().get().url("http://localhost").build()).execute(); + Assert.assertEquals(200, response.code()); + response = serviceClient.restClient().httpClient() + .newCall(new Request.Builder().get().url("http://localhost").build()).execute(); + Assert.assertEquals(200, response.code()); + } + + @Test + public void sameRequestIdForRetry() throws Exception { + RestClient restClient = new RestClient.Builder("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(); + if (request.header(REQUEST_ID_HEADER) != null) { + if (firstRequestId == null) { + firstRequestId = request.header(REQUEST_ID_HEADER); + return new Response.Builder().code(500).request(request) + .protocol(Protocol.HTTP_1_1).build(); + } else if (request.header(REQUEST_ID_HEADER).equals(firstRequestId)) { + return new Response.Builder().code(200).request(request) + .protocol(Protocol.HTTP_1_1).build(); + } + } + return new Response.Builder().code(400).request(request) + .protocol(Protocol.HTTP_1_1).build(); + } + }) + .withMapperAdapter(new AzureJacksonMapperAdapter()) + .build(); + AzureServiceClient serviceClient = new AzureServiceClient(restClient) { }; + Response response = serviceClient.restClient().httpClient() + .newCall(new Request.Builder().get().url("http://localhost").build()).execute(); + Assert.assertEquals(200, response.code()); + } +} diff --git a/client-runtime/build.gradle b/client-runtime/build.gradle index b734d33608eaf..2558fc5055f9a 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/pom.xml b/client-runtime/pom.xml index 029c12e26022d..a7c0b7441b02c 100644 --- a/client-runtime/pom.xml +++ b/client-runtime/pom.xml @@ -105,11 +105,6 @@ - - org.apache.maven.plugins - maven-antrun-plugin - - org.codehaus.mojo build-helper-maven-plugin diff --git a/client-runtime/src/main/java/com/microsoft/rest/RestClient.java b/client-runtime/src/main/java/com/microsoft/rest/RestClient.java index ffc52643040d7..0d5436b4fa6e1 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/RestClient.java +++ b/client-runtime/src/main/java/com/microsoft/rest/RestClient.java @@ -36,17 +36,21 @@ public final class RestClient { 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; } @@ -92,7 +96,11 @@ public Retrofit retrofit() { * URL instead of the raw one might be returned. * * @return the base URL. +<<<<<<< HEAD * @see {@link RestClient#setBaseUrl(String...)} +======= + * @see RestClient#setBaseUrl(String...) +>>>>>>> fddca6a8917951772a65a3e5b47c5e72c1f42fb5 */ public String baseUrl() { return baseUrlHandler.baseUrl(); @@ -135,11 +143,13 @@ public static class Builder { 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 varialbes wrapped in "{" and "}". + * @param baseUrl the dynamic base URL with variables wrapped in "{" and "}". */ public Builder(String baseUrl) { this(baseUrl, new OkHttpClient.Builder(), new Retrofit.Builder()); @@ -148,7 +158,7 @@ public Builder(String baseUrl) { /** * 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 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}. */ @@ -166,27 +176,15 @@ public Builder(String baseUrl, OkHttpClient.Builder httpClientBuilder, Retrofit. cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); customHeadersInterceptor = new CustomHeadersInterceptor(); baseUrlHandler = new BaseUrlHandler(baseUrl); + userAgentInterceptor = new UserAgentInterceptor(); // Set up OkHttp client this.httpClientBuilder = httpClientBuilder .cookieJar(new JavaNetCookieJar(cookieManager)) - .addInterceptor(new RetryHandler()) - .addInterceptor(new UserAgentInterceptor()); + .addInterceptor(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. * @@ -194,7 +192,7 @@ public Builder withBaseUrl(String baseUrl) { * @return the builder itself for chaining. */ public Builder withUserAgent(String userAgent) { - this.httpClientBuilder.addInterceptor(new UserAgentInterceptor(userAgent)); + this.userAgentInterceptor.setUserAgent(userAgent); return this; } @@ -205,10 +203,7 @@ public Builder withUserAgent(String userAgent) { * @return the builder itself for chaining. */ public Builder withMapperAdapter(JacksonMapperAdapter mapperAdapter) { - if (mapperAdapter != null) { - this.mapperAdapter = mapperAdapter; - this.retrofitBuilder = retrofitBuilder.addConverterFactory(mapperAdapter.getConverterFactory()); - } + this.mapperAdapter = mapperAdapter; return this; } @@ -254,14 +249,22 @@ public Builder withInterceptor(Interceptor interceptor) { * @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).build(), + 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 ef2f8cae9cfec..674b6a1bc6253 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java +++ b/client-runtime/src/main/java/com/microsoft/rest/ServiceClient.java @@ -20,6 +20,8 @@ public abstract class ServiceClient { /** * Initializes a new instance of the ServiceClient class. + * + * @param baseUrl the service endpoint */ protected ServiceClient(String baseUrl) { this(new RestClient.Builder(baseUrl) 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 4c6c4f6ca5dff..7705592ba9f72 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/UserAgentInterceptor.java +++ b/client-runtime/src/main/java/com/microsoft/rest/UserAgentInterceptor.java @@ -10,7 +10,6 @@ import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; -import okhttp3.internal.Version; import java.io.IOException; @@ -33,28 +32,34 @@ public class UserAgentInterceptor implements Interceptor { * 'User-Agent' header. */ public UserAgentInterceptor() { - this(DEFAULT_USER_AGENT_HEADER); + this.userAgent = DEFAULT_USER_AGENT_HEADER; } - /** - * Initialize an instance of {@link UserAgentInterceptor} class with the specified - * 'User-Agent' header. - * - * @param userAgent the 'User-Agent' header value. - */ - public UserAgentInterceptor(String userAgent) { + public void setUserAgent(String userAgent) { this.userAgent = userAgent; } + public void appendUserAgent(String userAgent) { + this.userAgent += " " + userAgent; + } + @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); String header = request.header("User-Agent"); - if (header == null || header.equals(Version.userAgent()) || header.equals(DEFAULT_USER_AGENT_HEADER)) { - request = chain.request().newBuilder() - .header("User-Agent", userAgent) - .build(); + if (header == null) { + header = DEFAULT_USER_AGENT_HEADER; + } + if (!userAgent.equals(DEFAULT_USER_AGENT_HEADER)) { + if (header.equals(DEFAULT_USER_AGENT_HEADER)) { + header = userAgent; + } else { + header = userAgent + " " + header; + } } + request = chain.request().newBuilder() + .header("User-Agent", header) + .build(); return chain.proceed(request); } } 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 19b7a8ca2a4f5..3e05c5d723fdb 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/CredentialsTests.java @@ -9,6 +9,7 @@ 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; @@ -29,6 +30,7 @@ public void basicCredentialsTest() throws Exception { 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 @@ -53,6 +55,7 @@ public void tokenCredentialsTest() throws Exception { 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() { @Override 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 050e7374aba18..97c46f6fe4fc3 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/RetryHandlerTests.java @@ -9,6 +9,7 @@ import com.microsoft.rest.retry.RetryHandler; +import com.microsoft.rest.serializer.JacksonMapperAdapter; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Protocol; @@ -41,7 +42,8 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + 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").get().build()).execute(); @@ -67,7 +69,8 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + 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").get().build()).execute(); 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 5497d607549d7..6423ef23d8081 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/ServiceClientTests.java @@ -7,8 +7,10 @@ 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; @@ -17,7 +19,6 @@ import okhttp3.Protocol; import okhttp3.Request; import okhttp3.Response; -import retrofit2.Retrofit; public class ServiceClientTests { @Test @@ -38,7 +39,8 @@ public Response intercept(Chain chain) throws IOException { .build(); } }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + 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(); 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 e6b938f933683..7949ad8433655 100644 --- a/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java +++ b/client-runtime/src/test/java/com/microsoft/rest/UserAgentTests.java @@ -7,9 +7,11 @@ package com.microsoft.rest; +import com.microsoft.rest.serializer.JacksonMapperAdapter; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Protocol; +import okhttp3.Request; import okhttp3.Response; import retrofit2.Retrofit; @@ -21,42 +23,47 @@ public class UserAgentTests { @Test public void defaultUserAgentTests() throws Exception { - 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(); - } - }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost") + .withInterceptor(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(); + } + }) + .withMapperAdapter(new JacksonMapperAdapter()); ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; + Response response = serviceClient.restClient().httpClient() + .newCall(new Request.Builder().get().url("http://localhost").build()).execute(); + Assert.assertEquals(200, response.code()); } @Test public void customUserAgentTests() throws Exception { - 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(); - } - }); - RestClient.Builder restBuilder = new RestClient.Builder("http://localhost", clientBuilder, retrofitBuilder); + + RestClient.Builder restBuilder = new RestClient.Builder("http://localhost") + .withUserAgent("Awesome") + .withInterceptor(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(); + } + }) + .withMapperAdapter(new JacksonMapperAdapter()); ServiceClient serviceClient = new ServiceClient(restBuilder.build()) { }; + Response response = serviceClient.restClient().httpClient() + .newCall(new Request.Builder().get().url("http://localhost").build()).execute(); + Assert.assertEquals(200, response.code()); } } diff --git a/client-runtime/src/test/java/com/microsoft/rest/package-info.java b/client-runtime/src/test/java/com/microsoft/rest/package-info.java deleted file mode 100644 index 137d82e99154e..0000000000000 --- a/client-runtime/src/test/java/com/microsoft/rest/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * The package contains the tests for the client runtime. - */ -package com.microsoft.rest; \ No newline at end of file diff --git a/pom.xml b/pom.xml index ae5dc28eaff4b..b6bb0bb29b042 100644 --- a/pom.xml +++ b/pom.xml @@ -44,28 +44,8 @@ - azureoss-snapshots-pr - Azure Private Snapshots - http://azureoss.westus.cloudapp.azure.com:8080/nexus/content/repositories/snapshots-pr/ - default - - true - always - - - - adx-snapshots - Azure ADX Snapshots - http://adxsnapshots.azurewebsites.net - default - - true - always - - - - oss-snapshots - Open Source Snapshots + ossrh + Sonatype Snapshots https://oss.sonatype.org/content/repositories/snapshots/ default @@ -77,12 +57,17 @@ - adx-snapshots - Azure ADX Snapshots - ftp://waws-prod-bay-005.ftp.azurewebsites.windows.net/site/wwwroot + ossrh + Maven Central Snapshots + https://oss.sonatype.org/content/repositories/snapshots true default + + ossrh + Maven Central + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + @@ -158,23 +143,6 @@ - - org.apache.maven.plugins - maven-help-plugin - 2.1.1 - - - validate - - evaluate - - - legal - - - - - org.apache.maven.plugins maven-compiler-plugin @@ -201,12 +169,6 @@
*/]]>
- - - org.apache.maven.plugins - maven-release-plugin - 2.5.3 -
@@ -238,35 +200,11 @@
- org.apache.maven.plugins maven-release-plugin 2.5.2 - - - org.codehaus.mojo - build-helper-maven-plugin - 1.10 - - - attach-artifacts - package - - attach-artifact - - - - - target/.gitrevision - gitrevision - - - - - -