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

joynr.start.WebSocketLibjoynrRuntime.js Maven / Gradle / Ivy

/*jslint es5: true */

/*
 * #%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/start/WebSocketLibjoynrRuntime", [
    "global/Promise",
    "global/WebSocket",
    "joynr/capabilities/arbitration/Arbitrator",
    "joynr/provider/ProviderBuilder",
    "joynr/proxy/ProxyBuilder",
    "joynr/types/GlobalDiscoveryEntry",
    "joynr/capabilities/CapabilitiesRegistrar",
    "joynr/capabilities/ParticipantIdStorage",
    "joynr/dispatching/RequestReplyManager",
    "joynr/dispatching/subscription/PublicationManager",
    "joynr/dispatching/subscription/SubscriptionManager",
    "joynr/dispatching/Dispatcher",
    "joynr/security/PlatformSecurityManager",
    "joynr/messaging/websocket/SharedWebSocket",
    "joynr/messaging/websocket/WebSocketMessagingSkeleton",
    "joynr/messaging/websocket/WebSocketMessagingStubFactory",
    "joynr/messaging/websocket/WebSocketMulticastAddressCalculator",
    "joynr/messaging/MessagingSkeletonFactory",
    "joynr/messaging/MessagingStubFactory",
    "joynr/messaging/routing/MessageRouter",
    "joynr/messaging/routing/MessageQueue",
    "joynr/system/RoutingTypes/WebSocketAddress",
    "joynr/system/RoutingTypes/WebSocketClientAddress",
    "joynr/messaging/inprocess/InProcessMessagingStubFactory",
    "joynr/messaging/inprocess/InProcessMessagingSkeleton",
    "joynr/messaging/inprocess/InProcessMessagingStub",
    "joynr/messaging/inprocess/InProcessAddress",
    "joynr/util/InProcessStub",
    "joynr/util/InProcessSkeleton",
    "joynr/messaging/MessagingQos",
    "joynr/proxy/DiscoveryQos",
    "joynr/system/DiscoveryProxy",
    "joynr/system/RoutingProxy",
    "joynr/types/TypeRegistrySingleton",
    "joynr/types/DiscoveryScope",
    "joynr/types/DiscoveryEntry",
    "joynr/util/UtilInternal",
    "joynr/util/CapabilitiesUtil",
    "joynr/util/Typing",
    "joynr/system/DistributedLoggingAppenderConstructorFactory",
    "joynr/system/DistributedLoggingAppender",
    "joynr/system/WebWorkerMessagingAppender",
    "uuid",
    "joynr/system/LoggingManager",
    "joynr/system/LoggerFactory",
    "joynr/start/settings/defaultSettings",
    "joynr/start/settings/defaultWebSocketSettings",
    "joynr/start/settings/defaultLibjoynrSettings",
    "global/LocalStorage"
], function(
        Promise,
        WebSocket,
        Arbitrator,
        ProviderBuilder,
        ProxyBuilder,
        GlobalDiscoveryEntry,
        CapabilitiesRegistrar,
        ParticipantIdStorage,
        RequestReplyManager,
        PublicationManager,
        SubscriptionManager,
        Dispatcher,
        PlatformSecurityManager,
        SharedWebSocket,
        WebSocketMessagingSkeleton,
        WebSocketMessagingStubFactory,
        WebSocketMulticastAddressCalculator,
        MessagingSkeletonFactory,
        MessagingStubFactory,
        MessageRouter,
        MessageQueue,
        WebSocketAddress,
        WebSocketClientAddress,
        InProcessMessagingStubFactory,
        InProcessMessagingSkeleton,
        InProcessMessagingStub,
        InProcessAddress,
        InProcessStub,
        InProcessSkeleton,
        MessagingQos,
        DiscoveryQos,
        DiscoveryProxy,
        RoutingProxy,
        TypeRegistrySingleton,
        DiscoveryScope,
        DiscoveryEntry,
        Util,
        CapabilitiesUtil,
        Typing,
        DistributedLoggingAppenderConstructorFactory,
        DistributedLoggingAppender,
        WebWorkerMessagingAppender,
        uuid,
        LoggingManager,
        LoggerFactory,
        defaultSettings,
        defaultWebSocketSettings,
        defaultLibjoynrSettings,
        LocalStorage) {
    var JoynrStates = {
        SHUTDOWN : "shut down",
        STARTING : "starting",
        STARTED : "started",
        SHUTTINGDOWN : "shutting down"
    };

    /**
     * The WebSocketLibjoynrRuntime is the version of the libjoynr-js runtime that communicates with
     * a cluster controller via a WebSocket. The cluster controller is the WebSocket Server, and the
     * libjoynr connects to it with a single websocket for all communication.
     *
     * @name WebSocketLibjoynrRuntime
     * @constructor
     * @param {Object} provisioning
     */
    function WebSocketLibjoynrRuntime(provisioning) {
        var log, loggingManager;
        var initialRoutingTable;
        var untypedCapabilities;
        var typedCapabilities;
        var messagingSkeletonFactory;
        var messagingStubFactory;
        var messageRouter;
        var libjoynrMessagingSkeleton;
        var dispatcher;
        var typeRegistry;
        var requestReplyManager;
        var subscriptionManager;
        var publicationManager;
        var participantIdStorage;
        var arbitrator;
        var providerBuilder;
        var proxyBuilder;
        var capabilitiesRegistrar;
        var discovery;
        var messageQueueSettings;
        var ccAddress;
        var sharedWebSocket;
        var webSocketMessagingSkeleton;
        var messageRouterSkeleton;
        var messageRouterStub;
        var persistency;
        var localAddress;
        var TWO_DAYS_IN_MS = 172800000;

        // this is required at load time of libjoynr
        typeRegistry = Object.freeze(TypeRegistrySingleton.getInstance());

        /**
         * @name WebSocketLibjoynrRuntime#typeRegistry
         * @type TypeRegistry
         */
        Object.defineProperty(this, "typeRegistry", {
            get : function() {
                return typeRegistry;
            },
            enumerable : true
        });

        /**
         * @name WebSocketLibjoynrRuntime#registration
         * @type CapabilitiesRegistrar
         */
        Object.defineProperty(this, "registration", {
            get : function() {
                return capabilitiesRegistrar;
            },
            enumerable : true
        });

        /**
         * @name WebSocketLibjoynrRuntime#capabilities
         * @type CapabilitiesRegistrar
         * @deprecated capabilities will be removed by 01.01.2017. please use registration instead
         */
        Object.defineProperty(this, "capabilities", {
            get : function() {
                return capabilitiesRegistrar;
            },
            enumerable : true
        });

        /**
         * @name WebSocketLibjoynrRuntime#providerBuilder
         * @type ProviderBuilder
         */
        Object.defineProperty(this, "providerBuilder", {
            get : function() {
                return providerBuilder;
            },
            enumerable : true
        });

        /**
         * @name WebSocketLibjoynrRuntime#proxyBuilder
         * @type ProxyBuilder
         */
        Object.defineProperty(this, "proxyBuilder", {
            get : function() {
                return proxyBuilder;
            },
            enumerable : true
        });

        /**
         * @name WebSocketLibjoynrRuntime#participantIdStorage
         * @type ParticipantIdStorage
         */
        Object.defineProperty(this, "participantIdStorage", {
            get : function() {
                return participantIdStorage;
            },
            enumerable : true
        });

        /**
         * @name WebSocketLibjoynrRuntime#logging
         * @type LoggingManager
         */
        Object.defineProperty(this, "logging", {
            get : function() {
                return loggingManager;
            },
            enumerable : true
        });

        var relativeTtl;

        if (provisioning.logging && provisioning.logging.ttl) {
            relativeTtl = provisioning.logging.ttl;
        } else {
            relativeTtl = TWO_DAYS_IN_MS;
        }

        var loggingMessagingQos = new MessagingQos({
            ttl : relativeTtl
        });
        loggingManager = Object.freeze(new LoggingManager());
        LoggerFactory.init(loggingManager);

        if (Util.checkNullUndefined(provisioning.ccAddress)) {
            throw new Error("ccAddress not set in provisioning.ccAddress");
        }

        ccAddress = new WebSocketAddress({
            protocol : provisioning.ccAddress.protocol || defaultWebSocketSettings.protocol,
            host : provisioning.ccAddress.host,
            port : provisioning.ccAddress.port,
            path : provisioning.ccAddress.path || defaultWebSocketSettings.path
        });

        var joynrState = JoynrStates.SHUTDOWN;

        /**
         * Starts up the libjoynr instance
         *
         * @name WebSocketLibjoynrRuntime#start
         * @function
         * @returns {Object} an A+ promise object, reporting when libjoynr startup is
         *          completed or has failed
         * @throws {Error}
         *             if libjoynr is not in SHUTDOWN state
         */
        this.start =
                function start() {
                    var i, j, routingProxyPromise, discoveryProxyPromise;

                    if (joynrState !== JoynrStates.SHUTDOWN) {
                        throw new Error("Cannot start libjoynr because it's currently \""
                            + joynrState
                            + "\"");
                    }
                    joynrState = JoynrStates.STARTING;

                    if (!provisioning) {
                        throw new Error("Constructor has been invoked without provisioning");
                    }

                    // initialize Logger with external logging configuration or default
                    // values
                    loggingManager.registerAppenderClass("WebWorker", WebWorkerMessagingAppender);
                    loggingManager.registerAppenderClass(
                            "Distributed",
                            DistributedLoggingAppenderConstructorFactory.build(
                                    proxyBuilder,
                                    loggingMessagingQos));

                    if (provisioning.logging) {
                        loggingManager.configure(provisioning.logging);
                    }

                    log = LoggerFactory.getLogger("joynr.start.WebSocketLibjoynrRuntime");

                    var persistencyProvisioning = provisioning.persistency || {};
                    persistency = new LocalStorage({
                        clearPersistency : persistencyProvisioning.clearPersistency,
                        location : persistencyProvisioning.location
                    });

                    initialRoutingTable = {};
                    untypedCapabilities = provisioning.capabilities || [];
                    var defaultCapabilities = defaultLibjoynrSettings.capabilities || [];

                    untypedCapabilities = untypedCapabilities.concat(defaultCapabilities);

                    typedCapabilities = [];
                    for (i = 0; i < untypedCapabilities.length; i++) {
                        var capability = new GlobalDiscoveryEntry(untypedCapabilities[i]);
                        initialRoutingTable[capability.participantId] = ccAddress;
                        typedCapabilities.push(capability);
                    }

                    messageQueueSettings = {};
                    if (provisioning.messaging !== undefined
                        && provisioning.messaging.maxQueueSizeInKBytes !== undefined) {
                        messageQueueSettings.maxQueueSizeInKBytes =
                                provisioning.messaging.maxQueueSizeInKBytes;
                    }

                    localAddress = new WebSocketClientAddress({
                        id : uuid()
                    });

                    sharedWebSocket = new SharedWebSocket({
                        remoteAddress : ccAddress,
                        localAddress : localAddress,
                        provisioning : provisioning.websocket || {}
                    });

                    webSocketMessagingSkeleton = new WebSocketMessagingSkeleton({
                        sharedWebSocket : sharedWebSocket,
                        mainTransport : true
                    });

                    messagingSkeletonFactory = new MessagingSkeletonFactory();

                    var messagingStubFactories = {};
                    /*jslint nomen: true */
                    messagingStubFactories[InProcessAddress._typeName] = new InProcessMessagingStubFactory();
                    messagingStubFactories[WebSocketAddress._typeName] = new WebSocketMessagingStubFactory({
                        address : ccAddress,
                        sharedWebSocket : sharedWebSocket
                    });
                    /*jslint nomen: false */

                    messagingStubFactory = new MessagingStubFactory({
                        messagingStubFactories :messagingStubFactories
                    });

                    messageRouter = new MessageRouter({
                        initialRoutingTable : initialRoutingTable,
                        persistency : persistency,
                        typeRegistry : typeRegistry,
                        joynrInstanceId : uuid(),
                        messagingSkeletonFactory : messagingSkeletonFactory,
                        messagingStubFactory : messagingStubFactory,
                        messageQueue : new MessageQueue(messageQueueSettings),
                        multicastAddressCalculator : new WebSocketMulticastAddressCalculator({
                            globalAddress : ccAddress
                        }),
                        parentMessageRouterAddress : ccAddress,
                        incomingAddress : localAddress
                    });
                    webSocketMessagingSkeleton.registerListener(messageRouter.route);

                    // link up clustercontroller messaging to dispatcher
                    messageRouterSkeleton = new InProcessMessagingSkeleton();
                    messageRouterStub = new InProcessMessagingStub(messageRouterSkeleton);

                    // clustercontroller messaging handled by the messageRouter
                    messageRouterSkeleton.registerListener(messageRouter.route);
                    var ttlUpLiftMs = (provisioning.messaging && provisioning.messaging.TTL_UPLIFT) ?
                        provisioning.messaging.TTL_UPLIFT : undefined;
                    dispatcher = new Dispatcher(messageRouterStub, new PlatformSecurityManager(), ttlUpLiftMs);

                    libjoynrMessagingSkeleton = new InProcessMessagingSkeleton();
                    libjoynrMessagingSkeleton.registerListener(dispatcher.receive);

                    messagingSkeletonFactory.setSkeletons({
                        InProcessAddress : libjoynrMessagingSkeleton,
                        WebSocketAddress : webSocketMessagingSkeleton
                    });

                    requestReplyManager = new RequestReplyManager(dispatcher, typeRegistry);
                    subscriptionManager = new SubscriptionManager(dispatcher);
                    publicationManager =
                            new PublicationManager(dispatcher, persistency, "joynrInstanceId");//TODO: create joynrInstanceId

                    dispatcher.registerRequestReplyManager(requestReplyManager);
                    dispatcher.registerSubscriptionManager(subscriptionManager);
                    dispatcher.registerPublicationManager(publicationManager);
                    dispatcher.registerMessageRouter(messageRouter);

                    participantIdStorage = new ParticipantIdStorage(persistency, uuid);
                    discovery = new InProcessStub();

                    capabilitiesRegistrar = Object.freeze(new CapabilitiesRegistrar({
                        discoveryStub : discovery,
                        messageRouter : messageRouter,
                        requestReplyManager : requestReplyManager,
                        publicationManager : publicationManager,
                        libjoynrMessagingAddress : new InProcessAddress(libjoynrMessagingSkeleton),
                        participantIdStorage : participantIdStorage,
                        loggingManager : loggingManager
                    }));

                    arbitrator = new Arbitrator(discovery, CapabilitiesUtil.toDiscoveryEntries(typedCapabilities));

                    providerBuilder = Object.freeze(new ProviderBuilder());

                    proxyBuilder = Object.freeze(new ProxyBuilder({
                        arbitrator : arbitrator,
                        typeRegistry : typeRegistry,
                        requestReplyManager : requestReplyManager,
                        subscriptionManager : subscriptionManager,
                        publicationManager : publicationManager
                    }, {
                        messageRouter : messageRouter,
                        libjoynrMessagingAddress : new InProcessAddress(libjoynrMessagingSkeleton),
                        loggingManager : loggingManager
                    }));

                    var internalMessagingQos = new MessagingQos(provisioning.internalMessagingQos);

                    discoveryProxyPromise = proxyBuilder.build(DiscoveryProxy, {
                            domain : "io.joynr",
                            messagingQos : internalMessagingQos,
                            discoveryQos : new DiscoveryQos({
                                discoveryScope : DiscoveryScope.LOCAL_ONLY
                            }),
                            staticArbitration : true
                        }).then(function(newDiscoveryProxy) {
                            discovery.setSkeleton(new InProcessSkeleton({
                                lookup : function lookup(domains, interfaceName, discoveryQos) {
                                    return newDiscoveryProxy.lookup({
                                        domains : domains,
                                        interfaceName : interfaceName,
                                        discoveryQos : discoveryQos
                                    }).then(function(opArgs){
                                        return opArgs.result;
                                    });
                                },
                                add : function add(discoveryEntry) {
                                    return newDiscoveryProxy.add({
                                        discoveryEntry : discoveryEntry
                                    });
                                },
                                remove : function remove(participantId) {
                                    return newDiscoveryProxy.remove({
                                        participantId : participantId
                                    });
                                }
                            }));
                            return;
                        }).catch(function(error) {
                            throw new Error("Failed to create discovery proxy: " + error);
                        });

                    routingProxyPromise = proxyBuilder.build(RoutingProxy, {
                            domain : "io.joynr",
                            messagingQos : internalMessagingQos,
                            discoveryQos : new DiscoveryQos({
                                discoveryScope : DiscoveryScope.LOCAL_ONLY
                            }),
                            staticArbitration : true
                        }).then(function(newRoutingProxy) {
                            messageRouter.setRoutingProxy(newRoutingProxy);
                            return newRoutingProxy;
                        }).catch(function(error) {
                            throw new Error("Failed to create routing proxy: " + error);
                        });

                    // when everything's ready we can trigger the app
                    return Promise.all([
                                        discoveryProxyPromise,
                                        routingProxyPromise
                                    ]).then(function() {
                            joynrState = JoynrStates.STARTED;
                            publicationManager.restore();
                            log.debug("joynr web socket initialized");
                            return;
                        }).catch(function(error) {
                            log.error("error starting up joynr: " + error);
                            throw error;
                        });
                };

        /**
         * Shuts down libjoynr
         *
         * @name WebSocketLibjoynrRuntime#shutdown
         * @function
         * @throws {Error}
         *             if libjoynr is not in the STARTED state
         */
        this.shutdown =
                function shutdown() {
                    if (joynrState !== JoynrStates.STARTED) {
                        throw new Error("Cannot shutdown libjoynr because it's currently \""
                            + joynrState
                            + "\"");
                    }
                    joynrState = JoynrStates.SHUTTINGDOWN;
                    if (webSocketMessagingSkeleton !== undefined) {
                        webSocketMessagingSkeleton.shutdown();
                    }

                    if (capabilitiesRegistrar !== undefined) {
                        capabilitiesRegistrar.shutdown();
                    }

                    if (arbitrator !== undefined) {
                        arbitrator.shutdown();
                    }

                    if (messageRouter !== undefined) {
                        messageRouter.shutdown();
                    }

                    if (requestReplyManager !== undefined) {
                        requestReplyManager.shutdown();
                    }

                    if (publicationManager !== undefined) {
                        publicationManager.shutdown();
                    }

                    if (subscriptionManager !== undefined) {
                        subscriptionManager.shutdown();
                    }

                    if (dispatcher !== undefined) {
                        dispatcher.shutdown();
                    }

                    if (typeRegistry !== undefined) {
                        typeRegistry.shutdown();
                    }

                    if (loggingManager !== undefined) {
                        loggingManager.shutdown();
                    }

                    joynrState = JoynrStates.SHUTDOWN;
                    log.debug("joynr shut down");
                    return Promise.resolve();
                };

        // make every instance immutable
        return Object.freeze(this);
    }

    return WebSocketLibjoynrRuntime;

});




© 2015 - 2025 Weber Informatics LLC | Privacy Policy