Package org.apache.tuscany.sca.binding.comet.runtime.handler

Source Code of org.apache.tuscany.sca.binding.comet.runtime.handler.CometBindingHandler

/*
* 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 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.QueryParam;

import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.binding.comet.runtime.JSONUtil;
import org.apache.tuscany.sca.binding.comet.runtime.manager.CometEndpointManager;
import org.apache.tuscany.sca.binding.comet.runtime.manager.CometOperationManager;
import org.apache.tuscany.sca.binding.comet.runtime.manager.CometSessionManager;
import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointImpl;
import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl;
import org.apache.tuscany.sca.core.invocation.Constants;
import org.apache.tuscany.sca.core.invocation.impl.MessageImpl;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.invocation.Message;
import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
import org.atmosphere.cpr.Broadcaster;
import org.atmosphere.cpr.BroadcasterLifeCyclePolicy;
import org.atmosphere.cpr.BroadcasterLifeCyclePolicy.ATMOSPHERE_RESOURCE_POLICY;
import org.atmosphere.cpr.BroadcasterLifeCyclePolicyListener;
import org.atmosphere.jersey.JerseyBroadcaster;
import org.atmosphere.jersey.SuspendResponse;

/**
* Handles requests for comet services and for creating a persistent connection.
*/
@Path("/")
public class CometBindingHandler {

    /**
     * Suspends the current HTTP connection.
     *
     * @param sessionId
     *            session id to identify client
     * @return a response that is not committed, just flushed
     */
    @GET
    @Path("/connect")
    public SuspendResponse<String> connect(@QueryParam("sessionId") String sessionId) {
        Broadcaster broadcaster = CometSessionManager.get(sessionId);
        if (broadcaster == null) {
            broadcaster = new JerseyBroadcaster(sessionId);
            BroadcasterLifeCyclePolicy policy = new BroadcasterLifeCyclePolicy.Builder().policy(
                    ATMOSPHERE_RESOURCE_POLICY.EMPTY_DESTROY).build();
            broadcaster.setBroadcasterLifeCyclePolicy(policy);
            broadcaster.addBroadcasterLifeCyclePolicyListener(new CometBroadcasterLifeCyclePolicyListener(sessionId));
            CometSessionManager.add(sessionId, broadcaster);
        }
        return new SuspendResponse.SuspendResponseBuilder<String>().broadcaster(broadcaster).outputComments(true)
                .build();
    }

    /**
     * Handles requests for service operations.
     *
     * @param service
     *            the service to invoke
     * @param method
     *            the method to invoke
     * @param sessionId
     *            the client session id
     * @param callbackMethod
     *            the callbackMethod to invoke once a response is available
     * @param jsonData
     *            method arguments sent by the client in JSON format
     * @throws InvocationTargetException
     *             if a problem occurs while invoking the service implementation
     */
    @POST
    @Path("/{service}/{method}")
    public void handleRequest(@PathParam("service") String service, @PathParam("method") String method,
            @FormParam("sessionId") String sessionId, @FormParam("callbackMethod") String callbackMethod,
            @FormParam("params") String jsonData) throws InvocationTargetException {
        String url = "/" + service + "/" + method;
        RuntimeEndpoint wire = CometEndpointManager.get(url);
        Operation operation = CometOperationManager.get(url);

        final Object[] args = JSONUtil.decodeJsonParamsForOperation(jsonData, operation);
        Message msg = createMessageWithMockedCometReference(args, sessionId, callbackMethod);
        boolean isVoidReturnType = operation.getOutputType().getLogical().isEmpty();
        if (!isVoidReturnType) {
            Object response = wire.invoke(operation, args);
            Broadcaster broadcaster = CometSessionManager.get(sessionId);
            if (broadcaster != null) {
                broadcaster.broadcast(callbackMethod + "($.secureEvalJSON('" + JSONUtil.encodeResponse(response)
                        + "'))");
            }
        } else {
            wire.invoke(operation, msg);
        }
    }

    /**
     * Creates a message with a mocked EndpointReference in the 'from' field to
     * simulate a comet reference (because requests are coming from browsers).
     * This is needed by the callback mechanism to have a source for the
     * request.
     *
     * @param args
     *            arguments for the method invocation
     * @param sessionId
     *            the session id of the client
     * @param callbackMethod
     *            method to call once a response is available
     * @return an invocation message
     */
    private Message createMessageWithMockedCometReference(Object[] args, String sessionId, String callbackMethod) {
        Message msg = new MessageImpl();
        msg.getHeaders().put(Constants.MESSAGE_ID, sessionId);
        msg.setBody(args);
        EndpointReference re = new RuntimeEndpointReferenceImpl();
        RuntimeEndpointImpl callbackEndpoint = new RuntimeEndpointImpl();
        callbackEndpoint.setURI(callbackMethod);
        re.setCallbackEndpoint(callbackEndpoint);
        msg.setFrom(re);
        return msg;
    }

    public class CometBroadcasterLifeCyclePolicyListener implements BroadcasterLifeCyclePolicyListener {

        private String sessionId;

        public CometBroadcasterLifeCyclePolicyListener(String sessionId) {
            this.sessionId = sessionId;
        }

        @Override
        public void onDestroy() {
        }

        @Override
        public void onEmpty() {
            CometSessionManager.remove(sessionId);
        }

        @Override
        public void onIdle() {
        }

    }

}
TOP

Related Classes of org.apache.tuscany.sca.binding.comet.runtime.handler.CometBindingHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.