<commit_before>/*!
 * ${copyright}
 */

// Provides control sap.ui.table.DataTable.
sap.ui.define(['jquery.sap.global', './TreeTable', './library'],
	function(jQuery, TreeTable, library) {
	"use strict";

	/**
	 * Constructor for a new DataTable.
	 *
	 * @param {string} [sId] id for the new control, generated automatically if no id is given
	 * @param {object} [mSettings] initial settings for the new control
	 *
	 * @class
	 * The DataTable control provides a set of sophisticated and comfort functions for table design. For example, you can make settings for the number of visible rows and a number for the displayed rows in the case the user expands the table. The first visible row can be explicitly set. For the selection of columns and rows, a Multi, a Single, a None, and an All mode are available. Setting the Editable property to true lets the user make changes on the table cell entries.
	 * @extends sap.ui.table.TreeTable
	 * @version ${version}
	 *
	 * @constructor
	 * @public
	 * @deprecated Since version 1.5.1.
	 * The DataTable has been replaced via the Table/TreeTable control.
	 * @alias sap.ui.table.DataTable
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var DataTable = TreeTable.extend("sap.ui.table.DataTable", /** @lends sap.ui.table.DataTable.prototype */ { metadata : {

		deprecated : true,
		library : "sap.ui.table",
		properties : {

			/**
			 * Count of visible rows when expanded
			 */
			expandedVisibleRowCount : {type : "int", defaultValue : null},

			/**
			 * Flag whether the Table is expanded or not
			 */
			expanded : {type : "boolean", defaultValue : false},

			/**
			 * Flag, whether the table displays its content hierarchical or not (**experimental**!!)
			 */
			hierarchical : {type : "boolean", defaultValue : false}
		},
		events : {

			/**
			 * fired when the row selection of the table has been changed
			 */
			rowSelect : {
				parameters : {

					/**
					 * row index which row has been selected or deselected
					 */
					rowIndex : {type : "int"},

					/**
					 * binding context of the row index which row has been selected or deselected
					 */
					rowContext : {type : "object"},

					/**
					 * array of row indices which selection has been changed (either selected or deselected)
					 */
					rowIndices : {type : "int[]"}
				}
			}
		}
	}});

	/**
	 * Initialization of the DataTable control
	 * @private
	 */
	DataTable.prototype.init = function() {

		TreeTable.prototype.init.apply(this, arguments);

		this._bInheritEditableToControls = true;

		// default values for DataTable
		this.setEditable(false);
		this.setSelectionBehavior(sap.ui.table.SelectionBehavior.Row);

		this.attachRowSelectionChange(function(oEvent) {
			this.fireRowSelect(oEvent.mParameters);
		});

		this._iLastFixedColIndex = -1;

	};

	DataTable.prototype.isTreeBinding = function(sName) {
		sName = sName || "rows";
		if (sName === "rows") {
			return this.getHierarchical();
		}
		return sap.ui.core.Element.prototype.isTreeBinding.apply(this, arguments);
	};

	DataTable.prototype.setHierarchical = function(bHierarchical) {
		this.setProperty("hierarchical", bHierarchical);
		this._iLastFixedColIndex = bHierarchical ? 0 : -1;
	};

	DataTable.prototype.setVisibleRowCount = function(iRowCount) {
		this._iVisibleRowCount = iRowCount;
		if (!this.getExpanded()) {
			sap.ui.table.Table.prototype.setVisibleRowCount.apply(this, arguments);
		}
	};

	DataTable.prototype.setExpandedVisibleRowCount = function(iRowCount) {
		this.setProperty("expandedVisibleRowCount", iRowCount, true);
		if (this.getExpanded()) {
			sap.ui.table.Table.prototype.setVisibleRowCount.apply(this, arguments);
		}
	};

	DataTable.prototype.setExpanded = function(bExpanded) {
		this.setProperty("expanded", bExpanded, true);
		if (this.getExpandedVisibleRowCount() > 0) {
			var iRowCount = bExpanded ? this.getExpandedVisibleRowCount() : this._iVisibleRowCount;
			sap.ui.table.Table.prototype.setVisibleRowCount.call(this, iRowCount);
		}
	};

	return DataTable;

}, /* bExport= */ true);
<commit_msg>[FIX] DataTable.js - Resolved undefined function call.<commit_after>/*!
 * ${copyright}
 */

// Provides control sap.ui.table.DataTable.
sap.ui.define(['jquery.sap.global', './TreeTable', './Table', './library'],
	function(jQuery, TreeTable, Table, library) {
	"use strict";

	/**
	 * Constructor for a new DataTable.
	 *
	 * @param {string} [sId] id for the new control, generated automatically if no id is given
	 * @param {object} [mSettings] initial settings for the new control
	 *
	 * @class
	 * The DataTable control provides a set of sophisticated and comfort functions for table design. For example, you can make settings for the number of visible rows and a number for the displayed rows in the case the user expands the table. The first visible row can be explicitly set. For the selection of columns and rows, a Multi, a Single, a None, and an All mode are available. Setting the Editable property to true lets the user make changes on the table cell entries.
	 * @extends sap.ui.table.TreeTable
	 * @version ${version}
	 *
	 * @constructor
	 * @public
	 * @deprecated Since version 1.5.1.
	 * The DataTable has been replaced via the Table/TreeTable control.
	 * @alias sap.ui.table.DataTable
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var DataTable = TreeTable.extend("sap.ui.table.DataTable", /** @lends sap.ui.table.DataTable.prototype */ { metadata : {

		deprecated : true,
		library : "sap.ui.table",
		properties : {

			/**
			 * Count of visible rows when expanded
			 */
			expandedVisibleRowCount : {type : "int", defaultValue : null},

			/**
			 * Flag whether the Table is expanded or not
			 */
			expanded : {type : "boolean", defaultValue : false},

			/**
			 * Flag, whether the table displays its content hierarchical or not (**experimental**!!)
			 */
			hierarchical : {type : "boolean", defaultValue : false}
		},
		events : {

			/**
			 * fired when the row selection of the table has been changed
			 */
			rowSelect : {
				parameters : {

					/**
					 * row index which row has been selected or deselected
					 */
					rowIndex : {type : "int"},

					/**
					 * binding context of the row index which row has been selected or deselected
					 */
					rowContext : {type : "object"},

					/**
					 * array of row indices which selection has been changed (either selected or deselected)
					 */
					rowIndices : {type : "int[]"}
				}
			}
		}
	}});

	/**
	 * Initialization of the DataTable control
	 * @private
	 */
	DataTable.prototype.init = function() {

		TreeTable.prototype.init.apply(this, arguments);

		this._bInheritEditableToControls = true;

		// default values for DataTable
		this.setEditable(false);
		this.setSelectionBehavior(sap.ui.table.SelectionBehavior.Row);

		this.attachRowSelectionChange(function(oEvent) {
			this.fireRowSelect(oEvent.mParameters);
		});

		this._iLastFixedColIndex = -1;

	};

	DataTable.prototype.isTreeBinding = function(sName) {
		sName = sName || "rows";
		if (sName === "rows") {
			return this.getHierarchical();
		}
		return sap.ui.core.Element.prototype.isTreeBinding.apply(this, arguments);
	};

	DataTable.prototype.setHierarchical = function(bHierarchical) {
		this.setProperty("hierarchical", bHierarchical);
		this._iLastFixedColIndex = bHierarchical ? 0 : -1;
	};

	DataTable.prototype.setVisibleRowCount = function(iRowCount) {
		this._iVisibleRowCount = iRowCount;
		if (!this.getExpanded()) {
			sap.ui.table.Table.prototype.setVisibleRowCount.apply(this, arguments);
		}
	};

	DataTable.prototype.setExpandedVisibleRowCount = function(iRowCount) {
		this.setProperty("expandedVisibleRowCount", iRowCount, true);
		if (this.getExpanded()) {
			sap.ui.table.Table.prototype.setVisibleRowCount.apply(this, arguments);
		}
	};

	DataTable.prototype.setExpanded = function(bExpanded) {
		this.setProperty("expanded", bExpanded, true);
		if (this.getExpandedVisibleRowCount() > 0) {
			var iRowCount = bExpanded ? this.getExpandedVisibleRowCount() : this._iVisibleRowCount;
			sap.ui.table.Table.prototype.setVisibleRowCount.call(this, iRowCount);
		}
	};

	DataTable.prototype.getContextByIndex = function (iRowIndex) {
		Table.prototype.getContextByIndex.call(this, iRowIndex);
	};

	return DataTable;

}, /* bExport= */ true);
<|endoftext|>


<commit_before>/**
 * Defines the stub as a Module to be loaded via requireJS.
 * This avoids name-spacing issues.
 * @returns {MessagingStub_IMS_External}
 */
define("MessagingStub_IMS_External", function (require, exports, module) {

	/*********************************************************************************
	 * Messaging Stub Class
	 * For websocket
	 */
	function MessagingStub_IMS_External(connectURI) {
		this.ownRtcIdentity;
		this.credentials;

		this.websocket;
		this.delayedMessages = {};
		this.signaling_server = "192.168.7.126:8282";
//		this.signaling_server = connectURI;
	}

	/**
	 * Sends the specified message.
	 * @param Message : message ... Message to send.
	 */
	MessagingStub_IMS_External.prototype.sendMessage = function (message) {
		/*
		 * constructs an identifier for this msg from contextId + to
		 */
		getMessageKey = function (msg) {
			var key = msg.contextId + "_";
			if (msg.to instanceof Identity)
				return key + msg.to.rtcIdentity;
			else if (msg.to instanceof Array && msg.to.length > 0) {
				if (msg.to[0] instanceof Identity)
					return key + msg.to[0].rtcIdentity;
				else
					return key + msg.to[0];
			}
			else
				return key + msg.to;
		};

		// From and To Identities are changed into strings containing rtcIdentities
		// To is always an array even if it wasnt.
		message.from = message.from.rtcIdentity;

		if (message.to instanceof Array)
			message.to.every(function (element, index, array) {
				array[index] = element.rtcIdentity;
			});
		else
			message.to = new Array(message.to.rtcIdentity);

		var msg = message;
		var msgKey = getMessageKey(message);
		console.log("msgKey = " + msgKey);

		switch (message.type) {
			case MessageType.INVITATION:
			case MessageType.ACCEPTED:
				this.delayedMessages[msgKey] = msg;
				console.log("set message on hold with key: " + msgKey);
				// don't send this msg now
				msg = null;
				break;

			case MessageType.CONNECTIVITY_CANDIDATE:
				// last candidate and we have a delayed message
				if (message.body.lastCandidate) {
					var delayedMessage = this.delayedMessages[msgKey]
					if (delayedMessage) {
						// replace RTCConnection with current localDescription in message.body.connectionDescription
						delayedMessage.body.connectionDescription = message.body.connectionDescription;
						msg = delayedMessage;
						delete this.delayedMessages[msgKey];
					}
				}
				else {
					// dont send candidates
					msg = null;
				}
				break;
			default:
				break;
		}
		if (msg) {
			var msgString = JSON.stringify(msg);
			this.websocket.send(msgString);
		}
	};

	/**
	 * Creates the connection, connects to the server and establish the callback to the listeners on new message.
	 * @param Identity : manager ...
	 * @param ???????? : credentials ... credentials to connect to the server.
	 */
	MessagingStub_IMS_External.prototype.connect = function (ownRtcIdentity, credentials, callbackFunction) {
		this.ownRtcIdentity = ownRtcIdentity;
		this.credentials = credentials;

		// If connect was already executed succesfully, it won't try to connect again, just execute the callback.
		if (this.websocket) {
			console.log("Websocket connection already opened, executing callback function: ");
			callbackFunction();
			return;
		}

		console.log('Opening channel: ' + this.signaling_server);
		this.websocket = new WebSocket(this.signaling_server);

		this.websocket.onopen = function () {
			console.log("Websocket connection opened");
			callbackFunction();
		};
		this.websocket.onerror = function () {
			console.log("Websocket connection error");
		};
		this.websocket.onclose = function () {
			console.log("Websocket connection closed");
		};

		// Maps the websocket listener to the MessagingStub listeners, and notifies filtering
		// by contextId
		var that = this;
		this.websocket.onmessage = function (full_message) {
			// IF it doesnt have contextID, it is the application.
			var message = JSON.parse(full_message.data);
			Idp.getInstance().createIdentity(message.from, function (identity) {
				message.from = identity;

				// createIdentities can take array or single rtcIdentity and always returns an Array in the callback result
				Idp.getInstance().createIdentities(message.to, function (identityArr) {
					//message.to = new Array(identityArr);
					message.to = identityArr;

					that.baseStub.sendOtherMessages(message);
				});
			});

		};
	}

	/**
	 * Disconnects from the server.
	 */
	MessagingStub_IMS_External.prototype.disconnect = function ()
	{
		this.websocket.close();
		this.websocket = null;
	};

	return new MessagingStub_IMS_External();
});
<commit_msg>fixed assignment of config to IMS external stub<commit_after>/**
 * Defines the stub as a Module to be loaded via requireJS.
 * This avoids name-spacing issues.
 * @returns {MessagingStub_IMS_External}
 */
