Added means to define and implement REST web-service and its clients.
Added missing copyright headers. Added TypedKey based methods in request/response classes.
This commit is contained in:
parent
1925fb966c
commit
ad0e0d6f54
@ -32,6 +32,7 @@ import com.google.gson.webservice.definition.ResponseBody;
|
||||
import com.google.gson.webservice.definition.ResponseBodySpec;
|
||||
import com.google.gson.webservice.definition.ResponseSpec;
|
||||
import com.google.gson.webservice.definition.WebServiceResponse;
|
||||
import com.google.gson.webservice.definition.WebServiceSystemException;
|
||||
|
||||
/**
|
||||
* Receives a response coming on an {@link HttpURLConnection}.
|
||||
@ -63,7 +64,7 @@ public final class ResponseReceiver {
|
||||
ResponseBody responseBody = readResponseBody(conn, bodySpec);
|
||||
return new WebServiceResponse(responseParams, responseBody);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new WebServiceSystemException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.webservice.definition.WebServiceSystemException;
|
||||
import com.google.gson.webservice.definition.rest.RestCallSpec;
|
||||
import com.google.gson.webservice.definition.rest.RestRequest;
|
||||
import com.google.gson.webservice.definition.rest.RestResponse;
|
||||
|
||||
/**
|
||||
* Main class used by clients to access a Gson Web service.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestClient {
|
||||
private final WebServiceConfig config;
|
||||
private final Logger logger;
|
||||
private final Level logLevel;
|
||||
|
||||
public RestClient(WebServiceConfig serverConfig) {
|
||||
this(serverConfig, null);
|
||||
}
|
||||
|
||||
public RestClient(WebServiceConfig serverConfig, Level logLevel) {
|
||||
this.config = serverConfig;
|
||||
this.logger = logLevel == null ? null : Logger.getLogger(RestClient.class.getName());
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
private URL getWebServiceUrl(RestCallSpec<?> callSpec) {
|
||||
String url = config.getServiceBaseUrl() + callSpec.getPath().get();
|
||||
try {
|
||||
return new URL(url);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public <R> RestResponse<R> getResponse(RestCallSpec<R> callSpec, RestRequest<R> request) {
|
||||
Gson gson = new GsonBuilder().create();
|
||||
return getResponse(callSpec, request, gson);
|
||||
}
|
||||
|
||||
public <R> RestResponse<R> getResponse(
|
||||
RestCallSpec<R> callSpec, RestRequest<R> request, Gson gson) {
|
||||
try {
|
||||
URL webServiceUrl = getWebServiceUrl(callSpec);
|
||||
if (logger != null) {
|
||||
logger.log(logLevel, "Opening connection to " + webServiceUrl);
|
||||
}
|
||||
HttpURLConnection conn = (HttpURLConnection) webServiceUrl.openConnection();
|
||||
RestRequestSender requestSender = new RestRequestSender(gson, logLevel);
|
||||
requestSender.send(conn, request);
|
||||
RestResponseReceiver<R> responseReceiver =
|
||||
new RestResponseReceiver<R>(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);
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.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.gson.Gson;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
import com.google.gson.webservice.definition.WebServiceSystemException;
|
||||
import com.google.gson.webservice.definition.rest.RestRequest;
|
||||
|
||||
/**
|
||||
* Class to send Web service requests on a {@link HttpURLConnection}.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestRequestSender {
|
||||
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 <R> void send(HttpURLConnection conn, RestRequest<R> 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);
|
||||
|
||||
R requestBody = request.getBody();
|
||||
String requestBodyContents = "";
|
||||
// Android Java VM ignore Content-Length if setDoOutput is not set
|
||||
conn.setDoOutput(true);
|
||||
if (requestBody != null) {
|
||||
requestBodyContents = gson.toJson(requestBody);
|
||||
}
|
||||
String contentLength = String.valueOf(requestBodyContents.length());
|
||||
setHeader(conn, "Content-Length", contentLength, true);
|
||||
addRequestParams(conn, request.getHeaders());
|
||||
if (requestBodyContents != null) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.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.gson.Gson;
|
||||
import com.google.gson.webservice.definition.ContentBodySpec;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
import com.google.gson.webservice.definition.WebServiceSystemException;
|
||||
import com.google.gson.webservice.definition.rest.RestResponse;
|
||||
import com.google.gson.webservice.definition.rest.RestResponseSpec;
|
||||
|
||||
/**
|
||||
* Receives a response coming on an {@link HttpURLConnection}.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestResponseReceiver<R> {
|
||||
private final Gson gson;
|
||||
private final RestResponseSpec<R> spec;
|
||||
private final Logger logger;
|
||||
private final Level logLevel;
|
||||
|
||||
public RestResponseReceiver(Gson gson, RestResponseSpec<R> spec) {
|
||||
this(gson, spec, null);
|
||||
}
|
||||
public RestResponseReceiver(Gson gson, RestResponseSpec<R> spec, Level logLevel) {
|
||||
this.gson = gson;
|
||||
this.spec = spec;
|
||||
this.logger = logLevel == null ? null : Logger.getLogger(RestResponseReceiver.class.getName());
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
public RestResponse<R> receive(HttpURLConnection conn) {
|
||||
try {
|
||||
HeaderMapSpec paramSpec = spec.getHeadersSpec();
|
||||
Class<R> bodySpec = spec.getResourceClass();
|
||||
// read response
|
||||
HeaderMap responseParams = readResponseHeaders(conn, paramSpec);
|
||||
R responseBody = readResponseBody(conn, bodySpec);
|
||||
return new RestResponse<R>(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 R readResponseBody(HttpURLConnection conn, Class<R> resourceClass) throws IOException {
|
||||
String connContentType = conn.getContentType();
|
||||
Preconditions.checkArgument(connContentType.contains(ContentBodySpec.JSON_CONTENT_TYPE), conn);
|
||||
Reader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
R body = gson.fromJson(reader, resourceClass);
|
||||
return body;
|
||||
}
|
||||
}
|
@ -25,10 +25,10 @@ import java.util.Set;
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
class ContentBodySpec implements ParamMapSpec {
|
||||
public class ContentBodySpec implements ParamMapSpec {
|
||||
|
||||
public static final String JSON_CONTENT_TYPE = "application/json";
|
||||
private static final String JSON_CHARACTER_ENCODING = "utf-8";
|
||||
public static final String JSON_CHARACTER_ENCODING = "utf-8";
|
||||
|
||||
private final Map<String, Type> paramsSpec;
|
||||
|
||||
|
@ -15,6 +15,10 @@
|
||||
*/
|
||||
package com.google.gson.webservice.definition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An enum of Http methods to provide strongly-typed versions instead of strings.
|
||||
*
|
||||
@ -29,4 +33,7 @@ public enum HttpMethod {
|
||||
public static HttpMethod getMethod(String method) {
|
||||
return valueOf(method.trim().toUpperCase());
|
||||
}
|
||||
|
||||
public static final List<HttpMethod> ALL_METHODS =
|
||||
Collections.unmodifiableList(Arrays.asList(values()));
|
||||
}
|
@ -1,5 +1,27 @@
|
||||
/*
|
||||
* 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.definition;
|
||||
|
||||
/**
|
||||
* A typed key for use in a {@link ParamMap} or a {@link ParamMapSpec}.
|
||||
*
|
||||
* @author inder
|
||||
*
|
||||
* @param <T> Intended type of the content for the key
|
||||
*/
|
||||
public class TypedKey<T> {
|
||||
private final String name;
|
||||
private final Class<T> classOfT;
|
||||
|
@ -50,6 +50,10 @@ public final class WebServiceResponse {
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> Builder putBody(TypedKey<T> paramName, T content) {
|
||||
return putBody(paramName.getName(), content);
|
||||
}
|
||||
|
||||
public Builder putBody(String paramName, Object content) {
|
||||
body.put(paramName, content);
|
||||
return this;
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
final class Preconditions {
|
||||
|
||||
public static void checkArgument(boolean condition) {
|
||||
if (!condition) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkNotNull(Object obj) {
|
||||
if (obj == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.webservice.definition.CallPath;
|
||||
|
||||
/**
|
||||
* A {@link Map} of {@link CallPath} to {@link RestCallSpec}
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class ResourceMap {
|
||||
|
||||
public static final class Builder {
|
||||
private final Map<CallPath, RestCallSpec<?>> resources =
|
||||
new HashMap<CallPath, RestCallSpec<?>>();
|
||||
|
||||
public <R> Builder set(CallPath callPath, RestCallSpec<R> spec) {
|
||||
resources.put(callPath, spec);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResourceMap build() {
|
||||
return new ResourceMap(resources);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<CallPath, RestCallSpec<?>> resources;
|
||||
|
||||
public ResourceMap(Map<CallPath, RestCallSpec<?>> resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
public <T> RestCallSpec<T> get(CallPath callPath) {
|
||||
@SuppressWarnings("unchecked")
|
||||
RestCallSpec<T> restCallSpec = (RestCallSpec<T>)resources.get(callPath);
|
||||
return restCallSpec;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
/**
|
||||
* The data associated with a Rest Web service call. This includes http request header parameters
|
||||
* (form and URL parameters), request body, response header parameters, and resource response body.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestCall<R> {
|
||||
|
||||
private final RestCallSpec<R> callSpec;
|
||||
private final RestRequest<R> request;
|
||||
private final RestResponse<R> response;
|
||||
|
||||
public RestCall(RestCallSpec<R> callSpec, RestRequest<R> request, RestResponse<R> response) {
|
||||
this.callSpec = callSpec;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public RestCallSpec<R> getSpec() {
|
||||
return callSpec;
|
||||
}
|
||||
|
||||
public RestRequest<R> getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public RestResponse<R> getResponse() {
|
||||
return response;
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.webservice.definition.CallPath;
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
import com.google.gson.webservice.definition.HttpMethod;
|
||||
import com.google.gson.webservice.definition.TypedKey;
|
||||
|
||||
/**
|
||||
* Specification for a REST service
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestCallSpec<R> {
|
||||
public static class Builder<R> {
|
||||
private final CallPath callPath;
|
||||
private final Set<HttpMethod> supportedHttpMethods = new LinkedHashSet<HttpMethod>();
|
||||
private final HeaderMapSpec.Builder reqParamsSpecBuilder = new HeaderMapSpec.Builder();
|
||||
private final HeaderMapSpec.Builder resParamsSpecBuilder = new HeaderMapSpec.Builder();
|
||||
private final Class<R> resourceClass;
|
||||
|
||||
public Builder(CallPath callPath, Class<R> resourceClass) {
|
||||
this.callPath = callPath;
|
||||
supportedHttpMethods.addAll(HttpMethod.ALL_METHODS);
|
||||
this.resourceClass = resourceClass;
|
||||
}
|
||||
|
||||
public Builder<R> disableHttpMethod(HttpMethod httpMethod) {
|
||||
supportedHttpMethods.remove(httpMethod);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> Builder<R> addRequestParam(TypedKey<T> paramKey, Class<T> typeOfParam) {
|
||||
reqParamsSpecBuilder.put(paramKey.getName(), typeOfParam);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> Builder<R> addResponseParam(TypedKey<T> paramKey, Class<T> typeOfParam) {
|
||||
resParamsSpecBuilder.put(paramKey.getName(), typeOfParam);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestCallSpec<R> build() {
|
||||
if (supportedHttpMethods.isEmpty()) {
|
||||
supportedHttpMethods.addAll(Arrays.asList(HttpMethod.values()));
|
||||
}
|
||||
RestRequestSpec<R> requestSpec =
|
||||
new RestRequestSpec<R>(reqParamsSpecBuilder.build(), resourceClass);
|
||||
RestResponseSpec<R> responseSpec =
|
||||
new RestResponseSpec<R>(resParamsSpecBuilder.build(), resourceClass);
|
||||
return new RestCallSpec<R>(supportedHttpMethods, callPath,
|
||||
requestSpec, responseSpec);
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<HttpMethod> supportedHttpMethods;
|
||||
private final CallPath path;
|
||||
private final RestRequestSpec<R> requestSpec;
|
||||
private final RestResponseSpec<R> responseSpec;
|
||||
|
||||
private RestCallSpec(Set<HttpMethod> supportedHttpMethods, CallPath path,
|
||||
RestRequestSpec<R> requestSpec, RestResponseSpec<R> responseSpec) {
|
||||
Preconditions.checkArgument(!supportedHttpMethods.isEmpty());
|
||||
Preconditions.checkNotNull(path);
|
||||
this.supportedHttpMethods = supportedHttpMethods;
|
||||
this.path = path;
|
||||
this.requestSpec = requestSpec;
|
||||
this.responseSpec = responseSpec;
|
||||
}
|
||||
|
||||
public CallPath getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public Set<HttpMethod> getSupportedHttpMethods() {
|
||||
return supportedHttpMethods;
|
||||
}
|
||||
|
||||
public RestResponseSpec<R> getResponseSpec() {
|
||||
return responseSpec;
|
||||
}
|
||||
|
||||
public RestRequestSpec<R> getRequestSpec() {
|
||||
return requestSpec;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
import com.google.gson.webservice.definition.ContentBodySpec;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.HttpMethod;
|
||||
import com.google.gson.webservice.definition.RequestBody;
|
||||
|
||||
/**
|
||||
* The data associated with a Web service request. This includes HTTP request header parameters
|
||||
* (form and URL parameters), and {@link RequestBody}.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestRequest<R> {
|
||||
private final HttpMethod method;
|
||||
private final HeaderMap headers;
|
||||
private final R body;
|
||||
private final RestRequestSpec<R> spec;
|
||||
|
||||
public RestRequest(HttpMethod method, HeaderMap requestHeaders,
|
||||
R requestBody, Class<R> resourceClass) {
|
||||
this.method = method;
|
||||
this.body = requestBody;
|
||||
this.headers = requestHeaders;
|
||||
this.spec = new RestRequestSpec<R>(requestHeaders.getSpec(), resourceClass);
|
||||
}
|
||||
|
||||
public HttpMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public RestRequestSpec<R> getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
public HttpMethod getHttpMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public R getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public HeaderMap getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return ContentBodySpec.JSON_CONTENT_TYPE;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getHeader(String headerName) {
|
||||
return (T) headers.get(headerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{method:%s,headers:%s,body:%s}", method, headers, body);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
|
||||
/**
|
||||
* Specification for a {@link RestRequest}.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestRequestSpec<R> {
|
||||
private final HeaderMapSpec headersSpec;
|
||||
private final Class<R> resourceClass;
|
||||
|
||||
public RestRequestSpec(HeaderMapSpec headersSpec, Class<R> resourceClass) {
|
||||
this.headersSpec = headersSpec;
|
||||
this.resourceClass = resourceClass;
|
||||
}
|
||||
|
||||
public Class<R> getResourceClass() {
|
||||
return resourceClass;
|
||||
}
|
||||
|
||||
public HeaderMapSpec getHeadersSpec() {
|
||||
return headersSpec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{headersSpec:%s,resourceClass:%s}", headersSpec, resourceClass);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.TypedKey;
|
||||
|
||||
/**
|
||||
* The data associated with a REST Web service response. This includes http response header
|
||||
* parameters, and the response body.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestResponse<R> {
|
||||
|
||||
private final HeaderMap headers;
|
||||
private final R body;
|
||||
private final RestResponseSpec<R> spec;
|
||||
|
||||
public static class Builder<R> {
|
||||
private final HeaderMap.Builder headers;
|
||||
private R body;
|
||||
private final RestResponseSpec<R> spec;
|
||||
|
||||
public Builder(RestResponseSpec<R> spec) {
|
||||
this.spec = spec;
|
||||
headers = new HeaderMap.Builder(spec.getHeadersSpec());
|
||||
}
|
||||
|
||||
public <T> Builder<R> putHeader(TypedKey<T> paramName, T content) {
|
||||
headers.put(paramName.getName(), content, paramName.getClassOfT());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<R> setBody(R body) {
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestResponse<R> build() {
|
||||
return new RestResponse<R>(spec, headers.build(), body);
|
||||
}
|
||||
}
|
||||
|
||||
private RestResponse(RestResponseSpec<R> spec, HeaderMap headers, R body) {
|
||||
this.spec = spec;
|
||||
this.headers = headers;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public RestResponse(HeaderMap responseHeaders, R responseBody) {
|
||||
this.spec = new RestResponseSpec<R>(responseHeaders.getSpec(),
|
||||
(Class<R>)responseBody.getClass());
|
||||
this.headers = responseHeaders;
|
||||
this.body = responseBody;
|
||||
}
|
||||
|
||||
public RestResponseSpec<R> getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
public HeaderMap getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public R getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getHeader(String headerName) {
|
||||
return (T) headers.get(headerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{headers:%s, body:%s}", headers, body);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.definition.rest;
|
||||
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
|
||||
/**
|
||||
* Specification for a {@link RestResponse}.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestResponseSpec<R> {
|
||||
private final HeaderMapSpec headersSpec;
|
||||
private final Class<R> resourceClass;
|
||||
|
||||
public RestResponseSpec(HeaderMapSpec headersSpec, Class<R> resourceClass) {
|
||||
this.headersSpec = headersSpec;
|
||||
this.resourceClass = resourceClass;
|
||||
}
|
||||
|
||||
public Class<R> getResourceClass() {
|
||||
return resourceClass;
|
||||
}
|
||||
|
||||
public HeaderMapSpec getHeadersSpec() {
|
||||
return headersSpec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{headersSpec:%s,resourceClass:%s}", headersSpec, resourceClass);
|
||||
}
|
||||
}
|
@ -26,7 +26,6 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
import com.google.gson.webservice.definition.ResponseBody;
|
||||
import com.google.gson.webservice.definition.ResponseBodySpec;
|
||||
import com.google.gson.webservice.definition.WebServiceResponse;
|
||||
|
||||
/**
|
||||
@ -45,7 +44,6 @@ public final class ResponseSender {
|
||||
|
||||
public void send(HttpServletResponse conn, WebServiceResponse response) {
|
||||
try {
|
||||
conn.setContentType(ResponseBodySpec.JSON_CONTENT_TYPE);
|
||||
sendHeaders(conn, response.getHeaders());
|
||||
sendBody(conn, response.getBody());
|
||||
} catch (IOException e) {
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.wsf.server.rest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
import com.google.gson.webservice.definition.HttpMethod;
|
||||
import com.google.gson.webservice.definition.WebServiceSystemException;
|
||||
import com.google.gson.webservice.definition.rest.RestRequest;
|
||||
import com.google.gson.webservice.definition.rest.RestRequestSpec;
|
||||
|
||||
/**
|
||||
* Receives and parses a request at the server side on a {@link HttpServletRequest}.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestRequestReceiver<R> {
|
||||
|
||||
private final Gson gson;
|
||||
private final RestRequestSpec<R> spec;
|
||||
|
||||
public RestRequestReceiver(Gson gson, RestRequestSpec<R> spec) {
|
||||
this.gson = gson;
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
public RestRequest<R> receive(HttpServletRequest request) {
|
||||
try {
|
||||
HeaderMap requestParams = buildRequestParams(request);
|
||||
R requestBody = buildRequestBody(request);
|
||||
|
||||
HttpMethod method = HttpMethod.getMethod(request.getMethod());
|
||||
return new RestRequest<R>(method, requestParams, requestBody, spec.getResourceClass());
|
||||
} catch (IOException e) {
|
||||
throw new WebServiceSystemException(e);
|
||||
} catch (JsonParseException e) {
|
||||
// Not a Web service request
|
||||
throw new WebServiceSystemException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private HeaderMap buildRequestParams(HttpServletRequest request) {
|
||||
HeaderMapSpec paramsSpec = this.spec.getHeadersSpec();
|
||||
HeaderMap.Builder paramsBuilder = new HeaderMap.Builder(paramsSpec);
|
||||
for (Map.Entry<String, Type> param : paramsSpec.entrySet()) {
|
||||
String name = param.getKey();
|
||||
Type type = param.getValue();
|
||||
String header = request.getHeader(name);
|
||||
if (header == null || header.equals("")) {
|
||||
// check parameter map for the value
|
||||
header = request.getParameter(name);
|
||||
}
|
||||
if (header != null && !header.equals("")) {
|
||||
Object value = gson.fromJson(header, type);
|
||||
paramsBuilder.put(name, value);
|
||||
}
|
||||
}
|
||||
return paramsBuilder.build();
|
||||
}
|
||||
|
||||
private R buildRequestBody(HttpServletRequest request) throws IOException {
|
||||
Class<R> resourceClass = spec.getResourceClass();
|
||||
Reader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
|
||||
R requestBody = gson.fromJson(reader, resourceClass);
|
||||
return requestBody;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.wsf.server.rest;
|
||||
|
||||
import com.google.gson.webservice.definition.rest.RestRequest;
|
||||
import com.google.gson.webservice.definition.rest.RestResponse;
|
||||
import com.google.gson.webservice.definition.rest.RestCallSpec;
|
||||
|
||||
public interface RestResponseBuilder<R> {
|
||||
public void buildResponse(RestCallSpec<R> callSpec, RestRequest<R> request,
|
||||
RestResponse.Builder<R> responseBuilder);
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.wsf.server.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.webservice.definition.ContentBodySpec;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||
import com.google.gson.webservice.definition.rest.RestResponse;
|
||||
|
||||
/**
|
||||
* Sends a JSON web service response on {@link HttpServletResponse}.
|
||||
*
|
||||
* @author inder
|
||||
*/
|
||||
public final class RestResponseSender<R> {
|
||||
private static final Logger logger = Logger.getLogger(RestResponseSender.class.getCanonicalName());
|
||||
|
||||
private Gson gson;
|
||||
|
||||
public RestResponseSender(Gson gson) {
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
public void send(HttpServletResponse conn, RestResponse<R> response) {
|
||||
try {
|
||||
sendHeaders(conn, response.getHeaders());
|
||||
sendBody(conn, response.getBody());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendHeaders(HttpServletResponse conn, HeaderMap responseParams) {
|
||||
HeaderMapSpec spec = responseParams.getSpec();
|
||||
for (Map.Entry<String, Object> param : responseParams.entrySet()) {
|
||||
String paramName = param.getKey();
|
||||
Object paramValue = param.getValue();
|
||||
Type paramType = spec.getTypeFor(paramName);
|
||||
String json = gson.toJson(paramValue, paramType);
|
||||
logger.fine("RESPONSE HEADER:{" + paramName + ", " + json + "}");
|
||||
conn.addHeader(paramName, json);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendBody(HttpServletResponse conn, R responseBody) throws IOException {
|
||||
conn.setContentType(ContentBodySpec.JSON_CONTENT_TYPE);
|
||||
conn.setCharacterEncoding(ContentBodySpec.JSON_CHARACTER_ENCODING);
|
||||
String json = gson.toJson(responseBody);
|
||||
logger.fine("RESPONSE BODY:" + json);
|
||||
conn.getWriter().append(json);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user