From 849612c50f60488095999c8a8240121ebea0c14d Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Mon, 1 Sep 2008 13:37:34 +0000 Subject: [PATCH] initial creation of the wsf project. --- wsf/pom.xml | 190 ++++++++++++++++++ .../java/com/google/gson/wsf/CallPath.java | 64 ++++++ .../java/com/google/gson/wsf/CallPathMap.java | 78 +++++++ .../java/com/google/gson/wsf/ContentBody.java | 83 ++++++++ .../com/google/gson/wsf/ContentBodySpec.java | 71 +++++++ .../java/com/google/gson/wsf/HeaderMap.java | 81 ++++++++ .../com/google/gson/wsf/HeaderMapSpec.java | 80 ++++++++ .../java/com/google/gson/wsf/HttpMethod.java | 32 +++ .../com/google/gson/wsf/ParamMapSpec.java | 40 ++++ .../java/com/google/gson/wsf/RequestBody.java | 67 ++++++ .../com/google/gson/wsf/RequestBodySpec.java | 46 +++++ .../java/com/google/gson/wsf/RequestSpec.java | 53 +++++ .../com/google/gson/wsf/ResponseBody.java | 53 +++++ .../com/google/gson/wsf/ResponseBodySpec.java | 46 +++++ .../com/google/gson/wsf/ResponseSpec.java | 52 +++++ .../java/com/google/gson/wsf/TypeUtils.java | 92 +++++++++ .../main/java/com/google/gson/wsf/Util.java | 75 +++++++ .../gson/wsf/WebServiceAppException.java | 37 ++++ .../com/google/gson/wsf/WebServiceCall.java | 48 +++++ .../google/gson/wsf/WebServiceCallSpec.java | 140 +++++++++++++ .../google/gson/wsf/WebServiceRequest.java | 75 +++++++ .../google/gson/wsf/WebServiceResponse.java | 67 ++++++ .../com/google/gson/wsf/WebServiceSpec.java | 26 +++ .../gson/wsf/WebServiceSystemException.java | 36 ++++ .../google/gson/wsf/client/RequestSender.java | 74 +++++++ .../gson/wsf/client/ResponseReceiver.java | 90 +++++++++ .../gson/wsf/client/WebServiceClient.java | 64 ++++++ .../gson/wsf/client/WebServiceConfig.java | 33 +++ .../gson/wsf/inject/CallPathProvider.java | 44 ++++ .../wsf/inject/RequestBodySpecProvider.java | 41 ++++ .../gson/wsf/inject/RequestSpecProvider.java | 41 ++++ .../wsf/inject/WebServiceCallProvider.java | 57 ++++++ .../inject/WebServiceCallSpecProvider.java | 43 ++++ .../gson/wsf/server/RequestReceiver.java | 101 ++++++++++ .../gson/wsf/server/ResponseSender.java | 73 +++++++ .../RequestBodyGsonConverter.java | 77 +++++++ .../ResponseBodyGsonConverter.java | 77 +++++++ 37 files changed, 2447 insertions(+) create mode 100755 wsf/pom.xml create mode 100644 wsf/src/main/java/com/google/gson/wsf/CallPath.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/CallPathMap.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/ContentBody.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/ContentBodySpec.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/HeaderMap.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/HeaderMapSpec.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/HttpMethod.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/ParamMapSpec.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/RequestBody.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/RequestBodySpec.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/RequestSpec.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/ResponseBody.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/ResponseBodySpec.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/ResponseSpec.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/TypeUtils.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/Util.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/WebServiceAppException.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/WebServiceCall.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/WebServiceCallSpec.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/WebServiceRequest.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/WebServiceResponse.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/WebServiceSpec.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/WebServiceSystemException.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/client/RequestSender.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/client/ResponseReceiver.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/client/WebServiceClient.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/client/WebServiceConfig.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/inject/CallPathProvider.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/inject/RequestBodySpecProvider.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/inject/RequestSpecProvider.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallProvider.java create mode 100755 wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallSpecProvider.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/server/RequestReceiver.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/server/ResponseSender.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/typeadapters/RequestBodyGsonConverter.java create mode 100644 wsf/src/main/java/com/google/gson/wsf/typeadapters/ResponseBodyGsonConverter.java diff --git a/wsf/pom.xml b/wsf/pom.xml new file mode 100755 index 00000000..4ecb24da --- /dev/null +++ b/wsf/pom.xml @@ -0,0 +1,190 @@ + + + + + 4.0.0 + com.google.code.gson + wsf + jar + 0.1 + Gson Web Service Framework + A Framework for JSON based Web-services + + + local.repo + file repository to svn + file://${basedir}/../../mavenrepo + + + + + gson + http://google-gson.googlecode.com/svn/mavenrepo + + true + + + true + + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + scm:svn:http://google-gson.googlecode.com/svn/trunk/wsf + scm:svn:https://google-gson.googlecode.com/svn/trunk/wsf + http://google-gson.codegoogle.com/svn/trunk/wsf + + + Google Code Issue Tracking + http://code.google.com/p/google-gson/issues/list + + + + + + + com.google.code.google-collections + google-collect + snapshot-20080530 + compile + + + + + com.google.code.gson + gson + 1.2 + compile + + + + + com.google.code.guice + guice + 1.0 + compile + + + + + javax.servlet + servlet-api + 2.4 + provided + + + + junit + junit + 3.8.2 + test + + + + + wsf + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.5.1 + + true + true + ../eclipse-ws + file:///${basedir}/../lib/gson-formatting-styles.xml + 1.5 + + + + org.mortbay.jetty + maven-jetty-plugin + 6.0.1 + + 10 + + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + http://java.sun.com/j2se/1.5.0/docs/api/ + + + + + org.apache.maven.plugins + maven-pmd-plugin + + 1.5 + + /rulesets/basic.xml + /rulesets/imports.xml + /rulesets/unusedcode.xml + /rulesets/finalizers.xml + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + config/maven_checks.xml + + + + org.codehaus.mojo + taglist-maven-plugin + + + TODO + @todo + FIXME + XXX + + + + + org.codehaus.mojo + cobertura-maven-plugin + + + clean + + clean + + + + + + org.apache.maven.plugins + maven-release-plugin + + -DenableCiProfile=true + + + + + diff --git a/wsf/src/main/java/com/google/gson/wsf/CallPath.java b/wsf/src/main/java/com/google/gson/wsf/CallPath.java new file mode 100644 index 00000000..dbed5ac9 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/CallPath.java @@ -0,0 +1,64 @@ +/* + * 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; + +/** + * Encapsulation of a Web service path that is sent by the client. + * + * @author inder + */ +public final class CallPath { + + private final String path; + + public CallPath(String path) { + this.path = path; + } + + public String get() { + return path; + } + + @Override + public int hashCode() { + return path.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + CallPath other = (CallPath) obj; + if (path == null && other.path != null) { + return false; + } else if (!path.equals(other.path)) { + return false; + } + return true; + } + + @Override + public String toString() { + return path; + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/CallPathMap.java b/wsf/src/main/java/com/google/gson/wsf/CallPathMap.java new file mode 100644 index 00000000..f7278855 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/CallPathMap.java @@ -0,0 +1,78 @@ +/* + * 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; + +import java.util.Map; + +import com.google.common.collect.Maps; + +/** + * A generic Map of calls with relative path where the call is available as the key. + * + * @author inder + * + * @param The target of the call path. + */ +public final class CallPathMap { + + public static class Builder { + private final Map contents = Maps.newHashMap(); + private final T nullValue; + + public Builder(T nullValue) { + this.nullValue = nullValue; + } + public Builder put(CallPath path, R content) { + contents.put(path, content); + return this; + } + + public CallPathMap create() { + return new CallPathMap(contents, nullValue); + } + } + + private final Map contents; + private final T nullValue; + + private CallPathMap(Map contents, T nullValue) { + this.contents = contents; + this.nullValue = nullValue; + } + + public T get(CallPath path) { + T content = contents.get(path); + return content == null ? nullValue : content; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{"); + boolean first = true; + for (Map.Entry entry : contents.entrySet()) { + if (first) { + first = false; + } else { + sb.append(","); + } + CallPath path = entry.getKey(); + sb.append(path.get()).append(":"); + sb.append(entry.getValue().toString()); + } + sb.append("}"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/wsf/src/main/java/com/google/gson/wsf/ContentBody.java b/wsf/src/main/java/com/google/gson/wsf/ContentBody.java new file mode 100755 index 00000000..57cbef8a --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/ContentBody.java @@ -0,0 +1,83 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; + +/** + * Body of a request or response. The body contains a map of name-value pairs. + * There is a {@link ContentBodySpec} associated with the body as well and only the name-value + * pairs consistent with the specification are permitted. + * + * @author inder + */ +class ContentBody { + + protected final ContentBodySpec spec; + protected final Map contents; + + ContentBody(ContentBodySpec spec) { + this.spec = spec; + this.contents = Maps.newLinkedHashMap(); + } + + ContentBody(ContentBodySpec spec, Map contents) { + this.spec = spec; + this.contents = contents; + } + + public ContentBodySpec getSpec() { + return spec; + } + + @SuppressWarnings("unchecked") + public T get(String key, Class classOfValue) { + Preconditions.checkArgument(spec.isCompatible(key, classOfValue)); + return (T) contents.get(key); + } + + @SuppressWarnings("unchecked") + public T get(String key, Type typeOfValue) { + Preconditions.checkArgument(spec.isCompatible(key, typeOfValue)); + return (T) contents.get(key); + } + + public Set> entrySet() { + return contents.entrySet(); + } + + public int size() { + return contents.size(); + } + + public String getContentType() { + return spec.getContentType(); + } + + public String getCharacterEncoding() { + return spec.getCharacterEncoding(); + } + + @Override + public String toString() { + return Util.toStringMap(contents); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/ContentBodySpec.java b/wsf/src/main/java/com/google/gson/wsf/ContentBodySpec.java new file mode 100755 index 00000000..18387884 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/ContentBodySpec.java @@ -0,0 +1,71 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * Base class for the specification of a {@link ContentBody}. + * + * @author inder + */ +class ContentBodySpec implements ParamMapSpec { + + public static final String JSON_CONTENT_TYPE = "application/json"; + private static final String JSON_CHARACTER_ENCODING = "utf-8"; + + private final Map paramsSpec; + + protected ContentBodySpec(Map paramsSpec) { + this.paramsSpec = Collections.unmodifiableMap(paramsSpec); + } + + public Type getTypeFor(String paramName) { + return paramsSpec.get(paramName); + } + + public boolean isCompatible(String paramName, Type type) { + return type.equals(getTypeFor(paramName)); + } + + public boolean isCompatible(String paramName, Object object) { + return isCompatible(paramName, object.getClass()); + } + + public Set> entrySet() { + return paramsSpec.entrySet(); + } + + public int size() { + return paramsSpec.size(); + } + + public String getContentType() { + return JSON_CONTENT_TYPE; + } + + public String getCharacterEncoding() { + return JSON_CHARACTER_ENCODING; + } + + @Override + public String toString() { + return Util.toStringMapKeys(paramsSpec); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/HeaderMap.java b/wsf/src/main/java/com/google/gson/wsf/HeaderMap.java new file mode 100755 index 00000000..db4ff6be --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/HeaderMap.java @@ -0,0 +1,81 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; + +/** + * Map of request or response header objects. There is a {@link HeaderMapSpec} associated with the + * map as well and only those headers are allowed that are consistent with the specification. + * + * @author inder + */ +public final class HeaderMap { + + private final Map contents; + private final HeaderMapSpec spec; + + public HeaderMap(HeaderMapSpec spec) { + this.spec = spec; + contents = Maps.newHashMap(); + } + + /** + * If paramValue is a generic type, use {@link #put(String, Object, Type)} instead. + * + * @param headerName + * @param headerValue + */ + public void put(String headerName, Object headerValue) { + Preconditions.checkArgument(spec.isCompatible(headerName, headerValue)); + contents.put(headerName, headerValue); + } + + public void put(String headerName, Object headerValue, Type typeOfHeaderValue) { + Preconditions.checkArgument(spec.isCompatible(headerName, typeOfHeaderValue)); + contents.put(headerName, headerValue); + } + + public HeaderMapSpec getSpec() { + return spec; + } + + public Object get(String headerName) { + return contents.get(headerName); + } + + public Type getSpec(String headerName) { + return spec.getTypeFor(headerName); + } + + public Set> entrySet() { + return contents.entrySet(); + } + + public int size() { + return contents.size(); + } + + @Override + public String toString() { + return Util.toStringMap(contents); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/HeaderMapSpec.java b/wsf/src/main/java/com/google/gson/wsf/HeaderMapSpec.java new file mode 100755 index 00000000..8b04537c --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/HeaderMapSpec.java @@ -0,0 +1,80 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.Maps; + +/** + * Specification of a header map for {@link HeaderMap}. + * + * @author inder + */ +public final class HeaderMapSpec implements ParamMapSpec { + + public static class Builder { + private final Map map = Maps.newLinkedHashMap(); + + public void put(String headerName, Type headerType) { + map.put(headerName, headerType); + } + + public HeaderMapSpec create() { + return new HeaderMapSpec(map); + } + } + private final Map map; + + private HeaderMapSpec(Map map) { + this.map = map; + } + + public Type getTypeFor(String headerName) { + return map.get(headerName); + } + + public Set> entrySet() { + return map.entrySet(); + } + + @Override + public boolean isCompatible(String headerName, Type targetType) { + Type typeOfHeader = getTypeFor(headerName); + if (typeOfHeader == null) { + return false; + } + Class rawClassOfHeader = TypeUtils.toRawClass(typeOfHeader); + Class rawClassOfTargetType = TypeUtils.toRawClass(targetType); + return rawClassOfHeader.isAssignableFrom(rawClassOfTargetType); + } + + public boolean isCompatible(String headerName, Object headerValue) { + return isCompatible(headerName, headerValue.getClass()); + } + + @Override + public String toString() { + return Util.toStringMapKeys(map); + } + + @Override + public int size() { + return map.size(); + } +} \ No newline at end of file diff --git a/wsf/src/main/java/com/google/gson/wsf/HttpMethod.java b/wsf/src/main/java/com/google/gson/wsf/HttpMethod.java new file mode 100644 index 00000000..e3e52c2f --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/HttpMethod.java @@ -0,0 +1,32 @@ +/* + * 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; + +/** + * An enum of Http methods to provide strongly-typed versions instead of strings. + * + * @author inder + */ +public enum HttpMethod { + GET, + POST, + PUT, + DELETE; + + public static HttpMethod getMethod(String method) { + return valueOf(method.trim().toUpperCase()); + } +} \ No newline at end of file diff --git a/wsf/src/main/java/com/google/gson/wsf/ParamMapSpec.java b/wsf/src/main/java/com/google/gson/wsf/ParamMapSpec.java new file mode 100644 index 00000000..59fd914c --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/ParamMapSpec.java @@ -0,0 +1,40 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; + +/** + * Specification of a parameter map. Both {@link ContentBody} and {@link HeaderMap} are + * parameter maps. + * + * @author inder + */ +interface ParamMapSpec { + + Type getTypeFor(String paramName); + + boolean isCompatible(String paramName, Type type); + + boolean isCompatible(String paramName, Object object); + + public Set> entrySet(); + + public int size(); + +} \ No newline at end of file diff --git a/wsf/src/main/java/com/google/gson/wsf/RequestBody.java b/wsf/src/main/java/com/google/gson/wsf/RequestBody.java new file mode 100644 index 00000000..56535907 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/RequestBody.java @@ -0,0 +1,67 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.google.inject.Inject; + +/** + * Definition of the request body of a {@link WebServiceCall}. The request body is what is sent out + * in the output stream of the request (for example, with + * {@link java.net.HttpURLConnection#getOutputStream()}) , and is read by the + * {@link javax.servlet.http.HttpServletRequest#getInputStream()}. + * + * @author inder + */ +public final class RequestBody extends ContentBody { + + public static class Builder { + private final Map contents = Maps.newLinkedHashMap(); + private final RequestBodySpec spec; + + @Inject + public Builder(RequestBodySpec spec) { + this.spec = spec; + } + + public Builder add(String paramName, Object content) { + return add(paramName, content, content.getClass()); + } + + public Builder add(String paramName, Object content, Type typeOfContent) { + spec.isCompatible(paramName, typeOfContent); + contents.put(paramName, content); + return this; + } + + public RequestBody create() { + RequestBody requestBody = new RequestBody(spec, contents); + return requestBody; + } + } + + public RequestBody(RequestBodySpec spec, Map contents) { + super(spec, contents); + } + + @Override + public RequestBodySpec getSpec() { + return (RequestBodySpec) spec; + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/RequestBodySpec.java b/wsf/src/main/java/com/google/gson/wsf/RequestBodySpec.java new file mode 100644 index 00000000..fe57f967 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/RequestBodySpec.java @@ -0,0 +1,46 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.google.common.collect.Maps; + +/** + * Specification of a {@link RequestBody}. + * + * @author inder + */ +public final class RequestBodySpec extends ContentBodySpec { + + public static class Builder { + private final Map paramsSpec = Maps.newLinkedHashMap(); + public Builder add(String paramName, Type type) { + paramsSpec.put(paramName, type); + return this; + } + + public RequestBodySpec create() { + RequestBodySpec spec = new RequestBodySpec(paramsSpec); + return spec; + } + } + + public RequestBodySpec(Map paramsSpec) { + super(paramsSpec); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/RequestSpec.java b/wsf/src/main/java/com/google/gson/wsf/RequestSpec.java new file mode 100644 index 00000000..41a2da3b --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/RequestSpec.java @@ -0,0 +1,53 @@ +/* + * 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; + +import com.google.common.base.Preconditions; + +/** + * Specification for a {@link WebServiceRequest}. + * + * @author inder + */ +public final class RequestSpec { + + private final HeaderMapSpec headersSpec; + private final RequestBodySpec bodySpec; + + public RequestSpec(HeaderMapSpec headersSpec, RequestBodySpec bodySpec) { + Preconditions.checkNotNull(headersSpec); + Preconditions.checkNotNull(bodySpec); + + this.headersSpec = headersSpec; + this.bodySpec = bodySpec; + } + + public HeaderMapSpec getHeadersSpec() { + return headersSpec; + } + + public RequestBodySpec getBodySpec() { + return bodySpec; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{headersSpec:"); + sb.append(headersSpec).append(",bodySpec:"); + sb.append(bodySpec).append("}"); + return sb.toString(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/ResponseBody.java b/wsf/src/main/java/com/google/gson/wsf/ResponseBody.java new file mode 100644 index 00000000..eea11d28 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/ResponseBody.java @@ -0,0 +1,53 @@ +/* + * 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; + +import java.lang.reflect.Type; + +import com.google.common.base.Preconditions; + +/** + * body of the response. This is written out as JSON to be sent out to the client. + * + * @author inder + */ +public final class ResponseBody extends ContentBody { + + public ResponseBody(ResponseBodySpec spec) { + super(spec); + } + + @Override + public ResponseBodySpec getSpec() { + return (ResponseBodySpec) spec; + } + + /** + * If value is a generic type, use {@link #put(String, Object, Type)} instead. + * + * @param key + * @param value + */ + public void put(String key, Object value) { + put(key, value, value.getClass()); + } + + public void put(String key, Object value, Type typeOfValue) { + Type expectedType = spec.getTypeFor(key); + Preconditions.checkArgument(Util.isAssignableFrom(typeOfValue, expectedType)); + contents.put(key, value); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/ResponseBodySpec.java b/wsf/src/main/java/com/google/gson/wsf/ResponseBodySpec.java new file mode 100644 index 00000000..742a2733 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/ResponseBodySpec.java @@ -0,0 +1,46 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.google.common.collect.Maps; + +/** + * Specification of a {@link ResponseBody}. + * + * @author inder + */ +public final class ResponseBodySpec extends ContentBodySpec { + + public static class Builder { + private final Map paramsSpec = Maps.newLinkedHashMap(); + public Builder add(String paramName, Type type) { + paramsSpec.put(paramName, type); + return this; + } + + public ResponseBodySpec create() { + ResponseBodySpec spec = new ResponseBodySpec(paramsSpec); + return spec; + } + } + + public ResponseBodySpec(Map paramsSpec) { + super(paramsSpec); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/ResponseSpec.java b/wsf/src/main/java/com/google/gson/wsf/ResponseSpec.java new file mode 100644 index 00000000..2dbe5032 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/ResponseSpec.java @@ -0,0 +1,52 @@ +/* + * 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; + +import com.google.common.base.Preconditions; + +/** + * Specification for a {@link WebServiceResponse}. + * + * @author inder + */ +public final class ResponseSpec { + private final HeaderMapSpec headersSpec; + private final ResponseBodySpec bodySpec; + + public ResponseSpec(HeaderMapSpec headersSpec, ResponseBodySpec bodySpec) { + Preconditions.checkNotNull(headersSpec); + Preconditions.checkNotNull(bodySpec); + + this.headersSpec = headersSpec; + this.bodySpec = bodySpec; + } + + public ResponseBodySpec getBodySpec() { + return bodySpec; + } + + public HeaderMapSpec getHeadersSpec() { + return headersSpec; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{headersSpec:"); + sb.append(headersSpec).append(",bodySpec:"); + sb.append(bodySpec).append("}"); + return sb.toString(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/TypeUtils.java b/wsf/src/main/java/com/google/gson/wsf/TypeUtils.java new file mode 100644 index 00000000..86660f87 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/TypeUtils.java @@ -0,0 +1,92 @@ +/* + * 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. + */ + +// Copied from com.google.gson.TypeUtils +package com.google.gson.wsf; + +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +/** + * Utility class containing some methods for obtaining information on types. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +final class TypeUtils { + + /** + * Returns the actual type matching up with the first type variable. + * So, for a {@code typeInfo} instance defined as: + *
+   *   class Foo {
+   *   }
+   *   Type fooType = new TypeToken>() {}.getType();
+   * 
+ * TypeUtils.getActualTypeForFirstTypeVariable(fooType) will return Integer.class. + */ + static Type getActualTypeForFirstTypeVariable(Type type) { + if (type instanceof Class) { + return Object.class; + } else if (type instanceof ParameterizedType) { + return ((ParameterizedType)type).getActualTypeArguments()[0]; + } else if (type instanceof GenericArrayType) { + return getActualTypeForFirstTypeVariable(((GenericArrayType)type).getGenericComponentType()); + } else { + throw new IllegalArgumentException("Type \'" + type + "\' is not a Class, " + + "ParameterizedType, or GenericArrayType. Can't extract class."); + } + } + + static boolean isArray(Type type) { + if (type instanceof Class) { + return ((Class)type).isArray(); + } else if (type instanceof GenericArrayType) { + return true; + } else { + return false; + } + } + + /** + * This method returns the actual raw class associated with the specified type. + */ + static Class toRawClass(Type type) { + if (type instanceof Class) { + return (Class) type; + } else if (type instanceof ParameterizedType) { + ParameterizedType actualType = (ParameterizedType)type; + return toRawClass(actualType.getRawType()); + } else if (type instanceof GenericArrayType) { + GenericArrayType actualType = (GenericArrayType) type; + Class rawClass = toRawClass(actualType.getGenericComponentType()); + return wrapWithArray(rawClass); + } else { + throw new IllegalArgumentException("Type \'" + type + "\' is not a Class, " + + "ParameterizedType, or GenericArrayType. Can't extract class."); + } + } + + static Class wrapWithArray(Class rawClass) { + return Array.newInstance(rawClass, 0).getClass(); + } + + private TypeUtils() { + // Class with just some static utility methods, should not be instantiated + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/Util.java b/wsf/src/main/java/com/google/gson/wsf/Util.java new file mode 100755 index 00000000..ac88bc40 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/Util.java @@ -0,0 +1,75 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Map; + +final class Util { + private Util() { } + + public static boolean isAssignableFrom(Type typeOfValue, Type expectedType) { + return typeOfValue.equals(expectedType); + } + + public static String toStringMapKeys(Map map) { + StringBuilder sb = new StringBuilder("["); + boolean first = true; + for (Map.Entry entry : map.entrySet()) { + if (first) { + first = false; + } else { + sb.append(","); + } + sb.append(entry.getKey()); + } + sb.append("]"); + return sb.toString(); + } + + public static String toStringMapOfTypes(Map map) { + StringBuilder sb = new StringBuilder("["); + boolean first = true; + for (Map.Entry entry : map.entrySet()) { + if (first) { + first = false; + } else { + sb.append(","); + } + sb.append(entry.getKey()).append(":"); + Class clazz = (Class) entry.getValue(); + sb.append(clazz.getSimpleName()); + } + sb.append("]"); + return sb.toString(); + } + + public static String toStringMap(Map map) { + StringBuilder sb = new StringBuilder("["); + boolean first = true; + for (Map.Entry entry : map.entrySet()) { + if (first) { + first = false; + } else { + sb.append(","); + } + sb.append(entry.getKey()).append(":").append(entry.getValue()); + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/wsf/src/main/java/com/google/gson/wsf/WebServiceAppException.java b/wsf/src/main/java/com/google/gson/wsf/WebServiceAppException.java new file mode 100644 index 00000000..44d8d5a8 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/WebServiceAppException.java @@ -0,0 +1,37 @@ +/* + * 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; + +/** + * Base class for exceptions thrown to indicate a Web service external or application error + * condition. This can happen due to bad input, or illegal sequence of operations. This should + * never be thrown to indicate a System error condition. For that purpose, use + * {@link WebServiceSystemException} instead. + * + * @author inder + */ +public class WebServiceAppException extends RuntimeException { + + private static final long serialVersionUID = 4422041697108937041L; + + public WebServiceAppException(Exception cause) { + super(cause); + } + + public WebServiceAppException(String msg, Exception cause) { + super(msg, cause); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/WebServiceCall.java b/wsf/src/main/java/com/google/gson/wsf/WebServiceCall.java new file mode 100755 index 00000000..8f258a9f --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/WebServiceCall.java @@ -0,0 +1,48 @@ +/* + * 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; + +/** + * The data associated with a Web service call. This includes http request header parameters (form + * and URL parameters), {@link RequestBody}, response header parameters, and {@link ResponseBody}. + * + * @author inder + */ +public final class WebServiceCall { + + private final WebServiceCallSpec callSpec; + private final WebServiceRequest request; + private final WebServiceResponse response; + + public WebServiceCall(WebServiceCallSpec callSpec, WebServiceRequest request, + WebServiceResponse response) { + this.callSpec = callSpec; + this.request = request; + this.response = response; + } + + public WebServiceCallSpec getSpec() { + return callSpec; + } + + public WebServiceRequest getRequest() { + return request; + } + + public WebServiceResponse getResponse() { + return response; + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/WebServiceCallSpec.java b/wsf/src/main/java/com/google/gson/wsf/WebServiceCallSpec.java new file mode 100755 index 00000000..bb6e8ac4 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/WebServiceCallSpec.java @@ -0,0 +1,140 @@ +/* + * 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; + +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import com.google.common.base.Preconditions; + + +/** + * Specification for a Json web service call. The call includes the relative path where the call + * is available, the specification of requests, and responses. + * + * @author inder + */ +public final class WebServiceCallSpec { + + public static final WebServiceCallSpec NULL_SPEC = new Builder(new CallPath("")).create(); + + public static class Builder { + private final CallPath callPath; + private final Set supportedHttpMethods = new LinkedHashSet(); + private final HeaderMapSpec.Builder reqParamsSpecBuilder = new HeaderMapSpec.Builder(); + private final RequestBodySpec.Builder reqBodySpecBuilder = new RequestBodySpec.Builder(); + private final HeaderMapSpec.Builder resParamsSpecBuilder = new HeaderMapSpec.Builder(); + private final ResponseBodySpec.Builder resBodySpecBuilder = new ResponseBodySpec.Builder(); + + public Builder(CallPath callPath) { + this.callPath = callPath; + } + + /** + * If this method is not invoked, then it is assumed that the WebServiceCall supports all + * methods specified in {@link HttpMethod#values()}. + * + * @param httpMethods list of methods that this call supports. + * @return self to follow the Builder pattern. + */ + public Builder supportsHttpMethod(HttpMethod... httpMethods) { + supportedHttpMethods.addAll(Arrays.asList(httpMethods)); + return this; + } + + public Builder addRequestParam(String paramName, Type type) { + reqParamsSpecBuilder.put(paramName, type); + return this; + } + public Builder addRequestBodyParam(String paramName, Type type) { + reqBodySpecBuilder.add(paramName, type); + return this; + } + public Builder addResponseParam(String paramName, Type type) { + resParamsSpecBuilder.put(paramName, type); + return this; + } + public Builder addResponseBodyParam(String paramName, Type type) { + resBodySpecBuilder.add(paramName, type); + return this; + } + public WebServiceCallSpec create() { + if (supportedHttpMethods.isEmpty()) { + supportedHttpMethods.addAll(Arrays.asList(HttpMethod.values())); + } + RequestSpec requestSpec = + new RequestSpec(reqParamsSpecBuilder.create(), reqBodySpecBuilder.create()); + ResponseSpec responseSpec = + new ResponseSpec(resParamsSpecBuilder.create(), resBodySpecBuilder.create()); + WebServiceCallSpec callSpec = new WebServiceCallSpec(supportedHttpMethods, callPath, + requestSpec, responseSpec); + return callSpec; + } + } + + private final Set supportedHttpMethods; + private final CallPath path; + private final ResponseSpec responseSpec; + private final RequestSpec requestSpec; + + private WebServiceCallSpec(Set supportedHttpMethods, CallPath path, + RequestSpec requestSpec, ResponseSpec 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 getSupportedHttpMethods() { + return supportedHttpMethods; + } + + public ResponseSpec getResponseSpec() { + return responseSpec; + } + + public RequestSpec getRequestSpec() { + return requestSpec; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{path:"); + sb.append(path).append(",supportedHttpMethods:"); + boolean first = true; + for (HttpMethod method : supportedHttpMethods) { + if (first) { + first = false; + } else { + sb.append(","); + } + sb.append(method); + } + sb.append(path).append(",requestSpec:"); + sb.append(requestSpec).append(",responseSpec:"); + sb.append(responseSpec).append("}"); + return sb.toString(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/WebServiceRequest.java b/wsf/src/main/java/com/google/gson/wsf/WebServiceRequest.java new file mode 100644 index 00000000..358ec7ed --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/WebServiceRequest.java @@ -0,0 +1,75 @@ +/* + * 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; + +/** + * 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 WebServiceRequest { + private final HttpMethod method; + private final HeaderMap headers; + private final RequestBody body; + private final RequestSpec spec; + + public WebServiceRequest(HttpMethod method, HeaderMap requestHeaders, RequestBody requestBody) { + this.method = method; + this.body = requestBody; + this.headers = requestHeaders; + this.spec = new RequestSpec(requestHeaders.getSpec(), requestBody.getSpec()); + } + + public HttpMethod getMethod() { + return method; + } + + public RequestSpec getSpec() { + return spec; + } + + public HttpMethod getHttpMethod() { + return method; + } + + public RequestBody getBody() { + return body; + } + + public HeaderMap getHeaders() { + return headers; + } + + public String getContentType() { + return ContentBodySpec.JSON_CONTENT_TYPE; + } + + @SuppressWarnings("unchecked") + public T getHeader(String headerName) { + return (T) headers.get(headerName); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{"); + sb.append(method).append(","); + sb.append(",headers:").append(headers); + sb.append(",body:").append(body); + sb.append("}"); + return sb.toString(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/WebServiceResponse.java b/wsf/src/main/java/com/google/gson/wsf/WebServiceResponse.java new file mode 100644 index 00000000..5a47d1ed --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/WebServiceResponse.java @@ -0,0 +1,67 @@ +/* + * 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; + +/** + * The data associated with a Web service response. This includes http response header parameters, + * and {@link ResponseBody}. + * + * @author inder + */ +public final class WebServiceResponse { + + private final HeaderMap headers; + private final ResponseBody body; + private final ResponseSpec spec; + + public WebServiceResponse(ResponseSpec spec) { + this.spec = spec; + headers = new HeaderMap(spec.getHeadersSpec()); + body = new ResponseBody(spec.getBodySpec()); + } + + public WebServiceResponse(HeaderMap responseHeaders, ResponseBody responseBody) { + this.spec = new ResponseSpec(responseHeaders.getSpec(), responseBody.getSpec()); + this.headers = responseHeaders; + this.body = responseBody; + } + + public ResponseSpec getSpec() { + return spec; + } + + public HeaderMap getHeaders() { + return headers; + } + + public ResponseBody getBody() { + return body; + } + + @SuppressWarnings("unchecked") + public T getHeader(String headerName) { + return (T) headers.get(headerName); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{headers:"); + sb.append(headers); + sb.append(",body:").append(body); + sb.append("}"); + return sb.toString(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/WebServiceSpec.java b/wsf/src/main/java/com/google/gson/wsf/WebServiceSpec.java new file mode 100755 index 00000000..414312b8 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/WebServiceSpec.java @@ -0,0 +1,26 @@ +/* + * 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; + +/** + * Specification of the Web service. This contains a specification of all the + * {@link WebServiceCall}s supported by this Web service. + * + * @author inder + */ +public interface WebServiceSpec { + public CallPathMap getCalls(); +} diff --git a/wsf/src/main/java/com/google/gson/wsf/WebServiceSystemException.java b/wsf/src/main/java/com/google/gson/wsf/WebServiceSystemException.java new file mode 100755 index 00000000..d02125a3 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/WebServiceSystemException.java @@ -0,0 +1,36 @@ +/* + * 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; + +/** + * Base class for all exceptions thrown by the Web service to indicate a system error condition. + * This should never be thrown to indicate bad user input. For that purpose, use + * {@link WebServiceAppException}. + * + * @author inder + */ +public class WebServiceSystemException extends RuntimeException { + + private static final long serialVersionUID = -2511829073381716183L; + + public WebServiceSystemException(Exception cause) { + super(cause); + } + + public WebServiceSystemException(String msg, Exception cause) { + super(msg, cause); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/client/RequestSender.java b/wsf/src/main/java/com/google/gson/wsf/client/RequestSender.java new file mode 100644 index 00000000..6f91d685 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/client/RequestSender.java @@ -0,0 +1,74 @@ +/* + * 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.client; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.wsf.HeaderMap; +import com.google.gson.wsf.HeaderMapSpec; +import com.google.gson.wsf.RequestBody; +import com.google.gson.wsf.WebServiceRequest; + +/** + * Class to send Web service requests on a {@link HttpURLConnection}. + * + * @author inder + */ +public final class RequestSender { + private final Gson gson; + + public RequestSender(Gson gson) { + this.gson = gson; + } + + public void send(HttpURLConnection conn, WebServiceRequest request) { + try { + conn.setRequestMethod(request.getHttpMethod().toString()); + conn.setRequestProperty("Content-Type", request.getContentType()); + addRequestParams(conn, request.getHeaders()); + RequestBody requestBody = request.getBody(); + if (requestBody.getSpec().size() > 0) { + conn.setDoOutput(true); + addRequestBody(conn, requestBody); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void addRequestParams(HttpURLConnection conn, HeaderMap requestParams) { + HeaderMapSpec spec = requestParams.getSpec(); + for (Map.Entry entry : requestParams.entrySet()) { + String paramName = entry.getKey(); + Type type = spec.getTypeFor(paramName); + Object value = entry.getValue(); + String json = gson.toJson(value, type); + conn.addRequestProperty(paramName, json); + } + } + + private void addRequestBody(HttpURLConnection conn, RequestBody body) throws IOException { + Writer writer = new PrintWriter(conn.getOutputStream()); + gson.toJson(body, writer); + writer.close(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/client/ResponseReceiver.java b/wsf/src/main/java/com/google/gson/wsf/client/ResponseReceiver.java new file mode 100644 index 00000000..1fe15104 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/client/ResponseReceiver.java @@ -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.wsf.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 com.google.common.base.Preconditions; +import com.google.gson.Gson; +import com.google.gson.wsf.HeaderMap; +import com.google.gson.wsf.HeaderMapSpec; +import com.google.gson.wsf.ResponseBody; +import com.google.gson.wsf.ResponseBodySpec; +import com.google.gson.wsf.ResponseSpec; +import com.google.gson.wsf.WebServiceResponse; + +/** + * Receives a response coming on an {@link HttpURLConnection}. + * + * @author inder + */ +public final class ResponseReceiver { + private final Gson gson; + private final ResponseSpec spec; + + public ResponseReceiver(Gson gson, ResponseSpec spec) { + this.gson = gson; + this.spec = spec; + } + + public WebServiceResponse receive(HttpURLConnection conn) { + try { + HeaderMapSpec paramSpec = spec.getHeadersSpec(); + ResponseBodySpec bodySpec = spec.getBodySpec(); + if (bodySpec.size() > 0) { + conn.setDoInput(true); + } + // read response + HeaderMap responseParams = readResponseHeaders(conn, paramSpec); + ResponseBody responseBody = readResponseBody(conn, bodySpec); + return new WebServiceResponse(responseParams, responseBody); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private HeaderMap readResponseHeaders(HttpURLConnection conn, HeaderMapSpec paramsSpec) { + HeaderMap params = new HeaderMap(paramsSpec); + for (Map.Entry entry : paramsSpec.entrySet()) { + String paramName = entry.getKey(); + String json = conn.getHeaderField(paramName); + if (json != null) { + Type typeOfT = paramsSpec.getTypeFor(paramName); + Object value = gson.fromJson(json, typeOfT); + params.put(paramName, value, typeOfT); + } + } + return params; + } + + private ResponseBody readResponseBody(HttpURLConnection conn, ResponseBodySpec bodySpec) + throws IOException { + if (bodySpec.size() == 0) { + return new ResponseBody(bodySpec); + } + String connContentType = conn.getContentType(); + Preconditions.checkArgument(connContentType.contains(bodySpec.getContentType())); + Reader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + ResponseBody body = gson.fromJson(reader, ResponseBody.class); + return body; + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/client/WebServiceClient.java b/wsf/src/main/java/com/google/gson/wsf/client/WebServiceClient.java new file mode 100644 index 00000000..a8c7f6d6 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/client/WebServiceClient.java @@ -0,0 +1,64 @@ +/* + * 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.client; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import com.google.gson.Gson; +import com.google.gson.wsf.WebServiceCallSpec; +import com.google.gson.wsf.WebServiceRequest; +import com.google.gson.wsf.WebServiceResponse; + +/** + * Main class used by clients to access a Gson Web service. + * + * @author inder + */ +public final class WebServiceClient { + private final WebServiceConfig config; + private final WebServiceCallSpec callSpec; + private final Gson gson; + + public WebServiceClient(Gson gson, WebServiceConfig serverConfig, WebServiceCallSpec callSpec) { + this.gson = gson; + this.config = serverConfig; + this.callSpec = callSpec; + } + + private URL getWebServiceUrl() { + String url = config.getServiceBaseUrl() + callSpec.getPath().get(); + try { + return new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + public WebServiceResponse getResponse(WebServiceRequest request) { + try { + HttpURLConnection conn = (HttpURLConnection) getWebServiceUrl().openConnection(); + RequestSender requestSender = new RequestSender(gson); + requestSender.send(conn, request); + ResponseReceiver responseReceiver = new ResponseReceiver(gson, callSpec.getResponseSpec()); + return responseReceiver.receive(conn); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/client/WebServiceConfig.java b/wsf/src/main/java/com/google/gson/wsf/client/WebServiceConfig.java new file mode 100644 index 00000000..72dc46db --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/client/WebServiceConfig.java @@ -0,0 +1,33 @@ +/* + * 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.client; + +/** + * Configuration needed to access a Gson web service. + * + * @author inder + */ +public final class WebServiceConfig { + private final String serviceBaseUrl; + + public WebServiceConfig(String serviceBaseUrl) { + this.serviceBaseUrl = serviceBaseUrl; + } + + public String getServiceBaseUrl() { + return serviceBaseUrl; + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/inject/CallPathProvider.java b/wsf/src/main/java/com/google/gson/wsf/inject/CallPathProvider.java new file mode 100644 index 00000000..b0173e0b --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/inject/CallPathProvider.java @@ -0,0 +1,44 @@ +/* + * 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.inject; + +import javax.servlet.http.HttpServletRequest; + +import com.google.gson.wsf.CallPath; +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * Guice provider for {@link CallPath} for an incoming web service request. + * + * @author inder + */ +final class CallPathProvider implements Provider { + private final HttpServletRequest request; + + @Inject + public CallPathProvider(HttpServletRequest request) { + this.request = request; + } + + @Override + public CallPath get() { + String pathInfo = request.getPathInfo(); + System.out.println("Incoming request with pathInfo: " + pathInfo); + String callPath = pathInfo; + return new CallPath(callPath); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/inject/RequestBodySpecProvider.java b/wsf/src/main/java/com/google/gson/wsf/inject/RequestBodySpecProvider.java new file mode 100644 index 00000000..bef5219c --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/inject/RequestBodySpecProvider.java @@ -0,0 +1,41 @@ +/* + * 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.inject; + +import com.google.gson.wsf.RequestBodySpec; +import com.google.gson.wsf.RequestSpec; +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * Guice provider for the {@link RequestBodySpec} to map to the incoming requests. + * + * @author inder + */ +final class RequestBodySpecProvider implements Provider { + + private final RequestSpec requestSpec; + + @Inject + public RequestBodySpecProvider(RequestSpec requestSpec) { + this.requestSpec = requestSpec; + } + + @Override + public RequestBodySpec get() { + return requestSpec.getBodySpec(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/inject/RequestSpecProvider.java b/wsf/src/main/java/com/google/gson/wsf/inject/RequestSpecProvider.java new file mode 100644 index 00000000..f21c9cd3 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/inject/RequestSpecProvider.java @@ -0,0 +1,41 @@ +/* + * 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.inject; + +import com.google.gson.wsf.RequestSpec; +import com.google.gson.wsf.WebServiceCallSpec; +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * Guice provider for the {@link RequestSpec} to map to the incoming requests. + * + * @author inder + */ +final class RequestSpecProvider implements Provider { + + private final WebServiceCallSpec webServiceCallSpec; + + @Inject + public RequestSpecProvider(WebServiceCallSpec webServiceCallSpec) { + this.webServiceCallSpec = webServiceCallSpec; + } + + @Override + public RequestSpec get() { + return webServiceCallSpec.getRequestSpec(); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallProvider.java b/wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallProvider.java new file mode 100755 index 00000000..f3ce7dab --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallProvider.java @@ -0,0 +1,57 @@ +/* + * 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.inject; + +import javax.servlet.http.HttpServletRequest; + +import com.google.gson.Gson; +import com.google.gson.wsf.WebServiceCall; +import com.google.gson.wsf.WebServiceCallSpec; +import com.google.gson.wsf.WebServiceRequest; +import com.google.gson.wsf.WebServiceResponse; +import com.google.gson.wsf.server.RequestReceiver; +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * Guice provider for {@link WebServiceCall} to be used by a server-side implementation. + * + * @author inder + */ +final class WebServiceCallProvider implements Provider { + private final Gson gson; + private final WebServiceCallSpec callSpec; + private final HttpServletRequest request; + + @Inject + public WebServiceCallProvider(Gson gson, HttpServletRequest request, + WebServiceCallSpec callSpec) { + this.callSpec = callSpec; + this.gson = gson; + this.request = request; + } + + @Override + public WebServiceCall get() { + RequestReceiver receiver = new RequestReceiver(gson, callSpec.getRequestSpec()); + WebServiceRequest wsRequest = receiver.receive(request); + + // No need to populate response headers or response body + WebServiceResponse wsResponse = new WebServiceResponse(callSpec.getResponseSpec()); + + return new WebServiceCall(callSpec, wsRequest, wsResponse); + } +} \ No newline at end of file diff --git a/wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallSpecProvider.java b/wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallSpecProvider.java new file mode 100755 index 00000000..b7a18c2d --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/inject/WebServiceCallSpecProvider.java @@ -0,0 +1,43 @@ +/* + * 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.inject; + +import com.google.gson.wsf.CallPath; +import com.google.gson.wsf.WebServiceCallSpec; +import com.google.gson.wsf.WebServiceSpec; +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * Guice provider for {@link WebServiceCallSpec}. + * + * @author inder + */ +final class WebServiceCallSpecProvider implements Provider { + private final CallPath callPath; + private final WebServiceSpec webServiceSpec; + + @Inject + WebServiceCallSpecProvider(CallPath callPath, WebServiceSpec webServiceSpec) { + this.callPath = callPath; + this.webServiceSpec = webServiceSpec; + } + + @Override + public WebServiceCallSpec get() { + return webServiceSpec.getCalls().get(callPath); + } +} \ No newline at end of file diff --git a/wsf/src/main/java/com/google/gson/wsf/server/RequestReceiver.java b/wsf/src/main/java/com/google/gson/wsf/server/RequestReceiver.java new file mode 100644 index 00000000..36ad88f5 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/server/RequestReceiver.java @@ -0,0 +1,101 @@ +/* + * 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; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import com.google.gson.Gson; +import com.google.gson.JsonParseException; +import com.google.gson.wsf.HeaderMap; +import com.google.gson.wsf.HeaderMapSpec; +import com.google.gson.wsf.HttpMethod; +import com.google.gson.wsf.RequestBody; +import com.google.gson.wsf.RequestBodySpec; +import com.google.gson.wsf.RequestSpec; +import com.google.gson.wsf.WebServiceRequest; +import com.google.gson.wsf.WebServiceSystemException; + +/** + * Receives and parses a request at the server side on a {@link HttpServletRequest}. + * + * @author inder + */ +public final class RequestReceiver { + + private final Gson gson; + private final RequestSpec spec; + + public RequestReceiver(Gson gson, RequestSpec spec) { + this.gson = gson; + this.spec = spec; + } + + public WebServiceRequest receive(HttpServletRequest request) { + try { + HeaderMap requestParams = buildRequestParams(request); + RequestBody requestBody = buildRequestBody(request); + + HttpMethod method = HttpMethod.getMethod(request.getMethod()); + return new WebServiceRequest(method, requestParams, requestBody); + } 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 params = new HeaderMap(paramsSpec); + for (Map.Entry 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); + params.put(name, value); + } + } + return params; + } + + private RequestBody buildRequestBody(HttpServletRequest request) throws IOException { + RequestBodySpec bodySpec = spec.getBodySpec(); + if (bodySpec.size() == 0) { + return createEmptyRequestBody(bodySpec); + } + Reader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); + RequestBody requestBody = gson.fromJson(reader, RequestBody.class); + return requestBody; + } + + private RequestBody createEmptyRequestBody(RequestBodySpec bodySpec) { + return new RequestBody(bodySpec, new HashMap()); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/server/ResponseSender.java b/wsf/src/main/java/com/google/gson/wsf/server/ResponseSender.java new file mode 100644 index 00000000..92c481a9 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/server/ResponseSender.java @@ -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; + +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.wsf.HeaderMap; +import com.google.gson.wsf.HeaderMapSpec; +import com.google.gson.wsf.ResponseBody; +import com.google.gson.wsf.WebServiceResponse; + +/** + * Sends a JSON web service response on {@link HttpServletResponse}. + * + * @author inder + */ +public final class ResponseSender { + private static final Logger logger = Logger.getLogger(ResponseSender.class.getCanonicalName()); + + private Gson gson; + + public ResponseSender(Gson gson) { + this.gson = gson; + } + + public void send(HttpServletResponse conn, WebServiceResponse 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 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, ResponseBody responseBody) throws IOException { + conn.setContentType(responseBody.getContentType()); + conn.setCharacterEncoding(responseBody.getCharacterEncoding()); + String json = gson.toJson(responseBody); + logger.fine("RESPONSE BODY:" + json); + conn.getWriter().append(json); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/typeadapters/RequestBodyGsonConverter.java b/wsf/src/main/java/com/google/gson/wsf/typeadapters/RequestBodyGsonConverter.java new file mode 100644 index 00000000..22c90dfa --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/typeadapters/RequestBodyGsonConverter.java @@ -0,0 +1,77 @@ +/* + * 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.typeadapters; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.InstanceCreator; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.wsf.RequestBody; +import com.google.gson.wsf.RequestBodySpec; + +/** + * Gson type adapter for {@link RequestBody}. + * + * @author inder + */ +public class RequestBodyGsonConverter implements JsonSerializer, + JsonDeserializer, InstanceCreator { + + private final RequestBodySpec spec; + + public RequestBodyGsonConverter(RequestBodySpec spec) { + this.spec = spec; + } + + @Override + public JsonElement serialize(RequestBody src, Type typeOfSrc, + JsonSerializationContext context) { + JsonObject root = new JsonObject(); + for(Map.Entry entry : src.entrySet()) { + String key = entry.getKey(); + Type entryType = src.getSpec().getTypeFor(key); + JsonElement value = context.serialize(entry.getValue(), entryType); + root.add(key, value); + } + return root; + } + + @Override + public RequestBody deserialize(JsonElement json, Type typeOfT, + JsonDeserializationContext context) throws JsonParseException { + RequestBody.Builder builder = new RequestBody.Builder(spec); + for (Map.Entry entry : json.getAsJsonObject().entrySet()) { + String key = entry.getKey(); + Type entryType = spec.getTypeFor(key); + Object value = context.deserialize(entry.getValue(), entryType); + builder.add(key, value); + } + return builder.create(); + } + + @Override + public RequestBody createInstance(Type type) { + return new RequestBody(spec, new HashMap()); + } +} diff --git a/wsf/src/main/java/com/google/gson/wsf/typeadapters/ResponseBodyGsonConverter.java b/wsf/src/main/java/com/google/gson/wsf/typeadapters/ResponseBodyGsonConverter.java new file mode 100644 index 00000000..64f64fd3 --- /dev/null +++ b/wsf/src/main/java/com/google/gson/wsf/typeadapters/ResponseBodyGsonConverter.java @@ -0,0 +1,77 @@ +/* + * 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.typeadapters; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.google.gson.InstanceCreator; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.wsf.RequestBody; +import com.google.gson.wsf.ResponseBody; +import com.google.gson.wsf.ResponseBodySpec; + +/** + * Gson type adapter for {@link ResponseBody}. + * + * @author inder + */ +public final class ResponseBodyGsonConverter implements JsonSerializer, + JsonDeserializer, InstanceCreator { + + private final ResponseBodySpec spec; + + public ResponseBodyGsonConverter(ResponseBodySpec spec) { + this.spec = spec; + } + + @Override + public JsonElement serialize(ResponseBody src, Type typeOfSrc, + JsonSerializationContext context) { + JsonObject root = new JsonObject(); + for(Map.Entry entry : src.entrySet()) { + String key = entry.getKey(); + Type entryType = src.getSpec().getTypeFor(key); + JsonElement value = context.serialize(entry.getValue(), entryType); + root.add(key, value); + } + return root; + } + + @Override + public ResponseBody deserialize(JsonElement json, Type typeOfT, + JsonDeserializationContext context) throws JsonParseException { + ResponseBody responseBody = new ResponseBody(spec); + for (Map.Entry entry : json.getAsJsonObject().entrySet()) { + String key = entry.getKey(); + Type entryType = spec.getTypeFor(key); + Object value = context.deserialize(entry.getValue(), entryType); + responseBody.put(key, value, entryType); + } + return responseBody; + } + + @Override + public ResponseBody createInstance(Type type) { + return new ResponseBody(spec); + } +} \ No newline at end of file