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:
Inderjeet Singh 2010-02-15 23:24:48 +00:00
parent 1925fb966c
commit ad0e0d6f54
20 changed files with 1011 additions and 5 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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()));
}

View File

@ -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;

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}