| orion.Bundle = function(framework, bundleData) { |
| this._framework = framework; |
| this._bundleData = bundleData; |
| this._name = null; |
| this._version = null; |
| this._imports = []; |
| this._requires = []; |
| this._exports = []; |
| this._resources = {}; |
| this._singleton = false; |
| this._markedStarted = false; |
| this._state = orion.Bundle.INSTALLED; |
| this._scope = {}; |
| this._bundleContext = null; |
| this._activator = null; |
| this._script = null; |
| |
| var headers = bundleData.getHeaders(); |
| this._parseName(headers[orion.Constants.BUNDLE_NAME]); |
| this._parseVersion(headers[orion.Constants.BUNDLE_VERSION]); |
| this._parseImports(headers[orion.Constants.BUNDLE_IMPORTS]); |
| this._parseExports(headers[orion.Constants.BUNDLE_EXPORTS]); |
| this._parseRequires(headers[orion.Constants.BUNDLE_REQUIRES]); |
| this._parseResources(headers[orion.Constants.BUNDLE_RESOURCES]); |
| this._parsePath(headers[orion.Constants.BUNDLE_PATH]); |
| }; |
| |
| orion.Bundle.UNINSTALLED = 1; |
| orion.Bundle.INSTALLED = 2; |
| orion.Bundle.RESOLVED = 4; |
| orion.Bundle.STARTING = 8; |
| orion.Bundle.STOPPING = 16; |
| orion.Bundle.ACTIVE = 32; |
| |
| orion.Bundle.prototype = { |
| getName : function() { |
| return this._name; |
| }, |
| getVersion : function() { |
| return this._version; |
| }, |
| getBundleId : function() { |
| return this._bundleData.getBundleId(); |
| }, |
| getLocation : function() { |
| return this._bundleData.getLocation(); |
| }, |
| getHeaders : function() { |
| return this._bundleData.getHeaders(); |
| }, |
| getState : function() { |
| return this._state; |
| }, |
| getEntry : function(path) { |
| if (!path || !path instanceof String || !this._resources[path]) |
| return null; |
| |
| return this.getLocation() + path; |
| }, |
| getResource : function(path) { |
| if (!path || !path instanceof String) |
| return null; |
| |
| var i = 0; |
| var resource; |
| for (i = 0; i < this._imports.length; i++) { |
| var jsImport = this._imports[i]; |
| var jsExport = jsImport.getWiredExport(); |
| if (!jsExport) |
| continue; // optional |
| var name = jsExport.getName(); |
| if (name.charAt(0) != "/") |
| continue; // not a resource |
| if (path.indexOf(name)==0) { |
| resource = jsExport.getExportingBundle().getEntry(path); |
| if (resource) |
| return resource; |
| } |
| } |
| |
| // process requires |
| for (i = 0; i < this._requires.length; i++) { |
| var jsRequire = this._requires[i]; |
| var wiredBundle = jsRequire.getWiredBundle(); |
| if (!wiredBundle) { |
| continue; //optional |
| } |
| var wiredBundleExports = wiredBundle._getExports(); |
| for (var j=0; j < wiredBundleExports.length; j++) { |
| jsExport = wiredBundleExports[j]; |
| var name = jsExport.getName(); |
| if (name.charAt(0) != "/") |
| continue; // not a resource |
| if (path.indexOf(name)==0) { |
| resource = jsExport.getExportingBundle().getEntry(path); |
| if (resource) |
| return resource; |
| } |
| } |
| } |
| return this.getEntry(path); |
| }, |
| equals : function(other) { |
| if (this === other) |
| return true; |
| |
| if (!other instanceof orion.Bundle) |
| return false; |
| |
| if (this._name !== other._name) |
| return false; |
| if (this._version === null) { |
| if (other._version !== null) |
| return false; |
| } else if (!this._version.equals(other._version)) |
| return false; |
| return true; |
| }, |
| uninstall : function() { |
| this._state = orion.Bundle.UNINSTALLED; |
| }, |
| start : function() { |
| this._markedStarted = true; |
| if (this._state !== orion.Bundle.RESOLVED) |
| return; |
| |
| this._state = orion.Bundle.STARTING; |
| this._bundleContext = this._framework._getBundleContext(this); |
| this._activator = this._createActivatorInstance(); |
| if (this._activator) { |
| this._activator.start(this._bundleContext); |
| } |
| this._state = orion.Bundle.ACTIVE; |
| }, |
| stop : function() { |
| markedStarted = false; |
| if (this._state !== orion.Bundle.ACTIVE) |
| return; |
| |
| this._state = orion.Bundle.STOPPING; |
| if (this._activator) { |
| this._activator.stop(this._bundleContext); |
| } |
| this._state = orion.Bundle.RESOLVED; |
| }, |
| load : function(name) { |
| var value = this._scope; |
| if (value === null || value === undefined) { |
| return undefined; |
| } |
| var names = name.split("."); |
| for ( var i = 0; i < names.length; i++) { |
| if (value === null || value === undefined) { |
| return undefined; |
| } |
| value = value[names[i]]; |
| } |
| return value; |
| }, |
| _isSingleton : function() { |
| return this._singleton; |
| }, |
| _isMarkedStarted : function() { |
| return this._markedStarted; |
| }, |
| _getImports : function() { |
| return this._imports; |
| }, |
| _getExports : function() { |
| return this._exports; |
| }, |
| _getRequires : function() { |
| return this._requires; |
| }, |
| _createActivatorInstance : function() { |
| var activatorName = this.getHeaders()[orion.Constants.BUNDLE_ACTIVATOR]; |
| if (activatorName === null || activatorName === undefined) |
| return null; |
| |
| var activatorFunction = this.load(activatorName); |
| if (typeof activatorFunction !== "function") |
| throw "" + activatorName + " is not a function."; |
| return new activatorFunction(); |
| }, |
| _resolve : function() { |
| if (this._state != orion.Bundle.INSTALLED) |
| return; |
| |
| var namedExports = {}; |
| var jsExport = null; |
| var i = 0; |
| // process imports (first) |
| for (i = 0; i < this._imports.length; i++) { |
| var jsImport = this._imports[i]; |
| var jsExport = jsImport.getWiredExport(); |
| if (!jsExport) |
| continue; // optional |
| var name = jsExport.getName(); |
| if (name.charAt(0) == "/") |
| continue; // resource |
| if (!namedExports.hasOwnProperty(name)) |
| namedExports[name] = jsImport.getWiredExport(); |
| } |
| |
| // process requires |
| for (i = 0; i < this._requires.length; i++) { |
| var jsRequire = this._requires[i]; |
| var wiredBundle = jsRequire.getWiredBundle(); |
| if (!wiredBundle) { |
| continue; //optional |
| } |
| var wiredBundleExports = wiredBundle._getExports(); |
| for (var j=0; j < wiredBundleExports.length; j++) { |
| jsExport = wiredBundleExports[j]; |
| var name = jsExport.getName(); |
| if (name.charAt(0) == "/") |
| continue; // resource |
| if (!namedExports.hasOwnProperty(name)) |
| namedExports[name] = jsImport.getWiredExport(); |
| } |
| } |
| |
| var names = []; |
| var exportName = null; |
| for (exportName in namedExports) { |
| if (namedExports.hasOwnProperty(exportName)) |
| names.push(exportName); |
| } |
| |
| // this sorts the set of names we'll be importing alphabetically and |
| // perhaps more importantly will allow us to create the shorter/parent dotted entries first |
| names.sort(); |
| |
| var importScope = {}; |
| for (i = 0; i < names.length; i++) { |
| exportName = names[i]; |
| jsExport = namedExports[exportName]; |
| jsExport.addToScope(importScope); |
| } |
| |
| this._evalScript(importScope); |
| this._state = orion.Bundle.RESOLVED; |
| }, |
| _evalScript : function(importScope) { |
| var parameterNames = []; |
| var parameterValues = []; |
| var parameterName = null; |
| for (parameterName in importScope) { |
| if (importScope.hasOwnProperty(parameterName)) { |
| parameterNames.push(parameterName); |
| parameterValues.push(importScope[parameterName]); |
| } |
| |
| } |
| |
| var exportNames = []; |
| for (i = 0; i < this._exports.length; i++) { |
| var exportName = this._exports[i].getName(); |
| if (exportName.charAt(0) == "/") |
| continue; // resource |
| var dotIndex = exportName.indexOf("."); |
| if (dotIndex !== -1) |
| exportName = exportName.substring(0,dotIndex); |
| |
| if (! exportNames.hasOwnProperty(exportName)) { |
| exportNames[exportName] = true; |
| exportNames.push(exportName + ":" + exportName); |
| } |
| } |
| |
| var parameterStatement = parameterNames.join(","); |
| var returnStatement = "\n\nreturn {" + exportNames.join(",") + "};"; |
| |
| var that = this; |
| var loader = { |
| getResources: function(path) { |
| return that.getResources(path); |
| } |
| }; |
| |
| var finalScript = this._script + returnStatement; |
| var load = new Function(parameterStatement, finalScript); |
| this._scope = load.apply(loader, parameterValues); |
| }, |
| _unresolve : function() { |
| if (this._state == orion.Bundle.ACTIVE) { |
| this.stop(); |
| markedStarted = true; |
| } |
| this._scope = null; |
| |
| if (this._state == orion.Bundle.RESOLVED) |
| this._state = orion.Bundle.INSTALLED; |
| }, |
| _parseName : function(header) { |
| var tokens = header.split(orion.Constants.PARAMETER_DELIMITER); |
| this._name = tokens[0].replace(/^\s+|\s+$/g, ''); |
| for ( var i = 1; i < tokens.length; i++) { |
| var token = tokens[i]; |
| if (token.indexOf(orion.Constants.DIRECTIVE_EQUALS) != -1) { |
| var index = token.indexOf(orion.Constants.DIRECTIVE_EQUALS); |
| var directiveName = token.substring(0, index).replace(/^\s+|\s+$/g, ''); |
| if (directiveName.length === 0) |
| throw "bad syntax: " + token + " in " + header; |
| |
| if (directiveName !== orion.Constants.SINGLETON_DIRECTIVE) |
| continue; |
| var value = token.substring(index + orion.Constants.DIRECTIVE_EQUALS.length).replace(/^\s+|\s+$/g, ''); |
| if (value.toLowerCase() === "true") |
| this._singleton = true; |
| } else |
| throw "bad syntax: " + token + " in " + header; |
| } |
| }, |
| _parseVersion : function(header) { |
| this._version = orion.Version.parseVersion(header); |
| }, |
| _parseResources : function(header) { |
| if (!header) |
| return; |
| |
| var tokens = header.split(orion.Constants.CLAUSE_DELIMITER); |
| for ( var i = 0; i < tokens.length; i++) { |
| if (tokens[i]) { |
| var path = tokens[i].replace(/^\s+|\s+$/g, ''); |
| this._resources[path] = true; |
| } |
| } |
| }, |
| _parseRequires : function(header) { |
| if (!header) |
| return; |
| |
| var tokens = header.split(orion.Constants.CLAUSE_DELIMITER); |
| for ( var i = 0; i < tokens.length; i++) { |
| var token = tokens[i]; |
| var jsRequire = new orion.Require(token); |
| if (jsRequire !== null) |
| this._requires.push(jsRequire); |
| } |
| }, |
| _parseExports : function(header) { |
| if (!header) |
| return; |
| var tokens = header.split(orion.Constants.CLAUSE_DELIMITER); |
| for ( var i = 0; i < tokens.length; i++) { |
| var token = tokens[i]; |
| var jsExport = new orion.Export(token, this); |
| if (jsExport !== null) |
| this._exports.push(jsExport); |
| } |
| }, |
| _parseImports : function(header) { |
| if (!header) |
| return; |
| |
| var tokens = header.split(orion.Constants.CLAUSE_DELIMITER); |
| for ( var i = 0; i < tokens.length; i++) { |
| var token = tokens[i]; |
| var jsImport = new orion.Import(token); |
| if (jsImport !== null) |
| this._imports.push(jsImport); |
| } |
| }, |
| _parsePath : function(header) { |
| if (!header) { |
| this._script = this._bundleData.getHeaders()[orion.Constants.BUNDLE_SCRIPT] || ""; |
| return; |
| } |
| var tokens = header.split(orion.Constants.CLAUSE_DELIMITER); |
| var scripts = []; |
| for ( var i = 0; i < tokens.length; i++) { |
| var token = tokens[i]; |
| var path = token.replace(/^\s+|\s+$/g, ''); |
| if (path === ".") { |
| scripts[i] = this._bundleData.getHeaders()[orion.Constants.BUNDLE_SCRIPT]; |
| } else { |
| var scriptURL = this.getResource(path); |
| scripts[i] = orion.Framework._fetch(scriptURL); |
| } |
| } |
| this._script = scripts.join("\n\n"); |
| } |
| }; |