Разрабатываю приложение для работы с бд(использую xulrunner 1.8). Есть php скрипты, которые отдают rdf-ки, на основе которых строится интерфейс. Неудобство в том, что приходиться в datasources прописывать полный uri к скрипту, а так как приложение в стадии разработки - эти uri часто меняются. Так же проблемно будет менять хост, с которого получаю данные. Возник вопрос - можно ли создавать свои источники данных с "короткими" именами, такими как "rdf:history", например - "rdf:coolprog-users"? Поиски ничего не дали.. :(

ps. Во всём этом я новичок - просьба сильно не пинать.. ;)

http://xulplanet.com/tutorials/mozsdk/rdfsources.php

Mozilla provides a number of additional datasources that can be retrieved by using a URI that begins with 'rdf:'. For example, the URI rdf:history will return the history datasource which holds data related to the user's browsing history. When you request a datasource of this form, that is, a datasource with a URI that begins with 'rdf:', Mozilla will look for a component that handles that datasource. It finds this component by taking the part of the URI after the prefix and appends it to the string @mozilla.org/rdf/datasource;1?name= to form a component name. For example, the URI rdf:bookmarks, will result in the component @mozilla.org/rdf/datasource;1?name=bookmarks.

То есть, чтобы использовать "короткие" имена, нужно написать свою собственный xpcom компонент с именем @mozilla.org/rdf/datasource;1?name=shortname. Этот компонент, соответственно, должен возвращать необходимые данные. Короче, это немного не то, что требуется.

Ну ещё, как вариант, менять datasources с помощью js.

Сложновато :/ А компоненту можно на java-script написать и зарегистрировать? Или обязательно в C++?

А про изменение datasources из js я тоже думал, но короткие имена источников имхо более красивое решение..

JustSlon пишет

...А компоненту можно на java-script написать и зарегистрировать?...

Кое-какие можно.

...но короткие имена источников имхо более красивое решение...

Красивое, да, но ведь трудоёмкое.

Всё, разобрался, и даже компоненту сделал :D Может пригодиться кому-нибудь..

nsusersdatasource.js:

Выделить код

Код:

const USERSDATASOURCE_CONTRACTID = '@mozilla.org/rdf/datasource;1?name=adsk-users';
const USERSDATASOURCE_CID = Components.ID('{1da0cb45-aea3-4a52-8b29-01429a542863}');
const USERSDATASOURCE_IID = Components.interfaces.nsIRDFDataSource;

var nsUsersDataSourceModule = {
    registerSelf: function(compMgr, fileSpec, location, type) {
        compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(USERSDATASOURCE_CID,
                                        "ADSK users built-in datasource",
                                        USERSDATASOURCE_CONTRACTID,
                                        fileSpec,
                                        location,
                                        type);
    },

    getClassObject: function(compMgr, cid, iid) {
        if (!cid.equals(USERSDATASOURCE_CID))
            throw Components.results.NS_ERROR_NO_INTERFACE;

        if (!iid.equals(Components.interfaces.nsIFactory))
            throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

        return nsUsersDatasourceFactory;
    },

    canUnload: function(compMgr) { return true; }
};

var nsUsersDatasourceFactory = {
    createInstance: function(outer, iid) {
        if (outer != null)
            throw Components.results.NS_ERROR_NO_AGGREGATION;
    
        if (!iid.equals(USERSDATASOURCE_IID) &&
            !iid.equals(Components.interfaces.nsISupports))
            throw Components.results.NS_ERROR_INVALID_ARG;

        return Components
		.classes["@mozilla.org/rdf/rdf-service;1"]
		.getService(Components.interfaces.nsIRDFService)
		.GetDataSource("http://localhost/rdfTest.php");
    }
}

function NSGetModule(comMgr, fileSpec) { return nsUsersDataSourceModule; }

Положил файл в директорию components/, удалил compreg.dat в профиле и перезапустил приложение.

В коде меняем http://localhost/rdfTest.php на нужный источник.
Теперь в XUL можно просто писать datasources="rdf:adsk-users". Что, собственно, и требовалось :cool:

ps. теперь надо подумать, как это дело поставить на поток, чтобы можно было проще добавлять источники ;)

Здорово :)

новичок

:lol:

