From 65fd05cdb8329f6b113bb17d0d4a1ea494463362 Mon Sep 17 00:00:00 2001 From: fmoga Date: Mon, 16 Aug 2010 13:51:55 +0000 Subject: Added complete javadoc. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@985927 13f79535-47bb-0310-9956-ffa450edef68 --- .../comet/runtime/CometServiceBindingProvider.java | 85 ++++++---- .../sca/binding/comet/runtime/ServletFactory.java | 147 +++++++++++----- .../comet/runtime/handler/CometBindingHandler.java | 188 +++++++++++++-------- .../runtime/javascript/JavascriptGenerator.java | 98 ++++++++--- .../runtime/javascript/JavascriptResource.java | 27 +-- 5 files changed, 371 insertions(+), 174 deletions(-) (limited to 'sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca') diff --git a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java index 1d295d9b4d..8be122d1b8 100644 --- a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java +++ b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java @@ -28,41 +28,68 @@ import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.provider.ServiceBindingProvider; import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +/** + * Provider for services having comet binding specified in the scdl. + */ public class CometServiceBindingProvider implements ServiceBindingProvider { - private RuntimeEndpoint endpoint; - private ServletHost servletHost; + /** + * Service's endpoint. + */ + private RuntimeEndpoint endpoint; + + /** + * The underlying servlet host. + */ + private ServletHost servletHost; - public CometServiceBindingProvider(RuntimeEndpoint endpoint, ServletHost servletHost) { - this.endpoint = endpoint; - this.servletHost = servletHost; - } + /** + * Constructor. + * + * @param endpoint + * the given endpoint + * @param servletHost + * the given servlet host + */ + public CometServiceBindingProvider(RuntimeEndpoint endpoint, + ServletHost servletHost) { + this.endpoint = endpoint; + this.servletHost = servletHost; + } - public void start() { - ComponentService service = endpoint.getService(); - Interface serviceInterface = service.getInterfaceContract().getInterface(); - JavascriptGenerator.generateServiceProxy(service); - for (Operation operation : serviceInterface.getOperations()) { - JavascriptGenerator.generateMethodProxy(service, operation); - ServletFactory.registerServlet(servletHost, endpoint, operation); - } - } + /** + * This method is used to start the provider. + */ + public void start() { + ComponentService service = endpoint.getService(); + Interface serviceInterface = service.getInterfaceContract() + .getInterface(); + JavascriptGenerator.generateServiceProxy(service); + for (Operation operation : serviceInterface.getOperations()) { + JavascriptGenerator.generateMethodProxy(service, operation); + ServletFactory.registerServlet(servletHost, endpoint, operation); + } + } - public void stop() { - ComponentService service = endpoint.getService(); - Interface serviceInterface = service.getInterfaceContract().getInterface(); - for (Operation op : serviceInterface.getOperations()) { - String path = service.getName() + "/" + op.getName(); - servletHost.removeServletMapping(path); - } - } + /** + * This method is used to stop the provider. + */ + public void stop() { + ComponentService service = endpoint.getService(); + Interface serviceInterface = service.getInterfaceContract() + .getInterface(); + for (Operation op : serviceInterface.getOperations()) { + String path = service.getName() + "/" + op.getName(); + servletHost.removeServletMapping(path); + } + } - public InterfaceContract getBindingInterfaceContract() { - return null; - } + public InterfaceContract getBindingInterfaceContract() { + return null; + } - public boolean supportsOneWayInvocation() { - return true; - } + public boolean supportsOneWayInvocation() { + return true; + } } diff --git a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java index 81631855bc..931333f8aa 100644 --- a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java +++ b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java @@ -28,47 +28,114 @@ import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.runtime.RuntimeEndpoint; import org.atmosphere.cpr.AtmosphereServlet; +/** + * This class is used to create two servlets: one exposing all the comet + * services, the other one exposing the javascript toolkit. + * + * Exposing all comet services through a single servlet is needed as the + * browsers are undergone by the two http connection limit so all comet services + * should send their responses via the same http connection to the same client. + * + * Dispatching to the corresponding endpoint and operation is done internally + * using Jersey RESTful Web Services integration with the AtmosphereServlet. + * + * The Javascript toolkit servlet is unique as it is not tied to any of the + * services - it offers a global API. + */ public class ServletFactory { - private static final String PACKAGE_KEY = "com.sun.jersey.config.property.packages"; - private static final String PACKAGE_VALUE = "org.apache.tuscany.sca.binding.comet.runtime.handler"; - private static final String JS_PACKAGE_VALUE = "org.apache.tuscany.sca.binding.comet.runtime.javascript"; - public static final String ENDPOINTS_KEY = "org.apache.tuscany.sca.binding.comet.endpoints"; - public static final String OPERATIONS_KEY = "org.apache.tuscany.sca.binding.comet.operations"; - public static final String JS_KEY = "org.apache.tuscany.sca.binding.comet.javascript"; - - public static final String PATH = "/tuscany-comet/*"; - public static final String JS_PATH = "/org.apache.tuscany.sca.cometComponentContext.js/*"; - - private static AtmosphereServlet cometServlet = null; - private static AtmosphereServlet javascriptServlet = null; - - public static synchronized void registerServlet(ServletHost servletHost, - RuntimeEndpoint endpoint, - Operation operation) { - if (cometServlet == null) { - cometServlet = new AtmosphereServlet(); - cometServlet.addInitParameter(PACKAGE_KEY, PACKAGE_VALUE); - servletHost.addServletMapping(PATH, cometServlet); - Map endpoints = new HashMap(); - cometServlet.getServletContext().setAttribute(ENDPOINTS_KEY, endpoints); - Map operations = new HashMap(); - cometServlet.getServletContext().setAttribute(OPERATIONS_KEY, operations); - } - String url = "/" + endpoint.getService().getName() + "/" + operation.getName(); - Map endpoints = - (Map)cometServlet.getServletContext().getAttribute(ENDPOINTS_KEY); - endpoints.put(url, endpoint); - Map operations = - (Map)cometServlet.getServletContext().getAttribute(OPERATIONS_KEY); - operations.put(url, operation); - - if (javascriptServlet == null) { - javascriptServlet = new AtmosphereServlet(); - javascriptServlet.addInitParameter(PACKAGE_KEY, JS_PACKAGE_VALUE); - servletHost.addServletMapping(JS_PATH, javascriptServlet); - javascriptServlet.getServletContext().setAttribute(JS_KEY, JavascriptGenerator.javascript); - } - } + /** + * Init-param key for the AtmosphereServlet defining where to look for + * Jersey classes. + */ + private static final String PACKAGE_KEY = "com.sun.jersey.config.property.packages"; + + /** + * Package of the class handling dispatching to endpoints. + */ + private static final String PACKAGE_VALUE = "org.apache.tuscany.sca.binding.comet.runtime.handler"; + + /** + * Package of the class handling Javascript toolkit retrieval. + */ + private static final String JS_PACKAGE_VALUE = "org.apache.tuscany.sca.binding.comet.runtime.javascript"; + + /** + * Property in the ServletContext where endpoints are added incrementally as + * the Tuscany runtime calls the CometServiceBindingProvider for each comet + * service. + */ + public static final String ENDPOINTS_KEY = "org.apache.tuscany.sca.binding.comet.endpoints"; + + /** + * Property in the ServletContext where operations are added incrementally + * as the CometServiceBindingProvider is calling the registerServlet method + * for each comet service method. + */ + public static final String OPERATIONS_KEY = "org.apache.tuscany.sca.binding.comet.operations"; + + /** + * Path where services will be exposed. + */ + public static final String PATH = "/tuscany-comet/*"; + + /** + * Path where Javascript toolkit will be exposed. + */ + public static final String JS_PATH = "/org.apache.tuscany.sca.cometComponentContext.js/*"; + + /** + * The servlet that is exposing the comet services. + */ + private static AtmosphereServlet cometServlet = null; + + /** + * The servlet that is exposing the Javascript toolkit. + */ + private static AtmosphereServlet javascriptServlet = null; + + /** + * Method called by CometServiceBindingProvider for each endpoint operation + * in order to create the two servlets and keep track of all the endpoints + * and their operations. + * + * @param servletHost + * the underlying servlet host + * @param endpoint + * the endpoint + * @param operation + * the operation + */ + public static synchronized void registerServlet(ServletHost servletHost, + RuntimeEndpoint endpoint, Operation operation) { + if (cometServlet == null) { + cometServlet = new AtmosphereServlet(); + cometServlet.addInitParameter(PACKAGE_KEY, PACKAGE_VALUE); + servletHost.addServletMapping(PATH, cometServlet); + // store operations and corresponding endpoint in the ServletContext + // so that they can be retrieved from inside the web service methods + Map endpoints = new HashMap(); + cometServlet.getServletContext().setAttribute(ENDPOINTS_KEY, + endpoints); + Map operations = new HashMap(); + cometServlet.getServletContext().setAttribute(OPERATIONS_KEY, + operations); + } + // add current operation to ServletContext + String url = "/" + endpoint.getService().getName() + "/" + + operation.getName(); + Map endpoints = (Map) cometServlet + .getServletContext().getAttribute(ENDPOINTS_KEY); + endpoints.put(url, endpoint); + Map operations = (Map) cometServlet + .getServletContext().getAttribute(OPERATIONS_KEY); + operations.put(url, operation); + + if (javascriptServlet == null) { + javascriptServlet = new AtmosphereServlet(); + javascriptServlet.addInitParameter(PACKAGE_KEY, JS_PACKAGE_VALUE); + servletHost.addServletMapping(JS_PATH, javascriptServlet); + } + } } diff --git a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java index 2e01a699a2..4d21f48c57 100644 --- a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java +++ b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java @@ -46,79 +46,135 @@ import org.atmosphere.jersey.SuspendResponse; import com.google.gson.Gson; import com.sun.jersey.spi.container.servlet.PerSession; +/** + * Class serving calls coming for comet services and operations. + */ @Path("/") @Produces("text/html;charset=ISO-8859-1") @PerSession public class CometBindingHandler { - private Broadcaster broadcaster; - private Map endpoints; - private Map operations; - private Gson gson; + /** + * The object used to suspend the response and send async responses back to + * client. + */ + private Broadcaster broadcaster; + + /** + * The service endpoints corresponding to each operation. + */ + private Map endpoints; + + /** + * The comet operations. + */ + private Map operations; + + /** + * JSON converter. + */ + private Gson gson; - @Context - private ServletContext sc; + @Context + private ServletContext sc; - @GET - public SuspendResponse connect() { - broadcaster = new DefaultBroadcaster(); - endpoints = (Map)sc.getAttribute(ServletFactory.ENDPOINTS_KEY); - operations = (Map)sc.getAttribute(ServletFactory.OPERATIONS_KEY); - gson = new Gson(); - return new SuspendResponse.SuspendResponseBuilder() - .broadcaster(broadcaster) - .outputComments(true) - .build(); - } + /** + * Method called at comet connect time. This suspends the response and keeps + * the connection opened. + * + * @return the suspended response + */ + @GET + public SuspendResponse connect() { + broadcaster = new DefaultBroadcaster(); + endpoints = (Map) sc + .getAttribute(ServletFactory.ENDPOINTS_KEY); + operations = (Map) sc + .getAttribute(ServletFactory.OPERATIONS_KEY); + gson = new Gson(); + return new SuspendResponse.SuspendResponseBuilder() + .broadcaster(broadcaster).outputComments(true).build(); + } - @POST - @Path("/{service}/{method}") - @Broadcast - public Broadcastable callAndRespond(@PathParam("service") String service, - @PathParam("method") String method, - @FormParam("callback") String callbackMethod, - @FormParam("params") String jsonData) throws InvocationTargetException { - String url = "/" + service + "/" + method; - RuntimeEndpoint wire = endpoints.get(url); - Operation operation = operations.get(url); - Object[] args = new Object[operation.getInputType().getLogical().size()]; - String[] json = parseArray(jsonData); - int index = 0; - for (DataType dataType : operation.getInputType().getLogical()) { - args[index] = gson.fromJson(json[index], dataType.getPhysical()); - index++; - } - Object response = wire.invoke(operation, args); - return new Broadcastable(callbackMethod + "($.secureEvalJSON('" + gson.toJson(response) + "'))", "", broadcaster); - } + /** + * 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}") + @Broadcast + public Broadcastable callAndRespond(@PathParam("service") String service, + @PathParam("method") String method, + @FormParam("callback") String callbackMethod, + @FormParam("params") String jsonData) + throws InvocationTargetException { + String url = "/" + service + "/" + method; + RuntimeEndpoint wire = endpoints.get(url); + Operation operation = operations.get(url); + Object[] args = new Object[operation.getInputType().getLogical().size()]; + String[] json = parseArray(jsonData); + int index = 0; + // convert each argument to the corresponding class + for (DataType dataType : operation.getInputType().getLogical()) { + args[index] = gson.fromJson(json[index], dataType.getPhysical()); + index++; + } + // invoke the service operation + Object response = wire.invoke(operation, args); + return new Broadcastable(callbackMethod + "($.secureEvalJSON('" + + gson.toJson(response) + "'))", "", broadcaster); + } - 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[] {}); - } + /** + * 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(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; + } + } + } + // add last object + objects.add(jsonArray.substring(startPos, jsonArray.length() - 1)); + return objects.toArray(new String[] {}); + } } diff --git a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java index b7c4fe88f7..4a4cadfeea 100644 --- a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java +++ b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java @@ -22,35 +22,77 @@ package org.apache.tuscany.sca.binding.comet.runtime.javascript; import org.apache.tuscany.sca.assembly.ComponentService; import org.apache.tuscany.sca.interfacedef.Operation; +/** + * This class generates proxies for the comet services. + */ public class JavascriptGenerator { - public static final String JS_NAMESPACE = "SCA"; - private static final String COMPONENT_CONTEXT = "this.CometComponentContext"; - private static final String TUSCANY_COMET = "SCA.TuscanyComet"; - - public static StringBuffer javascript = new StringBuffer(); - - public static void generateServiceProxy(ComponentService service) { - javascript.append(COMPONENT_CONTEXT + "." + service.getName() + " = new Object();\n"); - } - - public static void generateMethodProxy(ComponentService service, Operation operation) { - javascript.append(COMPONENT_CONTEXT + "." + service.getName() + "." + operation.getName() + " = function("); - for (int i = 0; i < operation.getInputType().getLogical().size(); i++) { - javascript.append("p" + i + ", "); - } - javascript.append("callbackMethod) {\n"); - javascript.append(" var params = [];\n"); - for (int i = 0; i < operation.getInputType().getLogical().size(); i++) { - javascript.append(" params.push(p" + i + ");\n"); - } - javascript.append(" " + TUSCANY_COMET - + ".callAsync('" - + service.getName() - + "/" - + operation.getName() - + "', $.toJSON(params), callbackMethod);\n"); - javascript.append("}\n"); - } + /** + * Namespace for the Tuscany Comet Javascript toolkit. + */ + public static final String JS_NAMESPACE = "SCA"; + + /** + * Name for the SCA component context. + */ + private static final String COMPONENT_CONTEXT = "this.CometComponentContext"; + + /** + * Name for the object performing comet specific tasks. + */ + private static final String TUSCANY_COMET = "SCA.TuscanyComet"; + + /** + * Generated Javascript. + */ + private static StringBuffer javascript = new StringBuffer(); + + /** + * Getter for the generated Javascript. + * + * @return the generated Javascript + */ + public static StringBuffer getJavascript() { + return javascript; + } + + /** + * Generates the proxy for a service. + * + * @param service + * the service for which generation is performed + */ + public static void generateServiceProxy(ComponentService service) { + javascript.append(COMPONENT_CONTEXT + "." + service.getName() + + " = new Object();\n"); + } + + /** + * Generates the method inside the service proxy for the specified + * operation. + * + * @param service + * the service containing the operation + * @param operation + * the operation + */ + public static void generateMethodProxy(ComponentService service, + Operation operation) { + javascript.append(COMPONENT_CONTEXT + "." + service.getName() + "." + + operation.getName() + " = function("); + for (int i = 0; i < operation.getInputType().getLogical().size(); i++) { + javascript.append("p" + i + ", "); + } + javascript.append("callbackMethod) {\n"); + // send method argumets as JSON array + javascript.append(" var params = [];\n"); + for (int i = 0; i < operation.getInputType().getLogical().size(); i++) { + javascript.append(" params.push(p" + i + ");\n"); + } + javascript.append(" " + TUSCANY_COMET + ".callAsync('" + + service.getName() + "/" + operation.getName() + + "', $.toJSON(params), callbackMethod);\n"); + javascript.append("}\n"); + } } diff --git a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java index 7360a77494..675b9838ae 100644 --- a/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java +++ b/sca-java-2.x/contrib/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java @@ -23,30 +23,34 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.SequenceInputStream; -import javax.servlet.ServletContext; import javax.ws.rs.GET; 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.PathSegment; - -import org.apache.tuscany.sca.binding.comet.runtime.ServletFactory; +/** + * Class serving the calls performed to retrieve the Javascript toolkit. + */ @Path("/") @Produces("text/javascript") public class JavascriptResource { + /** + * Dependencies for the Tuscany Comet Javascript API. + */ private static final String[] DEPENDENCIES = {"/jquery-1.4.2.min.js", "/jquery.atmosphere.js", "/jquery.json-2.2.min.js", "/cometComponentContext.js"}; - @Context - private ServletContext sc; - + /** + * Method called when the Javascript toolkit is requested. + * + * @return InputStream containing the Javascript code. + */ @GET - public InputStream getJavascript(@PathParam("file") PathSegment fileName) { + public InputStream getJavascript() { + // add namespace for embedded libraries InputStream stream = new ByteArrayInputStream(("var " + JavascriptGenerator.JS_NAMESPACE + " = new function() {\n").getBytes()); + // add dependencies in the specified order for (String dependency : DEPENDENCIES) { if (stream == null) { stream = getClass().getResourceAsStream(dependency); @@ -54,7 +58,8 @@ public class JavascriptResource { stream = new SequenceInputStream(stream, getClass().getResourceAsStream(dependency)); } } - String generatedJs = ((StringBuffer)sc.getAttribute(ServletFactory.JS_KEY)).toString() + "\n}"; + // add generated proxies + String generatedJs = JavascriptGenerator.getJavascript().toString() + "\n}"; return new SequenceInputStream(stream, new ByteArrayInputStream(generatedJs.getBytes())); } } -- cgit v1.2.3