Cannot call RegisterDataSource on a own datasource

mcben <[email protected]> Mon, 04 Feb 2008 00:33:38 +0100
Newsgroups gmane.comp.mozilla.devel.rdf
Message-ID <[email protected]>
Hi folks,

Here is quite a long post about a problem with a own datasource 
implementation based on a xml-datasource.

I'm looking for any clues or links that could help me to achieve my 
first goal : a custom datasource that i could fill from a CSV file.

Thanks in advance for reading me :)



I'm creating a javascript component that fetches a CSV file with 
XMLHttpRequest, parses it, then adds lines as RDF resources in a RDF 
datasource.
Its contractid is like "@mozilla.org/rdf/datasource;1?name=mydatasource" 
so as to get it in the chrome with the "rdf:mydatasource" keyword.

I started this work by using an in-memory-datasource as the __proto__ 
properties of my javascript prototype.
I could fetch my file and appends data in the datasource : the result 
was shown in a rdf tree.

The first problem with this design was that i was not able to overwrite 
some nsIRDFDataSource methods (not a real problem in fact), nor extends 
the in-memory-datasource component with other interfaces : the QI method 
of my component was never called, so i got a NS_ERROR_NO_INTERFACE 
error, when i QI another interface (eg: nsIDOMListener to adds 
XMLHttpRequest callback in my chrome).

Then i took a look a the rdf:localstore C++ implementation 
(nsLocalStore.cpp) and i'm quite happy with its design : it works like a 
wrapper around a xml-datasource. It "justs" load data from 
localstore.rdf in the profile directory or creates it if it does not exist.
Then with that, I could even read and store a cached version of my CSV 
file on disk.

So, I've made the same design in my javascript component, all 
nsIRDFDataSource related methods are forwarded to a "mInner" 
xml-datasource property.

But when i try to call RegisterDataSource to register my datasource in 
the constructor of my component, it throws a NS_ERROR_FAILURE :
Here is the code :

this._loadLocalData();
RDF.RegisterDataSource(this, false);
this._loadRemoteData();

If i log "this" the console service returns me that is an Object.

That's the problem ?


In fact I get from the chrome : [xpconnect wrapped (nsISupports, 
nsIRDFDataSource, nsIRDFRemoteDataSource)] after the registration, even 
if the registration fails.
But, the nsIRDFRemoteDatasource Init method is called at every calls 
from chrome.


Maybe the real problem comes from the xml-datasource initialization.
The following code is called by the constructor of my component :

this.mInner = Components
        .classes["@mozilla.org/rdf/datasource;1?name=xml-datasource"]
        .createInstance(Components.interfaces.nsIRDFDataSource);
var remote = this.mInner
        .QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
remote.Init(filespec);

The "Init" call throws an exception with the following code 
"0x804b000a". Its related with nsISocketTransport and means 
STATUS_WAITING_FOR. Ok, why not.
Then remote.loaded returns false, and calling remote.Refresh(false) 
throws a NS_ERROR_FAILURE

What is wrong with that ?

So i catch this Init exception and get my remote datasource with the RDF 
Service like this :
remote = RDF.GetDataSource(filespec)
           .QueryInterface(Components.interfaces.nsIRDFRemoteDataSource)
this.mInner = remote
           .QueryInterface(Components.interfaces.nsIRDFDataSource);

In that case no problem with remote ds, but the RegisterDataSource go on 
failing.

And later, in the chrome, when i call a method or property that is 
forwarded to the inner, i got back a undefined result.
And i cant look any result in my xul tree.

I can post the full source code of the component if needed.

Thank you.
++
mcben