From 74418e60f4b5caa715fc8f3fef17d354208fdb35 Mon Sep 17 00:00:00 2001 From: fmoga Date: Fri, 8 Jul 2011 04:22:43 +0000 Subject: Push fix for JSON array parser to comet binding. Refactor data conversion in the comet binding. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1144153 13f79535-47bb-0310-9956-ffa450edef68 --- .../comet/runtime/CometCallbackInvoker.java | 10 +- .../sca/binding/comet/runtime/JSONUtil.java | 127 +++++++++++++++++++++ .../comet/runtime/handler/CometBindingHandler.java | 79 +------------ 3 files changed, 133 insertions(+), 83 deletions(-) create mode 100644 sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/JSONUtil.java (limited to 'sca-java-2.x/trunk/modules/binding-comet-runtime/src') diff --git a/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometCallbackInvoker.java b/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometCallbackInvoker.java index a9d91d2f48..b973c90728 100644 --- a/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometCallbackInvoker.java +++ b/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometCallbackInvoker.java @@ -29,19 +29,11 @@ import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.Message; import org.atmosphere.cpr.Broadcaster; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - /** * Receives callback invocations and sends messages back to the browser. */ public class CometCallbackInvoker implements Invoker { - /** - * JSON converter - */ - private static Gson gson = new GsonBuilder().serializeNulls().create(); - protected Operation operation; protected EndpointReference endpoint; @@ -68,7 +60,7 @@ public class CometCallbackInvoker implements Invoker { } else { String callbackMethod = msg.getTo().getURI(); Object[] body = msg.getBody(); - broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + gson.toJson(body[0]) + "'))"); + broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + JSONUtil.encodeResponse(body[0]) + "'))"); response.setBody(Status.OK); } return response; diff --git a/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/JSONUtil.java b/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/JSONUtil.java new file mode 100644 index 0000000000..f3a1c3d884 --- /dev/null +++ b/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/JSONUtil.java @@ -0,0 +1,127 @@ +package org.apache.tuscany.sca.binding.comet.runtime; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; + +import com.google.gson.Gson; + +/** + * Helper class to facilitate JSON convertions. + */ +public class JSONUtil { + + private static Gson gson = new Gson(); + + /** + * Convert request parameters from JSON to operation parameter types. + * + * @param jsonData + * parameters in JSON array format + * @param operation + * the operation to invoke + * @return an array of objects + */ + public static Object[] decodeJsonParamsForOperation(String jsonData, Operation operation) { + Object[] args = new Object[operation.getInputType().getLogical().size()]; + final String[] json = parseArray(jsonData); + int index = 0; + for (final DataType dataType : operation.getInputType().getLogical()) { + args[index] = gson.fromJson(json[index], dataType.getPhysical()); + index++; + } + return args; + } + + /** + * Split the JSON array containing the arguments for the method call in + * order to avoid converting JSON to Object[]. Converting each object + * separately to it's corresponding type avoids type mismatch problems at + * service invocation. + * + * @param jsonArray + * the JSON array + * @return an array of JSON formatted strings + */ + private static String[] parseArray(String jsonArray) { + List objects = new ArrayList(); + int bracketNum = 0; + int parNum = 0; + int quoteNum = 0; + int startPos = 1; + for (int i = 0; i < jsonArray.length(); i++) { + switch (jsonArray.charAt(i)) { + case '{': + bracketNum++; + break; + case '}': + bracketNum--; + break; + case '[': + parNum++; + break; + case ']': + parNum--; + break; + case '\"': + quoteNum++; + break; + case ',': + if ((bracketNum == 0) && (parNum == 1) && quoteNum % 2 == 0) { + objects.add(jsonArray.substring(startPos, i)); + startPos = i + 1; + } + } + } + objects.add(jsonArray.substring(startPos, jsonArray.length() - 1)); + return objects.toArray(new String[] {}); + } + + private JSONUtil() { + } + + /** + * Converts a Java object to JSON format. + * + * @param response + * the response to convert + * @return the object in JSON format + */ + public static String encodeResponse(Object response) { + return gson.toJson(response); + } + + /** + * Convert request parameters as JSON array. + * + * @param params + * request parameters + * @return request parameters as JSON array + */ + public static String encodeRequestParams(Object[] params) { + StringBuilder builder = new StringBuilder(); + for (int index = 0; index < params.length; index++) { + Object param = params[index]; + builder.append(index == 0 ? "[" : ","); + builder.append(gson.toJson(param)); + } + builder.append("]"); + return builder.toString(); + } + + /** + * Decode JSON to a given Java type. + * + * @param responseJSON + * the json to convert + * @param returnType + * the return type to convert to + * @return the converted object + */ + public static Object decodeResponse(String responseJSON, Class returnType) { + return gson.fromJson(responseJSON, returnType); + } + +} diff --git a/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java b/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java index 7c23a4e73b..0c9902211c 100644 --- a/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java +++ b/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java @@ -20,8 +20,6 @@ package org.apache.tuscany.sca.binding.comet.runtime.handler; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; import javax.ws.rs.FormParam; import javax.ws.rs.GET; @@ -31,6 +29,7 @@ import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.binding.comet.runtime.JSONUtil; import org.apache.tuscany.sca.binding.comet.runtime.manager.CometEndpointManager; import org.apache.tuscany.sca.binding.comet.runtime.manager.CometOperationManager; import org.apache.tuscany.sca.binding.comet.runtime.manager.CometSessionManager; @@ -38,31 +37,22 @@ import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointImpl; import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl; import org.apache.tuscany.sca.core.invocation.Constants; import org.apache.tuscany.sca.core.invocation.impl.MessageImpl; -import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.invocation.Message; import org.apache.tuscany.sca.runtime.RuntimeEndpoint; import org.atmosphere.cpr.Broadcaster; import org.atmosphere.cpr.BroadcasterLifeCyclePolicy; -import org.atmosphere.cpr.BroadcasterLifeCyclePolicyListener; import org.atmosphere.cpr.BroadcasterLifeCyclePolicy.ATMOSPHERE_RESOURCE_POLICY; +import org.atmosphere.cpr.BroadcasterLifeCyclePolicyListener; import org.atmosphere.jersey.JerseyBroadcaster; import org.atmosphere.jersey.SuspendResponse; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - /** * Handles requests for comet services and for creating a persistent connection. */ @Path("/") public class CometBindingHandler { - /** - * JSON converter - */ - private static Gson gson = new GsonBuilder().serializeNulls().create(); - /** * Suspends the current HTTP connection. * @@ -111,14 +101,15 @@ public class CometBindingHandler { RuntimeEndpoint wire = CometEndpointManager.get(url); Operation operation = CometOperationManager.get(url); - final Object[] args = decodeJsonDataForOperation(jsonData, operation); + final Object[] args = JSONUtil.decodeJsonParamsForOperation(jsonData, operation); Message msg = createMessageWithMockedCometReference(args, sessionId, callbackMethod); boolean isVoidReturnType = operation.getOutputType().getLogical().isEmpty(); if (!isVoidReturnType) { Object response = wire.invoke(operation, args); Broadcaster broadcaster = CometSessionManager.get(sessionId); if (broadcaster != null) { - broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + gson.toJson(response) + "'))"); + broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + JSONUtil.encodeResponse(response) + + "'))"); } } else { wire.invoke(operation, msg); @@ -151,66 +142,6 @@ public class CometBindingHandler { return msg; } - /** - * Convert request parameters from JSON to operation parameter types. - * - * @param jsonData - * parameters in JSON array format - * @param operation - * the operation to invoke - * @return an array of objects - */ - private Object[] decodeJsonDataForOperation(String jsonData, Operation operation) { - Object[] args = new Object[operation.getInputType().getLogical().size()]; - final String[] json = this.parseArray(jsonData); - int index = 0; - for (final DataType dataType : operation.getInputType().getLogical()) { - args[index] = gson.fromJson(json[index], dataType.getPhysical()); - index++; - } - return args; - } - - /** - * Split the JSON array containing the arguments for the method call in - * order to avoid converting JSON to Object[]. Converting each object - * separately to it's corresponding type avoids type mismatch problems at - * service invocation. - * - * @param jsonArray - * the JSON array - * @return an array of JSON formatted strings - */ - private String[] parseArray(String jsonArray) { - List objects = new ArrayList(); - int bracketNum = 0; - int parNum = 0; - int startPos = 1; - for (int i = 0; i < jsonArray.length(); i++) { - switch (jsonArray.charAt(i)) { - case '{': - bracketNum++; - break; - case '}': - bracketNum--; - break; - case '[': - parNum++; - break; - case ']': - parNum--; - break; - case ',': - if ((bracketNum == 0) && (parNum == 1)) { - objects.add(jsonArray.substring(startPos, i)); - startPos = i + 1; - } - } - } - objects.add(jsonArray.substring(startPos, jsonArray.length() - 1)); - return objects.toArray(new String[] {}); - } - public class CometBroadcasterLifeCyclePolicyListener implements BroadcasterLifeCyclePolicyListener { private String sessionId; -- cgit v1.2.3