summaryrefslogtreecommitdiffstats
path: root/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca')
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometBindingProviderFactory.java72
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java62
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java72
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java90
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java155
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java174
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java107
-rw-r--r--sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java63
8 files changed, 795 insertions, 0 deletions
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometBindingProviderFactory.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometBindingProviderFactory.java
new file mode 100644
index 0000000000..fc5fd9f371
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometBindingProviderFactory.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.tuscany.sca.binding.comet.runtime;
+
+import org.apache.tuscany.sca.binding.comet.CometBinding;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.host.http.ServletHostHelper;
+import org.apache.tuscany.sca.provider.BindingProviderFactory;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+
+/**
+ * Factory for binding providers.
+ */
+public class CometBindingProviderFactory implements BindingProviderFactory<CometBinding> {
+
+ /**
+ * Underlying servlet host. Injected by constructor.
+ */
+ private final ServletHost servletHost;
+
+ /**
+ * Constructor.
+ */
+ public CometBindingProviderFactory(final ExtensionPointRegistry extensionPoints) {
+ this.servletHost = ServletHostHelper.getServletHost(extensionPoints);
+ }
+
+ @Override
+ public Class<CometBinding> getModelType() {
+ return CometBinding.class;
+ }
+
+ /**
+ * Creates a provider for a reference that has comet binding specified in
+ * the scdl.
+ */
+ @Override
+ public ReferenceBindingProvider createReferenceBindingProvider(final RuntimeEndpointReference endpoint) {
+ return new CometReferenceBindingProvider(endpoint);
+ }
+
+ /**
+ * Creates a provider for a service that has comet binding specified in the
+ * scdl.
+ */
+ @Override
+ public ServiceBindingProvider createServiceBindingProvider(final RuntimeEndpoint endpoint) {
+ return new CometServiceBindingProvider(endpoint, this.servletHost);
+ }
+
+}
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java
new file mode 100644
index 0000000000..9353571cb1
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.tuscany.sca.binding.comet.runtime;
+
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+
+/**
+ * Invoker for a service binding. Invoking is made from client Javascript so no
+ * behavior is needed.
+ */
+public class CometInvoker implements Invoker {
+
+ /**
+ * The invoked operation.
+ */
+ protected Operation operation;
+
+ /**
+ * The endpoint to which the operation belongs.
+ */
+ protected EndpointReference endpoint;
+
+ /**
+ * Default constructor.
+ *
+ * @param operation the operation
+ * @param endpoint the endpoint
+ */
+ public CometInvoker(final Operation operation, final EndpointReference endpoint) {
+ this.operation = operation;
+ this.endpoint = endpoint;
+ }
+
+ /**
+ * No behavior.
+ */
+ @Override
+ public Message invoke(final Message msg) {
+ return null;
+ }
+
+}
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java
new file mode 100644
index 0000000000..17470e3738
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.tuscany.sca.binding.comet.runtime;
+
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+
+/**
+ * Provider for references that have comet binding specified in the scdl. Not
+ * used as comet binding references would occur in client browser's Javascript.
+ */
+public class CometReferenceBindingProvider implements ReferenceBindingProvider {
+
+ /**
+ * Endpoint for which the binding provider is created.
+ */
+ private final EndpointReference endpoint;
+
+ public CometReferenceBindingProvider(final EndpointReference endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ @Override
+ public Invoker createInvoker(final Operation operation) {
+ return new CometInvoker(operation, this.endpoint);
+ }
+
+ /**
+ * No behavior.
+ */
+ @Override
+ public void start() {
+ }
+
+ /**
+ * No behavior.
+ */
+ @Override
+ public void stop() {
+ }
+
+ @Override
+ public InterfaceContract getBindingInterfaceContract() {
+ return null;
+ }
+
+ @Override
+ public boolean supportsOneWayInvocation() {
+ return true;
+ }
+
+}
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java
new file mode 100644
index 0000000000..31c0b5b4d8
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.tuscany.sca.binding.comet.runtime;
+
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.binding.comet.runtime.javascript.JavascriptGenerator;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+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 {
+
+ /**
+ * Service's endpoint.
+ */
+ private final RuntimeEndpoint endpoint;
+
+ /**
+ * The underlying servlet host.
+ */
+ private final ServletHost servletHost;
+
+ /**
+ * Constructor.
+ *
+ * @param endpoint the given endpoint
+ * @param servletHost the given servlet host
+ */
+ public CometServiceBindingProvider(final RuntimeEndpoint endpoint, final ServletHost servletHost) {
+ this.endpoint = endpoint;
+ this.servletHost = servletHost;
+ }
+
+ /**
+ * This method is used to start the provider.
+ */
+ @Override
+ public void start() {
+ ServletFactory.registerServlet(this.servletHost);
+ final ComponentService service = this.endpoint.getService();
+ final Interface serviceInterface = service.getInterfaceContract().getInterface();
+ JavascriptGenerator.generateServiceProxy(service);
+ for (final Operation operation : serviceInterface.getOperations()) {
+ JavascriptGenerator.generateMethodProxy(service, operation);
+ ServletFactory.addOperation(this.endpoint, operation);
+ }
+ }
+
+ /**
+ * This method is used to stop the provider.
+ */
+ @Override
+ public void stop() {
+ ServletFactory.unregisterServlet(this.servletHost);
+ }
+
+ @Override
+ public InterfaceContract getBindingInterfaceContract() {
+ return null;
+ }
+
+ @Override
+ public boolean supportsOneWayInvocation() {
+ return true;
+ }
+
+}
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java
new file mode 100644
index 0000000000..c1244b3183
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.tuscany.sca.binding.comet.runtime;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.host.http.ServletHost;
+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 final class ServletFactory {
+
+ /**
+ * 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;
+
+ /**
+ * Private constructor for the singleton class.
+ */
+ private ServletFactory() {
+ }
+
+ /**
+ * Method called by CometServiceBindingProvider for each endpoint in order
+ * to create the two singleton servlets.
+ *
+ * @param servletHost the underlying servlet host
+ */
+ public static synchronized void registerServlet(final ServletHost servletHost) {
+ if (ServletFactory.cometServlet == null) {
+ ServletFactory.cometServlet = new AtmosphereServlet();
+ ServletFactory.cometServlet.addInitParameter(ServletFactory.PACKAGE_KEY, ServletFactory.PACKAGE_VALUE);
+ servletHost.addServletMapping(ServletFactory.PATH, ServletFactory.cometServlet);
+ // store operations and corresponding endpoint in the ServletContext
+ // so that they can be retrieved from inside the web service methods
+ final Map<String, RuntimeEndpoint> endpoints = new HashMap<String, RuntimeEndpoint>();
+ ServletFactory.cometServlet.getServletContext().setAttribute(ServletFactory.ENDPOINTS_KEY, endpoints);
+ final Map<String, Operation> operations = new HashMap<String, Operation>();
+ ServletFactory.cometServlet.getServletContext().setAttribute(ServletFactory.OPERATIONS_KEY, operations);
+ }
+ if (ServletFactory.javascriptServlet == null) {
+ ServletFactory.javascriptServlet = new AtmosphereServlet();
+ ServletFactory.javascriptServlet.addInitParameter(ServletFactory.PACKAGE_KEY,
+ ServletFactory.JS_PACKAGE_VALUE);
+ servletHost.addServletMapping(ServletFactory.JS_PATH, ServletFactory.javascriptServlet);
+ }
+ }
+
+ /**
+ * Method called by CometServiceBindingProvider for each endpoint operation
+ * in order to store all the operations the servlet will serve.
+ *
+ * @param endpoint the endpoint
+ * @param operation the operation
+ */
+ public static synchronized void addOperation(final RuntimeEndpoint endpoint, final Operation operation) {
+ final String url = "/" + endpoint.getService().getName() + "/" + operation.getName();
+ final Map<String, RuntimeEndpoint> endpoints =
+ (Map<String, RuntimeEndpoint>)ServletFactory.cometServlet.getServletContext()
+ .getAttribute(ServletFactory.ENDPOINTS_KEY);
+ endpoints.put(url, endpoint);
+ final Map<String, Operation> operations =
+ (Map<String, Operation>)ServletFactory.cometServlet.getServletContext()
+ .getAttribute(ServletFactory.OPERATIONS_KEY);
+ operations.put(url, operation);
+ }
+
+ /**
+ * Method called by CometServiceBindingProvider for each endpoint operation
+ * in order to remove the two servlets.
+ *
+ * @param servletHost the underlying servlet host
+ */
+ public static synchronized void unregisterServlet(final ServletHost servletHost) {
+ servletHost.removeServletMapping(ServletFactory.PATH);
+ servletHost.removeServletMapping(ServletFactory.JS_PATH);
+ }
+
+}
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java
new file mode 100644
index 0000000000..512b834840
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.tuscany.sca.binding.comet.runtime.handler;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+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 org.apache.tuscany.sca.binding.comet.runtime.ServletFactory;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.atmosphere.annotation.Broadcast;
+import org.atmosphere.cpr.Broadcaster;
+import org.atmosphere.cpr.DefaultBroadcaster;
+import org.atmosphere.jersey.Broadcastable;
+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 {
+
+ /**
+ * 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<String, RuntimeEndpoint> endpoints;
+
+ /**
+ * The comet operations.
+ */
+ private Map<String, Operation> operations;
+
+ /**
+ * JSON converter.
+ */
+ private Gson gson;
+
+ /**
+ * The underlying servlet context.
+ */
+ @Context
+ private ServletContext sc;
+
+ /**
+ * Method called at comet connect time. This suspends the response and keeps
+ * the connection opened.
+ *
+ * @return the suspended response
+ */
+ @GET
+ public SuspendResponse<String> connect() {
+ this.broadcaster = new DefaultBroadcaster();
+ this.endpoints = (Map<String, RuntimeEndpoint>)this.sc.getAttribute(ServletFactory.ENDPOINTS_KEY);
+ this.operations = (Map<String, Operation>)this.sc.getAttribute(ServletFactory.OPERATIONS_KEY);
+ this.gson = new Gson();
+ 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}")
+ @Broadcast
+ public Broadcastable callAndRespond(@PathParam("service") final String service,
+ @PathParam("method") final String method,
+ @FormParam("callback") final String callbackMethod,
+ @FormParam("params") final String jsonData) throws InvocationTargetException {
+ final String url = "/" + service + "/" + method;
+ final RuntimeEndpoint wire = this.endpoints.get(url);
+ final Operation operation = this.operations.get(url);
+ final 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] = this.gson.fromJson(json[index], dataType.getPhysical());
+ index++;
+ }
+ // invoke the service operation
+ final Object response = wire.invoke(operation, args);
+ return new Broadcastable(callbackMethod + "($.secureEvalJSON('" + this.gson.toJson(response) + "'))", "",
+ this.broadcaster);
+ }
+
+ /**
+ * 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[] {});
+ }
+}
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java
new file mode 100644
index 0000000000..b1205596ea
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptGenerator.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 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 {
+
+ /**
+ * 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();
+
+ /**
+ * Default constructor for utility class.
+ */
+ private JavascriptGenerator() {
+ }
+
+ /**
+ * Getter for the generated Javascript.
+ *
+ * @return the generated Javascript
+ */
+ public static StringBuffer getJavascript() {
+ return JavascriptGenerator.javascript;
+ }
+
+ /**
+ * Generates the proxy for a service.
+ *
+ * @param service the service for which generation is performed
+ */
+ public static void generateServiceProxy(final ComponentService service) {
+ JavascriptGenerator.javascript.append(JavascriptGenerator.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(final ComponentService service, final Operation operation) {
+ JavascriptGenerator.javascript.append(JavascriptGenerator.COMPONENT_CONTEXT + "."
+ + service.getName()
+ + "."
+ + operation.getName()
+ + " = function(");
+ for (int i = 0; i < operation.getInputType().getLogical().size(); i++) {
+ JavascriptGenerator.javascript.append("p" + i + ", ");
+ }
+ JavascriptGenerator.javascript.append("callbackMethod) {\n");
+ // send method argumets as JSON array
+ JavascriptGenerator.javascript.append(" var params = [];\n");
+ for (int i = 0; i < operation.getInputType().getLogical().size(); i++) {
+ JavascriptGenerator.javascript.append(" params.push(p" + i + ");\n");
+ }
+ JavascriptGenerator.javascript.append(" " + JavascriptGenerator.TUSCANY_COMET
+ + ".callAsync('"
+ + service.getName()
+ + "/"
+ + operation.getName()
+ + "', $.toJSON(params), callbackMethod);\n");
+ JavascriptGenerator.javascript.append("}\n");
+ }
+
+}
diff --git a/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java
new file mode 100644
index 0000000000..9274009803
--- /dev/null
+++ b/sandbox/sebastien/java/wrapped/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/javascript/JavascriptResource.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.tuscany.sca.binding.comet.runtime.javascript;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * 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.atmosphere.js", "/jquery.json-2.2.min.js",
+ "/cometComponentContext.js"};
+
+ /**
+ * Method called when the Javascript toolkit is requested.
+ *
+ * @return InputStream containing the Javascript code.
+ */
+ @GET
+ public InputStream getJavascript() {
+ InputStream stream = null;
+ // add dependencies in the specified order
+ for (final String dependency : JavascriptResource.DEPENDENCIES) {
+ if (stream == null) {
+ stream = this.getClass().getResourceAsStream(dependency);
+ } else {
+ stream = new SequenceInputStream(stream, this.getClass().getResourceAsStream(dependency));
+ }
+ }
+ // add generated proxies
+ final String generatedJs = JavascriptGenerator.getJavascript().toString() + "\n}";
+ return new SequenceInputStream(stream, new ByteArrayInputStream(generatedJs.getBytes()));
+ }
+}