All Downloads are FREE. Search and download functionalities are using the official Maven repository.

joynr.dispatching.Dispatcher.js Maven / Gradle / Ivy

/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2016 BMW Car IT GmbH
 * %%
 * Licensed 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.
 * #L%
 */

define("joynr/dispatching/Dispatcher", [
    "global/Promise",
    "joynr/dispatching/types/Request",
    "joynr/dispatching/types/Reply",
    "joynr/dispatching/types/OneWayRequest",
    "joynr/dispatching/types/SubscriptionRequest",
    "joynr/dispatching/types/SubscriptionReply",
    "joynr/dispatching/types/SubscriptionStop",
    "joynr/dispatching/types/SubscriptionPublication",
    "joynr/messaging/JoynrMessage",
    "joynr/messaging/MessagingQosEffort",
    "joynr/messaging/inprocess/InProcessAddress",
    "joynr/system/DiagnosticTags",
    "joynr/util/UtilInternal",
    "joynr/util/JSONSerializer",
    "joynr/system/LoggerFactory"
], function(
        Promise,
        Request,
        Reply,
        OneWayRequest,
        SubscriptionRequest,
        SubscriptionReply,
        SubscriptionStop,
        SubscriptionPublication,
        JoynrMessage,
        MessagingQosEffort,
        InProcessAddress,
        DiagnosticTags,
        Util,
        JSONSerializer,
        LoggerFactory) {

    /**
     * @name Dispatcher
     * @constructor
     *
     * @param {MessagingStub}
     *            clusterControllerMessagingStub for sending outgoing joynr messages
     * @param {PlatformSecurityManager}
     *            securityManager for setting the creator user ID header
     */
    function Dispatcher(clusterControllerMessagingStub, securityManager) {
        var log = LoggerFactory.getLogger("joynr.dispatching.Dispatcher");

        var requestReplyManager;
        var subscriptionManager;
        var publicationManager;

        /**
         * @name Dispatcher#parsePayload
         * @function
         * @private
         *
         * @param {String}
         *            payload of a JoynrMessage
         * @returns payload if the payload is parsable JSON, this is parsed and returned as as an object; otherwise the payload itself
         *          is returned
         *
         */
        function parsePayload(payload) {
            if (typeof payload !== "string") {
                // TODO handle error properly
                log.error("payload is not of type string, cannot deserialize!");
            }

            try {
                return JSON.parse(payload);
            } catch (e) {
                // TODO handle error properly
                log.error("error while deserializing: " + e);
            }

            // TODO: handle errors correctly with respect to return value
            return payload;
        }

        /**
         * @name Dispatcher#sendJoynrMessage
         * @function
         * @private
         *
         * @param {JoynrMessage}
         *            joynrMessage
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {MessagingQos}
         *            settings.messagingQos the messaging Qos object for the ttl
         */
        function sendJoynrMessage(joynrMessage, settings) {
            // set headers
            joynrMessage.creator = securityManager.getCurrentProcessUserId();
            joynrMessage.from = settings.from;
            joynrMessage.to = settings.to;
            var expiryDate = Date.now() + settings.messagingQos.ttl;
            if (expiryDate > Util.getMaxLongValue()) {
                expiryDate = Util.getMaxLongValue();
            }
            var effort = settings.messagingQos.effort;
            if (effort !== MessagingQosEffort.NORMAL) {
                joynrMessage.effort = effort.value;
            }

            joynrMessage.expiryDate = expiryDate.toString();
            // send message
            return clusterControllerMessagingStub.transmit(joynrMessage);
        }

        /**
         * @name Dispatcher#registerRequestReplyManager
         * @function
         *
         * @param {RequestReplyManager}
         *            requestReplyManager handles incoming and outgoing requests and replies
         *
         */
        this.registerRequestReplyManager =
                function registerRequestReplyManager(newRequestReplyManager) {
                    requestReplyManager = newRequestReplyManager;
                };

        /**
         * @name Dispatcher#registerSubscriptionManager
         * @function
         *
         * @param {SubscriptionManager}
         *            subscriptionManager sends subscription requests; handles incoming publications and incoming replies to
         *            subscription requests
         */
        this.registerSubscriptionManager =
                function registerSubscriptionManager(newSubscriptionManager) {
                    subscriptionManager = newSubscriptionManager;
                };

        /**
         * @name Dispatcher#registerPublicationManager
         * @function
         *
         * @param {PublicationManager}
         *            publicationManager sends publications; handles incoming subscription start and stop requests
         */
        this.registerPublicationManager =
                function registerPublicationManager(newPublicationManager) {
                    publicationManager = newPublicationManager;
                };

        /**
         * @name Dispatcher#sendRequest
         * @function
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {MessagingQos}
         *            settings.messagingQos the messaging Qos object for the ttl
         * @param {Request}
         *            settings.request
         * @returns {Object} A+ promise object
         */
        this.sendRequest =
                function sendRequest(settings) {
                    // Create a JoynrMessage with the Request
                    var requestMessage = new JoynrMessage({
                        type : JoynrMessage.JOYNRMESSAGE_TYPE_REQUEST,
                        payload : JSONSerializer.stringify(settings.request)
                    });
                    if (settings.messagingQos.customHeaders) {
                        requestMessage.setCustomHeaders(settings.messagingQos.customHeaders);
                    }

                    log.info("calling "
                        + settings.request.methodName
                        + ". Request: "
                        + requestMessage.payload, DiagnosticTags.forRequest({
                        request : settings.request,
                        to : settings.to,
                        from : settings.from
                    }));

                    return sendJoynrMessage(requestMessage, settings);
                };

        /**
         * @name Dispatcher#sendOneWayRequest
         * @function
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {MessagingQos}
         *            settings.messagingQos the messaging Qos object for the ttl
         * @param {OneWayRequest}
         *            settings.request
         * @returns {Object} A+ promise object
         */
        this.sendOneWayRequest =
                function sendOneWayRequest(settings) {
                    // Create a JoynrMessage with the OneWayRequest
                    var oneWayRequestMessage = new JoynrMessage({
                        type : JoynrMessage.JOYNRMESSAGE_TYPE_ONE_WAY,
                        payload : JSONSerializer.stringify(settings.request)
                    });
                    if (settings.messagingQos.customHeaders) {
                        oneWayRequestMessage.setCustomHeaders(settings.messagingQos.customHeaders);
                    }
                    log.info("calling "
                        + settings.request.methodName
                        + ". OneWayRequest: "
                        + oneWayRequestMessage.payload, DiagnosticTags.forOneWayRequest({
                        request : settings.request,
                        to : settings.to,
                        from : settings.from
                    }));

                    return sendJoynrMessage(oneWayRequestMessage, settings);
                };

        /**
         * @name Dispatcher#sendSubscriptionRequest
         * @function
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {MessagingQos}
         *            settings.messagingQos the messaging Qos object for the ttl
         * @param {SubscriptionRequest}
         *            settings.subscriptionRequest
         * @returns {Object}  promise object that is resolved when the request is sent by the messaging stub
         */
        this.sendSubscriptionRequest =
                function sendSubscriptionRequest(settings) {
                    log.info(
                            "subscription to " + settings.subscriptionRequest.subscribedToName,
                            DiagnosticTags.forSubscriptionRequest({
                                subscriptionRequest : settings.subscriptionRequest,
                                to : settings.to,
                                from : settings.from
                            }));

                    var requestMessage = new JoynrMessage({
                        type : JoynrMessage.JOYNRMESSAGE_TYPE_SUBSCRIPTION_REQUEST,
                        payload : JSONSerializer.stringify(settings.subscriptionRequest)
                    });

                    return sendJoynrMessage(requestMessage, settings);
                };

        /**
         * @name Dispatcher#sendBroadcastSubscriptionRequest
         * @function
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {MessagingQos}
         *            settings.messagingQos the messaging Qos object for the ttl
         * @param {BroadcastSubscriptionRequest}
         *            settings.subscriptionRequest
         * @returns {Object}  promise object that is resolved when the request is sent by the messaging stub
         */
        this.sendBroadcastSubscriptionRequest =
                function sendSubscriptionRequest(settings) {
                    log.info("broadcast subscription to "
                        + settings.subscriptionRequest.subscribedToName, DiagnosticTags
                            .forSubscriptionRequest({
                                subscriptionRequest : settings.subscriptionRequest,
                                to : settings.to,
                                from : settings.from
                            }));

                    var requestMessage = new JoynrMessage({
                        type : JoynrMessage.JOYNRMESSAGE_TYPE_BROADCAST_SUBSCRIPTION_REQUEST,
                        payload : JSONSerializer.stringify(settings.subscriptionRequest)
                    });

                    return sendJoynrMessage(requestMessage, settings);
                };
        /**
         * @name Dispatcher#sendSubscriptionStop
         * @function
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {SubscriptionStop}
         *            settings.subscriptionStop
         * @param {MessagingQos}
         *            settings.messagingQos the messaging Qos object for the ttl
         * @returns {Object} A+ promise object
         */
        this.sendSubscriptionStop =
                function sendSubscriptionStop(settings) {
                    log.info(
                            "subscription stop " + settings.subscriptionStop.subscriptionId,
                            DiagnosticTags.forSubscriptionStop({
                                subscriptionId : settings.subscriptionStop.subscriptionId,
                                to : settings.to,
                                from : settings.from
                            }));

                    var message = new JoynrMessage({
                        type : JoynrMessage.JOYNRMESSAGE_TYPE_SUBSCRIPTION_STOP,
                        payload : JSONSerializer.stringify(settings.subscriptionStop)
                    });
                    return sendJoynrMessage(message, settings);
                };

        /**
         * @private
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {Number}
         *            settings.expiryDate time-to-live
         * @param {Object}
         *            settings.customHeaders custom headers from request
         * @param {Reply|SubscriptionReply}
         *            settings.reply the reply to be transmitted. It can either be a Reply or a SubscriptionReply object
         */
        function sendReply(settings) {
            // reply with the result in a JoynrMessage
            var message = new JoynrMessage({
                type : settings.messageType,
                payload : settings.reply
            });

            // set headers
            message.from = settings.from;
            message.to = settings.to;
            message.expiryDate = settings.expiryDate;
            message.setCustomHeaders(settings.customHeaders);

            clusterControllerMessagingStub.transmit(message);
        }
        /**
         * @private
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {Number}
         *            settings.expiryDate time-to-live
         * @param {Object}
         *            settings.customHeaders custom headers from request
         * @param {Reply}
         *            reply
         */
        function sendRequestReply(settings, reply) {
            log.info("replying", DiagnosticTags.forReply({
                reply : reply,
                to : settings.to,
                from : settings.from
            }));

            settings.reply = JSONSerializer.stringify(reply, reply.error !== undefined);
            settings.messageType = JoynrMessage.JOYNRMESSAGE_TYPE_REPLY;
            sendReply(settings);
        }
        /**
         * @private
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {Number}
         *            settings.expiryDate time-to-live
         * @param {Object}
         *            settings.customHeaders custom headers from request
         * @param {SubscriptionReply}
         *            subscriptionReply
         */
        function sendSubscriptionReply(settings, subscriptionReply) {
            log.info("replying", DiagnosticTags.forSubscriptionReply({
                subscriptionReply : subscriptionReply,
                to : settings.to,
                from : settings.from
            }));

            settings.reply =
                    JSONSerializer.stringify(
                            subscriptionReply,
                            subscriptionReply.error !== undefined);
            settings.messageType = JoynrMessage.JOYNRMESSAGE_TYPE_SUBSCRIPTION_REPLY;
            sendReply(settings);
        }

        /**
         * @name Dispatcher#sendPublication
         * @function
         *
         * @param {Object}
         *            settings
         * @param {String}
         *            settings.from participantId of the sender
         * @param {String}
         *            settings.to participantId of the receiver
         * @param {Number}
         *            settings.expiryDate time-to-live
         * @param {SubscriptionPublication}
         *            publication
         * @param {?}
         *            publication.response
         * @param {String}
         *            publication.subscriptionId
         *
         */
        this.sendPublication = function sendPublication(settings, publication) {
            log.info("publication", DiagnosticTags.forPublication({
                publication : publication,
                to : settings.to,
                from : settings.from
            }));

            // Reply with the result in a JoynrMessage
            var publicationMessage = new JoynrMessage({
                type : JoynrMessage.JOYNRMESSAGE_TYPE_PUBLICATION,
                payload : JSONSerializer.stringify(publication)
            });

            // set reply headers
            publicationMessage.from = settings.from;
            publicationMessage.to = settings.to;
            publicationMessage.expiryDate = settings.expiryDate;

            clusterControllerMessagingStub.transmit(publicationMessage);
        };

        /**
         * receives a new JoynrMessage that has to be routed to one of the managers
         *
         * @name Dispatcher#receive
         * @function
         * @param {JoynrMessage}
         *            joynrMessage being routed
         */
        this.receive =
                function receive(joynrMessage) {
                    log.debug("received message with the following payload: "
                        + joynrMessage.payload);
                    switch (joynrMessage.type) {

                        case JoynrMessage.JOYNRMESSAGE_TYPE_REQUEST:
                            try {
                                var request = new Request(parsePayload(joynrMessage.payload));

                                requestReplyManager.handleRequest(
                                        joynrMessage.to,
                                        request,
                                        function(reply) {
                                            sendRequestReply({
                                                from : joynrMessage.to,
                                                to : joynrMessage.from,
                                                expiryDate : joynrMessage.expiryDate,
                                                customHeaders : joynrMessage.getCustomHeaders()
                                            }, reply);
                                        });
                            } catch (errorInRequest) {
                                // TODO handle error in handling the request
                                log.error("error handling request: " + errorInRequest);
                            }
                            break;

                        case JoynrMessage.JOYNRMESSAGE_TYPE_REPLY:
                            try {
                                var settings = Util.extend(parsePayload(joynrMessage.payload), {
                                    requestReplyId : joynrMessage.requestReplyId
                                });
                                requestReplyManager.handleReply(new Reply(settings));
                            } catch (errorInReply) {
                                // TODO handle error in handling the reply
                                log.error("error handling reply: " + errorInReply);
                            }
                            break;

                        case JoynrMessage.JOYNRMESSAGE_TYPE_ONE_WAY:
                            try {
                                requestReplyManager.handleOneWayRequest(
                                        joynrMessage.to,
                                        new OneWayRequest(parsePayload(joynrMessage.payload)));
                            } catch (errorInOneWayRequest) {
                                log.error("error handling one way: " + errorInOneWayRequest);
                            }
                            break;

                        case JoynrMessage.JOYNRMESSAGE_TYPE_SUBSCRIPTION_REQUEST:
                            try {
                                publicationManager
                                        .handleSubscriptionRequest(
                                                joynrMessage.from,
                                                joynrMessage.to,
                                                new SubscriptionRequest(
                                                        parsePayload(joynrMessage.payload)),
                                                function(subscriptionReply) {
                                                    sendSubscriptionReply({
                                                        from : joynrMessage.to,
                                                        to : joynrMessage.from,
                                                        expiryDate : joynrMessage.expiryDate,
                                                        customHeaders : joynrMessage
                                                                .getCustomHeaders()
                                                    }, subscriptionReply);
                                                });
                            } catch (errorInSubscriptionRequest) {
                                // TODO handle error in handling the subscriptionRequest
                                log.error("error handling subscriptionRequest: "
                                    + errorInSubscriptionRequest);
                            }
                            break;

                        case JoynrMessage.JOYNRMESSAGE_TYPE_BROADCAST_SUBSCRIPTION_REQUEST:
                            try {
                                publicationManager
                                        .handleEventSubscriptionRequest(
                                                joynrMessage.from,
                                                joynrMessage.to,
                                                new SubscriptionRequest(
                                                        parsePayload(joynrMessage.payload)),
                                                function(subscriptionReply) {
                                                    sendSubscriptionReply({
                                                        from : joynrMessage.to,
                                                        to : joynrMessage.from,
                                                        expiryDate : joynrMessage.expiryDate,
                                                        customHeaders : joynrMessage
                                                                .getCustomHeaders()
                                                    }, subscriptionReply);
                                                });
                            } catch (errorInEventSubscriptionRequest) {
                                // TODO handle error in handling the subscriptionRequest
                                log.error("error handling eventSubscriptionRequest: "
                                    + errorInEventSubscriptionRequest);
                            }
                            break;

                        case JoynrMessage.JOYNRMESSAGE_TYPE_SUBSCRIPTION_REPLY:
                            try {
                                subscriptionManager.handleSubscriptionReply(new SubscriptionReply(
                                        parsePayload(joynrMessage.payload)));
                            } catch (errorInSubscriptionReply) {
                                // TODO handle error in handling the subscriptionReply
                                log.error("error handling subscriptionReply: "
                                    + errorInSubscriptionReply);
                            }
                            break;

                        case JoynrMessage.JOYNRMESSAGE_TYPE_SUBSCRIPTION_STOP:
                            try {
                                publicationManager.handleSubscriptionStop(new SubscriptionStop(
                                        parsePayload(joynrMessage.payload)));
                            } catch (errorInSubscriptionStop) {
                                // TODO handle error in handling the subscriptionStop
                                log.error("error handling subscriptionStop: "
                                    + errorInSubscriptionStop);
                            }
                            break;

                        case JoynrMessage.JOYNRMESSAGE_TYPE_PUBLICATION:
                            try {
                                subscriptionManager.handlePublication(new SubscriptionPublication(
                                        parsePayload(joynrMessage.payload)));
                            } catch (errorInPublication) {
                                // TODO handle error in handling the publication
                                log.error("error handling publication: " + errorInPublication);
                            }
                            break;

                        default:
                            log.error("unknown JoynrMessage type : "
                                + joynrMessage.type
                                + ". Discarding message: "
                                // TODO the js formatter is breaking this way, and jslint is
                                // complaining.....
                                + JSONSerializer.stringify(joynrMessage));
                            break;
                    }
                };
    }

    return Dispatcher;

});




© 2015 - 2025 Weber Informatics LLC | Privacy Policy