diff options
Diffstat (limited to 'sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java')
-rw-r--r-- | sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java | 316 |
1 files changed, 128 insertions, 188 deletions
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 3cd90304b8..c2d2181814 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 @@ -19,26 +19,21 @@ package org.apache.tuscany.sca.binding.comet.runtime.handler; -import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; -import java.util.UUID; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; +import javax.ws.rs.QueryParam; import org.apache.tuscany.sca.assembly.EndpointReference; -import org.apache.tuscany.sca.binding.comet.runtime.CometComponentContext; -import org.apache.tuscany.sca.binding.comet.runtime.ServletFactory; +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; 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; @@ -51,186 +46,131 @@ import org.atmosphere.cpr.Broadcaster; import org.atmosphere.jersey.JerseyBroadcaster; import org.atmosphere.jersey.SuspendResponse; -import com.sun.jersey.spi.container.servlet.PerSession; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; -/** - * Class serving calls coming for comet services and operations. - */ @Path("/") -@Produces("text/html;charset=ISO-8859-1") -@PerSession -public class CometBindingHandler implements Serializable { - - /** - * The object used to suspend the response and send async responses back to - * client. - */ - private Broadcaster broadcaster; - - /** - * The underlying servlet context. - */ - @Context - private ServletContext sc; - - @Context - private HttpServletRequest request; - - private CometComponentContext context; - - @GET - @Path("/sessionId") - @Produces(MediaType.TEXT_PLAIN) - public String establishSessionId() { - request.getSession().invalidate(); - request.getSession(true); - return "OK"; - } - - /** - * Method called at comet connect time. This suspends the response and keeps - * the connection opened. - * - * @return the suspended response - */ - @GET - @Path("/connect") - public SuspendResponse<String> connect() { - // System.out.println("-- connect -- Session Id: " + - // request.getSession().getId()); - if (broadcaster == null) { - broadcaster = new JerseyBroadcaster(UUID.randomUUID().toString()); - // broadcaster.setBroadcasterLifeCyclePolicy(new - // Builder().policy(ATMOSPHERE_RESOURCE_POLICY.IDLE_DESTROY) - // .idleTimeInMS(5000).build()); - context = (CometComponentContext) sc.getAttribute(ServletFactory.COMET_COMPONENT_CONTEXT_KEY); - } - CometComponentContext.broadcasters.put(request.getSession().getId(), broadcaster); - return new SuspendResponse.SuspendResponseBuilder<String>().broadcaster(this.broadcaster).outputComments(true) - .build(); - } - - /** - * Method called on service calls. - * - * @param service - * service called - * @param method - * operation called - * @param callbackMethod - * the callback method from Javascript - * @param jsonData - * arguments for the method sent as JSON array - * @return object used by the Broadcaster to send response through the - * persisted connection - * @throws InvocationTargetException - * if problems occur at service invocation - */ - @POST - @Path("/{service}/{method}") - public void handleRequest(@PathParam("service") final String service, @PathParam("method") final String method, - @FormParam("callbackMethod") final String callbackMethod, @FormParam("params") final String jsonData) - throws InvocationTargetException { - // System.out.println("-- handleRequest -- Session Id: " + - // request.getSession().getId()); - final String url = "/" + service + "/" + method; - final RuntimeEndpoint wire = context.getEndpoint(url); - final Operation operation = context.getOperation(url); - - final Object[] args = decodeJsonDataForOperation(jsonData, operation); - Message msg = createMessageWithMockedCometReference(args, callbackMethod); - boolean isVoidReturnType = operation.getOutputType().getLogical().isEmpty(); - if (!isVoidReturnType) { - Object response = wire.invoke(operation, args); - broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + CometComponentContext.gson.toJson(response) - + "'))"); - if (broadcaster.getAtmosphereResources().isEmpty()) { - CometComponentContext.broadcasters.remove(request.getSession().getId()); - } - } else { - wire.invoke(operation, msg); - } - } - - /** - * Convert request parameters from JSON to operation parameter types. - * - * @param jsonData - * @param operation - * @return - */ - private Object[] decodeJsonDataForOperation(String jsonData, Operation operation) { - Object[] args = new Object[operation.getInputType().getLogical().size()]; - final String[] json = this.parseArray(jsonData); - int index = 0; - // convert each argument to the corresponding class - for (final DataType<?> dataType : operation.getInputType().getLogical()) { - args[index] = CometComponentContext.gson.fromJson(json[index], dataType.getPhysical()); - index++; - } - return args; - } - - /** - * Creates the message to be sent with a mocked EndpointReference in the - * 'from' field as the request comes from a browser (there is no actual - * comet reference running in a controlled environment). - * - * @param args - * @param callbackMethod - * @return - */ - private Message createMessageWithMockedCometReference(Object[] args, String callbackMethod) { - Message msg = new MessageImpl(); - msg.getHeaders().put(Constants.MESSAGE_ID, request.getSession().getId()); - msg.setBody(args); - EndpointReference re = new RuntimeEndpointReferenceImpl(); - RuntimeEndpointImpl callbackEndpoint = new RuntimeEndpointImpl(); - callbackEndpoint.setURI(callbackMethod); - re.setCallbackEndpoint(callbackEndpoint); - msg.setFrom(re); - return msg; - } - - /** - * Parse 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 objects - */ - private String[] parseArray(final String jsonArray) { - final List<String> objects = new ArrayList<String>(); - 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; - } - } - } - // add last object - objects.add(jsonArray.substring(startPos, jsonArray.length() - 1)); - return objects.toArray(new String[] {}); - } +public class CometBindingHandler { + + private static Gson gson = new GsonBuilder().serializeNulls().create(); + + @GET + @Path("/connect") + public SuspendResponse<String> connect(@QueryParam("sessionId") String sessionId) { + System.out.println("-- connect -- Session Id: " + sessionId); + Broadcaster broadcaster = CometSessionManager.get(sessionId); + if (broadcaster == null) { + broadcaster = new JerseyBroadcaster(sessionId); + CometSessionManager.add(sessionId, broadcaster); + } + return new SuspendResponse.SuspendResponseBuilder<String>().broadcaster(broadcaster).outputComments(true) + .build(); + } + + @POST + @Path("/{service}/{method}") + public void handleRequest(@PathParam("service") String service, @PathParam("method") String method, + @FormParam("sessionId") String sessionId, @FormParam("callbackMethod") String callbackMethod, + @FormParam("params") String jsonData) throws InvocationTargetException { + System.out.println("-- handleRequest -- Session Id: " + sessionId); + String url = "/" + service + "/" + method; + RuntimeEndpoint wire = CometEndpointManager.get(url); + Operation operation = CometOperationManager.get(url); + + final Object[] args = decodeJsonDataForOperation(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); + broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + gson.toJson(response) + "'))"); + if (broadcaster.getAtmosphereResources().isEmpty()) { + CometSessionManager.remove(sessionId); + } + } else { + wire.invoke(operation, msg); + } + } + + /** + * Convert request parameters from JSON to operation parameter types. + * + * @param jsonData + * @param operation + * @return + */ + private Object[] decodeJsonDataForOperation(String jsonData, Operation operation) { + Object[] args = new Object[operation.getInputType().getLogical().size()]; + final String[] json = this.parseArray(jsonData); + int index = 0; + // convert each argument to the corresponding class + for (final DataType<?> dataType : operation.getInputType().getLogical()) { + args[index] = gson.fromJson(json[index], dataType.getPhysical()); + index++; + } + return args; + } + + /** + * Creates the message to be sent with a mocked EndpointReference in the + * 'from' field as the request comes from a browser (there is no actual + * comet reference running in a controlled environment). + * + * @param args + * @param callbackMethod + * @return + */ + private Message createMessageWithMockedCometReference(Object[] args, String sessionId, String callbackMethod) { + Message msg = new MessageImpl(); + msg.getHeaders().put(Constants.MESSAGE_ID, sessionId); + msg.setBody(args); + EndpointReference re = new RuntimeEndpointReferenceImpl(); + RuntimeEndpointImpl callbackEndpoint = new RuntimeEndpointImpl(); + callbackEndpoint.setURI(callbackMethod); + re.setCallbackEndpoint(callbackEndpoint); + msg.setFrom(re); + return msg; + } + + /** + * Parse 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 objects + */ + private String[] parseArray(final String jsonArray) { + final List<String> objects = new ArrayList<String>(); + 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; + } + } + } + // add last object + objects.add(jsonArray.substring(startPos, jsonArray.length() - 1)); + return objects.toArray(new String[] {}); + } } |