home *** CD-ROM | disk | FTP | other *** search
- XB.WidgetPackage = function XBPkg_constructor(rootDir, id) {
- if ( !(rootDir instanceof XB._Ci.nsIFile) )
- throw new TypeError(XB._base.consts.ERR_FILE_REQUIRED);
- if ( !rootDir.isDirectory() )
- throw new TypeError(this._consts.ERR_NOT_A_DIR);
- if (!sysutils.isString(id))
- throw new TypeError(XB._base.consts.ERR_STRING_EXPECTED);
-
- this._rootDir = rootDir.clone();
- this._id = id;
- this._idHash = misc.stringMD5(id + Math.random());
- this._files = {__proto__: null};
-
- this._logRoot = XB._base.loggersRoot + ".Package_" + this._idHash;
- this._logger = XB._base.application.core.Log4Moz.repository.getLogger(this._logRoot);
-
- this._xbProtocolHandler = Cc[PROTOCOL_XB_CONTRACT_ID].getService(Ci.nsIProtocolHandler).wrappedJSObject;
- this._xbProtocolHandler.addDataProvider(this);
-
- this._units = {};
- };
-
- XB.WidgetPackage.prototype = {
- constructor: XB.WidgetPackage,
-
- get id() {
- return this._id;
- },
-
- getUnit: function XBPkg_getUnit(unitName) {
- let unit = this._units[unitName];
- if (!unit) {
- let unitFile = this.findFile(unitName + ".xml");
- if (!unitFile)
- throw new Error(this._consts.ERR_FILE_NOT_FOUND + " \"" + unitName + ".xml\"");
- unit = this._loadUnit(unitFile);
- this._units[unitName] = unit;
- }
- return unit;
- },
-
- resolvePath: function XBPkg_resolvePath(path) {
- if (!path)
- return "";
-
- if (path.indexOf("xb://") == 0)
- return path;
-
-
- var spec = "xb://" + this.providerId + "/" + path;
- return spec;
- },
-
- findFile: function XBPkg_findFile(path) {
- if (!sysutils.isString(path))
- throw new TypeError(XB._base.consts.ERR_STRING_EXPECTED);
- if (this._files[path])
- return this._files[path];
-
- var root = this._rootDir.clone(),
- locales = this._locales(),
- components = path.split("/"),
- file = null;
-
- if (components[components.length - 1][0] == ".")
- return this._files[path] = null;
-
- var file = null;
- for (let i = locales.length; i--;) {
- let localeName = locales[i].name;
- let candidate = root.clone();
-
- if (localeName != '') {
- candidate.append("locale");
- candidate.append(localeName);
- }
-
- for (let j = 0; j < components.length; j++)
- candidate.append(components[j]);
-
- try {
- candidate.normalize();
-
- if (
- candidate.exists() &&
- candidate.isReadable() &&
- !candidate.isSymlink() &&
- !candidate.isDirectory() &&
- this._rootDir.contains(candidate, true)
- ) {
- file = candidate;
- break;
- }
- } catch(e) {
- continue;
- }
- }
-
- return this._files[path] = file;
- },
-
- finalize: function XBPkg_finalize() {
- for (let unitName in this._units)
- try {
- this._units[unitName].finalize();
- }
- catch (e) {
- this._logger.error("Couldn't clear loaded unit " + unitName + ". " + misc.formatError(e));
- }
- this._units = {};
-
- this._xbProtocolHandler.removeDataProvider(this);
- },
-
- get providerId() {
- return this._idHash + "." + XB._base.application.name;
- },
-
- newChannel: function XBPkg_newChannel(aURI) {
- var file = this.findFile(aURI.path);
- if (!file)
- throw new Error(this._consts.ERR_FILE_NOT_FOUND + " " + aURI.path);
-
- var filesStream = XB._Cc["@mozilla.org/network/file-input-stream;1"]
- .createInstance(XB._Ci.nsIFileInputStream);
- filesStream.init(file, 1, 0, 4);
-
- var channel = XB._Cc["@mozilla.org/network/input-stream-channel;1"]
- .createInstance(XB._Ci.nsIInputStreamChannel)
- .QueryInterface(XB._Ci.nsIChannel);
- channel.setURI(aURI);
- channel.originalURI = aURI;
- channel.contentStream = filesStream;
-
- return channel;
- },
-
- _consts: {
- ERR_NOT_A_DIR: "Root must be a directory",
- ERR_NO_UNIT: "No such unit",
- ERR_NO_WIDGET: "Unit does not describe a widget",
- ERR_FILE_NOT_FOUND: "File not found",
- ERR_ACCESS_DENIED: "Attempt to access a file outside the package directory",
- ERR_STRING_EXPECTED: "String expected"
- },
- _id: undefined,
- _idHash: undefined,
- _rootDir: null,
- _units: null,
- _logRoot: undefined,
- _name: undefined,
- _bestLocaleName: undefined,
- _logger: null,
-
- _ioService: Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService),
- _DOMParser: new Components.Constructor("@mozilla.org/xmlextras/domparser;1", "nsIDOMParser"),
-
- _loadUnit: function XBPkg_loadUnit(unitFile) {
- var unitName = unitFile.leafName.substr(0, unitFile.leafName.length - 4);
- var unitDoc = this._loadXMLDoc(this.resolvePath(unitFile.leafName));
- var unit = new XB._Parser.Unit(unitDoc, this, unitName, this._logRoot);
- return unit;
- },
-
- _loadXMLDoc: function XBPkg_loadXMLDoc(docURL) {
- var docURI = this._ioService.newURI(docURL, null, null);
- var channel = this.newChannel(docURI).QueryInterface(XB._Ci.nsIInputStreamChannel);
- return sysutils.xmlDocFromStream(channel.contentStream, docURI, docURI);
- },
-
- _locales: function() {
- if (this._localesCache)
- return this._localesCache;
-
- const weights = {
- language: 32,
- root: 16,
- ru: 8,
- en: 4,
- country: 2,
- region: 1
- };
-
- var locales = [];
-
- locales.push({
- name: '',
- weight: weights.root,
- components: null
- });
-
- var appLocale = misc.parseLocale(XB._base.application.localeString);
- var localeDir = this._rootDir.clone();
- localeDir.append("locale");
- if (!localeDir.exists())
- return locales;
-
- var entries = localeDir.directoryEntries;
- while (entries.hasMoreElements()) {
- var file = entries.getNext().QueryInterface(XB._Ci.nsIFile);
- if (file.isDirectory()) {
- var name = file.leafName;
- var components = misc.parseLocale(name);
-
- if (!components)
- continue;
-
- var weight = 0;
- for (let space in weights) {
- var component = components[space];
- if (component === undefined)
- continue;
-
- if (space == "language")
- if (component in weights)
- weight += weights[component];
-
- if (component === appLocale[space])
- weight += weights[space];
- }
-
- locales.push({
- name: name,
- weight: weight,
- components: components
- });
-
- }
- }
-
- locales.sort(function rule(a, b) {
- if (a.weight == b.weight)
- return 0;
- return a.weight < b.weight ? -1 : +1;
- });
-
- return this._localesCache = locales;
- }
- };
-