define("MessagingStub_IMS_External", function (require, exports, module) {

	/*********************************************************************************
	 * Messaging Stub Class
	 * For websocket
	 */
	function MessagingStub_IMS_External() {
		this.ownRtcIdentity;
		this.credentials;

		this.websocket;
		this.delayedMessages = {};
//		this.signaling_server = "192.168.7.126:8282";
		this.signaling_server = module.config().connectURL;
	}

	/**
	 * Sends the specified message.
	 * @param Message : message ... Message to send.
	 */
	MessagingStub_IMS_External.prototype.sendMessage = function (message) {
		/*
		 * constructs an identifier for this msg from contextId + to
		 */
		getMessageKey = function (msg) {
			var key = msg.contextId + "_";
			if (msg.to instanceof Identity)
				return key + msg.to.rtcIdentity;
			else if (msg.to instanceof Array && msg.to.length > 0) {
				if (msg.to[0] instanceof Identity)
					return key + msg.to[0].rtcIdentity;
				else
					return key + msg.to[0];
			}
			else
				return key + msg.to;
		};

		// From and To Identities are changed into strings containing rtcIdentities
		// To is always an array even if it wasnt.
		message.from = message.from.rtcIdentity;

		if (message.to instanceof Array)
			message.to.every(function (element, index, array) {
				array[index] = element.rtcIdentity;
			});
		else
			message.to = new Array(message.to.rtcIdentity);

		var msg = message;
		var msgKey = getMessageKey(message);
		console.log("msgKey = " + msgKey);

		switch (message.type) {
			case MessageType.INVITATION:
			case MessageType.ACCEPTED:
				this.delayedMessages[msgKey] = msg;
				console.log("set message on hold with key: " + msgKey);
				// don't send this msg now
				msg = null;
				break;

			case MessageType.CONNECTIVITY_CANDIDATE:
				// last candidate and we have a delayed message
				if (message.body.lastCandidate) {
					var delayedMessage = this.delayedMessages[msgKey]
					if (delayedMessage) {
						// replace RTCConnection with current localDescription in message.body.connectionDescription
						delayedMessage.body.connectionDescription = message.body.connectionDescription;
						msg = delayedMessage;
						delete this.delayedMessages[msgKey];
					}
				}
				else {
					// dont send candidates
					msg = null;
				}
				break;
			default:
				break;
		}
		if (msg) {
			var msgString = JSON.stringify(msg);
			this.websocket.send(msgString);
		}
	};

	/**
	 * Creates the connection, connects to the server and establish the callback to the listeners on new message.
	 * @param Identity : manager ...
	 * @param ???????? : credentials ... credentials to connect to the server.
	 */
	MessagingStub_IMS_External.prototype.connect = function (ownRtcIdentity, credentials, callbackFunction) {
		this.ownRtcIdentity = ownRtcIdentity;
		this.credentials = credentials;

		// If connect was already executed succesfully, it won't try to connect again, just execute the callback.
		if (this.websocket) {
			console.log("Websocket connection already opened, executing callback function: ");
			callbackFunction();
			return;
		}

		console.log('Opening channel: ' + this.signaling_server);
		this.websocket = new WebSocket(this.signaling_server);

		this.websocket.onopen = function () {
			console.log("Websocket connection opened");
			callbackFunction();
		};
		this.websocket.onerror = function () {
			console.log("Websocket connection error");
		};
		this.websocket.onclose = function () {
			console.log("Websocket connection closed");
		};

		// Maps the websocket listener to the MessagingStub listeners, and notifies filtering
		// by contextId
		var that = this;
		this.websocket.onmessage = function (full_message) {
			// IF it doesnt have contextID, it is the application.
			var message = JSON.parse(full_message.data);
			Idp.getInstance().createIdentity(message.from, function (identity) {
				message.from = identity;

				// createIdentities can take array or single rtcIdentity and always returns an Array in the callback result
				Idp.getInstance().createIdentities(message.to, function (identityArr) {
					//message.to = new Array(identityArr);
					message.to = identityArr;

					that.baseStub.sendOtherMessages(message);
				});
			});

		};
	}

	/**
	 * Disconnects from the server.
	 */
	MessagingStub_IMS_External.prototype.disconnect = function ()
	{
		this.websocket.close();
		this.websocket = null;
	};

	return new MessagingStub_IMS_External();
});
<|endoftext|>


<commit_before>/*globals define, _, WebGMEGlobal*/
/*jshint browser: true*/

define([
    'js/logger',
    'js/Constants',
    'js/RegistryKeys',
    'js/PanelBase/PanelBase',
    'js/Utils/ComponentSettings',
    'text!/api/visualizers'
], function (
    Logger,
    CONSTANTS,
    REGISTRY_KEYS,
    PanelBase,
    ComponentSettings,
    VisualizersJSON
) {
    'use strict';

    var VisualizerIds,
        AutoVizPanel;

    VisualizersJSON = JSON.parse(VisualizersJSON)
        .filter(viz => viz.panel.indexOf('/AutoVizPanel') === -1);
    VisualizerIds = VisualizersJSON.map(viz => viz.id);

    // This visualizer simply checks the validVisualizers in the given node
    // and loads the appropriate visualizer.
    //
    // It is very similar to the "Visualizer" in the core WebGME library
    // except it is completely UI-less
    AutoVizPanel = function (layoutManager, params) {
        var options = {};
        options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = 'AutoViz';
        PanelBase.call(this, options);

        this._layoutManager = layoutManager;
        this._params = params;
        // Add setting for embedded behavior
        this._params.embedded = true;

        this._activePanel = null;
        this._activePanelId = null;
        this._activeProject = null;
        this.currentNode = null;
        this._panels = {};

        this._territoryId = null;
        this._client = params.client;

        this.config = {
            preloadIds: [],
            visualizerOverrides: {}
        };
        ComponentSettings.resolveWithWebGMEGlobal(this.config, AutoVizPanel.getComponentId());
        this.preloadId = 0;

        //initialize event handlers
        this._initialize();
        this.preloadNext();

        this.logger.debug('ctor finished');
    };

    AutoVizPanel.getComponentId = function() {
        return 'AutoViz';
    };

    AutoVizPanel.prototype.preloadNext = function() {
        var panelId,
            panelIndex = -1;

        // Load the next visualizer id
        while (this.preloadId < this.config.preloadIds.length && panelIndex === -1) {
            panelId = this.config.preloadIds[this.preloadId++];
            panelIndex = VisualizerIds.indexOf(panelId);
        }

        if (panelIndex !== -1) {
            this.getPanel(VisualizersJSON[panelIndex].panel, this.preloadNext.bind(this));
        }
    };

    AutoVizPanel.prototype._initialize = function() {
        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
            (model, id) => {
                var currentProject = this._client.getActiveProjectName(),
                    refresh = this._activeProject !== currentProject ||
                        !this.currentNode || this.currentNode.getId() !== id;

                if (refresh) {
                    if (this._activeProject !== currentProject) {
                        this.logger.debug(`Project changed: ${this._activeProject} -> ${currentProject}`);
                    }
                    this.logger.debug(`Loading node "${id}"`);
                    this.selectedObjectChanged(id);
                    this._activeProject = currentProject;
                }
            });

        this._defaultPanelIndex = 0;
        for (var i = VisualizersJSON.length; i--;) {
            if (VisualizersJSON[i].default) {
                this._defaultPanelIndex = i;
            }
        }
    };

    AutoVizPanel.prototype.TERRITORY_RULE = {children: 0};
    AutoVizPanel.prototype.selectedObjectChanged = function(nodeId) {
        if (this._territoryId) {
            this._client.removeUI(this._territoryId);
        }

        if (typeof nodeId === 'string') {
            this._territoryId = this._client.addUI(this, events => {
                this.logger.debug(`Received ${events.length} events`);
                this._eventCallback(events);
            });
            this.logger.debug(`AutoViz current territory id is ${this._territoryId}`);

            this._selfPatterns = {};
            this._selfPatterns[nodeId] = this.TERRITORY_RULE;
            this.logger.debug(`updating territory: ${JSON.stringify(this._selfPatterns)}`);
            this._client.updateTerritory(this._territoryId, this._selfPatterns);
        }
    };

    AutoVizPanel.prototype._eventCallback = function(events) {
        var event = events.find(e => e.etype === CONSTANTS.TERRITORY_EVENT_LOAD),
            currentId = event ? event.eid : null,
            newNode;

        if (event) {
            this.logger.info(`received event for node "${currentId}"`);
            newNode = this._client.getNode(currentId);
            if (!this.currentNode || this.currentNode !== newNode) {
                this.currentNode = newNode;
                this.update();
            }
        }
    };

    // Update the active panel
    AutoVizPanel.prototype.update = function() {
        var panelId,
            panelIndex;

        panelId = this.getPanelId();

        // If the panel id does not exist or is undefined, set it to the defaultId
        panelIndex = VisualizerIds.indexOf(panelId);
        if (panelIndex === -1) {
            panelIndex = this._defaultPanelIndex;
        }

        this.logger.info(`setting active panel to ${panelId}`);
        this.setPanel(VisualizersJSON[panelIndex], () => {
            if (this._activePanel.control &&
                this._activePanel.control.selectedObjectChanged) {
                this.logger.info('invoking selectedObjectChanged on active panel');
                this._activePanel.control.selectedObjectChanged(this.currentNode.getId());
            }
        });
    };

    AutoVizPanel.prototype.getPanelId = function() {
        var base = this._client.getNode(this.currentNode.getMetaTypeId()),
            baseType = base && base.getAttribute('name');

        if (baseType && this.config.visualizerOverrides[baseType]) {
            return this.config.visualizerOverrides[baseType];
        }

        return (this.currentNode.getRegistry(REGISTRY_KEYS.VALID_VISUALIZERS) || '')
            .split(' ')
            .shift();
    };

    AutoVizPanel.prototype.setPanel = function(panelDesc, cb) {
        var self = this;

        // Load the panel
        this.getPanel(panelDesc.panel, function(panel) {
            if (self._activePanel) {
                self._activePanel.destroy();
                self._activePanel.$pEl.remove();
            }
            self._layoutManager.addPanel('activePanel', panel, 'center');
            self._activePanel = panel;
            // set read only
            self._activePanel.setReadOnly(self.isReadOnly());
            self._activePanelId = panelDesc.id;
            cb();
        });

        this._activePanelId = panelDesc.id;
    };

    AutoVizPanel.prototype.getPanel = function(panelPath, callback) {
        var self = this;

        if (this._panels[panelPath]) {
            callback(new this._panels[panelPath](this._layoutManager, this._params));
        } else {
            require([panelPath], function (PanelClass) {
                var panel = new PanelClass(self._layoutManager, self._params);
                self._panels[panelPath] = PanelClass;
                callback(panel);
            },
            function(err) {
                self.logger.error('Failed to download "' + err.requireModules[0] + '"');
            });

        }
    };

    AutoVizPanel.prototype._forwardFn = function(fn, args) {
        if (this._activePanel) {
            return this._activePanel[fn].apply(this._activePanel, args);
        }
    };

    _.extend(AutoVizPanel.prototype, PanelBase.prototype);

    // Pass through functions
    AutoVizPanel.prototype.setSize = function() {
        return this._forwardFn('setSize', arguments);
    };

    AutoVizPanel.prototype.destroy = function() {
        return this._forwardFn('destroy', arguments);
    };

    AutoVizPanel.prototype.clear = function() {
        return this._forwardFn('clear', arguments);
    };

    AutoVizPanel.prototype.afterAppend = function() {
        return this._forwardFn('afterAppend', arguments);
    };

    AutoVizPanel.prototype.setReadOnly = function() {
        PanelBase.prototype.setReadOnly.apply(this, arguments);
        return this._forwardFn('setReadOnly', arguments);
    };

    AutoVizPanel.prototype.isReadOnly = function() {
        return PanelBase.prototype.isReadOnly.apply(this, arguments);
    };

    AutoVizPanel.prototype.onReadOnlyChanged = function() {
        PanelBase.prototype.onReadOnlyChanged.apply(this, arguments);
        return this._forwardFn('onReadOnlyChanged', arguments);
    };

    return AutoVizPanel;
});
<commit_msg>Added root visualizer override support. Fixes #28 (#29)<commit_after>/*globals define, _, WebGMEGlobal*/
/*jshint browser: true*/

