Skip to content

Commit

Permalink
Add RestClient
Browse files Browse the repository at this point in the history
  • Loading branch information
jianghaolu committed Apr 26, 2016
1 parent dfba322 commit b6c78d5
Show file tree
Hide file tree
Showing 10 changed files with 435 additions and 208 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@

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;
Expand All @@ -24,11 +24,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;

Expand All @@ -42,32 +40,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);
}

/**
Expand Down Expand Up @@ -98,13 +82,13 @@ public <T> ServiceResponse<T> getPutOrPatchResult(Response<ResponseBody> 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<T> pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, mapperAdapter);
PollingState<T> pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, restClient().mapperAdapter());
String url = response.raw().request().url().toString();

// Check provisioning state
Expand Down Expand Up @@ -151,7 +135,7 @@ public <T, THeader> ServiceResponseWithHeaders<T, THeader> getPutOrPatchResultWi
ServiceResponse<T> bodyResponse = getPutOrPatchResult(response, resourceType);
return new ServiceResponseWithHeaders<>(
bodyResponse.getBody(),
mapperAdapter.<THeader>deserialize(mapperAdapter.serialize(bodyResponse.getResponse().headers()), headerType),
restClient().mapperAdapter().<THeader>deserialize(restClient().mapperAdapter().serialize(bodyResponse.getResponse().headers()), headerType),
bodyResponse.getResponse()
);
}
Expand Down Expand Up @@ -186,7 +170,7 @@ public <T> AsyncPollingTask<T> getPutOrPatchResultAsync(Response<ResponseBody> 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 */ }
Expand All @@ -196,7 +180,7 @@ public <T> AsyncPollingTask<T> getPutOrPatchResultAsync(Response<ResponseBody> r

PollingState<T> 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;
Expand Down Expand Up @@ -235,7 +219,7 @@ public void success(ServiceResponse<T> result) {
try {
callback.success(new ServiceResponseWithHeaders<>(
result.getBody(),
mapperAdapter.<THeader>deserialize(mapperAdapter.serialize(result.getResponse().headers()), headerType),
restClient().mapperAdapter().<THeader>deserialize(restClient().mapperAdapter().serialize(result.getResponse().headers()), headerType),
result.getResponse()
));
} catch (IOException e) {
Expand Down Expand Up @@ -273,13 +257,13 @@ public <T> ServiceResponse<T> getPostOrDeleteResult(Response<ResponseBody> 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<T> pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, mapperAdapter);
PollingState<T> pollingState = new PollingState<>(response, this.getLongRunningOperationRetryTimeout(), resourceType, restClient().mapperAdapter());

// Check provisioning state
while (!AzureAsyncOperation.getTerminalStatuses().contains(pollingState.getStatus())) {
Expand Down Expand Up @@ -325,7 +309,7 @@ public <T, THeader> ServiceResponseWithHeaders<T, THeader> getPostOrDeleteResult
ServiceResponse<T> bodyResponse = getPostOrDeleteResult(response, resourceType);
return new ServiceResponseWithHeaders<>(
bodyResponse.getBody(),
mapperAdapter.<THeader>deserialize(mapperAdapter.serialize(bodyResponse.getResponse().headers()), headerType),
restClient().mapperAdapter().<THeader>deserialize(restClient().mapperAdapter().serialize(bodyResponse.getResponse().headers()), headerType),
bodyResponse.getResponse()
);
}
Expand Down Expand Up @@ -360,7 +344,7 @@ public <T> AsyncPollingTask<T> getPostOrDeleteResultAsync(Response<ResponseBody>
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 */ }
Expand All @@ -370,7 +354,7 @@ public <T> AsyncPollingTask<T> getPostOrDeleteResultAsync(Response<ResponseBody>

PollingState<T> 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;
Expand Down Expand Up @@ -408,7 +392,7 @@ public void success(ServiceResponse<T> result) {
try {
callback.success(new ServiceResponseWithHeaders<>(
result.getBody(),
mapperAdapter.<THeader>deserialize(mapperAdapter.serialize(result.getResponse().headers()), headerType),
restClient().mapperAdapter().<THeader>deserialize(restClient().mapperAdapter().serialize(result.getResponse().headers()), headerType),
result.getResponse()
));
} catch (IOException e) {
Expand Down Expand Up @@ -584,15 +568,15 @@ private <T> void updateStateFromAzureAsyncOperationHeader(PollingState<T> 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();
}

if (body == null || body.getStatus() == null) {
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;
Expand Down Expand Up @@ -624,14 +608,14 @@ public void success(ServiceResponse<ResponseBody> 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);
Expand Down Expand Up @@ -663,18 +647,17 @@ private Response<ResponseBody> 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<ResponseBody> 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;
Expand All @@ -701,8 +684,7 @@ private Call<ResponseBody> pollAsync(String url, final ServiceCallback<ResponseB
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);
Call<ResponseBody> call = service.get(endpoint.getFile());
call.enqueue(new ServiceResponseCallback<ResponseBody>(callback) {
@Override
Expand All @@ -713,10 +695,10 @@ public void onResponse(Call<ResponseBody> call, Response<ResponseBody> 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);
Expand Down Expand Up @@ -749,24 +731,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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
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 com.microsoft.rest.serializer.JacksonMapperAdapter;

import java.net.CookieManager;
import java.net.CookiePolicy;
Expand All @@ -23,42 +25,17 @@
* 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
*/
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.
* @param restClient the REST client
*/
@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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
*
* 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;
import okhttp3.internal.Version;
import retrofit2.BaseUrl;

/**
* User agent interceptor for putting a 'User-Agent' header in the request.
*/
public class BaseUrlInterceptor implements Interceptor {
private String baseUrl;

public BaseUrlInterceptor() {
}

public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (baseUrl != null) {
HttpUrl newUrl = request.url().newBuilder()
.host(baseUrl)
.build();
request = request.newBuilder()
.url(newUrl)
.build();
}
return chain.proceed(request);
}
}
Loading

0 comments on commit b6c78d5

Please sign in to comment.