aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGert Scholten <gscholt@gmail.com>2009-05-11 15:17:34 +0200
committerGert Scholten <gscholt@gmail.com>2009-05-15 09:13:28 +0200
commitf0f7d146fdcb303cd3312641517fbef8c65d5c1f (patch)
treebb2223edd98de868b742055599115361baaaf546
parentdce37e430c0fa2bbff9e2370249236e14e4064ca (diff)
downloadgwtjsonrpc-f0f7d146fdcb303cd3312641517fbef8c65d5c1f.tar.gz
Added suport for non-object return values using simple RPC.
(missing at the moment are HPC and CallbackHandle) Signed-off-by: Gert Scholten <gscholt@gmail.com>
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/AbstractJsonProxy.java2
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/ArrayResultDeserializer.java33
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/JavaLangString_JsonSerializer.java10
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/JavaSqlDate_JsonSerializer.java11
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/JavaSqlTimestamp_JsonSerializer.java10
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/JavaUtilDate_JsonSerializer.java9
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/JsonCall.java10
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/JsonUtil.java15
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/ObjectSerializer.java15
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/PrimitiveArrayResultDeserializers.java90
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/PrimitiveResultDeserializers.java108
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/ResultDeserializer.java28
-rw-r--r--src/main/java/com/google/gwtjsonrpc/client/VoidResult_JsonSerializer.java10
-rw-r--r--src/main/java/com/google/gwtjsonrpc/rebind/ProxyCreator.java43
-rw-r--r--src/main/java/com/google/gwtjsonrpc/rebind/ResultDeserializerCreator.java210
15 files changed, 579 insertions, 25 deletions
diff --git a/src/main/java/com/google/gwtjsonrpc/client/AbstractJsonProxy.java b/src/main/java/com/google/gwtjsonrpc/client/AbstractJsonProxy.java
index 44ad157..a57cf8a 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/AbstractJsonProxy.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/AbstractJsonProxy.java
@@ -40,7 +40,7 @@ public abstract class AbstractJsonProxy implements ServiceDefTarget {
}
protected <T> void doInvoke(final String methodName, final String reqData,
- final JsonSerializer<T> ser, final AsyncCallback<T> cb)
+ final ResultDeserializer<T> ser, final AsyncCallback<T> cb)
throws InvocationException {
if (url == null) {
throw new NoServiceEntryPointSpecifiedException();
diff --git a/src/main/java/com/google/gwtjsonrpc/client/ArrayResultDeserializer.java b/src/main/java/com/google/gwtjsonrpc/client/ArrayResultDeserializer.java
new file mode 100644
index 0000000..55ae773
--- /dev/null
+++ b/src/main/java/com/google/gwtjsonrpc/client/ArrayResultDeserializer.java
@@ -0,0 +1,33 @@
+// Copyright 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.gwtjsonrpc.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+/**
+ * Base class for the {@link PrimitiveArrayResultDeserializer} and generated
+ * object array result deserializers.
+ */
+public abstract class ArrayResultDeserializer {
+ protected static native JavaScriptObject getResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ protected static native int getResultSize(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result.length;
+ }-*/;
+}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/JavaLangString_JsonSerializer.java b/src/main/java/com/google/gwtjsonrpc/client/JavaLangString_JsonSerializer.java
index 90a3685..5a044ff 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/JavaLangString_JsonSerializer.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/JavaLangString_JsonSerializer.java
@@ -14,9 +14,12 @@
package com.google.gwtjsonrpc.client;
+import com.google.gwt.core.client.JavaScriptObject;
+
/** Default serialization for a String. */
public final class JavaLangString_JsonSerializer extends
- JsonSerializer<java.lang.String> {
+ JsonSerializer<java.lang.String> implements
+ ResultDeserializer<java.lang.String> {
public static final JavaLangString_JsonSerializer INSTANCE =
new JavaLangString_JsonSerializer();
@@ -29,4 +32,9 @@ public final class JavaLangString_JsonSerializer extends
public void printJson(final StringBuilder sb, final java.lang.String o) {
sb.append(escapeString(o));
}
+
+ @Override
+ public String fromResult(JavaScriptObject responseObject) {
+ return PrimitiveResultDeserializers.stringResult(responseObject);
+ }
}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/JavaSqlDate_JsonSerializer.java b/src/main/java/com/google/gwtjsonrpc/client/JavaSqlDate_JsonSerializer.java
index fbf1ed9..cb26673 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/JavaSqlDate_JsonSerializer.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/JavaSqlDate_JsonSerializer.java
@@ -14,9 +14,13 @@
package com.google.gwtjsonrpc.client;
+import com.google.gwt.core.client.JavaScriptObject;
+
+import java.sql.Date;
+
/** Default serialization for a {@link java.sql.Date}. */
public final class JavaSqlDate_JsonSerializer extends
- JsonSerializer<java.sql.Date> {
+ JsonSerializer<java.sql.Date> implements ResultDeserializer<java.sql.Date> {
public static final JavaSqlDate_JsonSerializer INSTANCE =
new JavaSqlDate_JsonSerializer();
@@ -69,4 +73,9 @@ public final class JavaSqlDate_JsonSerializer extends
throw new IllegalArgumentException("Invalid escape format: " + s);
}
}
+
+ @Override
+ public Date fromResult(JavaScriptObject responseObject) {
+ return fromJson(PrimitiveResultDeserializers.stringResult(responseObject));
+ }
}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/JavaSqlTimestamp_JsonSerializer.java b/src/main/java/com/google/gwtjsonrpc/client/JavaSqlTimestamp_JsonSerializer.java
index 719b692..01e6cf3 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/JavaSqlTimestamp_JsonSerializer.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/JavaSqlTimestamp_JsonSerializer.java
@@ -14,11 +14,14 @@
package com.google.gwtjsonrpc.client;
+import com.google.gwt.core.client.JavaScriptObject;
+
+import java.sql.Timestamp;
import java.util.Date;
/** Default serialization for a {@link java.sql.Timestamp}. */
public final class JavaSqlTimestamp_JsonSerializer extends
- JsonSerializer<java.sql.Timestamp> {
+ JsonSerializer<java.sql.Timestamp> implements ResultDeserializer<java.sql.Timestamp> {
public static final JavaSqlTimestamp_JsonSerializer INSTANCE =
new JavaSqlTimestamp_JsonSerializer();
@@ -120,4 +123,9 @@ public final class JavaSqlTimestamp_JsonSerializer extends
}
}
}
+
+ @Override
+ public Timestamp fromResult(JavaScriptObject responseObject) {
+ return fromJson(PrimitiveResultDeserializers.stringResult(responseObject));
+ }
}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/JavaUtilDate_JsonSerializer.java b/src/main/java/com/google/gwtjsonrpc/client/JavaUtilDate_JsonSerializer.java
index 384cb6d..da27685 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/JavaUtilDate_JsonSerializer.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/JavaUtilDate_JsonSerializer.java
@@ -14,11 +14,13 @@
package com.google.gwtjsonrpc.client;
+import com.google.gwt.core.client.JavaScriptObject;
+
import java.util.Date;
/** Default serialization for a {@link java.util.Date}. */
public final class JavaUtilDate_JsonSerializer extends
- JsonSerializer<java.util.Date> {
+ JsonSerializer<java.util.Date> implements ResultDeserializer<java.util.Date>{
public static final JavaUtilDate_JsonSerializer INSTANCE =
new JavaUtilDate_JsonSerializer();
@@ -41,4 +43,9 @@ public final class JavaUtilDate_JsonSerializer extends
private static Date parse(final String o) {
return new java.util.Date(o);
}
+
+ @Override
+ public Date fromResult(JavaScriptObject responseObject) {
+ return fromJson(PrimitiveResultDeserializers.stringResult(responseObject));
+ }
}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/JsonCall.java b/src/main/java/com/google/gwtjsonrpc/client/JsonCall.java
index fe7d5bf..8ac7b3e 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/JsonCall.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/JsonCall.java
@@ -29,17 +29,17 @@ class JsonCall<T> implements RequestCallback {
private final AbstractJsonProxy proxy;
private final String methodName;
private final String requestParams;
- private final JsonSerializer<T> resultSerializer;
+ private final ResultDeserializer<T> resultDeserializer;
private final AsyncCallback<T> callback;
private int attempts;
JsonCall(final AbstractJsonProxy abstractJsonProxy, final String methodName,
- final String requestParams, final JsonSerializer<T> resultSerializer,
+ final String requestParams, final ResultDeserializer<T> resultDeserializer,
final AsyncCallback<T> callback) {
this.proxy = abstractJsonProxy;
this.methodName = methodName;
this.requestParams = requestParams;
- this.resultSerializer = resultSerializer;
+ this.resultDeserializer = resultDeserializer;
this.callback = callback;
}
@@ -115,7 +115,7 @@ class JsonCall<T> implements RequestCallback {
if (sc == Response.SC_OK) {
JsonUtil.fireOnCallEnd();
- JsonUtil.invoke(resultSerializer, callback, r.result());
+ JsonUtil.invoke(resultDeserializer, callback, r);
return;
}
}
@@ -163,8 +163,6 @@ class JsonCall<T> implements RequestCallback {
final native RpcError error()/*-{ return this.error; }-*/;
- final native JavaScriptObject result()/*-{ return this.result; }-*/;
-
final native String xsrfKey()/*-{ return this.xsrfKey; }-*/;
}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/JsonUtil.java b/src/main/java/com/google/gwtjsonrpc/client/JsonUtil.java
index 6ed732d..004cc59 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/JsonUtil.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/JsonUtil.java
@@ -15,6 +15,7 @@
package com.google.gwtjsonrpc.client;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
@@ -78,6 +79,20 @@ public class JsonUtil {
}
}
+ public static <T> void invoke(final ResultDeserializer<T> resultDeserializer,
+ final AsyncCallback<T> callback, final JavaScriptObject rpcResult) {
+ final T result;
+ try {
+ result = resultDeserializer.fromResult(rpcResult);
+ } catch (RuntimeException e) {
+ callback.onFailure(new InvocationException("Invalid JSON Response", e));
+ return;
+ }
+ callback.onSuccess(result);
+ }
+
+ // TODO: remove when the CallbackHandle supports primitive 'return' types?
+ // It is not called from anywhere in gwtjsonrpc, but it is a public method
public static <T> void invoke(final JsonSerializer<T> resultSerializer,
final AsyncCallback<T> callback, final Object encoded) {
final T resobj;
diff --git a/src/main/java/com/google/gwtjsonrpc/client/ObjectSerializer.java b/src/main/java/com/google/gwtjsonrpc/client/ObjectSerializer.java
index 211e76a..0c98cfc 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/ObjectSerializer.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/ObjectSerializer.java
@@ -14,8 +14,11 @@
package com.google.gwtjsonrpc.client;
+import com.google.gwt.core.client.JavaScriptObject;
+
/** Base class for generated JsonSerializer implementations. */
-public abstract class ObjectSerializer extends JsonSerializer<Object> {
+public abstract class ObjectSerializer<T extends Object> extends
+ JsonSerializer<T> implements ResultDeserializer<T> {
@Override
public void printJson(final StringBuilder sb, final Object o) {
sb.append("{");
@@ -24,4 +27,14 @@ public abstract class ObjectSerializer extends JsonSerializer<Object> {
}
protected abstract int printJsonImpl(int field, StringBuilder sb, Object o);
+
+ @Override
+ public T fromResult(JavaScriptObject responseObject) {
+ final JavaScriptObject result = objectResult(responseObject);
+ return result == null ? null : fromJson(result);
+ }
+
+ static native JavaScriptObject objectResult(JavaScriptObject responseObject) /*-{
+ return responseObject.result;
+ }-*/;
}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/PrimitiveArrayResultDeserializers.java b/src/main/java/com/google/gwtjsonrpc/client/PrimitiveArrayResultDeserializers.java
new file mode 100644
index 0000000..ce22644
--- /dev/null
+++ b/src/main/java/com/google/gwtjsonrpc/client/PrimitiveArrayResultDeserializers.java
@@ -0,0 +1,90 @@
+// Copyright 2009 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.gwtjsonrpc.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+public class PrimitiveArrayResultDeserializers extends ArrayResultDeserializer {
+ public static ResultDeserializer<Boolean[]> BOOLEAN_INSTANCE =
+ new ResultDeserializer<Boolean[]>() {
+ @Override
+ public Boolean[] fromResult(JavaScriptObject responseObject) {
+ final Boolean[] tmp = new Boolean[getResultSize(responseObject)];
+ PrimitiveArraySerializer.INSTANCE.fromJson(getResult(responseObject),
+ tmp);
+ return tmp;
+ }
+ };
+ public static ResultDeserializer<Byte[]> BYTE_INSTANCE =
+ new ResultDeserializer<Byte[]>() {
+ @Override
+ public Byte[] fromResult(JavaScriptObject responseObject) {
+ final Byte[] tmp = new Byte[getResultSize(responseObject)];
+ PrimitiveArraySerializer.INSTANCE.fromJson(getResult(responseObject),
+ tmp);
+ return tmp;
+ }
+ };
+ public static ResultDeserializer<Character[]> CHARACTER_INSTANCE =
+ new ResultDeserializer<Character[]>() {
+ @Override
+ public Character[] fromResult(JavaScriptObject responseObject) {
+ final Character[] tmp = new Character[getResultSize(responseObject)];
+ PrimitiveArraySerializer.INSTANCE.fromJson(getResult(responseObject),
+ tmp);
+ return tmp;
+ }
+ };
+ public static ResultDeserializer<Double[]> DOUBLE_INSTANCE =
+ new ResultDeserializer<Double[]>() {
+ @Override
+ public Double[] fromResult(JavaScriptObject responseObject) {
+ final Double[] tmp = new Double[getResultSize(responseObject)];
+ PrimitiveArraySerializer.INSTANCE.fromJson(getResult(responseObject),
+ tmp);
+ return tmp;
+ }
+ };
+ public static ResultDeserializer<Float[]> FLOAT_INSTANCE =
+ new ResultDeserializer<Float[]>() {
+ @Override
+ public Float[] fromResult(JavaScriptObject responseObject) {
+ final Float[] tmp = new Float[getResultSize(responseObject)];
+ PrimitiveArraySerializer.INSTANCE.fromJson(getResult(responseObject),
+ tmp);
+ return tmp;
+ }
+ };
+ public static ResultDeserializer<Integer[]> INTEGER_INSTANCE =
+ new ResultDeserializer<Integer[]>() {
+ @Override
+ public Integer[] fromResult(JavaScriptObject responseObject) {
+ final Integer[] tmp = new Integer[getResultSize(responseObject)];
+ PrimitiveArraySerializer.INSTANCE.fromJson(getResult(responseObject),
+ tmp);
+ return tmp;
+ }
+ };
+ public static ResultDeserializer<Short[]> SHORT_INSTANCE =
+ new ResultDeserializer<Short[]>() {
+ @Override
+ public Short[] fromResult(JavaScriptObject responseObject) {
+ final Short[] tmp = new Short[getResultSize(responseObject)];
+ PrimitiveArraySerializer.INSTANCE.fromJson(getResult(responseObject),
+ tmp);
+ return tmp;
+ }
+ };
+}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/PrimitiveResultDeserializers.java b/src/main/java/com/google/gwtjsonrpc/client/PrimitiveResultDeserializers.java
new file mode 100644
index 0000000..5725d08
--- /dev/null
+++ b/src/main/java/com/google/gwtjsonrpc/client/PrimitiveResultDeserializers.java
@@ -0,0 +1,108 @@
+// Copyright 2009 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.gwtjsonrpc.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+public class PrimitiveResultDeserializers {
+ static native boolean booleanResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ static native byte byteResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ static native String stringResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ static char charResult(JavaScriptObject responseObject) {
+ return JsonSerializer.toChar(stringResult(responseObject));
+ }
+
+ static native double doubleResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ static native float floatResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ static native int intResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ static native short shortResult(JavaScriptObject responseObject)
+ /*-{
+ return responseObject.result;
+ }-*/;
+
+ public static final ResultDeserializer<Boolean> BOOLEAN_INSTANCE =
+ new ResultDeserializer<Boolean>() {
+ @Override
+ public Boolean fromResult(JavaScriptObject responseObject) {
+ return booleanResult(responseObject);
+ }
+ };
+ public static final ResultDeserializer<Byte> BYTE_INSTANCE =
+ new ResultDeserializer<Byte>() {
+ @Override
+ public Byte fromResult(JavaScriptObject responseObject) {
+ return byteResult(responseObject);
+ }
+ };
+ public static final ResultDeserializer<Character> CHARACTER_INSTANCE =
+ new ResultDeserializer<Character>() {
+ @Override
+ public Character fromResult(JavaScriptObject responseObject) {
+ return charResult(responseObject);
+ }
+ };
+ public static final ResultDeserializer<Double> DOUBLE_INSTANCE =
+ new ResultDeserializer<Double>() {
+ @Override
+ public Double fromResult(JavaScriptObject responseObject) {
+ return doubleResult(responseObject);
+ }
+ };
+ public static final ResultDeserializer<Float> FLOAT_INSTANCE =
+ new ResultDeserializer<Float>() {
+ @Override
+ public Float fromResult(JavaScriptObject responseObject) {
+ return floatResult(responseObject);
+ }
+ };
+ public static final ResultDeserializer<Integer> INTEGER_INSTANCE =
+ new ResultDeserializer<Integer>() {
+ @Override
+ public Integer fromResult(JavaScriptObject responseObject) {
+ return intResult(responseObject);
+ }
+ };
+ public static final ResultDeserializer<Short> SHORT_INSTANCE =
+ new ResultDeserializer<Short>() {
+ @Override
+ public Short fromResult(JavaScriptObject responseObject) {
+ return shortResult(responseObject);
+ }
+ };
+}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/ResultDeserializer.java b/src/main/java/com/google/gwtjsonrpc/client/ResultDeserializer.java
new file mode 100644
index 0000000..87b0bbc
--- /dev/null
+++ b/src/main/java/com/google/gwtjsonrpc/client/ResultDeserializer.java
@@ -0,0 +1,28 @@
+// Copyright 2009 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.gwtjsonrpc.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+/**
+ * Inteface class for deserializers of results from JSON RPC calls. Since
+ * primitive and array results need to be handled specially, not all results can
+ * be deserialized using the standard object serializers.
+ *
+ * @param <T> the result type of an RPC call.
+ */
+public interface ResultDeserializer<T> {
+ public T fromResult(JavaScriptObject responseObject);
+}
diff --git a/src/main/java/com/google/gwtjsonrpc/client/VoidResult_JsonSerializer.java b/src/main/java/com/google/gwtjsonrpc/client/VoidResult_JsonSerializer.java
index 9bf444b..d0ab55b 100644
--- a/src/main/java/com/google/gwtjsonrpc/client/VoidResult_JsonSerializer.java
+++ b/src/main/java/com/google/gwtjsonrpc/client/VoidResult_JsonSerializer.java
@@ -14,7 +14,10 @@
package com.google.gwtjsonrpc.client;
-public class VoidResult_JsonSerializer extends JsonSerializer<VoidResult> {
+import com.google.gwt.core.client.JavaScriptObject;
+
+public class VoidResult_JsonSerializer extends JsonSerializer<VoidResult>
+ implements ResultDeserializer<VoidResult> {
public static final VoidResult_JsonSerializer INSTANCE =
new VoidResult_JsonSerializer();
@@ -30,4 +33,9 @@ public class VoidResult_JsonSerializer extends JsonSerializer<VoidResult> {
public VoidResult fromJson(final Object o) {
return VoidResult.INSTANCE;
}
+
+ @Override
+ public VoidResult fromResult(JavaScriptObject responseObject) {
+ return VoidResult.INSTANCE;
+ }
}
diff --git a/src/main/java/com/google/gwtjsonrpc/rebind/ProxyCreator.java b/src/main/java/com/google/gwtjsonrpc/rebind/ProxyCreator.java
index 16b1f23..f5ad548 100644
--- a/src/main/java/com/google/gwtjsonrpc/rebind/ProxyCreator.java
+++ b/src/main/java/com/google/gwtjsonrpc/rebind/ProxyCreator.java
@@ -45,6 +45,7 @@ class ProxyCreator {
private JClassType svcInf;
private JClassType asyncCallbackClass;
private SerializerCreator serializerCreator;
+ private ResultDeserializerCreator deserializerCreator;
private int instanceField;
ProxyCreator(final JClassType remoteService) {
@@ -54,6 +55,7 @@ class ProxyCreator {
String create(final TreeLogger logger, final GeneratorContext context)
throws UnableToCompleteException {
serializerCreator = new SerializerCreator(context);
+ deserializerCreator = new ResultDeserializerCreator(context, serializerCreator);
final TypeOracle typeOracle = context.getTypeOracle();
try {
asyncCallbackClass = typeOracle.getType(AsyncCallback.class.getName());
@@ -143,7 +145,8 @@ class ProxyCreator {
logger.branch(TreeLogger.DEBUG, m.getName() + ", parameter "
+ p.getName());
serializerCreator.checkCanSerialize(branch, p.getType());
- if (p.getType().isPrimitive() == null && !SerializerCreator.isBoxedPrimitive(p.getType())) {
+ if (p.getType().isPrimitive() == null
+ && !SerializerCreator.isBoxedPrimitive(p.getType())) {
serializerCreator.create((JClassType) p.getType(), branch);
}
}
@@ -151,13 +154,25 @@ class ProxyCreator {
final TreeLogger branch =
logger.branch(TreeLogger.DEBUG, m.getName() + ", result "
+ resultType.getQualifiedSourceName());
- // For now, extra-check on result deserialisation
- if (resultType.isArray() != null || SerializerCreator.isJsonPrimitive(resultType) || SerializerCreator.isBoxedPrimitive(resultType))
- invalid(branch, "(Boxed)Primitives and Arrays are not allowed as result values");
- else {
- serializerCreator.checkCanSerialize(branch, resultType);
- serializerCreator.create(resultType, branch);
+ // For now, extra-check on result deserialisation using CbHandles or HPC
+ if (returnsCallbackHandle(m)
+ || m.getAnnotation(HostPageCache.class) != null) {
+ if (resultType.isArray() != null
+ || SerializerCreator.isJsonPrimitive(resultType)
+ || SerializerCreator.isBoxedPrimitive(resultType))
+ invalid(branch, "GwtJsonRpc does not support (Boxed)Primitives or "
+ + "Arrays as result values using a CallbackHandle "
+ + "or HostPageCache");
}
+ serializerCreator.checkCanSerialize(branch, resultType);
+ if (resultType.isArray() != null) {
+ // Arrays need a special deserializer
+ deserializerCreator.create(branch, resultType.isArray());
+ } else if (resultType.isPrimitive() == null
+ && !SerializerCreator.isBoxedPrimitive(resultType))
+ // Non primitives get deserialized by their normal serializer
+ serializerCreator.create(resultType, branch);
+ // (Boxed)Primitives are left, they are handled specially
}
}
@@ -226,7 +241,7 @@ class ProxyCreator {
w.println(";");
}
}
- if (SerializerCreator.needsTypeParameter(resultType)) {
+ if (resultType.isParameterized() != null) {
serializerFields[params.length - 1] = "serializer_" + instanceField++;
w.print("private static final ");
w.print(JsonSerializer.class.getName());
@@ -264,6 +279,7 @@ class ProxyCreator {
w.println(") {");
w.indent();
+ // TODO: add support for non-object return values with a CallbackHandle
if (returnsCallbackHandle(method)) {
w.print("return new ");
w.print(CallbackHandle.class.getName());
@@ -280,6 +296,7 @@ class ProxyCreator {
return;
}
+ // TODO: add support for non-object return values using HostPageCache
if (hpc != null) {
final String objName = nameFactory.createName("cached");
w.print("final Object " + objName + " = ");
@@ -320,12 +337,14 @@ class ProxyCreator {
final JType pType = params[i].getType();
final String pName = params[i].getName();
- if (pType == JPrimitiveType.CHAR || SerializerCreator.isBoxedCharacter(pType)) {
+ if (pType == JPrimitiveType.CHAR
+ || SerializerCreator.isBoxedCharacter(pType)) {
w.println(reqData + ".append(\"\\\"\");");
w.println(reqData + ".append(" + JsonSerializer.class.getSimpleName()
+ ".escapeChar(" + pName + "));");
w.println(reqData + ".append(\"\\\"\");");
- } else if ((SerializerCreator.isJsonPrimitive(pType) || SerializerCreator.isBoxedPrimitive(pType))
+ } else if ((SerializerCreator.isJsonPrimitive(pType) || SerializerCreator
+ .isBoxedPrimitive(pType))
&& !SerializerCreator.isJsonString(pType)) {
w.println(reqData + ".append(" + pName + ");");
} else {
@@ -353,10 +372,10 @@ class ProxyCreator {
w.print("\"" + method.getName() + "\"");
w.print(", " + reqDataStr);
w.print(", ");
- if (SerializerCreator.needsTypeParameter(resultType)) {
+ if (resultType.isParameterized() != null) {
w.print(serializerFields[params.length - 1]);
} else {
- serializerCreator.generateSerializerReference(resultType, w);
+ deserializerCreator.generateDeserializerReference(resultType, w);
}
w.print(", " + callback.getName());
w.println(");");
diff --git a/src/main/java/com/google/gwtjsonrpc/rebind/ResultDeserializerCreator.java b/src/main/java/com/google/gwtjsonrpc/rebind/ResultDeserializerCreator.java
new file mode 100644
index 0000000..69477c0
--- /dev/null
+++ b/src/main/java/com/google/gwtjsonrpc/rebind/ResultDeserializerCreator.java
@@ -0,0 +1,210 @@
+// Copyright 2009 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.gwtjsonrpc.rebind;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JArrayType;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JType;
+import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
+import com.google.gwt.user.rebind.SourceWriter;
+import com.google.gwtjsonrpc.client.ArrayResultDeserializer;
+import com.google.gwtjsonrpc.client.JavaLangString_JsonSerializer;
+import com.google.gwtjsonrpc.client.PrimitiveArrayResultDeserializers;
+import com.google.gwtjsonrpc.client.PrimitiveResultDeserializers;
+import com.google.gwtjsonrpc.client.ResultDeserializer;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+
+/**
+ * Creator of ResultDeserializers. Actually, only object arrays have created
+ * deserializers:
+ * <ul>
+ * <li>Boxed primitives are handled by {@link PrimitiveResultDeserializers}
+ * <li>Normal objects have their (generated) serializers extending
+ * {@link com.google.gwtjsonrpc.client.ObjectSerializer}, that handle result
+ * deserialisation as well.
+ * <li>Arrays of (boxed) primitives are handled by
+ * {@link PrimitiveArrayResultDeserializers}.
+ * <li>And object arrays get a generated deserializer extending
+ * {@link ArrayResultDeserializer}
+ * </ul>
+ * All object arrays that have a JSONSerializer for the array component can be
+ * generated, but they will need to live in the same package as the serializer.
+ * To do this, if the serializer lives in the
+ * <code>com.google.gwtjsonrpc.client</code> package (where custom object
+ * serializers live), the ResultDeserializer for it's array will be placed in
+ * this package as well. Else it will be placed with the serializer in the
+ * package the object lives.
+ */
+class ResultDeserializerCreator {
+ private static final String DSER_SUFFIX = "_ResultDeserializer";
+ private static final String CUSTOM_SERIALIZER_PACKAGE =
+ JavaLangString_JsonSerializer.class.getPackage().getName();
+
+ private GeneratorContext context;
+ private HashMap<String, String> generatedDeserializers;
+ private SerializerCreator serializerCreator;
+
+ private JArrayType targetType;
+ private JType componentType;
+
+ ResultDeserializerCreator(GeneratorContext c, SerializerCreator sc) {
+ context = c;
+ generatedDeserializers = new HashMap<String, String>();
+ serializerCreator = sc;
+ }
+
+ void create(TreeLogger logger, JArrayType targetType)
+ throws UnableToCompleteException {
+ this.targetType = targetType;
+ this.componentType = targetType.getComponentType();
+
+ if (componentType.isPrimitive() != null
+ || SerializerCreator.isBoxedPrimitive(componentType)) {
+ logger.log(TreeLogger.DEBUG,
+ "No need to create array deserializer for primitive array "
+ + targetType);
+ return;
+ }
+
+ if (deserializerFor(targetType) != null) {
+ return;
+ }
+
+ logger.log(TreeLogger.DEBUG, "Creating result deserializer for "
+ + targetType.getSimpleSourceName());
+ final SourceWriter srcWriter = getSourceWriter(logger, context);
+ if (srcWriter == null) {
+ return;
+ }
+ final String dsn = getDeserializerQualifiedName(targetType);
+ generatedDeserializers.put(targetType.getQualifiedSourceName(), dsn);
+
+ generateSingleton(srcWriter);
+ generateInstanceMembers(srcWriter);
+ generateFromResult(srcWriter);
+
+ srcWriter.commit(logger);
+ }
+
+ private void generateSingleton(final SourceWriter w) {
+ w.print("public static final ");
+ w.print(getDeserializerSimpleName(targetType));
+ w.print(" INSTANCE = new ");
+ w.print(getDeserializerSimpleName(targetType));
+ w.println("();");
+ w.println();
+ }
+
+ private void generateInstanceMembers(SourceWriter w) {
+ w.print("private final ");
+ w.print(serializerCreator.serializerFor(targetType));
+ w.print(" ");
+ w.print("serializer");
+ w.print(" = ");
+ serializerCreator.generateSerializerReference(targetType, w);
+ w.println(";");
+ w.println();
+ }
+
+ private void generateFromResult(SourceWriter w) {
+ final String ctn = componentType.getQualifiedSourceName();
+
+ w.println("@Override");
+ w.print("public " + ctn + "[] ");
+ w.println("fromResult(JavaScriptObject responseObject) {");
+ w.indent();
+
+ w.print("final " + ctn + "[] tmp = new " + ctn);
+ w.println("[getResultSize(responseObject)];");
+
+ w.println("serializer.fromJson(getResult(responseObject), tmp);");
+ w.println("return tmp;");
+ w.outdent();
+
+ w.println("}");
+ }
+
+ private String getDeserializerQualifiedName(JArrayType targetType) {
+ final String pkgName = getDeserializerPackageName(targetType);
+ final String className = getDeserializerSimpleName(targetType);
+ return pkgName.length() == 0 ? className : pkgName + "." + className;
+ }
+
+ private String getDeserializerPackageName(JArrayType targetType) {
+ // Place array deserializer in same package as the component deserializer
+ final String compSerializer =
+ serializerCreator.serializerFor(targetType.getComponentType());
+ final int end = compSerializer.lastIndexOf('.');
+ return end >= 0 ? compSerializer.substring(0, end) : "";
+ }
+
+ private static String getDeserializerSimpleName(JClassType targetType) {
+ return ProxyCreator.synthesizeTopLevelClassName(targetType, DSER_SUFFIX)[1];
+ }
+
+ private SourceWriter getSourceWriter(TreeLogger logger,
+ GeneratorContext context) {
+ String pkgName = getDeserializerPackageName(targetType);
+ final String simpleName = getDeserializerSimpleName(targetType);
+ final PrintWriter pw;
+ final ClassSourceFileComposerFactory cf;
+
+ pw = context.tryCreate(logger, pkgName, simpleName);
+ if (pw == null) {
+ return null;
+ }
+
+ cf = new ClassSourceFileComposerFactory(pkgName, simpleName);
+ cf.addImport(JavaScriptObject.class.getCanonicalName());
+ cf.addImport(ResultDeserializer.class.getCanonicalName());
+
+ cf.setSuperclass(ArrayResultDeserializer.class.getCanonicalName());
+ cf.addImplementedInterface(ResultDeserializer.class.getCanonicalName()
+ + "<" + targetType.getQualifiedSourceName() + ">");
+
+ return cf.createSourceWriter(context, pw);
+ }
+
+ private String deserializerFor(JArrayType targetType) {
+ final JType componentType = targetType.getComponentType();
+ // Custom primitive deserializers
+ if (SerializerCreator.isBoxedPrimitive(componentType))
+ return PrimitiveArrayResultDeserializers.class.getCanonicalName() + "."
+ + componentType.getSimpleSourceName().toUpperCase() + "_INSTANCE";
+ final String name =
+ generatedDeserializers.get(targetType.getQualifiedSourceName());
+
+ return name == null ? null : name + ".INSTANCE";
+ }
+
+ public void generateDeserializerReference(JType targetType, SourceWriter w) {
+ if (SerializerCreator.isBoxedPrimitive(targetType)) {
+ w.print(PrimitiveResultDeserializers.class.getCanonicalName());
+ w.print(".");
+ w.print(targetType.getSimpleSourceName().toUpperCase());
+ w.print("_INSTANCE");
+ } else if (targetType.isArray() != null) {
+ w.print(deserializerFor(targetType.isArray()));
+ } else {
+ serializerCreator.generateSerializerReference(targetType, w);
+ }
+ }
+}