define([
    'js/logger',
    'js/Constants',
    'js/RegistryKeys',
    'js/PanelBase/PanelBase',
    'js/Utils/ComponentSettings',
    'text!/api/visualizers'
], function (
    Logger,
    CONSTANTS,
    REGISTRY_KEYS,
    PanelBase,
    ComponentSettings,
    VisualizersJSON
) {
    'use strict';

    var VisualizerIds,
        AutoVizPanel;

    VisualizersJSON = JSON.parse(VisualizersJSON)
        .filter(viz => viz.panel.indexOf('/AutoVizPanel') === -1);
    VisualizerIds = VisualizersJSON.map(viz => viz.id);

    // This visualizer simply checks the validVisualizers in the given node
    // and loads the appropriate visualizer.
    //
    // It is very similar to the "Visualizer" in the core WebGME library
    // except it is completely UI-less
    AutoVizPanel = function (layoutManager, params) {
        var options = {};
        options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = 'AutoViz';
        PanelBase.call(this, options);

        this._layoutManager = layoutManager;
        this._params = params;
        // Add setting for embedded behavior
        this._params.embedded = true;

        this._activePanel = null;
        this._activePanelId = null;
        this._activeProject = null;
        this.currentNode = null;
        this._panels = {};

        this._territoryId = null;
        this._client = params.client;

        this.config = {
            preloadIds: [],
            visualizerOverrides: {}
        };
        ComponentSettings.resolveWithWebGMEGlobal(this.config, AutoVizPanel.getComponentId());
        this.preloadId = 0;

        //initialize event handlers
        this._initialize();
        this.preloadNext();

        this.logger.debug('ctor finished');
    };

    AutoVizPanel.getComponentId = function() {
        return 'AutoViz';
    };

    AutoVizPanel.prototype.preloadNext = function() {
        var panelId,
            panelIndex = -1;

        // Load the next visualizer id
        while (this.preloadId < this.config.preloadIds.length && panelIndex === -1) {
            panelId = this.config.preloadIds[this.preloadId++];
            panelIndex = VisualizerIds.indexOf(panelId);
        }

        if (panelIndex !== -1) {
            this.getPanel(VisualizersJSON[panelIndex].panel, this.preloadNext.bind(this));
        }
    };

    AutoVizPanel.prototype._initialize = function() {
        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT,
            (model, id) => {
                var currentProject = this._client.getActiveProjectName(),
                    refresh = this._activeProject !== currentProject ||
                        !this.currentNode || this.currentNode.getId() !== id;

                if (refresh) {
                    if (this._activeProject !== currentProject) {
                        this.logger.debug(`Project changed: ${this._activeProject} -> ${currentProject}`);
                    }
                    this.logger.debug(`Loading node "${id}"`);
                    this.selectedObjectChanged(id);
                    this._activeProject = currentProject;
                }
            });

        this._defaultPanelIndex = 0;
        for (var i = VisualizersJSON.length; i--;) {
            if (VisualizersJSON[i].default) {
                this._defaultPanelIndex = i;
            }
        }
    };

    AutoVizPanel.prototype.TERRITORY_RULE = {children: 0};
    AutoVizPanel.prototype.selectedObjectChanged = function(nodeId) {
        if (this._territoryId) {
            this._client.removeUI(this._territoryId);
        }

        if (typeof nodeId === 'string') {
            this._territoryId = this._client.addUI(this, events => {
                this.logger.debug(`Received ${events.length} events`);
                this._eventCallback(events);
            });
            this.logger.debug(`AutoViz current territory id is ${this._territoryId}`);

            this._selfPatterns = {};
            this._selfPatterns[nodeId] = this.TERRITORY_RULE;
            this.logger.debug(`updating territory: ${JSON.stringify(this._selfPatterns)}`);
            this._client.updateTerritory(this._territoryId, this._selfPatterns);
        }
    };

    AutoVizPanel.prototype._eventCallback = function(events) {
        var event = events.find(e => e.etype === CONSTANTS.TERRITORY_EVENT_LOAD),
            currentId = event ? event.eid : null,
            newNode;

        if (event) {
            this.logger.info(`received event for node "${currentId}"`);
            newNode = this._client.getNode(currentId);
            if (!this.currentNode || this.currentNode !== newNode) {
                this.currentNode = newNode;
                this.update();
            }
        }
    };

    // Update the active panel
    AutoVizPanel.prototype.update = function() {
        var panelId,
            panelIndex;

        panelId = this.getPanelId();

        // If the panel id does not exist or is undefined, set it to the defaultId
        panelIndex = VisualizerIds.indexOf(panelId);
        if (panelIndex === -1) {
            panelIndex = this._defaultPanelIndex;
        }

        this.logger.info(`setting active panel to ${panelId}`);
        this.setPanel(VisualizersJSON[panelIndex], () => {
            if (this._activePanel.control &&
                this._activePanel.control.selectedObjectChanged) {
                this.logger.info('invoking selectedObjectChanged on active panel');
                this._activePanel.control.selectedObjectChanged(this.currentNode.getId());
            }
        });
    };

    AutoVizPanel.prototype.getPanelId = function() {
        var base = this._client.getNode(this.currentNode.getMetaTypeId()),
            baseType = base && base.getAttribute('name');

        // If currentNode is the root node, use "" as the baseType
        if (this.currentNode.getId() === CONSTANTS.PROJECT_ROOT_ID) {
            baseType = '';
        }

        if (this.config.visualizerOverrides[baseType]) {
            return this.config.visualizerOverrides[baseType];
        }

        return (this.currentNode.getRegistry(REGISTRY_KEYS.VALID_VISUALIZERS) || '')
            .split(' ')
            .shift();
    };

    AutoVizPanel.prototype.setPanel = function(panelDesc, cb) {
        var self = this;

        // Load the panel
        this.getPanel(panelDesc.panel, function(panel) {
            if (self._activePanel) {
                self._activePanel.destroy();
                self._activePanel.$pEl.remove();
            }
            self._layoutManager.addPanel('activePanel', panel, 'center');
            self._activePanel = panel;
            // set read only
            self._activePanel.setReadOnly(self.isReadOnly());
            self._activePanelId = panelDesc.id;
            cb();
        });

        this._activePanelId = panelDesc.id;
    };

    AutoVizPanel.prototype.getPanel = function(panelPath, callback) {
        var self = this;

        if (this._panels[panelPath]) {
            callback(new this._panels[panelPath](this._layoutManager, this._params));
        } else {
            require([panelPath], function (PanelClass) {
                var panel = new PanelClass(self._layoutManager, self._params);
                self._panels[panelPath] = PanelClass;
                callback(panel);
            },
            function(err) {
                self.logger.error('Failed to download "' + err.requireModules[0] + '"');
            });

        }
    };

    AutoVizPanel.prototype._forwardFn = function(fn, args) {
        if (this._activePanel) {
            return this._activePanel[fn].apply(this._activePanel, args);
        }
    };

    _.extend(AutoVizPanel.prototype, PanelBase.prototype);

    // Pass through functions
    AutoVizPanel.prototype.setSize = function() {
        return this._forwardFn('setSize', arguments);
    };

    AutoVizPanel.prototype.destroy = function() {
        return this._forwardFn('destroy', arguments);
    };

    AutoVizPanel.prototype.clear = function() {
        return this._forwardFn('clear', arguments);
    };

    AutoVizPanel.prototype.afterAppend = function() {
        return this._forwardFn('afterAppend', arguments);
    };

    AutoVizPanel.prototype.setReadOnly = function() {
        PanelBase.prototype.setReadOnly.apply(this, arguments);
        return this._forwardFn('setReadOnly', arguments);
    };

    AutoVizPanel.prototype.isReadOnly = function() {
        return PanelBase.prototype.isReadOnly.apply(this, arguments);
    };

    AutoVizPanel.prototype.onReadOnlyChanged = function() {
        PanelBase.prototype.onReadOnlyChanged.apply(this, arguments);
        return this._forwardFn('onReadOnlyChanged', arguments);
    };

    return AutoVizPanel;
});
<|endoftext|>


