Author: fmoga
Date: Fri Feb 11 20:06:28 2011
New Revision: 1069936

URL: http://svn.apache.org/viewvc?rev=1069936&view=rev
Log:
Added multiple response support for the comet binding.

Added:
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometComponentContext.java
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometMessageContext.java
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/callback/
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/callback/CometCallback.java
Modified:
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java
    
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java

Added: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometComponentContext.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometComponentContext.java?rev=1069936&view=auto
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometComponentContext.java
 (added)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometComponentContext.java
 Fri Feb 11 20:06:28 2011
@@ -0,0 +1,54 @@
+/*
+ * 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.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+
+public class CometComponentContext {
+
+       private Map<String, RuntimeEndpoint> endpoints;
+       private Map<String, Operation> operations;
+
+       public CometComponentContext() {
+               endpoints = new ConcurrentHashMap<String, RuntimeEndpoint>();
+               operations = new ConcurrentHashMap<String, Operation>();
+       }
+
+       public void addEndpoint(String key, RuntimeEndpoint endpoint) {
+               endpoints.put(key, endpoint);
+       }
+
+       public void addOperation(String key, Operation operation) {
+               operations.put(key, operation);
+       }
+
+       public RuntimeEndpoint getEndpoint(String key) {
+               return endpoints.get(key);
+       }
+
+       public Operation getOperation(String key) {
+               return operations.get(key);
+       }
+
+}

Modified: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java?rev=1069936&r1=1069935&r2=1069936&view=diff
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java
 (original)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometInvoker.java
 Fri Feb 11 20:06:28 2011
@@ -20,43 +20,36 @@
 package org.apache.tuscany.sca.binding.comet.runtime;
 
 import org.apache.tuscany.sca.assembly.EndpointReference;
+import 
org.apache.tuscany.sca.binding.comet.runtime.handler.CometBindingHandler;
+import org.apache.tuscany.sca.core.invocation.impl.MessageImpl;
 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;
-    }
+       protected Operation operation;
+       protected EndpointReference endpoint;
+
+       public CometInvoker(final Operation operation, final EndpointReference 
endpoint) {
+               this.operation = operation;
+               this.endpoint = endpoint;
+       }
+
+       @Override
+       public Message invoke(final Message msg) {
+               String operation = msg.getOperation().getName();
+               CometMessageContext context = msg.getBindingContext();
+               CometBindingHandler handler = context.getCometHandler();
+               Message message = new MessageImpl();
+               if (operation.equals("sendResponse")) {
+                       String callbackMethod = context.getCallbackMethod();
+                       Object[] body = msg.getBody();
+                       handler.respondToClient(callbackMethod, body[0]);
+               } else if (operation.equals("isClientConnected")) {
+                       message.setBody(handler.isClientConnected());
+               }
+               return message;
+       }
 
 }

Added: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometMessageContext.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometMessageContext.java?rev=1069936&view=auto
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometMessageContext.java
 (added)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometMessageContext.java
 Fri Feb 11 20:06:28 2011
@@ -0,0 +1,51 @@
+/*
+ * 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.runtime.handler.CometBindingHandler;
+
+public class CometMessageContext {
+
+       private CometBindingHandler cometHandler;
+
+       private String callbackMethod;
+
+       public CometMessageContext(CometBindingHandler cometHandler, String 
callbackMethod) {
+               this.cometHandler = cometHandler;
+               this.callbackMethod = callbackMethod;
+       }
+
+       public CometBindingHandler getCometHandler() {
+               return cometHandler;
+       }
+
+       public void setCometHandler(CometBindingHandler cometHandler) {
+               this.cometHandler = cometHandler;
+       }
+
+       public String getCallbackMethod() {
+               return callbackMethod;
+       }
+
+       public void setCallbackMethod(String callbackMethod) {
+               this.callbackMethod = callbackMethod;
+       }
+
+}

Modified: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java?rev=1069936&r1=1069935&r2=1069936&view=diff
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java
 (original)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometReferenceBindingProvider.java
 Fri Feb 11 20:06:28 2011
@@ -61,7 +61,7 @@ public class CometReferenceBindingProvid
 
     @Override
     public InterfaceContract getBindingInterfaceContract() {
-        return null;
+        return endpoint.getReference().getInterfaceContract();
     }
 
     @Override

Modified: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java?rev=1069936&r1=1069935&r2=1069936&view=diff
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java
 (original)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/CometServiceBindingProvider.java
 Fri Feb 11 20:06:28 2011
@@ -65,7 +65,7 @@ public class CometServiceBindingProvider
         JavascriptGenerator.generateServiceProxy(service);
         for (final Operation operation : serviceInterface.getOperations()) {
             JavascriptGenerator.generateMethodProxy(service, operation);
-            ServletFactory.addOperation(this.endpoint, operation);
+            ServletFactory.registerOperation(this.endpoint, operation);
         }
     }
 
@@ -79,7 +79,7 @@ public class CometServiceBindingProvider
 
     @Override
     public InterfaceContract getBindingInterfaceContract() {
-        return null;
+        return endpoint.getService().getInterfaceContract();
     }
 
     @Override

Modified: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java?rev=1069936&r1=1069935&r2=1069936&view=diff
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java
 (original)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/ServletFactory.java
 Fri Feb 11 20:06:28 2011
@@ -19,9 +19,6 @@
 
 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;
@@ -40,116 +37,121 @@ import org.atmosphere.cpr.AtmosphereServ
  */
 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);
