blob: 04c85aaa7a0cecfad667691818c668997dbfc341 [file] [log] [blame]
function Bundle(framework, bundleData) {
this._framework = framework;
this._bundleData = bundleData;
this._symbolicName = null;
this._version = null;
this._imports = [];
this._requires = [];
this._exports = [];
this._singleton = false;
this._markedStarted = false;
this._state = INSTALLED;
this._scope = {};
this._bundleContext = null;
this._activator = null;
var headers = bundleData.getHeaders();
_parseSymbolicName(headers[Constants.BUNDLE_SYMBOLICNAME]);
_parseVersion(headers[Constants.BUNDLE_VERSION]);
_parseImports(headers[Constants.IMPORT_PACKAGE]);
_parseExports(headers[Constants.EXPORT_PACKAGE]);
_parseRequires(headers[Constants.REQUIRE_BUNDLE]);
}
Bundle.UNINSTALLED = 1;
Bundle.INSTALLED = 2;
Bundle.RESOLVED = 4;
Bundle.STARTING = 8;
Bundle.STOPPING = 16;
Bundle.ACTIVE = 32;
Bundle.prototype = {
getSymbolicName : function() {
return this._symbolicName;
},
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;
},
isSingleton : function() {
return this._singleton;
},
isMarkedStarted : function() {
return this._markedStarted;
},
equals : function(other) {
if (this === other)
return true;
if (!other instanceof Bundle)
return false;
if (this._symbolicName !== other._symbolicName)
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 = Bundle.UNINSTALLED;
},
start : function() {
this._markedStarted = true;
if (this._state !== Bundle.RESOLVED)
return;
this._state = Bundle.STARTING;
this._bundleContext = this._framework.getBundleContext(this);
this._activator = this._createActivatorInstance();
if (this._activator) {
this._activator.start(this._bundleContext);
}
this._state = Bundle.ACTIVE;
},
stop : function() {
markedStarted = false;
if (this._state !== Bundle.ACTIVE)
return;
this._state = Bundle.STOPPING;
if (this._activator) {
this._activator.stop(this._bundleContext);
}
this._state = Bundle.RESOLVED;
},
_createActivatorInstance : function() {
var activatorName = this.getHeaders()[Constants.BUNDLE_ACTIVATOR];
if (activatorName === null)
return null;
var activatorFunction = this.lookup(activatorName);
if (typeof activatorFunction !== "function")
throw "" + activatorName + " is not a function.";
return new activatorFunction();
},
_resolve : function() {
if (this._state != Bundle.INSTALLED)
return;
var namedExports = new Object(); // FIXME: jsdt bug for using {} with hasOwnProperty
var jsExport = null;
var i = 0;
// process imports (first)
for (i = 0; i < this._imports.length; i++) {
var jsImport = this._imports[i];
jsExport = jsImport.getWiredExport();
if (!namedExports.hasOwnProperty(jsExport.getName()))
namedExports[jsExport.getName()] = jsExport;
}
// process requires
for (i = 0; i < this._requires.length; i++) {
var jsRequire = this._requires[i];
var wiredBundle = jsRequire.getWiredBundle();
var wiredBundleExports = wiredBundle.getExports();
for (var j=0; j < wiredBundleExports.length; j++) {
jsExport = wiredBundleExports[j];
if (!namedExports.hasOwnProperty(jsExport.getName()))
namedExports[jsExport.getName()] = jsExport;
}
}
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 newScope = {};
for (i = 0; i < names.length; i++) {
exportName = names[i];
jsExport = namedExports[exportName];
jsExport.addToScope(newScope);
}
this._evalScript(newScope);
this._scope = newScope;
this._state = Bundle.RESOLVED;
},
_evalScript : function(scope) {
var scriptPath = this._bundleData.getHeaders()[Constants.BUNDLE_SCRIPTPATH];
if (scriptPath === null)
scriptPath = Constants.BUNDLE_SCRIPT;
var script = null;
var finalScript = "";
var tokens = scriptPath.split(Constants.SCRIPT_PATH_DELIMITER);
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i].replace(/^\s+|\s+$/g, '');
if (token === Constants.SCRIPT_PATH_DOT) {
script = this._bundleData.getHeaders()[Constants.BUNDLE_SCRIPT];
} else {
var scriptURI = this._bundleData.getEntry(token);
script = this._framework.fetch(scriptURI);
}
if (script !== null)
finalScript += script;
//TODO: figure out exports
with(scope) {
eval(finalScript);
}
}
},
_unresolve : function() {
if (this._state == Bundle.ACTIVE) {
this.stop();
markedStarted = true;
}
this._scope = null;
if (this._state == Bundle.RESOLVED)
this._state = Bundle.INSTALLED;
},
_parseSymbolicName : function(header) {
var tokens = header.split(Constants.PARAMETER_DELIMITER);
this._symbolicName = tokens[0].replace(/^\s+|\s+$/g, '');
for ( var i = 1; i < tokens.length; i++) {
var token = tokens[i];
if (token.indexOf(Constants.DIRECTIVE_EQUALS) != -1) {
var index = token.indexOf(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 !== Constants.SINGLETON_ATTRIBUTE)
continue;
var value = token.substring(index + 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 = Version.parseVersion(header);
},
_parseRequires : function(header) {
if (header === null)
return;
var tokens = header.split(Constants.CLAUSE_DELIMITER);
for ( var i = 0; i < tokens.length; i++) {
var token = tokens[i];
var jsRequire = new RequireBundle(token);
if (jsRequire !== null)
this._requires.push(jsRequire);
}
},
_parseExports : function(header) {
if (header === null)
return;
var tokens = header.split(Constants.CLAUSE_DELIMITER);
for ( var i = 0; i < tokens.length; i++) {
var token = tokens[i];
var jsExport = new ExportPackage(token, this);
if (jsExport !== null)
this._exports.push(jsExport);
}
},
_parseImports : function(header) {
if (header === null)
return;
var tokens = header.split(Constants.CLAUSE_DELIMITER);
for ( var i = 0; i < tokens.length; i++) {
var token = tokens[i];
var jsImport = new ImportPackage(token);
if (jsImport !== null)
this._imports.push(jsImport);
}
},
lookup : 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;
}
};