<commit_before>ZBase.registerView((function() {

  var kPathPrefix = "/a/sql/";

  var query_mgr;
  var docsync;

  var init = function(params) {
    query_mgr = EventSourceHandler();
    loadQuery(params.path);
  };

  var destroy = function() {
    query_mgr.closeAll();

    if (docsync) {
      docsync.close();
    }
  };

  var loadQuery = function(path) {
    var query_id = path.substr(kPathPrefix.length);

    $.showLoader();
    ZBaseMainMenu.update("/a/datastore/queries");

    $.httpGet("/api/v1/documents/" + query_id, function(r) {
      if (r.status == 200) {
        var doc = JSON.parse(r.response);
        renderQueryEditor(doc);
        $.hideLoader();
      } else {
        $.fatalError();
      }
    });
  };

  var executeQuery = function(query_string) {
    renderQueryProgress();

    var query = query_mgr.get(
      "sql_query",
      "/api/v1/sql?format=json_sse&query=" + encodeURIComponent(query_string));

    query.addEventListener('result', function(e) {
      query_mgr.close("sql_query");

      console.log("DONE!");
      var data = JSON.parse(e.data);
      renderQueryResult(data.results);
    });

    query.addEventListener('query_error', function(e) {
      query_mgr.close("sql_query");
      renderQueryError(JSON.parse(e.data).error);
    });

    query.addEventListener('error', function(e) {
      query_mgr.close("sql_query");
      renderQueryError("Server Error");
    });

    query.addEventListener('status', function(e) {
      renderQueryProgress(JSON.parse(e.data));
    });
  }

  var renderQueryEditor = function(doc) {
    var readonly = !doc.is_writable;
    var page = $.getTemplate(
        "views/sql_editor",
        "zbase_sql_editor_main_tpl");

    if (!readonly) {
      // setup docsync
      docsync = DocSync(
          getDocument,
          "/api/v1/documents/" + doc.uuid,
          $(".zbase_sql_editor_infobar", page));
    }

    //breadcrumbs
    $(".query_name_breadcrumb", page).href = kPathPrefix + doc.uuid;

    // code editor
    var editor = $("z-codeeditor", page);
    editor.setValue(doc.content);
    if (readonly) editor.setAttribute("data-readonly", "readonly");
    editor.addEventListener("execute", function(e) {
      executeQuery(e.value);
      if (docsync) docsync.saveDocument();
    });

    var execute_btn = $("button[data-action='execute-query']", page);
    $.onClick(execute_btn, function() {
      editor.execute();
    });
    $("z-tooltip.execute_hint", page).init(execute_btn);

    //table_list
    var table_list = TableListWidget($(".table_list", page));
    table_list.render();

    //preferences
    var settings_widget = DocumentSettingsWidget(
        $(".document_settings", page),
        doc.uuid);
    settings_widget.render();

    // sharing widget/button
    if (readonly) {
      $(".share_button", page).remove();
    } else {
      var share_modal = ShareDocModal(
          $(".zbase_sql_editor", page),
          doc.uuid,
          "http://zbase.io/a/sql/" + doc.uuid);
      $.onClick($("button[data-action='share-query']", page), function() {
        share_modal.show();
      });
    }

    //sidebar visibility
    $.onClick($(".sidebar_visibility", page), toggleSidebarVisibility);

    $.handleLinks(page);
    $.replaceViewport(page);

    if (!readonly) {
      editor.focus();
    }

    // document name + name editing
    setDocumentTitle(doc.name);
    if (!readonly) {
      $(".zbase_sql_editor .document_name").classList.add("editable");
      initDocumentNameEditModal();
    } else {
      $(".zbase_sql_editor .readonly_hint").classList.remove("hidden");
    }

    // execute query
    if (doc.content.length > 0) {
      executeQuery(doc.content);
    }
  };

  var renderQueryResult = function(res) {
    QueryProgressWidget.finish();
    var result_list = SQLEditorResultList(res);
    result_list.render($(".zbase_sql_editor_result_pane"));
  }

  var renderQueryError = function(error) {
    var error_msg = $.getTemplate(
        "views/sql_editor",
        "zbase_sql_editor_error_msg_tpl");

    $(".error_text", error_msg).innerHTML = error;
    $.replaceContent($(".zbase_sql_editor_result_pane"), error_msg);
  }

  var renderQueryProgress = function(progress) {
    QueryProgressWidget.render(
        $(".zbase_sql_editor_result_pane"),
        progress);
  }

  var initDocumentNameEditModal = function() {
    var modal = $(".zbase_sql_editor_pane z-modal.rename_query");
    var name_input = $(".zbase_sql_editor_pane input[name='doc_name']");

    $.onClick($(".zbase_sql_editor_title h2"), function() {
      modal.show();
      name_input.focus();
    });

    $.onClick($("button[data-action='submit']", modal), function() {
      setDocumentTitle(name_input.value);
      docsync.saveDocument();
      modal.close();
    });
  };

  var setDocumentTitle = function(title) {
    var escaped_name = $.escapeHTML(title);
    $(".zbase_sql_editor_breadcrumbs .query_name_breadcrumb").innerHTML = escaped_name;
    $(".zbase_sql_editor_title h2").innerHTML = escaped_name;
    $(".zbase_sql_editor_pane input[name='doc_name']").value = title;
  }

  var getDocument = function() {
    return {
      content: $(".zbase_sql_editor_pane z-codeeditor").getValue(),
      name: $(".zbase_sql_editor_pane input[name='doc_name']").value
    };
  };

  var toggleSidebarVisibility = function(e) {
    this.classList.toggle("closed");
    $(".zbase_sql_editor_sidebar").classList.toggle("hidden");
  };

  return {
    name: "sql_editor",
    loadView: init,
    unloadView: destroy,
    handleNavigationChange: loadQuery
  };

})());
<commit_msg>sql editor: render error message if doc load failed<commit_after>ZBase.registerView((function() {

  var kPathPrefix = "/a/sql/";

  var query_mgr;
  var docsync;

  var init = function(params) {
    query_mgr = EventSourceHandler();
    loadQuery(params.path);
  };

  var destroy = function() {
    query_mgr.closeAll();

    if (docsync) {
      docsync.close();
    }
  };

  var loadQuery = function(path) {
    var query_id = path.substr(kPathPrefix.length);

    $.showLoader();
    ZBaseMainMenu.update("/a/datastore/queries");

    $.httpGet("/api/v1/documents/" + query_id, function(r) {
      if (r.status == 200) {
        var doc = JSON.parse(r.response);
        renderQueryEditor(doc);
      } else {
        renderError(r.statusText, kPathPrefix + query_id);
      }
      $.hideLoader();
    });
  };

  var executeQuery = function(query_string) {
    renderQueryProgress();

    var query = query_mgr.get(
      "sql_query",
      "/api/v1/sql?format=json_sse&query=" + encodeURIComponent(query_string));

    query.addEventListener('result', function(e) {
      query_mgr.close("sql_query");

      console.log("DONE!");
      var data = JSON.parse(e.data);
      renderQueryResult(data.results);
    });

    query.addEventListener('query_error', function(e) {
      query_mgr.close("sql_query");
      renderQueryError(JSON.parse(e.data).error);
    });

    query.addEventListener('error', function(e) {
      query_mgr.close("sql_query");
      renderQueryError("Server Error");
    });

    query.addEventListener('status', function(e) {
      renderQueryProgress(JSON.parse(e.data));
    });
  }

  var renderQueryEditor = function(doc) {
    var readonly = !doc.is_writable;
    var page = $.getTemplate(
        "views/sql_editor",
        "zbase_sql_editor_main_tpl");

    if (!readonly) {
      // setup docsync
      docsync = DocSync(
          getDocument,
          "/api/v1/documents/" + doc.uuid,
          $(".zbase_sql_editor_infobar", page));
    }

    //breadcrumbs
    $(".query_name_breadcrumb", page).href = kPathPrefix + doc.uuid;

    // code editor
    var editor = $("z-codeeditor", page);
    editor.setValue(doc.content);
    if (readonly) editor.setAttribute("data-readonly", "readonly");
    editor.addEventListener("execute", function(e) {
      executeQuery(e.value);
      if (docsync) docsync.saveDocument();
    });

    var execute_btn = $("button[data-action='execute-query']", page);
    $.onClick(execute_btn, function() {
      editor.execute();
    });
    $("z-tooltip.execute_hint", page).init(execute_btn);

    //table_list
    var table_list = TableListWidget($(".table_list", page));
    table_list.render();

    //preferences
    var settings_widget = DocumentSettingsWidget(
        $(".document_settings", page),
        doc.uuid);
    settings_widget.render();

    // sharing widget/button
    if (readonly) {
      $(".share_button", page).remove();
    } else {
      var share_modal = ShareDocModal(
          $(".zbase_sql_editor", page),
          doc.uuid,
          "http://zbase.io/a/sql/" + doc.uuid);
      $.onClick($("button[data-action='share-query']", page), function() {
        share_modal.show();
      });
    }

    //sidebar visibility
    $.onClick($(".sidebar_visibility", page), toggleSidebarVisibility);

    $.handleLinks(page);
    $.replaceViewport(page);

    if (!readonly) {
      editor.focus();
    }

    // document name + name editing
    setDocumentTitle(doc.name);
    if (!readonly) {
      $(".zbase_sql_editor .document_name").classList.add("editable");
      initDocumentNameEditModal();
    } else {
      $(".zbase_sql_editor .readonly_hint").classList.remove("hidden");
    }

    // execute query
    if (doc.content.length > 0) {
      executeQuery(doc.content);
    }
  };

  var renderQueryResult = function(res) {
    QueryProgressWidget.finish();
    var result_list = SQLEditorResultList(res);
    result_list.render($(".zbase_sql_editor_result_pane"));
  }

  var renderQueryError = function(error) {
    var error_msg = $.getTemplate(
        "views/sql_editor",
        "zbase_sql_editor_error_msg_tpl");

    $(".error_text", error_msg).innerHTML = error;
    $.replaceContent($(".zbase_sql_editor_result_pane"), error_msg);
  }

  var renderQueryProgress = function(progress) {
    QueryProgressWidget.render(
        $(".zbase_sql_editor_result_pane"),
        progress);
  }

  var renderError = function(msg, path) {
    var error_elem = document.createElement("div");
    error_elem.classList.add("zbase_error");
    error_elem.innerHTML =
        "" +
        "
We're sorry
" +
        "
An error occured.

" + msg + "
 " +
        "
Please try it again or contact support if the problem persists.
" +
        "" +
        " Back" +
        "" +
        " Reload" +
        "";

    $.replaceViewport(error_elem);
  };

  var initDocumentNameEditModal = function() {
    var modal = $(".zbase_sql_editor_pane z-modal.rename_query");
    var name_input = $(".zbase_sql_editor_pane input[name='doc_name']");

    $.onClick($(".zbase_sql_editor_title h2"), function() {
      modal.show();
      name_input.focus();
    });

    $.onClick($("button[data-action='submit']", modal), function() {
      setDocumentTitle(name_input.value);
      docsync.saveDocument();
      modal.close();
    });
  };

  var setDocumentTitle = function(title) {
    var escaped_name = $.escapeHTML(title);
    $(".zbase_sql_editor_breadcrumbs .query_name_breadcrumb").innerHTML = escaped_name;
    $(".zbase_sql_editor_title h2").innerHTML = escaped_name;
    $(".zbase_sql_editor_pane input[name='doc_name']").value = title;
  }

  var getDocument = function() {
    return {
      content: $(".zbase_sql_editor_pane z-codeeditor").getValue(),
      name: $(".zbase_sql_editor_pane input[name='doc_name']").value
    };
  };

  var toggleSidebarVisibility = function(e) {
    this.classList.toggle("closed");
    $(".zbase_sql_editor_sidebar").classList.toggle("hidden");
  };

  return {
    name: "sql_editor",
    loadView: init,
    unloadView: destroy,
    handleNavigationChange: loadQuery
  };

})());
<|endoftext|>


