blob: 9d31d9da2a531a0bc1ce56ead82008686275f12a [file] [log] [blame]
orion.Bundle = function(framework, bundleData) {
this._framework = framework;
this._bundleData = bundleData;
this._name = null;
this._version = null;
this._singleton = false;
this._imports = [];
this._requires = [];
this._exports = [];
this._resources = {};
this._globals = [];
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.name);
this._parseVersion(headers.version);
this._parseSingleton(headers.singleton);
this._parseImports(headers.imports);
this._parseExports(headers.exports);
this._parseRequires(headers.requires);
this._parseResources(headers.resources);
this._parsePath(headers.path);
this._parseGlobals(headers.globals);
};
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().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 = ["getResource"];
var that = this;
var boundGetResource = function(path) {
return that.getResource(path);
};
var parameterValues = [boundGetResource];
var parameterName = null;
for (parameterName in importScope) {
if (importScope.hasOwnProperty(parameterName)) {
parameterNames.push(parameterName);
parameterValues.push(importScope[parameterName]);
}
}
var exportNames = [];
for (var 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 finalScript = this._script + returnStatement;
// var load = new Function(parameterStatement, finalScript);
var load = orion.Framework._eval("(function("+parameterStatement+") {\n" + finalScript + "\n})//@ sourceURL=" + this.getLocation());
this._scope = load.apply(null, 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) {
this._name = header;
},
_parseSingleton : function(header) {
if (typeof header == "boolean")
this._singleton = header;
},
_parseVersion : function(header) {
this._version = orion.Version.parseVersion(header);
},
_parseGlobals : function(header) {
if (!header)
return;
for ( var i = 0; i < header.length; i++) {
if (header[i]) {
this._globals.push(header[i]);
}
}
},
_parseResources : function(header) {
if (!header)
return;
for ( var i = 0; i < header.length; i++) {
if (header[i]) {
this._resources[header[i]] = true;
}
}
},
_parseRequires : function(header) {
if (!header)
return;
for ( var i = 0; i < header.length; i++) {
var jsRequire = new orion.Require(header[i]);
if (jsRequire !== null)
this._requires.push(jsRequire);
}
},
_parseExports : function(header) {
if (!header)
return;
for ( var i = 0; i < header.length; i++) {
var jsExport = new orion.Export(header[i], this);
if (jsExport !== null)
this._exports.push(jsExport);
}
},
_parseImports : function(header) {
if (!header)
return;
for ( var i = 0; i < header.length; i++) {
var jsImport = new orion.Import(header[i]);
if (jsImport !== null)
this._imports.push(jsImport);
}
},
_parsePath : function(header) {
if (!header) {
this._script = this._bundleData.getHeaders().script || "";
return;
}
var scripts = [];
for ( var i = 0; i < header.length; i++) {
var path = header[i];
if (path === ".") {
scripts[i] = this._bundleData.getHeaders().script || "";
} else {
var scriptURL = this.getResource(path);
scripts[i] = orion.Framework._fetch(scriptURL);
}
}
this._script = scripts.join("\n\n");
}
};