moved contents of wsclient into greaze-client
This commit is contained in:
parent
520259fefa
commit
0fa317045b
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.rest.client;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.CallPath;
|
|
||||||
import com.google.greaze.definition.HeaderMap;
|
|
||||||
import com.google.greaze.definition.HttpMethod;
|
|
||||||
import com.google.greaze.definition.rest.ID;
|
|
||||||
import com.google.greaze.definition.rest.ResourceDepot;
|
|
||||||
import com.google.greaze.definition.rest.RestCallSpec;
|
|
||||||
import com.google.greaze.definition.rest.RestRequest;
|
|
||||||
import com.google.greaze.definition.rest.RestResource;
|
|
||||||
import com.google.greaze.definition.rest.RestResponse;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A client class to access a rest resource
|
|
||||||
*
|
|
||||||
* @author Inderjeet Singh
|
|
||||||
*/
|
|
||||||
public class ResourceDepotClient<I extends ID, R extends RestResource<I, R>>
|
|
||||||
implements ResourceDepot<I, R> {
|
|
||||||
private final RestClientStub stub;
|
|
||||||
private final RestCallSpec callSpec;
|
|
||||||
private final Type resourceType;
|
|
||||||
private final Gson gson;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param stub stub containing server info to access the rest client
|
|
||||||
* @param callPath relative path to the resource
|
|
||||||
* @param resourceType Class for the resource. Such as Cart.class
|
|
||||||
*/
|
|
||||||
public ResourceDepotClient(RestClientStub stub, CallPath callPath, Type resourceType, Gson gson) {
|
|
||||||
this(stub, resourceType, generateRestCallSpec(callPath, resourceType), gson);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ResourceDepotClient(RestClientStub stub, Type resourceType, RestCallSpec callSpec, Gson gson) {
|
|
||||||
this.stub = stub;
|
|
||||||
this.callSpec = callSpec;
|
|
||||||
this.resourceType = resourceType;
|
|
||||||
this.gson = gson;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> RestCallSpec generateRestCallSpec(CallPath callPath, Type resourceType) {
|
|
||||||
return new RestCallSpec.Builder(callPath, resourceType).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public R get(I resourceId) {
|
|
||||||
HeaderMap requestHeaders =
|
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
|
||||||
RestRequest<I, R> request =
|
|
||||||
new RestRequest<I, R>(HttpMethod.GET, requestHeaders, resourceId, null, resourceType);
|
|
||||||
RestResponse<I, R> response = stub.getResponse(callSpec, request, gson);
|
|
||||||
return response.getBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public R post(R resource) {
|
|
||||||
HeaderMap requestHeaders =
|
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
|
||||||
RestRequest<I, R> request =
|
|
||||||
new RestRequest<I, R>(HttpMethod.POST, requestHeaders, resource.getId(), resource, resourceType);
|
|
||||||
RestResponse<I, R> response = stub.getResponse(callSpec, request, gson);
|
|
||||||
return response.getBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public R put(R resource) {
|
|
||||||
HeaderMap requestHeaders =
|
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
|
||||||
RestRequest<I, R> request =
|
|
||||||
new RestRequest<I, R>(HttpMethod.PUT, requestHeaders, resource.getId(), resource, resourceType);
|
|
||||||
RestResponse<I, R> response = stub.getResponse(callSpec, request, gson);
|
|
||||||
return response.getBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(I resourceId) {
|
|
||||||
HeaderMap requestHeaders =
|
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
|
||||||
RestRequest<I, R> request =
|
|
||||||
new RestRequest<I, R>(HttpMethod.DELETE, requestHeaders, resourceId, null, resourceType);
|
|
||||||
stub.getResponse(callSpec, request, gson);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.rest.client;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.rest.ID;
|
|
||||||
import com.google.greaze.definition.rest.RestCallSpec;
|
|
||||||
import com.google.greaze.definition.rest.RestRequest;
|
|
||||||
import com.google.greaze.definition.rest.RestResource;
|
|
||||||
import com.google.greaze.definition.rest.RestResponse;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.webservice.client.ServerConfig;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A stub to access the rest service
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public class RestClientStub {
|
|
||||||
private final ServerConfig config;
|
|
||||||
private final Logger logger;
|
|
||||||
private final Level logLevel;
|
|
||||||
|
|
||||||
public RestClientStub(ServerConfig serverConfig) {
|
|
||||||
this(serverConfig, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestClientStub(ServerConfig serverConfig, Level logLevel) {
|
|
||||||
this.config = serverConfig;
|
|
||||||
this.logger = logLevel == null ? null : Logger.getLogger(RestClientStub.class.getName());
|
|
||||||
this.logLevel = logLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <I extends ID> URL getWebServiceUrl(
|
|
||||||
RestCallSpec callSpec, ID id) {
|
|
||||||
double version = callSpec.getVersion();
|
|
||||||
StringBuilder url = new StringBuilder(config.getServiceBaseUrl());
|
|
||||||
if (version != -1D) {
|
|
||||||
url.append('/').append(version);
|
|
||||||
}
|
|
||||||
url.append(callSpec.getPath().get());
|
|
||||||
if (id != null) {
|
|
||||||
url.append('/').append(id.getValue());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new URL(url.toString());
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <I extends ID, R extends RestResource<I, R>> RestResponse<I, R> getResponse(
|
|
||||||
RestCallSpec callSpec, RestRequest<I, R> request) {
|
|
||||||
Gson gson = new GsonBuilder().setVersion(callSpec.getVersion()).create();
|
|
||||||
return getResponse(callSpec, request, gson);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <I extends ID, R extends RestResource<I, R>> RestResponse<I, R> getResponse(
|
|
||||||
RestCallSpec callSpec, RestRequest<I, R> request, Gson gson) {
|
|
||||||
HttpURLConnection conn = null;
|
|
||||||
try {
|
|
||||||
URL webServiceUrl = getWebServiceUrl(callSpec, request.getId());
|
|
||||||
conn = (HttpURLConnection) webServiceUrl.openConnection();
|
|
||||||
return getResponse(callSpec, request, gson, conn);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
} finally {
|
|
||||||
closeIgnoringErrors(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this method if you want to mange the HTTP Connection yourself. This is useful when you
|
|
||||||
* want to use HTTP pipelining.
|
|
||||||
*/
|
|
||||||
public <I extends ID, R extends RestResource<I, R>> RestResponse<I, R> getResponse(
|
|
||||||
RestCallSpec callSpec, RestRequest<I, R> request, Gson gson,
|
|
||||||
HttpURLConnection conn) {
|
|
||||||
try {
|
|
||||||
if (logger != null) {
|
|
||||||
URL webServiceUrl = getWebServiceUrl(callSpec, request.getId());
|
|
||||||
logger.log(logLevel, "Opening connection to " + webServiceUrl);
|
|
||||||
}
|
|
||||||
RestRequestSender requestSender = new RestRequestSender(gson, logLevel);
|
|
||||||
requestSender.send(conn, request);
|
|
||||||
RestResponseReceiver<I, R> responseReceiver =
|
|
||||||
new RestResponseReceiver<I, R>(gson, callSpec.getResponseSpec(), logLevel);
|
|
||||||
return responseReceiver.receive(conn);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void closeIgnoringErrors(HttpURLConnection conn) {
|
|
||||||
if (conn != null) {
|
|
||||||
conn.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("config:%s", config);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.rest.client;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.HeaderMap;
|
|
||||||
import com.google.greaze.definition.HeaderMapSpec;
|
|
||||||
import com.google.greaze.definition.HttpMethod;
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.rest.ID;
|
|
||||||
import com.google.greaze.definition.rest.RestRequest;
|
|
||||||
import com.google.greaze.definition.rest.RestResource;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.wsclient.internal.utils.Streams;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to send Web service requests on a {@link HttpURLConnection}.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public final class RestRequestSender {
|
|
||||||
private static final boolean SIMULATE_GET_WITH_POST = true;
|
|
||||||
private static final boolean SIMULATE_PUT_WITH_POST = true;
|
|
||||||
|
|
||||||
private final Gson gson;
|
|
||||||
private final Logger logger;
|
|
||||||
private final Level logLevel;
|
|
||||||
|
|
||||||
public RestRequestSender(Gson gson) {
|
|
||||||
this(gson, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestRequestSender(Gson gson, Level logLevel) {
|
|
||||||
this.gson = gson;
|
|
||||||
logger = logLevel == null ? null : Logger.getLogger(RestRequestSender.class.getName());
|
|
||||||
this.logLevel = logLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <I extends ID, R extends RestResource<I, R>> void send(
|
|
||||||
HttpURLConnection conn, RestRequest<I, R> request) {
|
|
||||||
try {
|
|
||||||
HttpMethod method = request.getHttpMethod();
|
|
||||||
if (SIMULATE_PUT_WITH_POST && method == HttpMethod.PUT) {
|
|
||||||
method = HttpMethod.POST;
|
|
||||||
setHeader(conn, HttpMethod.SIMULATED_METHOD_HEADER, HttpMethod.PUT.toString(), true);
|
|
||||||
} else if (SIMULATE_GET_WITH_POST && method == HttpMethod.GET) {
|
|
||||||
method = HttpMethod.POST;
|
|
||||||
setHeader(conn, HttpMethod.SIMULATED_METHOD_HEADER, HttpMethod.GET.toString(), true);
|
|
||||||
}
|
|
||||||
conn.setRequestMethod(method.toString());
|
|
||||||
setHeader(conn, "Content-Type", request.getContentType(), true);
|
|
||||||
|
|
||||||
// Assume conservatively that the response will need to be read.
|
|
||||||
// This is done here instead of in the response receiver because this property must be set
|
|
||||||
// before sending any data on the connection.
|
|
||||||
conn.setDoInput(true);
|
|
||||||
|
|
||||||
R requestBody = request.getBody();
|
|
||||||
String requestBodyContents = "";
|
|
||||||
if (method == HttpMethod.POST || method == HttpMethod.PUT) {
|
|
||||||
// Android Java VM ignore Content-Length if setDoOutput is not set
|
|
||||||
conn.setDoOutput(true);
|
|
||||||
}
|
|
||||||
if (requestBody != null) {
|
|
||||||
requestBodyContents = gson.toJson(requestBody, request.getSpec().getResourceType());
|
|
||||||
}
|
|
||||||
String contentLength = String.valueOf(requestBodyContents.length());
|
|
||||||
setHeader(conn, "Content-Length", contentLength, true);
|
|
||||||
addRequestParams(conn, request.getHeaders());
|
|
||||||
Streams.copy(requestBodyContents, conn.getOutputStream(), false);
|
|
||||||
|
|
||||||
// Initiate the sending of the request.
|
|
||||||
conn.connect();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addRequestParams(HttpURLConnection conn, HeaderMap requestParams) {
|
|
||||||
HeaderMapSpec spec = requestParams.getSpec();
|
|
||||||
for (Map.Entry<String, Object> entry : requestParams.entrySet()) {
|
|
||||||
String paramName = entry.getKey();
|
|
||||||
Type type = spec.getTypeFor(paramName);
|
|
||||||
Object value = entry.getValue();
|
|
||||||
String json = gson.toJson(value, type);
|
|
||||||
setHeader(conn, paramName, json, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setHeader(HttpURLConnection conn, String name, String value, boolean overwrite) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.log(logLevel, String.format("Request param: %s:%s", name, value));
|
|
||||||
}
|
|
||||||
if (overwrite) {
|
|
||||||
conn.setRequestProperty(name, value);
|
|
||||||
} else {
|
|
||||||
conn.addRequestProperty(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.rest.client;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.ContentBodySpec;
|
|
||||||
import com.google.greaze.definition.HeaderMap;
|
|
||||||
import com.google.greaze.definition.HeaderMapSpec;
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.rest.ID;
|
|
||||||
import com.google.greaze.definition.rest.RestResource;
|
|
||||||
import com.google.greaze.definition.rest.RestResponse;
|
|
||||||
import com.google.greaze.definition.rest.RestResponseSpec;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.wsclient.internal.utils.ConnectionPreconditions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives a response coming on an {@link HttpURLConnection}.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public final class RestResponseReceiver<I extends ID, R extends RestResource<I, R>> {
|
|
||||||
private final Gson gson;
|
|
||||||
private final RestResponseSpec spec;
|
|
||||||
private final Logger logger;
|
|
||||||
private final Level logLevel;
|
|
||||||
|
|
||||||
public RestResponseReceiver(Gson gson, RestResponseSpec spec) {
|
|
||||||
this(gson, spec, null);
|
|
||||||
}
|
|
||||||
public RestResponseReceiver(Gson gson, RestResponseSpec spec, Level logLevel) {
|
|
||||||
this.gson = gson;
|
|
||||||
this.spec = spec;
|
|
||||||
this.logger = logLevel == null ? null : Logger.getLogger(RestResponseReceiver.class.getName());
|
|
||||||
this.logLevel = logLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestResponse<I, R> receive(HttpURLConnection conn) {
|
|
||||||
try {
|
|
||||||
HeaderMapSpec paramSpec = spec.getHeadersSpec();
|
|
||||||
Type bodyType = spec.getResourceType();
|
|
||||||
// read response
|
|
||||||
HeaderMap responseParams = readResponseHeaders(conn, paramSpec);
|
|
||||||
R responseBody = readResponseBody(conn, bodyType);
|
|
||||||
return new RestResponse<I, R>(responseParams, responseBody, bodyType);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private HeaderMap readResponseHeaders(HttpURLConnection conn, HeaderMapSpec paramsSpec) {
|
|
||||||
HeaderMap.Builder paramsBuilder = new HeaderMap.Builder(paramsSpec);
|
|
||||||
for (Map.Entry<String, Type> entry : paramsSpec.entrySet()) {
|
|
||||||
String paramName = entry.getKey();
|
|
||||||
String json = conn.getHeaderField(paramName);
|
|
||||||
if (json != null) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.log(logLevel, String.format("Response Header: %s:%s\n", paramName, json));
|
|
||||||
}
|
|
||||||
Type typeOfT = paramsSpec.getTypeFor(paramName);
|
|
||||||
Object value = gson.fromJson(json, typeOfT);
|
|
||||||
paramsBuilder.put(paramName, value, typeOfT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return paramsBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private R readResponseBody(
|
|
||||||
HttpURLConnection conn, Type resourceType) throws IOException {
|
|
||||||
String connContentType = conn.getContentType();
|
|
||||||
ConnectionPreconditions.checkArgument(
|
|
||||||
connContentType.contains(ContentBodySpec.JSON_CONTENT_TYPE), conn);
|
|
||||||
Reader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
|
||||||
R body = (R) gson.fromJson(reader, resourceType);
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.rest.query.client;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.CallPath;
|
|
||||||
import com.google.greaze.definition.HeaderMap;
|
|
||||||
import com.google.greaze.definition.HttpMethod;
|
|
||||||
import com.google.greaze.definition.rest.ID;
|
|
||||||
import com.google.greaze.definition.rest.RestResource;
|
|
||||||
import com.google.greaze.definition.rest.query.ResourceQuery;
|
|
||||||
import com.google.greaze.definition.rest.query.TypedKeysQuery;
|
|
||||||
import com.google.greaze.definition.webservice.RequestBody;
|
|
||||||
import com.google.greaze.definition.webservice.ResponseBody;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceCallSpec;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceRequest;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceResponse;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.webservice.client.WebServiceClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A client to invoke {@link ResourceQuery}s associated with a REST resource
|
|
||||||
*
|
|
||||||
* @author Inderjeet Singh
|
|
||||||
*
|
|
||||||
* @param <I> ID type of the REST resource
|
|
||||||
* @param <R> type of the REST resource
|
|
||||||
* @param <Q> Query parameters
|
|
||||||
*/
|
|
||||||
public class ResourceQueryClient<I extends ID, R extends RestResource<I, R>, Q>
|
|
||||||
implements ResourceQuery<I, R, Q> {
|
|
||||||
|
|
||||||
private final WebServiceClient stub;
|
|
||||||
private final WebServiceCallSpec callSpec;
|
|
||||||
private final Gson gson;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param stub stub containing server info to access the rest client
|
|
||||||
* @param callPath relative path to the resource
|
|
||||||
*/
|
|
||||||
public ResourceQueryClient(WebServiceClient stub, CallPath callPath, Gson gson) {
|
|
||||||
this(stub, generateCallSpec(callPath), gson);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ResourceQueryClient(WebServiceClient stub, WebServiceCallSpec callSpec, Gson gson) {
|
|
||||||
this.stub = stub;
|
|
||||||
this.callSpec = callSpec;
|
|
||||||
this.gson = gson;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> WebServiceCallSpec generateCallSpec(CallPath callPath) {
|
|
||||||
return new WebServiceCallSpec.Builder(callPath)
|
|
||||||
.supportsHttpMethod(HttpMethod.GET)
|
|
||||||
.addResponseBodyParam(TypedKeysQuery.RESOURCE_LIST)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
||||||
@Override
|
|
||||||
public List<R> query(Q query) {
|
|
||||||
HeaderMap requestHeaders =
|
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
|
||||||
RequestBody requestBody =
|
|
||||||
new RequestBody.Builder(callSpec.getRequestSpec().getBodySpec())
|
|
||||||
.build();
|
|
||||||
WebServiceRequest request = new WebServiceRequest(HttpMethod.GET, requestHeaders, requestBody);
|
|
||||||
WebServiceResponse response = stub.getResponse(callSpec, request, gson);
|
|
||||||
ResponseBody body = response.getBody();
|
|
||||||
List list = body.get(TypedKeysQuery.RESOURCE_LIST);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceCall;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A consumer that executes in its own thread consuming queue entries and invoking web-service calls
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
final class QueueConsumer implements Runnable {
|
|
||||||
|
|
||||||
private final BlockingQueue<QueueEntry> queue;
|
|
||||||
private WebServiceClient client;
|
|
||||||
|
|
||||||
QueueConsumer(BlockingQueue<QueueEntry> queue, WebServiceClient client) {
|
|
||||||
this.queue = queue;
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
while(true) {
|
|
||||||
consume(queue.take());
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void consume(QueueEntry entry) {
|
|
||||||
try {
|
|
||||||
WebServiceResponse response = client.getResponse(entry.callSpec, entry.request);
|
|
||||||
WebServiceCall call = new WebServiceCall(entry.callSpec, entry.request, response);
|
|
||||||
entry.responseCallback.handleResponse(call);
|
|
||||||
} catch (WebServiceSystemException e) {
|
|
||||||
entry.responseCallback.handleError(e, entry.request, entry.callSpec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceCallSpec;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A holder class for an entry stored in queue. It contains references to the request, callspec,
|
|
||||||
* and the client-supplied callback to provide sufficient information to execute a web-service call.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
final class QueueEntry {
|
|
||||||
final WebServiceCallSpec callSpec;
|
|
||||||
final WebServiceRequest request;
|
|
||||||
final ResponseCallback responseCallback;
|
|
||||||
|
|
||||||
QueueEntry(WebServiceCallSpec callSpec, WebServiceRequest request,
|
|
||||||
ResponseCallback responseCallback) {
|
|
||||||
this.callSpec = callSpec;
|
|
||||||
this.request = request;
|
|
||||||
this.responseCallback = responseCallback;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2008 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.HeaderMap;
|
|
||||||
import com.google.greaze.definition.HeaderMapSpec;
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.webservice.RequestBody;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceRequest;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.wsclient.internal.utils.Streams;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to send Web service requests on a {@link HttpURLConnection}.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public final class RequestSender {
|
|
||||||
private final Gson gson;
|
|
||||||
private final Logger logger;
|
|
||||||
private final Level logLevel;
|
|
||||||
|
|
||||||
public RequestSender(Gson gson) {
|
|
||||||
this(gson, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestSender(Gson gson, Level logLevel) {
|
|
||||||
this.gson = gson;
|
|
||||||
logger = logLevel == null ? null : Logger.getLogger(RequestSender.class.getName());
|
|
||||||
this.logLevel = logLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void send(HttpURLConnection conn, WebServiceRequest request) {
|
|
||||||
try {
|
|
||||||
conn.setRequestMethod(request.getHttpMethod().toString());
|
|
||||||
setHeader(conn, "Content-Type", request.getContentType(), true);
|
|
||||||
|
|
||||||
// Assume conservatively that the response will need to be read.
|
|
||||||
// This is done here instead of in the response receiver because this property must be set
|
|
||||||
// before sending any data on the connection.
|
|
||||||
conn.setDoInput(true);
|
|
||||||
|
|
||||||
RequestBody requestBody = request.getBody();
|
|
||||||
String requestBodyContents = "";
|
|
||||||
// Android Java VM ignore Content-Length if setDoOutput is not set
|
|
||||||
conn.setDoOutput(true);
|
|
||||||
if (requestBody.getSpec().size() > 0) {
|
|
||||||
requestBodyContents = gson.toJson(requestBody);
|
|
||||||
}
|
|
||||||
String contentLength = String.valueOf(requestBodyContents.length());
|
|
||||||
setHeader(conn, "Content-Length", contentLength, true);
|
|
||||||
addRequestParams(conn, request.getHeaders());
|
|
||||||
Streams.copy(requestBodyContents, conn.getOutputStream(), false);
|
|
||||||
|
|
||||||
// Initiate the sending of the request.
|
|
||||||
conn.connect();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addRequestParams(HttpURLConnection conn, HeaderMap requestParams) {
|
|
||||||
HeaderMapSpec spec = requestParams.getSpec();
|
|
||||||
for (Map.Entry<String, Object> entry : requestParams.entrySet()) {
|
|
||||||
String paramName = entry.getKey();
|
|
||||||
Type type = spec.getTypeFor(paramName);
|
|
||||||
Object value = entry.getValue();
|
|
||||||
String json = gson.toJson(value, type);
|
|
||||||
setHeader(conn, paramName, json, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setHeader(HttpURLConnection conn, String name, String value, boolean overwrite) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.log(logLevel, String.format("Request param: %s:%s", name, value));
|
|
||||||
}
|
|
||||||
if (overwrite) {
|
|
||||||
conn.setRequestProperty(name, value);
|
|
||||||
} else {
|
|
||||||
conn.addRequestProperty(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceCall;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceCallSpec;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A client-supplied callback to be used with {@link WebServiceClientAsync}. When a web-service
|
|
||||||
* call is executed asynchronously, this callback is invoked with the results.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public interface ResponseCallback {
|
|
||||||
public void handleResponse(WebServiceCall call);
|
|
||||||
public void handleError(WebServiceSystemException e, WebServiceRequest request,
|
|
||||||
WebServiceCallSpec callSpec);
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2008 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.HeaderMap;
|
|
||||||
import com.google.greaze.definition.HeaderMapSpec;
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.webservice.ResponseBody;
|
|
||||||
import com.google.greaze.definition.webservice.ResponseBodySpec;
|
|
||||||
import com.google.greaze.definition.webservice.ResponseSpec;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceResponse;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.wsclient.internal.utils.ConnectionPreconditions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives a response coming on an {@link HttpURLConnection}.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public final class ResponseReceiver {
|
|
||||||
private final Gson gson;
|
|
||||||
private final ResponseSpec spec;
|
|
||||||
private final Logger logger;
|
|
||||||
private final Level logLevel;
|
|
||||||
|
|
||||||
public ResponseReceiver(Gson gson, ResponseSpec spec) {
|
|
||||||
this(gson, spec, null);
|
|
||||||
}
|
|
||||||
public ResponseReceiver(Gson gson, ResponseSpec spec, Level logLevel) {
|
|
||||||
this.gson = gson;
|
|
||||||
this.spec = spec;
|
|
||||||
this.logger = logLevel == null ? null : Logger.getLogger(ResponseReceiver.class.getName());
|
|
||||||
this.logLevel = logLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebServiceResponse receive(HttpURLConnection conn) {
|
|
||||||
try {
|
|
||||||
HeaderMapSpec paramSpec = spec.getHeadersSpec();
|
|
||||||
ResponseBodySpec bodySpec = spec.getBodySpec();
|
|
||||||
// read response
|
|
||||||
HeaderMap responseParams = readResponseHeaders(conn, paramSpec);
|
|
||||||
ResponseBody responseBody = readResponseBody(conn, bodySpec);
|
|
||||||
return new WebServiceResponse(responseParams, responseBody);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private HeaderMap readResponseHeaders(HttpURLConnection conn, HeaderMapSpec paramsSpec) {
|
|
||||||
HeaderMap.Builder paramsBuilder = new HeaderMap.Builder(paramsSpec);
|
|
||||||
for (Map.Entry<String, Type> entry : paramsSpec.entrySet()) {
|
|
||||||
String paramName = entry.getKey();
|
|
||||||
String json = conn.getHeaderField(paramName);
|
|
||||||
if (json != null) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.log(logLevel, String.format("Response Header: %s:%s\n", paramName, json));
|
|
||||||
}
|
|
||||||
Type typeOfT = paramsSpec.getTypeFor(paramName);
|
|
||||||
Object value = gson.fromJson(json, typeOfT);
|
|
||||||
paramsBuilder.put(paramName, value, typeOfT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return paramsBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResponseBody readResponseBody(HttpURLConnection conn, ResponseBodySpec bodySpec)
|
|
||||||
throws IOException {
|
|
||||||
if (bodySpec.size() == 0) {
|
|
||||||
return new ResponseBody.Builder(bodySpec).build();
|
|
||||||
}
|
|
||||||
String connContentType = conn.getContentType();
|
|
||||||
ConnectionPreconditions.checkArgument(connContentType.contains(bodySpec.getContentType()), conn);
|
|
||||||
Reader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
|
||||||
ResponseBody body = gson.fromJson(reader, ResponseBody.class);
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2008 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration needed to access a Gson web service.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public final class ServerConfig {
|
|
||||||
private final String serviceBaseUrl;
|
|
||||||
|
|
||||||
public ServerConfig(String serviceBaseUrl) {
|
|
||||||
this.serviceBaseUrl = serviceBaseUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getServiceBaseUrl() {
|
|
||||||
return serviceBaseUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return serviceBaseUrl;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An executor that uses a single thread to execute all calls
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
final class SingleThreadExecutor implements TaskExecutor {
|
|
||||||
private ExecutorService executor;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable r) {
|
|
||||||
executor = Executors.newSingleThreadExecutor();
|
|
||||||
executor.execute(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdownNow() {
|
|
||||||
executor.shutdownNow();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An {@link Executor} with an additional method for shutdown. We could have just used
|
|
||||||
* {@link java.util.concurrent.ExecutorService}, however, that requires too many methods to be
|
|
||||||
* implemented.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
interface TaskExecutor extends Executor {
|
|
||||||
public void shutdownNow();
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An executor that uses a new thread to execute each call
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
final class ThreadPerTaskExecutor implements TaskExecutor {
|
|
||||||
private Thread thread;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable r) {
|
|
||||||
thread = new Thread(r);
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdownNow() {
|
|
||||||
if (thread != null) {
|
|
||||||
thread.interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2008 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.webservice.ResponseBody;
|
|
||||||
import com.google.greaze.definition.webservice.ResponseBodyGsonConverter;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceCallSpec;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceRequest;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceResponse;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main class used by clients to access a Gson Web service.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public class WebServiceClient {
|
|
||||||
private final ServerConfig config;
|
|
||||||
private final Logger logger;
|
|
||||||
private final Level logLevel;
|
|
||||||
|
|
||||||
public WebServiceClient(ServerConfig serverConfig) {
|
|
||||||
this(serverConfig, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebServiceClient(ServerConfig serverConfig, Level logLevel) {
|
|
||||||
this.config = serverConfig;
|
|
||||||
this.logger = logLevel == null ? null : Logger.getLogger(WebServiceClient.class.getName());
|
|
||||||
this.logLevel = logLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private URL getWebServiceUrl(WebServiceCallSpec callSpec) {
|
|
||||||
String url = config.getServiceBaseUrl() + callSpec.getPath().get();
|
|
||||||
try {
|
|
||||||
return new URL(url);
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebServiceResponse getResponse(WebServiceCallSpec callSpec, WebServiceRequest request) {
|
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(ResponseBody.class,
|
|
||||||
new ResponseBodyGsonConverter(callSpec.getResponseSpec().getBodySpec()))
|
|
||||||
.create();
|
|
||||||
return getResponse(callSpec, request, gson);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebServiceResponse getResponse(
|
|
||||||
WebServiceCallSpec callSpec, WebServiceRequest request, Gson gson) {
|
|
||||||
try {
|
|
||||||
URL webServiceUrl = getWebServiceUrl(callSpec);
|
|
||||||
if (logger != null) {
|
|
||||||
logger.log(logLevel, "Opening connection to " + webServiceUrl);
|
|
||||||
}
|
|
||||||
HttpURLConnection conn = (HttpURLConnection) webServiceUrl.openConnection();
|
|
||||||
RequestSender requestSender = new RequestSender(gson, logLevel);
|
|
||||||
requestSender.send(conn, request);
|
|
||||||
ResponseReceiver responseReceiver =
|
|
||||||
new ResponseReceiver(gson, callSpec.getResponseSpec(), logLevel);
|
|
||||||
return responseReceiver.receive(conn);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("config:%s", config);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.webservice.client;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import com.google.greaze.definition.WebServiceSystemException;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceCallSpec;
|
|
||||||
import com.google.greaze.definition.webservice.WebServiceRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A client for invoking a JSON-based Web-service in an asynchronous manner. The call is queued,
|
|
||||||
* and control returns to the caller. A separate thread executes the call, and invokes the
|
|
||||||
* client-supplied callback with results.
|
|
||||||
*
|
|
||||||
* @author inder
|
|
||||||
*/
|
|
||||||
public class WebServiceClientAsync {
|
|
||||||
|
|
||||||
private final BlockingQueue<QueueEntry> queue;
|
|
||||||
private final boolean threadPerTask;
|
|
||||||
private final TaskExecutor executor;
|
|
||||||
|
|
||||||
public WebServiceClientAsync(ServerConfig serverConfig) {
|
|
||||||
this(serverConfig, null);
|
|
||||||
}
|
|
||||||
public WebServiceClientAsync(ServerConfig serverConfig, Level logLevel) {
|
|
||||||
this(new WebServiceClient(serverConfig, logLevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebServiceClientAsync(WebServiceClient client) {
|
|
||||||
queue = new LinkedBlockingQueue<QueueEntry>();
|
|
||||||
this.threadPerTask = true;
|
|
||||||
QueueConsumer consumer = new QueueConsumer(queue, client);
|
|
||||||
executor = getExecutor();
|
|
||||||
executor.execute(consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TaskExecutor getExecutor() {
|
|
||||||
return threadPerTask ? new ThreadPerTaskExecutor() : new SingleThreadExecutor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void callAsync(WebServiceCallSpec callSpec, WebServiceRequest request,
|
|
||||||
ResponseCallback responseCallback) {
|
|
||||||
try {
|
|
||||||
queue.put(new QueueEntry(callSpec, request, responseCallback));
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new WebServiceSystemException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutdownNow() {
|
|
||||||
executor.shutdownNow();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.wsclient.internal.utils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
public final class ConnectionPreconditions {
|
|
||||||
|
|
||||||
public static void checkArgument(boolean condition, HttpURLConnection conn) {
|
|
||||||
if (!condition) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
try {
|
|
||||||
sb.append("HttpURLConnection Details\n");
|
|
||||||
sb.append("ResponseCode:" + conn.getResponseCode());
|
|
||||||
sb.append(", ContentType: " + conn.getContentType() + "\n");
|
|
||||||
Map<String, List<String>> headerFields = conn.getHeaderFields();
|
|
||||||
for (Entry<String, List<String>> header : headerFields.entrySet()) {
|
|
||||||
sb.append(header.getKey()).append(":");
|
|
||||||
boolean first = true;
|
|
||||||
for (String value : header.getValue()) {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
sb.append(",");
|
|
||||||
}
|
|
||||||
sb.append(value);
|
|
||||||
}
|
|
||||||
sb.append("\n");
|
|
||||||
}
|
|
||||||
byte[] data = readInByteArray(conn.getInputStream());
|
|
||||||
sb.append(new String(data));
|
|
||||||
} catch (IOException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException(sb.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] readInByteArray(InputStream src) {
|
|
||||||
ByteArrayOutputStream dst = new ByteArrayOutputStream();
|
|
||||||
try {
|
|
||||||
Streams.copy(src, dst, true, true);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
return dst.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConnectionPreconditions() {
|
|
||||||
// prevent instantiation
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.gson.wsclient.internal.utils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
public final class Streams {
|
|
||||||
|
|
||||||
public static void copy(String str, OutputStream dst, boolean closeOutput) throws IOException {
|
|
||||||
byte[] bytes = str.getBytes("UTF-8");
|
|
||||||
copy(new ByteArrayInputStream(bytes), dst, true, closeOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy contents of src to dst. Exhausts src completely, and closes both streams.
|
|
||||||
*/
|
|
||||||
public static void copy(InputStream src, OutputStream dst, boolean closeInput,
|
|
||||||
boolean closeOutput) throws IOException {
|
|
||||||
try {
|
|
||||||
final byte[] buf = new byte[2048];
|
|
||||||
int count;
|
|
||||||
while ((count = src.read(buf)) != -1) {
|
|
||||||
dst.write(buf, 0, count);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (closeInput) src.close();
|
|
||||||
if (closeOutput) dst.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Streams() {
|
|
||||||
// Prevent instantiation
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,13 +21,13 @@ import com.google.greaze.definition.webservice.RequestBody;
|
||||||
import com.google.greaze.definition.webservice.WebServiceCallSpec;
|
import com.google.greaze.definition.webservice.WebServiceCallSpec;
|
||||||
import com.google.greaze.definition.webservice.WebServiceRequest;
|
import com.google.greaze.definition.webservice.WebServiceRequest;
|
||||||
import com.google.greaze.definition.webservice.WebServiceResponse;
|
import com.google.greaze.definition.webservice.WebServiceResponse;
|
||||||
|
import com.google.greaze.webservice.client.ServerConfig;
|
||||||
|
import com.google.greaze.webservice.client.WebServiceClient;
|
||||||
import com.google.gson.example.model.Cart;
|
import com.google.gson.example.model.Cart;
|
||||||
import com.google.gson.example.model.LineItem;
|
import com.google.gson.example.model.LineItem;
|
||||||
import com.google.gson.example.model.Order;
|
import com.google.gson.example.model.Order;
|
||||||
import com.google.gson.example.model.TypedKeys;
|
import com.google.gson.example.model.TypedKeys;
|
||||||
import com.google.gson.example.service.SampleJsonService;
|
import com.google.gson.example.service.SampleJsonService;
|
||||||
import com.google.gson.webservice.client.ServerConfig;
|
|
||||||
import com.google.gson.webservice.client.WebServiceClient;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -16,16 +16,16 @@
|
||||||
|
|
||||||
import com.google.greaze.definition.CallPath;
|
import com.google.greaze.definition.CallPath;
|
||||||
import com.google.greaze.definition.rest.ValueBasedId;
|
import com.google.greaze.definition.rest.ValueBasedId;
|
||||||
|
import com.google.greaze.rest.client.ResourceDepotClient;
|
||||||
|
import com.google.greaze.rest.client.RestClientStub;
|
||||||
|
import com.google.greaze.rest.query.client.ResourceQueryClient;
|
||||||
|
import com.google.greaze.webservice.client.ServerConfig;
|
||||||
|
import com.google.greaze.webservice.client.WebServiceClient;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.example.model.Cart;
|
import com.google.gson.example.model.Cart;
|
||||||
import com.google.gson.example.model.LineItem;
|
import com.google.gson.example.model.LineItem;
|
||||||
import com.google.gson.example.model.Order;
|
import com.google.gson.example.model.Order;
|
||||||
import com.google.gson.example.model.QueryOrdersByItemName;
|
import com.google.gson.example.model.QueryOrdersByItemName;
|
||||||
import com.google.gson.rest.client.ResourceDepotClient;
|
|
||||||
import com.google.gson.rest.client.RestClientStub;
|
|
||||||
import com.google.gson.rest.query.client.ResourceQueryClient;
|
|
||||||
import com.google.gson.webservice.client.ServerConfig;
|
|
||||||
import com.google.gson.webservice.client.WebServiceClient;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user