<commit_before>function ConnectionManager(server, resourceName, peerId, maxPeers, options) {

    options = options || {};

	var self = this;
	this.peers = {}; //connected peers
    var connectedPeerCount = 0;
    var timeoutHandlers = {};

    var logger = debug('connection-manager');

    this.connectNew = function connectNew(otherPeerId, connectOptions) {

        connectOptions = connectOptions || {};

        logger('start connecting with peer: ' + otherPeerId);

        var connection = new PeerSocket(resourceName, otherPeerId, 'offered');
        connection.on('disconnected', onDisconnected);
        connection.on('candidate', sendCandidate);
        connection.on('connected', onConnected);

        this.peers[otherPeerId] = connection;

        connection.offer(function(desc) {

            server.emit('offer', otherPeerId, desc);
        });

        if(connectOptions.timeout) {
            enableTimeout(otherPeerId, connectOptions.timeout);
        }
    };

    this.getConnectedPeerNames = function getConnectedPeers() {

        var rtn = [];
        for(var peerName in this.peers) {
            if(this.peers[peerName].connected) {
                rtn.push(peerName);
            }
        }

        return peerName;
    };

    this.getConnectedPeerCount = function getConnectedPeerCount() {

        return connectedPeerCount;
    };

    this.canHaveMorePeers = function canHaveMorePeers(count) {

        var cntMoreNeeded = maxPeers - connectedPeerCount;
        if(cntMoreNeeded > 0) {
            return (cntMoreNeeded > count)? count: cntMoreNeeded;
        } else {
            return 0;
        }
    };

    this.close = function close() {

        //server based listeners
        server.removeListener('answer', onAnswer);
        server.removeListener('offer', onOffer);
        server.removeListener('ice-candidate', onIceCandidate);
        server.removeListener('error', onServerError);

        //close connections
        for(var peerId in this.peers) {
            this.peers[peerId].close();
        }
    };

    server.on('answer', onAnswer);
    server.on('offer', onOffer);
    server.on('ice-candidate', onIceCandidate);
    server.on('error', onServerError);

    function onAnswer(from, status, answerDesc) {

        logger('answer from: ' + from  + ' with status: ' + status);
        var connection = self.peers[from];
        if(connection) {
            if(status == 'ACCEPTED') {
                connection.setRemote(answerDesc);
            } else {
                connection.close();
            }
        } else {
            logger('no connection to answer: ' + from);
        }
    }

    function onOffer(from, desc) {

        logger('offer from: ' + from);
        if(self.peers[desc]) {
            logger('offer rejected because of exisitng from: ' + from);
            server.emit('answer', from, 'REJECTED');
        } else {
            var connection = new PeerSocket(resourceName, from, 'answered');
            if(connection) {
                connection.on('disconnected', onDisconnected);
                connection.on('candidate', sendCandidate);
                connection.on('connected', onConnected);
                connection.answer(desc, function(answerDesc) {

                    server.emit('answer', from, 'ACCEPTED', answerDesc);
                });

                self.peers[from] = connection;

                if(options.answerTimeout) {
                    enableTimeout(from, options.answerTimeout);
                }
            } else {
                logger('no connection to offer: ' + from);
            }
        }

    }

    function onIceCandidate(from, candidate) {

        var connection = self.peers[from];
        if(connection) {
            connection.addCandidate(candidate);
        } else {
            logger('no connection to offer ice-candidate: ' + from);
        }
    }

    function onServerError(event, error) {

        logger('server error on: ' + event + ' error: ' + JSON.stringify(error));
        if(error && error.code == 'NO_CLIENT') {
            var connection = self.peers[error.to];
            if(connection) {
                connection.close();
            }
        }
    }

    function sendCandidate(candidate) {

        server.emit('ice-candidate', this.peerId, candidate);
    }

    function onConnected() {

        logger('connecting: ' + this.peerId);
        connectedPeerCount++;
        self.emit('peer', this);
        this.removeListener('connected', onConnected);

        cancleTimeout(this.peerId);
    }

    function onDisconnected() {

        logger('disconnecting: ' + this.peerId);
        connectedPeerCount--;

    	delete self.peers[this.peerId];
        this.removeListener('disconnected', onDisconnected);
        this.removeListener('candidate', sendCandidate);
        this.removeListener('connected', onConnected);

        cancleTimeout(this.peerId);
    }

    function enableTimeout(peerId, timeoutMillis) {

        timeoutHandlers[peerId] = setTimeout(function() {

            var connection = self.peers[peerId];
            if(connection && !connection.connected) {
                logger('timeouting: ' + peerId + ' after: ' + timeoutMillis);
                connection.close();
                timeoutHandlers[peerId] = null;
            }
        }, timeoutMillis);
    }

    function cancleTimeout(peerId) {

        var handler = timeoutHandlers[peerId];
        if(handler) {
            logger('clearing timeout handler for: ' + peerId);
            clearTimeout(handler);
            timeoutHandlers[peerId] = null;
        }
    }
}

extend(ConnectionManager, EventEmitter);<commit_msg>fix some code typos<commit_after>function ConnectionManager(server, resourceName, peerId, maxPeers, options) {

    options = options || {};

	var self = this;
	this.peers = {}; //connected peers
    var connectedPeerCount = 0;
    var timeoutHandlers = {};

    var logger = debug('connection-manager');

    this.connectNew = function connectNew(otherPeerId, connectOptions) {

        connectOptions = connectOptions || {};

        logger('start connecting with peer: ' + otherPeerId);

        var connection = new PeerSocket(resourceName, otherPeerId, 'offered');
        connection.on('disconnected', onDisconnected);
        connection.on('candidate', sendCandidate);
        connection.on('connected', onConnected);

        this.peers[otherPeerId] = connection;

        connection.offer(function(desc) {

            server.emit('offer', otherPeerId, desc);
        });

        if(connectOptions.timeout) {
            enableTimeout(otherPeerId, connectOptions.timeout);
        }
    };

    this.getConnectedPeerNames = function getConnectedPeers() {

        var rtn = [];
        for(var peerName in this.peers) {
            if(this.peers[peerName].connected) {
                rtn.push(peerName);
            }
        }

        return peerName;
    };

    this.getConnectedPeerCount = function getConnectedPeerCount() {

        return connectedPeerCount;
    };

    this.canHaveMorePeers = function canHaveMorePeers(count) {

        var cntMoreNeeded = maxPeers - connectedPeerCount;
        if(cntMoreNeeded > 0) {
            return (cntMoreNeeded > count)? count: cntMoreNeeded;
        } else {
            return 0;
        }
    };

    this.close = function close() {

        //server based listeners
        server.removeListener('answer', onAnswer);
        server.removeListener('offer', onOffer);
        server.removeListener('ice-candidate', onIceCandidate);
        server.removeListener('error', onServerError);

        //close connections
        for(var peerId in this.peers) {
            this.peers[peerId].close();
        }
    };

    server.on('answer', onAnswer);
    server.on('offer', onOffer);
    server.on('ice-candidate', onIceCandidate);
    server.on('error', onServerError);

    function onAnswer(from, status, answerDesc) {

        logger('answer from: ' + from  + ' with status: ' + status);
        var connection = self.peers[from];
        if(connection) {
            if(status == 'ACCEPTED') {
                connection.setRemote(answerDesc);
            } else {
                connection.close();
            }
        } else {
            logger('no connection to answer: ' + from);
        }
    }

    function onOffer(from, desc) {

        logger('offer from: ' + from);
        if(self.peers[from]) {
            logger('offer rejected because of exisitng from: ' + from);
            server.emit('answer', from, 'REJECTED');
        } else {
            var connection = new PeerSocket(resourceName, from, 'answered');
            if(connection) {
                connection.on('disconnected', onDisconnected);
                connection.on('candidate', sendCandidate);
                connection.on('connected', onConnected);
                connection.answer(desc, function(answerDesc) {

                    server.emit('answer', from, 'ACCEPTED', answerDesc);
                });

                self.peers[from] = connection;

                if(options.answerTimeout) {
                    enableTimeout(from, options.answerTimeout);
                }
            } else {
                logger('no connection to offer: ' + from);
            }
        }

    }

    function onIceCandidate(from, candidate) {

        var connection = self.peers[from];
        if(connection) {
            connection.addCandidate(candidate);
        } else {
            logger('no connection to offer ice-candidate: ' + from);
        }
    }

    function onServerError(event, error) {

        logger('server error on: ' + event + ' error: ' + JSON.stringify(error));
        if(error && error.code == 'NO_CLIENT') {
            var connection = self.peers[error.to];
            if(connection) {
                connection.close();
            }
        }
    }

    function sendCandidate(candidate) {

        server.emit('ice-candidate', this.peerId, candidate);
    }

    function onConnected() {

        logger('connecting: ' + this.peerId);
        connectedPeerCount++;
        self.emit('peer', this);
        this.removeListener('connected', onConnected);

        cancleTimeout(this.peerId);
    }

    function onDisconnected() {

        logger('disconnecting: ' + this.peerId);
        connectedPeerCount--;

    	delete self.peers[this.peerId];
        this.removeListener('disconnected', onDisconnected);
        this.removeListener('candidate', sendCandidate);
        this.removeListener('connected', onConnected);

        cancleTimeout(this.peerId);
    }

    function enableTimeout(peerId, timeoutMillis) {

        timeoutHandlers[peerId] = setTimeout(function() {

            var connection = self.peers[peerId];
            if(connection && !connection.connected) {
                logger('timeouting: ' + peerId + ' after: ' + timeoutMillis);
                connection.close();
                timeoutHandlers[peerId] = null;
            }
        }, timeoutMillis);
    }

    function cancleTimeout(peerId) {

        var handler = timeoutHandlers[peerId];
        if(handler) {
            logger('clearing timeout handler for: ' + peerId);
            clearTimeout(handler);
            timeoutHandlers[peerId] = null;
        }
    }
}

extend(ConnectionManager, EventEmitter);<|endoftext|>


<commit_before>var Promise = require('promise');
var Config = require('./config.json');
var ursa = require('ursa');
var os = require('os');
var crypto = require('crypto');
var request = require('request');

var db = require('./include/container-manager-db.js');

var dockerHelper = require('./include/container-manager-docker-helper.js');

var docker = dockerHelper.getDocker();

var ip = '127.0.0.1';

//ARCH to append -amd to the end of a container name if running on arm
var ARCH = '';
if(process.arch == 'arm'){
  ARCH = '-arm';
}

exports.connect  = function () {
  return new Promise( (resolve, reject) => docker.ping(function (err,data) {
    if(err) reject("Cant connect to docker!");
    resolve();
  }));
}

exports.getDockerEmitter = function () {
  return dockerHelper.getDockerEmitter();
}

var listContainers = function(){
  return new Promise( (resolve, reject) =>  {
    docker.listContainers({all: true, filters: { "label": [ "databox.type" ] }},
        (err, containers) => {
          if(err) {
            reject(err);
            return;
          }
          resolve(containers);
        }
      );

  });
}
exports.listContainers = listContainers;