-    }
+       /**
+        * 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";
+
+       /**
+        * Key in the ServletContext where the comet component context is 
stored.
+        */
+       public static final String COMET_COMPONENT_CONTEXT_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) {
+               registerCometServlet(servletHost);
+               registerJavascriptServlet(servletHost);
+       }
+
+       private static void registerCometServlet(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);
+                       final CometComponentContext context = new 
CometComponentContext();
+                       
ServletFactory.cometServlet.getServletContext().setAttribute(
+                                       
ServletFactory.COMET_COMPONENT_CONTEXT_KEY, context);
+               }
+       }
+
+       private static void registerJavascriptServlet(ServletHost servletHost) {
+               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 void registerOperation(final RuntimeEndpoint endpoint,
+                       final Operation operation) {
+               final String url = "/" + endpoint.getService().getName() + "/"
+                               + operation.getName();
+               CometComponentContext context = (CometComponentContext) 
cometServlet
+                               
.getServletContext().getAttribute(COMET_COMPONENT_CONTEXT_KEY);
+               context.addEndpoint(url, endpoint);
+               context.addOperation(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 void unregisterServlet(final ServletHost servletHost) {
+               synchronized (servletHost) {
+                       servletHost.removeServletMapping(ServletFactory.PATH);
+                       
servletHost.removeServletMapping(ServletFactory.JS_PATH);
+               }
+       }
 
 }

Added: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/callback/CometCallback.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/callback/CometCallback.java?rev=1069936&view=auto
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/callback/CometCallback.java
 (added)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/callback/CometCallback.java
 Fri Feb 11 20:06:28 2011
@@ -0,0 +1,31 @@
+/*
+ * 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.callback;
+
+import org.oasisopen.sca.annotation.Remotable;
+
+@Remotable
+public interface CometCallback {
+
+       void sendResponse(Object response);
+
+       boolean isClientConnected();
+
+}

Modified: 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java
URL: 
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java?rev=1069936&r1=1069935&r2=1069936&view=diff
==============================================================================
--- 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java
 (original)
+++ 
tuscany/sca-java-2.x/trunk/modules/binding-comet-runtime/src/main/java/org/apache/tuscany/sca/binding/comet/runtime/handler/CometBindingHandler.java
 Fri Feb 11 20:06:28 2011
@@ -22,9 +22,9 @@ package org.apache.tuscany.sca.binding.c
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
@@ -33,14 +33,20 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.binding.comet.runtime.CometComponentContext;
+import org.apache.tuscany.sca.binding.comet.runtime.CometMessageContext;
 import org.apache.tuscany.sca.binding.comet.runtime.ServletFactory;
+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.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.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;
@@ -54,121 +60,163 @@ import com.sun.jersey.spi.container.serv
 @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[] {});
-    }
+       /**
+        * The object used to suspend the response and send async responses 
back to
+        * client.
+        */
+       private Broadcaster broadcaster;
+
+       /**
+        * JSON converter.
+        */
+       private Gson gson = new Gson();
+
+       /**
+        * The underlying servlet context.
+        */
+       @Context
+       private ServletContext sc;
+
+       @Context
+       private HttpServletRequest request;
+
+       private CometComponentContext context;
+
+       /**
+        * Method called at comet connect time. This suspends the response and 
keeps
+        * the connection opened.
+        * 
+        * @return the suspended response
+        */
+       @GET
+       public SuspendResponse<String> connect() {
+               System.out.println("-- connect -- Session Id: " + 
request.getSession().getId());
+               if (broadcaster == null) {
+                       broadcaster = new DefaultBroadcaster();
+                       context = (CometComponentContext) 
sc.getAttribute(ServletFactory.COMET_COMPONENT_CONTEXT_KEY);
+               }
+               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 void handleRequest(@PathParam("service") final String service, 
@PathParam("method") final String method,
+                       @FormParam("callback") 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);
+               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] = this.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.setBody(args);
+               CometMessageContext messageContext = new 
CometMessageContext(this, callbackMethod);
+               msg.setBindingContext(messageContext);
+               EndpointReference re = new RuntimeEndpointReferenceImpl();
+               re.setCallbackEndpoint(new RuntimeEndpointImpl());
+               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 void respondToClient(String callbackMethod, Object response) {
+               broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + 
this.gson.toJson(response) + "'))");
+       }
+
+       public boolean isClientConnected() {
+               return !broadcaster.getAtmosphereResources().isEmpty();
+       }
+
 }


Reply via email to