blob: d56f4fc643a0107ddecd8618b8420e2a1bc59270 [file] [log] [blame]
function Framework() {
this._installOrderBundles = [];
this._resolveOrderBundles = [];
this._exports = {};
this._requiredBundles = {};
this._properties = {};
this._currentBundleId = 0;
}
Framework.prototype = {
getBundles : function() {
return this._installOrderBundles.slice();
},
getProperty : function(name) {
return this._properties[name];
},
setProperty : function(name, value) {
this._properties[name] = value;
},
installBundle : function(location, headers) {
if (location === undefined)
throw "location cannot be undefined";
if (location === null)
throw "location cannot be null";
var bundleData = new BundleData(this._currentBundleId, location, headers);
var bundle = new Bundle(this, bundleData);
for ( var i = 0; i < this._installOrderBundles.length; i++) {
if (bundle.equals(this._installOrderBundles[i]))
return this._installOrderBundles[i];
}
this._installOrderBundles[this._currentBundleId] = bundle;
this._currentBundleId++;
return bundle;
},
refresh : function() {
var uninstalledBundleFound = false;
var resolvedBundles = this._resolveOrderBundles.slice();
var i = 0;
var bundle = null;
var newInstallOrderBundles = [];
for (i = 0; i < this._installOrderBundles.length; i++) {
bundle = this._installOrderBundles[i];
if (bundle.getState() !== Bundle.UNINSTALLED) {
newInstallOrderBundles.push(bundle);
}
}
this._installOrderBundles = newInstallOrderBundles;
for (i = 0; i < resolvedBundles.length; i++) {
bundle = resolvedBundles[i];
if (bundle.getState() === Bundle.UNINSTALLED) {
uninstalledBundleFound = true;
}
if (uninstalledBundleFound) {
this._unresolveBundle(bundle);
}
}
if (uninstalledBundleFound) {
var newResolveOrderBundles = [];
for (i = 0; i < this._resolveOrderBundles.length; i++) {
bundle = this._resolveOrderBundles[i];
if (bundle.getState() === Bundle.RESOLVED || bundle.getState() === Bundle.ACTIVE) {
newResolveOrderBundles.push(bundle);
}
}
this._resolveOrderBundles = newResolveOrderBundles;
this.resolve();
}
},
resolve : function() {
var unresolvedBundles = [];
var i = 0;
for (i = 0; i < this._installOrderBundles.length; i++) {
var bundle = this._installOrderBundles[i];
if (bundle.getState() === Bundle.INSTALLED)
unresolvedBundles.push(bundle);
}
var resolvedBundles = [];
var resolvedBundle = null;
while (unresolvedBundles.length !== 0) {
resolvedBundle = this._stepResolver(unresolvedBundles);
if (resolvedBundle !== null)
resolvedBundles.push(resolvedBundle);
else
break;
}
for (i = 0; i < resolvedBundles; i++) {
resolvedBundle = resolvedBundles[i];
if (resolvedBundle.isMarkedStarted())
resolvedBundle.start();
}
},
shutdown : function() {
var reversed = this._installOrderBundles.slice().reverse();
for ( var i = 0; i < reversed.length; i++) {
var bundle = reversed[i];
bundle.stop();
bundle.uninstall();
}
this.refresh();
},
_getBundleContext : function(bundle) {
return new BundleContext(bundle, this);
},
_stepResolver : function(unresolvedBundles) {
for (var i = 0; i < unresolvedBundles.length; i++) {
var bundle = unresolvedBundles[i];
if (this._resolveBundle(bundle)) {
this._resolveOrderBundles.push(bundle);
unresolvedBundles.splice(i,1);
return bundle;
}
}
return null;
},
_resolveBundle: function(bundle) {
if (bundle._isSingleton() && this._requiredBundles[bundle.getName()])
return false;
if (this._wire(bundle)) {
bundle._resolve();
this._addExports(bundle);
this._addRequiredBundle(bundle);
return true;
}
this._unwire(bundle);
return false;
},
_wire : function(bundle) {
return this._wireRequires(bundle) && this._wireImports(bundle);
},
_wireRequires : function(bundle) {
var requires = bundle._getRequires();
for (var i = 0; i < requires.length; i++) {
var jsRequire = requires[i];
var name = jsRequire.getName();
var candidates = this._requiredBundles[name];
var satisfied = false;
if (candidates) {
for (var j = 0; j < candidates.length; j++) {
var candidate = candidates[j];
satisfied = jsRequire.wire(candidate);
if (satisfied)
break;
}
}
if (!satisfied && !jsRequire.isOptional())
return false;
}
return true;
},
_wireImports : function(bundle) {
var imports = bundle._getImports();
for (var i = 0; i < imports.length; i++) {
var jsImport = imports[i];
var name = jsImport.getName();
var candidates = this._exports[name];
var satisfied = false;
if (candidates) {
for (var j = 0; j < candidates.length; j++) {
var candidate = candidates[j];
satisfied = jsImport.wire(candidate);
if (satisfied)
break;
}
}
if (!satisfied && !jsImport.isOptional())
return false;
}
return true;
},
_addExports : function(bundle) {
var exports = bundle._getExports();
for (var i = 0; i < exports.length; i++) {
var jsExport = exports[i];
var name = jsExport.getName();
var namedExports = this._exports[name];
if (!namedExports) {
namedExports = [];
this._exports[name] = namedExports;
}
namedExports.push(jsExport);
namedExports.sort(Framework._exportsComparator);
}
},
_addRequiredBundle : function(bundle) {
var name = bundle.getName();
var namedBundles = this._requiredBundles[name];
if (! namedBundles) {
namedBundles = [];
this._requiredBundles[name]= namedBundles;
}
namedBundles.push(bundle);
namedBundles.sort(Framework._requireBundlesComparator);
},
_unresolveBundle : function(bundle) {
this._removeExports(bundle);
this._removeRequiredBunde(bundle);
bundle._unresolve();
this._unwire(bundle);
},
_removeExports : function(bundle) {
var exports = bundle._getExports();
for ( var i = 0; i < exports.length; i++) {
var jsExport = exports[i];
var name = jsExport.getName();
var namedExports = this._exports[name];
if (!namedExports)
continue;
for ( var j = 0; j < namedExports.length; j++) {
if (namedExports[j] === jsExport) {
namedExports.splice(j, 1);
break;
}
}
if (namedExports.length === 0)
delete this._exports[name];
}
},
_removeRequiredBunde : function(bundle) {
var name = bundle.getName();
var namedBundles = this._requiredBundles[name];
if (!namedBundles)
return;
for ( var i = 0; i < namedBundles.length; i++) {
if (namedBundles[i] === bundle) {
namedBundles.splice(i, 1);
break;
}
}
if (namedBundles.length === 0)
delete this._requiredBundles[name];
},
_unwire : function(bundle) {
this._unwireImports(bundle);
this._unwireRequires(bundle);
},
_unwireImports : function(bundle) {
var imports = bundle._getImports();
for ( var i = 0; i < imports.length; i++) {
var jsImport = imports[i];
jsImport.unwire();
}
},
_unwireRequires : function(bundle) {
var requires = bundle._getRequires();
for ( var i = 0; i < requires.length; i++) {
var jsRequires = requires[i];
jsRequires.unwire();
}
}
};
Framework._exportsComparator = function(export0, export1) {
// order switched for descending order
var result = export1.getVersion().compareTo(export0.getVersion());
if (result == 0)
result = export0.getBundleId() - export1.getBundleId();
return result;
};
Framework._requireBundlesComparator = function(bundle0, bundle1) {
// order switched for descending order
var result = bundle1.getVersion().compareTo(bundle0.getVersion());
if (result == 0)
result = bundle0.getBundleId() - bundle1.getBundleId();
return result;
};