exports.killAll = function () {
  return new Promise( (resolve, reject) =>  {
    listContainers()
      .then(containers => {
        ids = []
        for(var i in containers) {
          var e = containers[i];
          console.log("killing " + e.Image + " id=" + e.Id + " ...");
          ids.push(dockerHelper.kill(e.Id));
          console.log("removing " + e.Image + " id=" + e.Id + " ...");
          ids.push(dockerHelper.remove(e.Id));
        };
        return Promise.all(ids)
      })
      .then((data) => {resolve()})
      .catch(err => {consol.log("[killAll-2]" + err); reject(err)})
  });
}

var getContainer = function(id) {
  return new Promise( (resolve, reject) =>  {
    resolve(docker.getContainer(id));
  });
}
exports.getContainer = getContainer;

exports.initNetworks = function () {
  return new Promise( (resolve, reject) =>  {
      console.log('initNetworks');
      dockerHelper.listNetworks()
        .then(networks => {
          var requiredNets =  [
                      dockerHelper.getNetwork(networks,'databox-driver-net'),
                      dockerHelper.getNetwork(networks,'databox-app-net')
                    ]

          return Promise.all(requiredNets)
              .then((networks) => {
                console.log("Networks already exist");
                //console.log(networks);
                resolve(networks);
              })
              .catch(err => {
                console.log("initNetworks::"+err);
                reject(err);
              })

        })
        .then( (networks) => {
          resolve(networks)
        });
    })
    .catch(err => reject(err))
  };

var pullImage = function (imageName) {
	return new Promise((resolve, reject) => {
		//Pull latest Arbiter image
		console.log('Pulling ' + imageName);
		docker.pull(Config.registryUrl + "/" + imageName, (err, stream) => {
			if (err) {
				reject(err);
				return;
			}

			stream.pipe(process.stdout);
			docker.modem.followProgress(stream, (err, output) => {
				if (err) {
					reject(err);
					return;
				}
        resolve(";->");
			});
		})
	});
};
exports.pullImage = pullImage;

var keyPair = null;
var generatingCMkeyPair = function () {
return new Promise( (resolve, reject) =>  {
      //Generating CM Key Pair
      console.log('Generating CM key pair');
      keyPair = ursa.generatePrivateKey();
      var publicKey = keyPair.toPublicPem('base64');
      resolve({'keyPair':keyPair,'publicKey':publicKey});
  });
}

var startContainer = function(cont) {
  return new Promise( (resolve, reject) =>  {
    //TODO: check cont
    cont.start((err ,data) => {
      if(err) {
        reject('startContainer:: '+err);
        return;
      }
       dockerHelper.inspectContainer(cont)
      .then( (info) => {
        var name = repoTagToName(info.Name);
        console.log("updateSLAContainerRunningState:: to true" + name);
        db.updateSLAContainerRunningState(name,true)
        .then(resolve(cont))
        .catch((err) => reject(err));
      })
    })
  });
}
exports.startContainer = startContainer;

exports.stopContainer = function(cont) {
  return new Promise( (resolve, reject) =>  {
    //TODO: check cont
    cont.stop((err ,data) => {
      if(err && err['statusCode'] != 304) { //don't error if container is already stopped!
        reject(err);
        return;
      }
      dockerHelper.inspectContainer(cont)
      .then( (info) => {
        var name = repoTagToName(info.Name);
        console.log("updateSLAContainerRunningState to false::" + name);
        db.updateSLAContainerRunningState(name,false)
        .then(resolve(cont))
        .catch((err) => reject(err));
      })

    })
  });
}

exports.removeContainer = function (cont) {

  return new Promise( (resolve, reject) =>  {

    dockerHelper.inspectContainer(cont)
    .then( (info) => {
      cont.remove({force: true},(err,data) => {
        if(err) {
          console.log("[remove]" + err);
          reject(err);
          return;
        }
        var name = repoTagToName(info.Name);
        console.log("removed " + name + "!");
        console.log("deleteSLA::" + name);
        db.deleteSLA(name,false)
        .then(resolve(cont))
        .catch((err) => reject(err));
      })
    });
  });
}

var arbiterName = '';
var DATABOX_ARBITER_ENDPOINT = null;
exports.launchArbiter = function () {
  return new Promise( (resolve, reject) =>  {
    var name = "databox-arbiter"+ARCH;
    arbiterName = name;
    pullImage(name+":latest")
    .then(() => {return generatingCMkeyPair()})
    .then(keys => {

        return dockerHelper.createContainer(
              {'name': name,
               'Image': Config.registryUrl + "/"+name+":latest",
               'PublishAllPorts': true,
               'Env': [ "CM_PUB_KEY=" + keys['publicKey'] ]
            }
          );
      })
    .then((Arbiter) => { return startContainer(Arbiter) })
    .then((Arbiter) => {
      console.log("connecting to driver network");
      return dockerHelper.connectToNetwork(Arbiter,'databox-driver-net');
    })
    .then((Arbiter) => {
      console.log("connecting to app network");
      return dockerHelper.connectToNetwork(Arbiter,'databox-app-net');
    })
    .then((Arbiter) => {return dockerHelper.inspectContainer(Arbiter)} )
    .then((data) => {
      DATABOX_ARBITER_ENDPOINT = data.NetworkSettings.IPAddress + ':' + parseInt(data.NetworkSettings.Ports['8080/tcp'][0].HostPort)
      resolve({'name': name, port: parseInt(data.NetworkSettings.Ports['8080/tcp'][0].HostPort) })
    })
    .catch((err) => {
      console.log("Error creating Arbiter");
      reject(err)
    });

  });
}

var directoryName = null;
var DATABOX_DIRECTORY_ENDPOINT = null;
exports.launchDirectory = function () {
  return new Promise( (resolve, reject) =>  {
    var name = "databox-directory"+ARCH;
    directoryName = name;
    pullImage(name+":latest")
    .then(() => {
        return dockerHelper.createContainer(
              {'name': name,
               'Image': Config.registryUrl + "/"+name+":latest",
               'PublishAllPorts': true
            }
          );
      })
    .then((Directory) => { return startContainer(Directory) })
    .then((Directory) => {
      console.log("connecting to driver network");
      return dockerHelper.connectToNetwork(Directory,'databox-driver-net');
    })
    .then((Directory) => {
      console.log("connecting to app network");
      return dockerHelper.connectToNetwork(Directory,'databox-app-net');
    })
    .then((Directory) => {return dockerHelper.inspectContainer(Directory)} )
    .then((data) => {
      DATABOX_DIRECTORY_ENDPOINT = data.NetworkSettings.IPAddress + ':' + parseInt(data.NetworkSettings.Ports['3000/tcp'][0].HostPort) + '/api'
      resolve({'name': name, port: parseInt(data.NetworkSettings.Ports['3000/tcp'][0].HostPort) })
    })
    .catch((err) => {
      console.log("Error creating Directory");
      reject(err)
    });

  });
}

var repoTagToName = function (repoTag) {
  return repoTag.match(/(?:.*\/)?([^/:\s]+)(?::.*|$)/)[1];
}

var generateArbiterToken = function () {
  return new Promise( (resolve, reject) =>  {
    crypto.randomBytes(32, function (err, buffer) {
      if(err) reject(err);
      var token = buffer.toString('base64');
      resolve(token)
    });
  });
}

var configureDriver = function (cont) {
  return new Promise( (resolve, reject) =>  {
      dockerHelper.connectToNetwork(cont,'databox-driver-net')
      .then(resolve())
      .catch((err) => reject(err))
  });
}

var configureApp = function (cont) {
  return new Promise( (resolve, reject) =>  {
      dockerHelper.connectToNetwork(cont,'databox-app-net')
      .then(resolve())
      .catch((err) => reject(err))
  });
}

var configureStore = function (cont) {
  return new Promise( (resolve, reject) =>  {
      dockerHelper.connectToNetwork(cont,'databox-driver-net')
      .then(()=>{ return dockerHelper.connectToNetwork(cont,'databox-app-net')} )
      .then(resolve())
      .catch((err) => reject(err))
  });
}

var updateArbiter = function(data) {
  return new Promise( (resolve, reject) =>  {
    getContainer(arbiterName)
    .then((Arbiter) => {return dockerHelper.inspectContainer(Arbiter)})
    .then((arbiterInfo) => {
      var port = parseInt(arbiterInfo.NetworkSettings.Ports['8080/tcp'][0].HostPort);
      request.post(
                    { url: "http://localhost:"+port+"/update",
                      form: data
                    }
                    ,
                    function(err, response, body) {
                      if(err) {
                        reject(err);
                        return;
                      }
                      resolve(JSON.parse(body));
                    }
                  )
    })
    .catch((err) => reject(err))
  });
}

var launchContainer = function (repoTag, sla, saveSla) {
  console.log("launchContainer::",repoTag, sla);
  var env = [];
  var name = repoTagToName(repoTag);
  name = name + ARCH;

  var arbiterToken = null;
  var type = null;
  var containerInfo = null;
  var container = null;
  var containerPort = null;
  var containerSLA = sla ? sla : false;
  var SLA_RetrievedFromDB = false;
  saveSla = typeof saveSla != 'undifined' ? saveSla : true;

  return new Promise( (resolve, reject) =>  {

    pullImage(name + ":latest")
    .then( () => {
      //Look for an SLA to use. If one is not provided then, look for one stored in the DB.
      //If no SLA can be found db.getSLA() will reject its promise and stop the container
      //installing.
      if(containerSLA !== false) {
        return new Promise.resolve(containerSLA);
      }
      //sla not provided look to see if we have one for this container
      SLA_RetrievedFromDB = true;
      return db.getSLA();
    } )
    .then((sla) => {
      containerSLA = sla;
    })
    .then(() => {
      console.log("Generating Arbiter token for "+name+" container");
      return generateArbiterToken();
    })
    .then((token) => {
      arbiterToken = token;
      var env = [ "DATABOX_IP="+ip,
                  "ARBITER_TOKEN="+token,
                  "DATABOX_DIRECTORY_ENDPOINT="+DATABOX_DIRECTORY_ENDPOINT,
                  "DATABOX_ARBITER_ENDPOINT="+DATABOX_ARBITER_ENDPOINT
                ]

      //TODO: Parse containerSLA and set ENV and start dependencies.

      return dockerHelper.createContainer(
                              {
                                'name': name,
                                'Image': Config.registryUrl + '/' + name + ARCH +":latest",
                                'Env': env,
                                'PublishAllPorts': true
                              }
                            );
    })
    .then((cont) => {
      container = cont
      return dockerHelper.inspectContainer(container)
    })
    //.then((info) => {
    //
    //  console.log("Checking ports exposed by #name container");
    //  TODO: this might be needed here!!
    //})
    .then( (info) => {
      type = info.Config.Labels['databox.type'];

      console.log("Passing "+name+" token to Arbiter");

      var update = JSON.stringify({ name:name, token:arbiterToken, type:type });

      var sig = keyPair.hashAndSign('md5', new Buffer(update)).toString('base64');

      return updateArbiter({data:update, sig });

    })
    .then(() => {
      return startContainer(container);
    })
    .then(() => {
      if(type == 'driver') {
        return configureDriver(container);
      } else if(type == 'store') {
        return configureStore(container);
      } else {
        return configureApp(container);
      }
    })
    .then( () => {
      if(SLA_RetrievedFromDB) {
        return new Promise.resolve();
      } else if (!saveSla) {
        return new Promise.resolve();
      } else {
        return db.putSLA(name,containerSLA);}
      }
    )
    .then( () => {
      if (!saveSla) {
        return new Promise.resolve();
      } else {
        return db.updateSLAContainerRunningState(name,true);
      }
     })
    .then( () => { return getContainer(name)})
    .then((cont) => { return dockerHelper.inspectContainer(cont) })
    .then( (info) => {
      containerInfo = info;
      containerPort = parseInt(info.NetworkSettings.Ports['8080/tcp'][0].HostPort);
      console.log("Container " + name + " launched");
      resolve({name:name, port:containerPort})
    })
    .catch((err) => {
      console.log("[launchContainer ERROR]" + err);
      reject(err);
    });

  });
}
exports.launchContainer = launchContainer;