...как это дело поставить на поток, чтобы можно было проще добавлять источники...

Десять модулей написать :)
Или селектор в nsUsersDatasourceFactory. createInstance

p.s.

Может пригодиться кому-нибудь..

Кстати, спасибо. Мне такой примерчик нужен был.

Anton пишет

Кстати, спасибо. Мне такой примерчик нужен был.

Не за что :)

Довёл компонент до ума. Теперь можно определять несколько встроенных источников через один модуль.

nsCustomDatasouces.js:

Выделить код

Код:

const CUSTOMDATASOURCE_IID = Components.interfaces.nsIRDFDataSource;

// контракты
var aContractsID = new Array(
			'@mozilla.org/rdf/datasource;1?name=adsk-users',
			'@mozilla.org/rdf/datasource;1?name=adsk-test'
			);

// id компонентов
var aCID = new Array(
		Components.ID('{1da0cb45-aea3-4a52-8b29-01429a542863}'),
		Components.ID('{1da1cb45-aea3-4a52-8b29-01429a542863}')
		);

// uri источников данных
var aURI = new Array(
		'http://localhost/rdfTest.php',
		'http://localhost/test.rdf'
		);

/*  Поиск в массиве */
function findCID(cid)
{
	var i;
	for(i=0; i<aCID.length; i++)
		if(cid.equals(aCID[i]))
			return i;
	return null;
}

/* Проверка наличия в массиве */
function CIDExists(cid)
{
	if(findCID(cid)!=null)
		return true;
	return false;
}

/* модуль */
var nsCustomDataSourceModule = {
    registerSelf: function(compMgr, fileSpec, location, type) {
	var i = 0;
        compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
	for(i=0; i<aCID.length; i++) {
	        compMgr.registerFactoryLocation(aCID[i],
        	                                "Custom built-in datasource",
                	                        aContractsID[i],
                        	                fileSpec,
                                	        location,
                                        	type);
	}
    },

    getClassObject: function(compMgr, cid, iid) {
        if (!CIDExists(cid))
            throw Components.results.NS_ERROR_NO_INTERFACE;

        if (!iid.equals(Components.interfaces.nsIFactory))
            throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

        return new nsCustomDatasourceFactory(cid);
    },

    canUnload: function(compMgr) { return true; }
};

/* Фабрика объектов. cid - идентификатор необходимой компоненты */
function nsCustomDatasourceFactory(cid)
{
	this.__uri = aURI[findCID(cid)];
}

nsCustomDatasourceFactory.prototype = {
    createInstance: function(outer, iid) {
        if (outer != null)
            throw Components.results.NS_ERROR_NO_AGGREGATION;
    
        if (!iid.equals(CUSTOMDATASOURCE_IID) &&
            !iid.equals(Components.interfaces.nsISupports))
            throw Components.results.NS_ERROR_INVALID_ARG;

        return Components
		.classes["@mozilla.org/rdf/rdf-service;1"]
		.getService(Components.interfaces.nsIRDFService)
		.GetDataSource(this.__uri);
    }
}

/* no comments */
function NSGetModule(comMgr, fileSpec) { return nsCustomDataSourceModule; }

для добавления источника необходимо добавить в массивы aContractsID, aCID, aURI в начале скрипта контракт, GUID компонента и URI источника данных соответсвенно. Порядок, ессно, важен. Код хоть и кривой, зато работает.. Жду комментариев и поправок ;)

JustSlon пишет

Не за что :)

Есть.

...Жду комментариев...

А почему бы одним источником данных не обойтись ? Добавить метод, скажем, changeDataSourceURL (url).

А почему бы одним источником данных не обойтись? Добавить метод, скажем, changeDataSourceURL (url).

Вообще было бы идеально зарегистрировать один компонент с одним GUIDом и несколькими контрактами, а в фабрике в зависимости от контракта создавать разные источники. Но так как до фабрики объектов createInstance доходит только нужный интерфейс(nsIRDFDataSource) и GUID компоненты(это действительно так?) -  остаётся создавать конкретный источник только по cid. Это, конечно, немного не удобно.. Или, может, я просто неправильно понял вопрос? :rolleyes:

И еще. Если добавлять свой метод в интерфейс - придётся idl к нему писать, а потом его еще и компилировать в xpt..