exports.restoreContainers = function (slas) {

  console.log("Launching " + slas.length + " containers");
  var proms = [];
  for(sla of slas){
    //don't pass the SLA here it make the logic in launchContainer complex
    proms.push(launchContainer(sla.name));
  }
  return new Promise.all(proms);
}

exports.getActiveSLAs = function() {
  return db.getActiveSLAs();
}<commit_msg>arm naming bug fix<commit_after>var Promise = require('promise');
var Config = require('./config.json');
var ursa = require('ursa');
var os = require('os');
var crypto = require('crypto');
var request = require('request');

var db = require('./include/container-manager-db.js');

var dockerHelper = require('./include/container-manager-docker-helper.js');

var docker = dockerHelper.getDocker();

var ip = '127.0.0.1';

//ARCH to append -amd to the end of a container name if running on arm
var ARCH = '';
if(process.arch == 'arm'){
  ARCH = '-arm';
}

exports.connect  = function () {
  return new Promise( (resolve, reject) => docker.ping(function (err,data) {
    if(err) reject("Cant connect to docker!");
    resolve();
  }));
}

exports.getDockerEmitter = function () {
  return dockerHelper.getDockerEmitter();
}

var listContainers = function(){
  return new Promise( (resolve, reject) =>  {
    docker.listContainers({all: true, filters: { "label": [ "databox.type" ] }},
        (err, containers) => {
          if(err) {
            reject(err);
            return;
          }
          resolve(containers);
        }
      );

  });
}
exports.listContainers = listContainers;

exports.killAll = function () {
  return new Promise( (resolve, reject) =>  {
    listContainers()
      .then(containers => {
        ids = []
        for(var i in containers) {
          var e = containers[i];
          console.log("killing " + e.Image + " id=" + e.Id + " ...");
          ids.push(dockerHelper.kill(e.Id));
          console.log("removing " + e.Image + " id=" + e.Id + " ...");
          ids.push(dockerHelper.remove(e.Id));
        };
        return Promise.all(ids)
      })
      .then((data) => {resolve()})
      .catch(err => {consol.log("[killAll-2]" + err); reject(err)})
  });
}

var getContainer = function(id) {
  return new Promise( (resolve, reject) =>  {
    resolve(docker.getContainer(id));
  });
}
exports.getContainer = getContainer;

exports.initNetworks = function () {
  return new Promise( (resolve, reject) =>  {
      console.log('initNetworks');
      dockerHelper.listNetworks()
        .then(networks => {
          var requiredNets =  [
                      dockerHelper.getNetwork(networks,'databox-driver-net'),
                      dockerHelper.getNetwork(networks,'databox-app-net')
                    ]

          return Promise.all(requiredNets)
              .then((networks) => {
                console.log("Networks already exist");
                //console.log(networks);
                resolve(networks);
              })
              .catch(err => {
                console.log("initNetworks::"+err);
                reject(err);
              })

        })
        .then( (networks) => {
          resolve(networks)
        });
    })
    .catch(err => reject(err))
  };

var pullImage = function (imageName) {
	return new Promise((resolve, reject) => {
		//Pull latest Arbiter image
		console.log('Pulling ' + imageName);
		docker.pull(Config.registryUrl + "/" + imageName, (err, stream) => {
			if (err) {
				reject(err);
				return;
			}

			stream.pipe(process.stdout);
			docker.modem.followProgress(stream, (err, output) => {
				if (err) {
					reject(err);
					return;
				}
        resolve(";->");
			});
		})
	});
};
exports.pullImage = pullImage;

var keyPair = null;
var generatingCMkeyPair = function () {
return new Promise( (resolve, reject) =>  {
      //Generating CM Key Pair
      console.log('Generating CM key pair');
      keyPair = ursa.generatePrivateKey();
      var publicKey = keyPair.toPublicPem('base64');
      resolve({'keyPair':keyPair,'publicKey':publicKey});
  });
}

var startContainer = function(cont) {
  return new Promise( (resolve, reject) =>  {
    //TODO: check cont
    cont.start((err ,data) => {
      if(err) {
        reject('startContainer:: '+err);
        return;
      }
       dockerHelper.inspectContainer(cont)
      .then( (info) => {
        var name = repoTagToName(info.Name);
        console.log("updateSLAContainerRunningState:: to true" + name);
        db.updateSLAContainerRunningState(name,true)
        .then(resolve(cont))
        .catch((err) => reject(err));
      })
    })
  });
}
exports.startContainer = startContainer;

exports.stopContainer = function(cont) {
  return new Promise( (resolve, reject) =>  {
    //TODO: check cont
    cont.stop((err ,data) => {
      if(err && err['statusCode'] != 304) { //don't error if container is already stopped!
        reject(err);
        return;
      }
      dockerHelper.inspectContainer(cont)
      .then( (info) => {
        var name = repoTagToName(info.Name);
        console.log("updateSLAContainerRunningState to false::" + name);
        db.updateSLAContainerRunningState(name,false)
        .then(resolve(cont))
        .catch((err) => reject(err));
      })

    })
  });
}

exports.removeContainer = function (cont) {

  return new Promise( (resolve, reject) =>  {

    dockerHelper.inspectContainer(cont)
    .then( (info) => {
      cont.remove({force: true},(err,data) => {
        if(err) {
          console.log("[remove]" + err);
          reject(err);
          return;
        }
        var name = repoTagToName(info.Name);
        console.log("removed " + name + "!");
        console.log("deleteSLA::" + name);
        db.deleteSLA(name,false)
        .then(resolve(cont))
        .catch((err) => reject(err));
      })
    });
  });
}

var arbiterName = '';
var DATABOX_ARBITER_ENDPOINT = null;
exports.launchArbiter = function () {
  return new Promise( (resolve, reject) =>  {
    var name = "databox-arbiter"+ARCH;
    arbiterName = name;
    pullImage(name+":latest")
    .then(() => {return generatingCMkeyPair()})
    .then(keys => {

        return dockerHelper.createContainer(
              {'name': name,
               'Image': Config.registryUrl + "/"+name+":latest",
               'PublishAllPorts': true,
               'Env': [ "CM_PUB_KEY=" + keys['publicKey'] ]
            }
          );
      })
    .then((Arbiter) => { return startContainer(Arbiter) })
    .then((Arbiter) => {
      console.log("connecting to driver network");
      return dockerHelper.connectToNetwork(Arbiter,'databox-driver-net');
    })
    .then((Arbiter) => {
      console.log("connecting to app network");
      return dockerHelper.connectToNetwork(Arbiter,'databox-app-net');
    })
    .then((Arbiter) => {return dockerHelper.inspectContainer(Arbiter)} )
    .then((data) => {
      DATABOX_ARBITER_ENDPOINT = data.NetworkSettings.IPAddress + ':' + parseInt(data.NetworkSettings.Ports['8080/tcp'][0].HostPort)
      resolve({'name': name, port: parseInt(data.NetworkSettings.Ports['8080/tcp'][0].HostPort) })
    })
    .catch((err) => {
      console.log("Error creating Arbiter");
      reject(err)
    });

  });
}

var directoryName = null;
var DATABOX_DIRECTORY_ENDPOINT = null;
exports.launchDirectory = function () {
  return new Promise( (resolve, reject) =>  {
    var name = "databox-directory"+ARCH;
    directoryName = name;
    pullImage(name+":latest")
    .then(() => {
        return dockerHelper.createContainer(
              {'name': name,
               'Image': Config.registryUrl + "/"+name+":latest",
               'PublishAllPorts': true
            }
          );
      })
    .then((Directory) => { return startContainer(Directory) })
    .then((Directory) => {
      console.log("connecting to driver network");
      return dockerHelper.connectToNetwork(Directory,'databox-driver-net');
    })
    .then((Directory) => {
      console.log("connecting to app network");
      return dockerHelper.connectToNetwork(Directory,'databox-app-net');
    })
    .then((Directory) => {return dockerHelper.inspectContainer(Directory)} )
    .then((data) => {
      DATABOX_DIRECTORY_ENDPOINT = data.NetworkSettings.IPAddress + ':' + parseInt(data.NetworkSettings.Ports['3000/tcp'][0].HostPort) + '/api'
      resolve({'name': name, port: parseInt(data.NetworkSettings.Ports['3000/tcp'][0].HostPort) })
    })
    .catch((err) => {
      console.log("Error creating Directory");
      reject(err)
    });

  });
}

var repoTagToName = function (repoTag) {
  return repoTag.match(/(?:.*\/)?([^/:\s]+)(?::.*|$)/)[1];
}

var generateArbiterToken = function () {
  return new Promise( (resolve, reject) =>  {
    crypto.randomBytes(32, function (err, buffer) {
      if(err) reject(err);
      var token = buffer.toString('base64');
      resolve(token)
    });
  });
}

var configureDriver = function (cont) {
  return new Promise( (resolve, reject) =>  {
      dockerHelper.connectToNetwork(cont,'databox-driver-net')
      .then(resolve())
      .catch((err) => reject(err))
  });
}

var configureApp = function (cont) {
  return new Promise( (resolve, reject) =>  {
      dockerHelper.connectToNetwork(cont,'databox-app-net')
      .then(resolve())
      .catch((err) => reject(err))
  });
}

var configureStore = function (cont) {
  return new Promise( (resolve, reject) =>  {
      dockerHelper.connectToNetwork(cont,'databox-driver-net')
      .then(()=>{ return dockerHelper.connectToNetwork(cont,'databox-app-net')} )
      .then(resolve())
      .catch((err) => reject(err))
  });
}

var updateArbiter = function(data) {
  return new Promise( (resolve, reject) =>  {
    getContainer(arbiterName)
    .then((Arbiter) => {return dockerHelper.inspectContainer(Arbiter)})
    .then((arbiterInfo) => {
      var port = parseInt(arbiterInfo.NetworkSettings.Ports['8080/tcp'][0].HostPort);
      request.post(
                    { url: "http://localhost:"+port+"/update",
                      form: data
                    }
                    ,
                    function(err, response, body) {
                      if(err) {
                        reject(err);
                        return;
                      }
                      resolve(JSON.parse(body));
                    }
                  )
    })
    .catch((err) => reject(err))
  });
}

var launchContainer = function (repoTag, sla, saveSla) {
  console.log("launchContainer::",repoTag, sla);
  var env = [];
  var name = repoTagToName(repoTag);
  name = name + ARCH;

  var arbiterToken = null;
  var type = null;
  var containerInfo = null;
  var container = null;
  var containerPort = null;
  var containerSLA = sla ? sla : false;
  var SLA_RetrievedFromDB = false;
  saveSla = typeof saveSla != 'undifined' ? saveSla : true;

  return new Promise( (resolve, reject) =>  {

    pullImage(name + ":latest")
    .then( () => {
      //Look for an SLA to use. If one is not provided then, look for one stored in the DB.
      //If no SLA can be found db.getSLA() will reject its promise and stop the container
      //installing.
      if(containerSLA !== false) {
        return new Promise.resolve(containerSLA);
      }
      //sla not provided look to see if we have one for this container
      SLA_RetrievedFromDB = true;
      return db.getSLA();
    } )
    .then((sla) => {
      containerSLA = sla;
    })
    .then(() => {
      console.log("Generating Arbiter token for "+name+" container");
      return generateArbiterToken();
    })
    .then((token) => {
      arbiterToken = token;
      var env = [ "DATABOX_IP="+ip,
                  "ARBITER_TOKEN="+token,
                  "DATABOX_DIRECTORY_ENDPOINT="+DATABOX_DIRECTORY_ENDPOINT,
                  "DATABOX_ARBITER_ENDPOINT="+DATABOX_ARBITER_ENDPOINT
                ]

      //TODO: Parse containerSLA and set ENV and start dependencies.

      return dockerHelper.createContainer(
                              {
                                'name': name,
                                'Image': Config.registryUrl + '/' + name +":latest",
                                'Env': env,
                                'PublishAllPorts': true
                              }
                            );
    })
    .then((cont) => {
      container = cont
      return dockerHelper.inspectContainer(container)
    })
    //.then((info) => {
    //
    //  console.log("Checking ports exposed by #name container");
    //  TODO: this might be needed here!!
    //})
    .then( (info) => {
      type = info.Config.Labels['databox.type'];

      console.log("Passing "+name+" token to Arbiter");

      var update = JSON.stringify({ name:name, token:arbiterToken, type:type });

      var sig = keyPair.hashAndSign('md5', new Buffer(update)).toString('base64');

      return updateArbiter({data:update, sig });

    })
    .then(() => {
      return startContainer(container);
    })
    .then(() => {
      if(type == 'driver') {
        return configureDriver(container);
      } else if(type == 'store') {
        return configureStore(container);
      } else {
        return configureApp(container);
      }
    })
    .then( () => {
      if(SLA_RetrievedFromDB) {
        return new Promise.resolve();
      } else if (!saveSla) {
        return new Promise.resolve();
      } else {
        return db.putSLA(name,containerSLA);}
      }
    )
    .then( () => {
      if (!saveSla) {
        return new Promise.resolve();
      } else {
        return db.updateSLAContainerRunningState(name,true);
      }
     })
    .then( () => { return getContainer(name)})
    .then((cont) => { return dockerHelper.inspectContainer(cont) })
    .then( (info) => {
      containerInfo = info;
      containerPort = parseInt(info.NetworkSettings.Ports['8080/tcp'][0].HostPort);
      console.log("Container " + name + " launched");
      resolve({name:name, port:containerPort})
    })
    .catch((err) => {
      console.log("[launchContainer ERROR]" + err);
      reject(err);
    });

  });
}
exports.launchContainer = launchContainer;

exports.restoreContainers = function (slas) {

  console.log("Launching " + slas.length + " containers");
  var proms = [];
  for(sla of slas){
    //don't pass the SLA here it make the logic in launchContainer complex
    proms.push(launchContainer(sla.name));
  }
  return new Promise.all(proms);
}

exports.getActiveSLAs = function() {
  return db.getActiveSLAs();
}<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
// react-md
import FileInput from 'react-md/lib/FileInputs';
import TextField from 'react-md/lib/TextFields';
import Button from 'react-md/lib/Buttons';
import Subheader from 'react-md/lib/Subheaders';
import CircularProgress from 'react-md/lib/Progress/CircularProgress';
// redux
import { connect } from 'react-redux'
import { addJob } from '../actions'
import { subtypingDescription } from '../middleware/subtyping'
import { panseqDescription } from '../middleware/panseq'

// axios
import axios from 'axios'
import { API_ROOT } from '../middleware/api'
// router
import { Redirect } from 'react-router'
import Loading from '../components/Loading'

class Panseq extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      file: null,
      pi: 90,
      submitted: false,
      open: false,
      pan: true,
      msg: '',
      jobId: "",
      hasResult: false,
      progress: 0
    }
  }
  _selectFile = (file) => {
    console.log(file)
    if (!file) { return; }
    this.setState({ file });
  }

  _updateUploadProgress = ( progress ) => {
    this.setState({progress})
  }
  _handleSubmit = (e) => {
    e.preventDefault() // disable default HTML form behavior
    // open and msg are for Snackbar
    // uploading is to notify users
    this.setState({
      uploading: true
    });
    // configure a progress for axios
    const createConfig = (_updateUploadProgress) => {
      var config = {
        onUploadProgress: function(progressEvent) {
          var percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
          _updateUploadProgress(percentCompleted)
        }
      }
      return config
    }
    // create form data with files```
    var data = new FormData()
    // eslint-disable-next-line
    this.state.file.map((f) => {
      data.append('file', f)
    })
    // append options
    // to match spfy(angular)'s format, we dont use a dict
    data.append('options.pi', this.state.pi)

    // POST
    axios.post(API_ROOT + 'panseq', data, createConfig(this._updateUploadProgress))
      .then(response => {
        console.log(response)
        // no longer uploading
        this.setState({
          uploading: false
        })
        let jobs = response.data
        // handle the return
        for(let job in jobs){
          // console.log(jobs[job].analysis)
          // check filename
          let f = (this.state.file.length > 1 ?
          String(this.state.file.length + ' Files')
          :this.state.file[0].name)

            // regular subtyping uplods
            if((jobs[job].analysis === "Panseq") && (jobs[job].file.includes('Results'))){
              this.props.dispatch(addJob(job,
              'Panseq',
              new Date().toLocaleTimeString(),
              panseqDescription(f, this.state.pi, this.state.pan)
              ))
              }

        }
        const hasResult = true
        this.setState({hasResult})
      })
  };
  render(){
    const { file, pi, amr, serotype, vf, groupresults, bulk, uploading, hasResult, progress } = this.state
    return (
      <div>
        {/* uploading bar */}
        {(uploading && !hasResult) ?
          <div>
            <CircularProgress key="progress" id="loading" value={progress} centered={false} />
            Uploading... {progress} %
          </div>
          : ""
        }
        {/* actual form */}
        {(!hasResult && !uploading)?
          <form className="md-text-container md-grid">
            <div className="md-cell md-cell--12">
              <FileInput
                id="inputFile"
                secondary
                label="Select File(s)"
                onChange={this._selectFile}
                multiple
              />

              <Button
                raised
                secondary
                type="submit"
                label="Submit"
                disabled={!file}
                onClick={this._handleSubmit}
              />
            </div>
            <div className="md-cell md-cell--12">
              {this.state.file ? this.state.file.map(f => (
                <TextField
                  key={f.name}
                  defaultValue={f.name}
                />
              )) : ''}
            </div>
          </form> :
          // if results are grouped, display the Loading page
          // else, results are separate and display the JobsList cards page
          (!uploading?(!groupresults?
            <Redirect to='/results' />:
            <Loading jobId={this.state.jobId} />
          ):"")

        }
      </div>
    )
  }
}

Panseq = connect()(Panseq)

export default Panseq
<commit_msg>FIX: del stuff for linter<commit_after>import React, { PureComponent } from 'react';
// react-md
import FileInput from 'react-md/lib/FileInputs';
import TextField from 'react-md/lib/TextFields';
import Button from 'react-md/lib/Buttons';
import CircularProgress from 'react-md/lib/Progress/CircularProgress';
// redux
import { connect } from 'react-redux'
import { addJob } from '../actions'
import { panseqDescription } from '../middleware/panseq'

// axios
import axios from 'axios'
import { API_ROOT } from '../middleware/api'
// router
import { Redirect } from 'react-router'
import Loading from '../components/Loading'

class Panseq extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      file: null,
      submitted: false,
      open: false,
      pan: true,
      msg: '',
      jobId: "",
      hasResult: false,
      progress: 0
    }
  }
  _selectFile = (file) => {
    console.log(file)
    if (!file) { return; }
    this.setState({ file });
  }

  _updateUploadProgress = ( progress ) => {
    this.setState({progress})
  }
  _handleSubmit = (e) => {
    e.preventDefault() // disable default HTML form behavior
    // open and msg are for Snackbar
    // uploading is to notify users
    this.setState({
      uploading: true
    });
    // configure a progress for axios
    const createConfig = (_updateUploadProgress) => {
      var config = {
        onUploadProgress: function(progressEvent) {
          var percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
          _updateUploadProgress(percentCompleted)
        }
      }
      return config
    }
    // create form data with files```
    var data = new FormData()
    // eslint-disable-next-line
    this.state.file.map((f) => {
      data.append('file', f)
    })
    // append options
    // to match spfy(angular)'s format, we dont use a dict
    data.append('options.pi', this.state.pi)

    // POST
    axios.post(API_ROOT + 'panseq', data, createConfig(this._updateUploadProgress))
      .then(response => {
        console.log(response)
        // no longer uploading
        this.setState({
          uploading: false
        })
        let jobs = response.data
        // handle the return
        for(let job in jobs){
          // console.log(jobs[job].analysis)
          // check filename
          let f = (this.state.file.length > 1 ?
          String(this.state.file.length + ' Files')
          :this.state.file[0].name)

            // regular subtyping uplods
            if((jobs[job].analysis === "Panseq") && (jobs[job].file.includes('Results'))){
              this.props.dispatch(addJob(job,
              'Panseq',
              new Date().toLocaleTimeString(),
              panseqDescription(f, this.state.pi, this.state.pan)
              ))
              }

        }
        const hasResult = true
        this.setState({hasResult})
      })
  };
  render(){
    const { file, groupresults, uploading, hasResult, progress } = this.state
    return (

        {/* uploading bar */}
        {(uploading && !hasResult) ?

            <CircularProgress key="progress" id="loading" value={progress} centered={false} />
            Uploading... {progress} %

          : ""
        }
        {/* actual form */}
        {(!hasResult && !uploading)?
          <form className="md-text-container md-grid">

              <FileInput
                id="inputFile"
                secondary
                label="Select File(s)"
                onChange={this._selectFile}
                multiple
              />

              <Button
                raised
                secondary
                type="submit"
                label="Submit"
                disabled={!file}
                onClick={this._handleSubmit}
              />

              {this.state.file ? this.state.file.map(f => (
                <TextField
                  key={f.name}
                  defaultValue={f.name}
                />
              )) : ''}

          </form> :
          // if results are grouped, display the Loading page
          // else, results are separate and display the JobsList cards page
          (!uploading?(!groupresults?
            <Redirect to='/results' />:
            <Loading jobId={this.state.jobId} />
          ):"")

        }

    )
  }
}

Panseq = connect()(Panseq)

export default Panseq
<|endoftext|>