Cannot call RegisterDataSource on a own datasource

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Cannot call RegisterDataSource on a own datasource

mcben
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
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

Axel Hecht-2
mcben wrote:

> 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.
>

I suspect that it has something to do with your move from an in-memory
datasource as inner to an rdf/xml as inner. I didn't get why you made
that move, was that intentional?

Axel
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

Neil-4
In reply to this post by mcben
mcben wrote:

> Its contractid is like
> "@mozilla.org/rdf/datasource;1?name=mydatasource" so as to get it in
> the chrome with the "rdf:mydatasource" keyword.

Technically it's not necessary to register it in this case, and in fact
you can crash if you don't register it correctly, so I'd advise you to
avoid that.

--
Warning: May contain traces of nuts.
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

mcben
In reply to this post by Axel Hecht-2
On 4 fév, 09:27, Axel Hecht <[hidden email]> wrote:

> mcben wrote:
> > 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.
>
> I suspect that it has something to do with your move from an in-memory
> datasource as inner to an rdf/xml as inner. I didn't get why you made
> that move, was that intentional?

Hi Axel,
Thank you for your answer.

To begin, you can grab my component source code here, with the "second
design" implementation (with inner):
http://pastebin.mozilla.org/319272

And the xul tree that should show my results look quite simple :
<tree id="itemtypes-tree" flex="1"
        datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list">
  <treecols>
    <treecol id="col-name" primary="true" label="Name" flex="1"/>
  </treecols>
  <template>
    <treechildren>
      <treeitem uri="rdf:*">
        <treerow>
          <treecell label="rdf:*" />
        </treerow>
      </treeitem>
    </treechildren>
  </template>
</tree>


Hum. yes, the move was partially intentional :

 * My first try with an in-memory datasource was with the instance set
as __proto__ property in the prototype of my component. That is to
say, that it was not with the "inner" design.
The main problem with this design was that i could not extends my
component by implementing other public interface : the QI function of
my component was never called, nor any method that i though they
overrode existing methods of the in-mem. The only thing that i could
improve in this design was the init phase of my component (by filling
in-mem with XMLHttpRequest) nothing else.

Is it normal that with the following code, the QueryInterface method
is never called, that's why i cant implement any other interfaces ? (i
think that the __proto__ QI is called instead).

function myComponentImplementation() {
}
myComponentImplementation.prototype {
    __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
name=in-memory-datasource"]
                         .createInstance(Components.interfaces.nsIRDFDataSource),

    QueryInterface : function(iid) {
        if (!iid.equals(C_i.nsIDOMEventListener) &&
            !iid.equals(C_i.nsIRDFDataSource) &&
            !iid.equals(C_i.nsIRDFRemoteDataSource) &&
            !iid.equals(C_i.nsISupports))
            throw Components.results.NS_ERROR_NO_INTERFACE;
        ConsoleService.logStringMessage("QI called:" + iid);
        return this;
    }
}


 * With the "inner" design, i immediatly use a xml-datasource, just
like the nsLocalStore implementation. With that, i could load a cached
version of the rdf file from disk, and then update it with
XMLHttpRequest only if it really needed.

Since, you are thinking that the problem can come from the xml-
datasource, i took the same component, and just replaced the xml-
datasource inner, with an in-memory-datasource.
Indeed, it seems there is no major failure with initialization, i can
register the datasource, but the content that i downloaded with
XMLHttpRequest and that i put in the ds is not reflected in my chrome
xul tree, nor i can query my datasource for any target that sould
exists.

More precisely, about any errors, i had to create the container (the
one to wich I append downloaded resources) with this.mInner (the in-
mem ds) and not my component. Is it normal ?
Look:
this._container = RDFContainer.MakeSeq(this.mInner,
RDF.GetResource(this._struct.ref));
Even though my component should implement nsIRDFDataSource, that's why
i thought i could do that :
this._container = RDFContainer.MakeSeq(this,
RDF.GetResource(this._struct.ref));

But it seems that append does not work anyway.


* Finally, why I made the move to xml-datasource ?
(I thought) I could parse a local rdf file at init, and flushes the
modified results at destruction. I even could observe the download
progress from chrome (eg: with a progressbar), etc.

So any clue ?
What do you think is the best implementation ?

The first design could be perfect if i could override and extends
methods and interfaces of the __proto__ instance.

Thank you for reading me.
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

mcben
In reply to this post by Neil-4
Hi Neil,
Thank you for your answer.

On 4 fév, 12:59, Neil <[hidden email]> wrote:
> mcben wrote:
> > Its contractid is like
> > "@mozilla.org/rdf/datasource;1?name=mydatasource" so as to get it in
> > the chrome with the "rdf:mydatasource" keyword.
>
> Technically it's not necessary to register it in this case, and in fact
> you can crash if you don't register it correctly, so I'd advise you to
> avoid that.

The case you explain is the "rdf:mydatasource" keywork trick ?
Related to my other reply to Axel, i had managed to register a in-
memory datasource, the same way i tried to with an xml datasource.

But anyway, after a few test, it seems that registration is indeed not
required.

_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

Axel Hecht-2
In reply to this post by mcben
mcben wrote:

> On 4 fév, 09:27, Axel Hecht <[hidden email]> wrote:
>> mcben wrote:
>>> 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.
>> I suspect that it has something to do with your move from an in-memory
>> datasource as inner to an rdf/xml as inner. I didn't get why you made
>> that move, was that intentional?
>
> Hi Axel,
> Thank you for your answer.
>
> To begin, you can grab my component source code here, with the "second
> design" implementation (with inner):
> http://pastebin.mozilla.org/319272
>
> And the xul tree that should show my results look quite simple :
> <tree id="itemtypes-tree" flex="1"
>         datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list">
>   <treecols>
>     <treecol id="col-name" primary="true" label="Name" flex="1"/>
>   </treecols>
>   <template>
>     <treechildren>
>       <treeitem uri="rdf:*">
>         <treerow>
>           <treecell label="rdf:*" />
>         </treerow>
>       </treeitem>
>     </treechildren>
>   </template>
> </tree>
>
>
> Hum. yes, the move was partially intentional :
>
>  * My first try with an in-memory datasource was with the instance set
> as __proto__ property in the prototype of my component. That is to
> say, that it was not with the "inner" design.
> The main problem with this design was that i could not extends my
> component by implementing other public interface : the QI function of
> my component was never called, nor any method that i though they
> overrode existing methods of the in-mem. The only thing that i could
> improve in this design was the init phase of my component (by filling
> in-mem with XMLHttpRequest) nothing else.
>
> Is it normal that with the following code, the QueryInterface method
> is never called, that's why i cant implement any other interfaces ? (i
> think that the __proto__ QI is called instead).
>
> function myComponentImplementation() {
> }
> myComponentImplementation.prototype {
>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
> name=in-memory-datasource"]
>                          .createInstance(Components.interfaces.nsIRDFDataSource),
>
>     QueryInterface : function(iid) {
>         if (!iid.equals(C_i.nsIDOMEventListener) &&
>             !iid.equals(C_i.nsIRDFDataSource) &&
>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
>             !iid.equals(C_i.nsISupports))
>             throw Components.results.NS_ERROR_NO_INTERFACE;
>         ConsoleService.logStringMessage("QI called:" + iid);
>         return this;
>     }
> }
>
>
>  * With the "inner" design, i immediatly use a xml-datasource, just
> like the nsLocalStore implementation. With that, i could load a cached
> version of the rdf file from disk, and then update it with
> XMLHttpRequest only if it really needed.
>
> Since, you are thinking that the problem can come from the xml-
> datasource, i took the same component, and just replaced the xml-
> datasource inner, with an in-memory-datasource.
> Indeed, it seems there is no major failure with initialization, i can
> register the datasource, but the content that i downloaded with
> XMLHttpRequest and that i put in the ds is not reflected in my chrome
> xul tree, nor i can query my datasource for any target that sould
> exists.
>
> More precisely, about any errors, i had to create the container (the
> one to wich I append downloaded resources) with this.mInner (the in-
> mem ds) and not my component. Is it normal ?
> Look:
> this._container = RDFContainer.MakeSeq(this.mInner,
> RDF.GetResource(this._struct.ref));
> Even though my component should implement nsIRDFDataSource, that's why
> i thought i could do that :
> this._container = RDFContainer.MakeSeq(this,
> RDF.GetResource(this._struct.ref));
>
> But it seems that append does not work anyway.
>
>
> * Finally, why I made the move to xml-datasource ?
> (I thought) I could parse a local rdf file at init, and flushes the
> modified results at destruction. I even could observe the download
> progress from chrome (eg: with a progressbar), etc.
>
> So any clue ?
> What do you think is the best implementation ?
>
> The first design could be perfect if i could override and extends
> methods and interfaces of the __proto__ instance.
>
> Thank you for reading me.

I suspect that something in your implementation is broken. There is
http://developer.mozilla.org/en/docs/Aggregating_the_In-Memory_Datasource,
but that hasn't been maintained in years, same goes for its sibling
documents.

Sorry, no better idea, maybe if you post parts of your code there's
better chances.

Axel
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

mcben
On 4 fév, 14:52, Axel Hecht <[hidden email]> wrote:

> mcben wrote:
> > On 4 fév, 09:27, Axel Hecht <[hidden email]> wrote:
> >> mcben wrote:
> >>> 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.
> >> I suspect that it has something to do with your move from an in-memory
> >> datasource as inner to an rdf/xml as inner. I didn't get why you made
> >> that move, was that intentional?
>
> > Hi Axel,
> > Thank you for your answer.
>
> > To begin, you can grab my component source code here, with the "second
> > design" implementation (with inner):
> >http://pastebin.mozilla.org/319272
>
> > And the xul tree that should show my results look quite simple :
> > <tree id="itemtypes-tree" flex="1"
> >         datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list">
> >   <treecols>
> >     <treecol id="col-name" primary="true" label="Name" flex="1"/>
> >   </treecols>
> >   <template>
> >     <treechildren>
> >       <treeitem uri="rdf:*">
> >         <treerow>
> >           <treecell label="rdf:*" />
> >         </treerow>
> >       </treeitem>
> >     </treechildren>
> >   </template>
> > </tree>
>
> > Hum. yes, the move was partially intentional :
>
> >  * My first try with an in-memory datasource was with the instance set
> > as __proto__ property in the prototype of my component. That is to
> > say, that it was not with the "inner" design.
> > The main problem with this design was that i could not extends my
> > component by implementing other public interface : the QI function of
> > my component was never called, nor any method that i though they
> > overrode existing methods of the in-mem. The only thing that i could
> > improve in this design was the init phase of my component (by filling
> > in-mem with XMLHttpRequest) nothing else.
>
> > Is it normal that with the following code, the QueryInterface method
> > is never called, that's why i cant implement any other interfaces ? (i
> > think that the __proto__ QI is called instead).
>
> > function myComponentImplementation() {
> > }
> > myComponentImplementation.prototype {
> >     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
> > name=in-memory-datasource"]
> >                          .createInstance(Components.interfaces.nsIRDFDataSource),
>
> >     QueryInterface : function(iid) {
> >         if (!iid.equals(C_i.nsIDOMEventListener) &&
> >             !iid.equals(C_i.nsIRDFDataSource) &&
> >             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
> >             !iid.equals(C_i.nsISupports))
> >             throw Components.results.NS_ERROR_NO_INTERFACE;
> >         ConsoleService.logStringMessage("QI called:" + iid);
> >         return this;
> >     }
> > }
>
> >  * With the "inner" design, i immediatly use a xml-datasource, just
> > like the nsLocalStore implementation. With that, i could load a cached
> > version of the rdf file from disk, and then update it with
> > XMLHttpRequest only if it really needed.
>
> > Since, you are thinking that the problem can come from the xml-
> > datasource, i took the same component, and just replaced the xml-
> > datasource inner, with an in-memory-datasource.
> > Indeed, it seems there is no major failure with initialization, i can
> > register the datasource, but the content that i downloaded with
> > XMLHttpRequest and that i put in the ds is not reflected in my chrome
> > xul tree, nor i can query my datasource for any target that sould
> > exists.
>
> > More precisely, about any errors, i had to create the container (the
> > one to wich I append downloaded resources) with this.mInner (the in-
> > mem ds) and not my component. Is it normal ?
> > Look:
> > this._container = RDFContainer.MakeSeq(this.mInner,
> > RDF.GetResource(this._struct.ref));
> > Even though my component should implement nsIRDFDataSource, that's why
> > i thought i could do that :
> > this._container = RDFContainer.MakeSeq(this,
> > RDF.GetResource(this._struct.ref));
>
> > But it seems that append does not work anyway.
>
> > * Finally, why I made the move to xml-datasource ?
> > (I thought) I could parse a local rdf file at init, and flushes the
> > modified results at destruction. I even could observe the download
> > progress from chrome (eg: with a progressbar), etc.
>
> > So any clue ?
> > What do you think is the best implementation ?
>
> > The first design could be perfect if i could override and extends
> > methods and interfaces of the __proto__ instance.
>
> > Thank you for reading me.
>
> I suspect that something in your implementation is broken. There ishttp://developer.mozilla.org/en/docs/Aggregating_the_In-Memory_Dataso...,
> but that hasn't been maintained in years, same goes for its sibling
> documents.

Yes, i know this document, and tried some months ago to agregate a xml-
datasource (for another project) and gave up when i saw that xml-
datasource cant be aggregated ;-)

Maybe i should give another try with the in-mem datasource.

But can you confirm me that i could try that with a javascript
implementation ?


> Sorry, no better idea, maybe if you post parts of your code there's
> better chances.

Héhé. The whole component is too long / time consuming for you to take
a look ?
I understand.

So first question, that i previously asked. WIth a component
implementation below, is it normal that I cant override public methods
of the __proto__. In fact, I can only add private method, that cant be
accessed by the chrome ?

function myComponentImplementation() {
}

myComponentImplementation.prototype {
    __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
name=in-memory-datasource"]
                         .createInstance(Components.interfaces.nsIRDFDataSource),

    QueryInterface : function(iid) {
        if (!iid.equals(C_i.nsIDOMEventListener) &&
            !iid.equals(C_i.nsIRDFDataSource) &&
            !iid.equals(C_i.nsIRDFRemoteDataSource) &&
            !iid.equals(C_i.nsISupports))
            throw Components.results.NS_ERROR_NO_INTERFACE;
        ConsoleService.logStringMessage("QI called:" + iid);
        return this;
    }

}
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

Axel Hecht-2
mcben wrote:

> On 4 fév, 14:52, Axel Hecht <[hidden email]> wrote:
>> mcben wrote:
>>> On 4 fév, 09:27, Axel Hecht <[hidden email]> wrote:
>>>> mcben wrote:
>>>>> 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.
>>>> I suspect that it has something to do with your move from an in-memory
>>>> datasource as inner to an rdf/xml as inner. I didn't get why you made
>>>> that move, was that intentional?
>>> Hi Axel,
>>> Thank you for your answer.
>>> To begin, you can grab my component source code here, with the "second
>>> design" implementation (with inner):
>>> http://pastebin.mozilla.org/319272
>>> And the xul tree that should show my results look quite simple :
>>> <tree id="itemtypes-tree" flex="1"
>>>         datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list">
>>>   <treecols>
>>>     <treecol id="col-name" primary="true" label="Name" flex="1"/>
>>>   </treecols>
>>>   <template>
>>>     <treechildren>
>>>       <treeitem uri="rdf:*">
>>>         <treerow>
>>>           <treecell label="rdf:*" />
>>>         </treerow>
>>>       </treeitem>
>>>     </treechildren>
>>>   </template>
>>> </tree>
>>> Hum. yes, the move was partially intentional :
>>>  * My first try with an in-memory datasource was with the instance set
>>> as __proto__ property in the prototype of my component. That is to
>>> say, that it was not with the "inner" design.
>>> The main problem with this design was that i could not extends my
>>> component by implementing other public interface : the QI function of
>>> my component was never called, nor any method that i though they
>>> overrode existing methods of the in-mem. The only thing that i could
>>> improve in this design was the init phase of my component (by filling
>>> in-mem with XMLHttpRequest) nothing else.
>>> Is it normal that with the following code, the QueryInterface method
>>> is never called, that's why i cant implement any other interfaces ? (i
>>> think that the __proto__ QI is called instead).
>>> function myComponentImplementation() {
>>> }
>>> myComponentImplementation.prototype {
>>>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
>>> name=in-memory-datasource"]
>>>                          .createInstance(Components.interfaces.nsIRDFDataSource),
>>>     QueryInterface : function(iid) {
>>>         if (!iid.equals(C_i.nsIDOMEventListener) &&
>>>             !iid.equals(C_i.nsIRDFDataSource) &&
>>>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
>>>             !iid.equals(C_i.nsISupports))
>>>             throw Components.results.NS_ERROR_NO_INTERFACE;
>>>         ConsoleService.logStringMessage("QI called:" + iid);
>>>         return this;
>>>     }
>>> }
>>>  * With the "inner" design, i immediatly use a xml-datasource, just
>>> like the nsLocalStore implementation. With that, i could load a cached
>>> version of the rdf file from disk, and then update it with
>>> XMLHttpRequest only if it really needed.
>>> Since, you are thinking that the problem can come from the xml-
>>> datasource, i took the same component, and just replaced the xml-
>>> datasource inner, with an in-memory-datasource.
>>> Indeed, it seems there is no major failure with initialization, i can
>>> register the datasource, but the content that i downloaded with
>>> XMLHttpRequest and that i put in the ds is not reflected in my chrome
>>> xul tree, nor i can query my datasource for any target that sould
>>> exists.
>>> More precisely, about any errors, i had to create the container (the
>>> one to wich I append downloaded resources) with this.mInner (the in-
>>> mem ds) and not my component. Is it normal ?
>>> Look:
>>> this._container = RDFContainer.MakeSeq(this.mInner,
>>> RDF.GetResource(this._struct.ref));
>>> Even though my component should implement nsIRDFDataSource, that's why
>>> i thought i could do that :
>>> this._container = RDFContainer.MakeSeq(this,
>>> RDF.GetResource(this._struct.ref));
>>> But it seems that append does not work anyway.
>>> * Finally, why I made the move to xml-datasource ?
>>> (I thought) I could parse a local rdf file at init, and flushes the
>>> modified results at destruction. I even could observe the download
>>> progress from chrome (eg: with a progressbar), etc.
>>> So any clue ?
>>> What do you think is the best implementation ?
>>> The first design could be perfect if i could override and extends
>>> methods and interfaces of the __proto__ instance.
>>> Thank you for reading me.
>> I suspect that something in your implementation is broken. There ishttp://developer.mozilla.org/en/docs/Aggregating_the_In-Memory_Dataso...,
>> but that hasn't been maintained in years, same goes for its sibling
>> documents.
>
> Yes, i know this document, and tried some months ago to agregate a xml-
> datasource (for another project) and gave up when i saw that xml-
> datasource cant be aggregated ;-)
>
> Maybe i should give another try with the in-mem datasource.
>
> But can you confirm me that i could try that with a javascript
> implementation ?
>
>
>> Sorry, no better idea, maybe if you post parts of your code there's
>> better chances.
>
> Héhé. The whole component is too long / time consuming for you to take
> a look ?
> I understand.
>
> So first question, that i previously asked. WIth a component
> implementation below, is it normal that I cant override public methods
> of the __proto__. In fact, I can only add private method, that cant be
> accessed by the chrome ?
>
> function myComponentImplementation() {
> }
>
> myComponentImplementation.prototype {
>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
> name=in-memory-datasource"]
>                          .createInstance(Components.interfaces.nsIRDFDataSource),
>
>     QueryInterface : function(iid) {
>         if (!iid.equals(C_i.nsIDOMEventListener) &&
>             !iid.equals(C_i.nsIRDFDataSource) &&
>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
>             !iid.equals(C_i.nsISupports))
>             throw Components.results.NS_ERROR_NO_INTERFACE;
>         ConsoleService.logStringMessage("QI called:" + iid);
>         return this;
>     }
>
> }

That is more of a js/xpconnect question. Trying

function A(){this.bar=3;}
function B(){this.__proto__ = new A();this.foo=6};
b=new B()
[object Object]
props(b)
Fields: foo
Fields of prototype: bar
Methods of prototype of prototype of prototype: extend
b.bar
3
b.foo
6

makes me think that you should set the __proto__ to a new instance of
the in-mem ds in the Constructor. Which makes sense, as you don't want
to share the in-mem ds across all instances of
myComponentImplementation, right?

But I guess for real questions on this, you should try .js-engine.

Axel
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

mcben
On 4 fév, 15:47, Axel Hecht <[hidden email]> wrote:

> mcben wrote:
> > On 4 fév, 14:52, Axel Hecht <[hidden email]> wrote:
> >> mcben wrote:
> >>> On 4 fév, 09:27, Axel Hecht <[hidden email]> wrote:
> >>>> mcben wrote:
> >>>>> 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.
> >>>> I suspect that it has something to do with your move from an in-memory
> >>>> datasource as inner to an rdf/xml as inner. I didn't get why you made
> >>>> that move, was that intentional?
> >>> Hi Axel,
> >>> Thank you for your answer.
> >>> To begin, you can grab my component source code here, with the "second
> >>> design" implementation (with inner):
> >>>http://pastebin.mozilla.org/319272
> >>> And the xul tree that should show my results look quite simple :
> >>> <tree id="itemtypes-tree" flex="1"
> >>>         datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list">
> >>>   <treecols>
> >>>     <treecol id="col-name" primary="true" label="Name" flex="1"/>
> >>>   </treecols>
> >>>   <template>
> >>>     <treechildren>
> >>>       <treeitem uri="rdf:*">
> >>>         <treerow>
> >>>           <treecell label="rdf:*" />
> >>>         </treerow>
> >>>       </treeitem>
> >>>     </treechildren>
> >>>   </template>
> >>> </tree>
> >>> Hum. yes, the move was partially intentional :
> >>>  * My first try with an in-memory datasource was with the instance set
> >>> as __proto__ property in the prototype of my component. That is to
> >>> say, that it was not with the "inner" design.
> >>> The main problem with this design was that i could not extends my
> >>> component by implementing other public interface : the QI function of
> >>> my component was never called, nor any method that i though they
> >>> overrode existing methods of the in-mem. The only thing that i could
> >>> improve in this design was the init phase of my component (by filling
> >>> in-mem with XMLHttpRequest) nothing else.
> >>> Is it normal that with the following code, the QueryInterface method
> >>> is never called, that's why i cant implement any other interfaces ? (i
> >>> think that the __proto__ QI is called instead).
> >>> function myComponentImplementation() {
> >>> }
> >>> myComponentImplementation.prototype {
> >>>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
> >>> name=in-memory-datasource"]
> >>>                          .createInstance(Components.interfaces.nsIRDFDataSource),
> >>>     QueryInterface : function(iid) {
> >>>         if (!iid.equals(C_i.nsIDOMEventListener) &&
> >>>             !iid.equals(C_i.nsIRDFDataSource) &&
> >>>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
> >>>             !iid.equals(C_i.nsISupports))
> >>>             throw Components.results.NS_ERROR_NO_INTERFACE;
> >>>         ConsoleService.logStringMessage("QI called:" + iid);
> >>>         return this;
> >>>     }
> >>> }
> >>>  * With the "inner" design, i immediatly use a xml-datasource, just
> >>> like the nsLocalStore implementation. With that, i could load a cached
> >>> version of the rdf file from disk, and then update it with
> >>> XMLHttpRequest only if it really needed.
> >>> Since, you are thinking that the problem can come from the xml-
> >>> datasource, i took the same component, and just replaced the xml-
> >>> datasource inner, with an in-memory-datasource.
> >>> Indeed, it seems there is no major failure with initialization, i can
> >>> register the datasource, but the content that i downloaded with
> >>> XMLHttpRequest and that i put in the ds is not reflected in my chrome
> >>> xul tree, nor i can query my datasource for any target that sould
> >>> exists.
> >>> More precisely, about any errors, i had to create the container (the
> >>> one to wich I append downloaded resources) with this.mInner (the in-
> >>> mem ds) and not my component. Is it normal ?
> >>> Look:
> >>> this._container = RDFContainer.MakeSeq(this.mInner,
> >>> RDF.GetResource(this._struct.ref));
> >>> Even though my component should implement nsIRDFDataSource, that's why
> >>> i thought i could do that :
> >>> this._container = RDFContainer.MakeSeq(this,
> >>> RDF.GetResource(this._struct.ref));
> >>> But it seems that append does not work anyway.
> >>> * Finally, why I made the move to xml-datasource ?
> >>> (I thought) I could parse a local rdf file at init, and flushes the
> >>> modified results at destruction. I even could observe the download
> >>> progress from chrome (eg: with a progressbar), etc.
> >>> So any clue ?
> >>> What do you think is the best implementation ?
> >>> The first design could be perfect if i could override and extends
> >>> methods and interfaces of the __proto__ instance.
> >>> Thank you for reading me.
> >> I suspect that something in your implementation is broken. There ishttp://developer.mozilla.org/en/docs/Aggregating_the_In-Memory_Dataso...,
> >> but that hasn't been maintained in years, same goes for its sibling
> >> documents.
>
> > Yes, i know this document, and tried some months ago to agregate a xml-
> > datasource (for another project) and gave up when i saw that xml-
> > datasource cant be aggregated ;-)
>
> > Maybe i should give another try with the in-mem datasource.
>
> > But can you confirm me that i could try that with a javascript
> > implementation ?
>
> >> Sorry, no better idea, maybe if you post parts of your code there's
> >> better chances.
>
> > Héhé. The whole component is too long / time consuming for you to take
> > a look ?
> > I understand.
>
> > So first question, that i previously asked. WIth a component
> > implementation below, is it normal that I cant override public methods
> > of the __proto__. In fact, I can only add private method, that cant be
> > accessed by the chrome ?
>
> > function myComponentImplementation() {
> > }
>
> > myComponentImplementation.prototype {
> >     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
> > name=in-memory-datasource"]
> >                          .createInstance(Components.interfaces.nsIRDFDataSource),
>
> >     QueryInterface : function(iid) {
> >         if (!iid.equals(C_i.nsIDOMEventListener) &&
> >             !iid.equals(C_i.nsIRDFDataSource) &&
> >             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
> >             !iid.equals(C_i.nsISupports))
> >             throw Components.results.NS_ERROR_NO_INTERFACE;
> >         ConsoleService.logStringMessage("QI called:" + iid);
> >         return this;
> >     }
>
> > }
>
> That is more of a js/xpconnect question. Trying
>
> function A(){this.bar=3;}
> function B(){this.__proto__ = new A();this.foo=6};
> b=new B()
> [object Object]
> props(b)
> Fields: foo
> Fields of prototype: bar
> Methods of prototype of prototype of prototype: extend
> b.bar
> 3
> b.foo
> 6
>
> makes me think that you should set the __proto__ to a new instance of
> the in-mem ds in the Constructor. Which makes sense, as you don't want
> to share the in-mem ds across all instances of
> myComponentImplementation, right?

Good point.

I just tried that :

function myDataSourceImplementation(struct)
{
    this.__proto__ = Components.classes["@mozilla.org/rdf/datasource;1?
name=in-memory-datasource"]
                         .createInstance(Components.interfaces.nsIRDFDataSource);

    this.init = function() {
       // load data with XMLHttpRequest
    };

   this.QueryInterface = function(iid) {
        ConsoleService.logStringMessage("QI called:" + iid);
        if (!iid.equals(Components.interfaces.nsIDOMEventListener) &&
            !iid.equals(Components.interfaces.nsIRDFDataSource) &&
            !iid.equals(Components.interfaces.nsIRDFRemoteDataSource)
&&
            !iid.equals(Components.interfaces.nsISupports))
            throw Components.results.NS_ERROR_NO_INTERFACE;
        return this;
    };

    this.init();

}

As you can see, i'm compelled to binds new methods in the constructor
since, the prototype is overriden by "this.__proto__". Not a real
problem.
Code works (i see the data in the chrome).

But my new QI is never called, like before, and prevents me from
implementing other interfaces :-(

>
> But I guess for real questions on this, you should try .js-engine.

Maybe.
This evening, I'll try XPCOM aggregation (like in "Aggregating In
Memory Datasource"), and will ask .js-engine for any clues.
I'll post back here any progress about this subject.

Thanks for your time.
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

this.__proto__ = Ci[].createInstance and QueryInterface calling problem

Axel Hecht-2
Asking js-engine for some xpconnect help.

I left all the context in, I guess it's best to read from the bottom up
for those in js-engine.

Axel

mcben wrote:

> On 4 fév, 15:47, Axel Hecht <[hidden email]> wrote:
>> mcben wrote:
>>> On 4 fév, 14:52, Axel Hecht <[hidden email]> wrote:
>>>> mcben wrote:
>>>>> On 4 fév, 09:27, Axel Hecht <[hidden email]> wrote:
>>>>>> mcben wrote:
>>>>>>> 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.
>>>>>> I suspect that it has something to do with your move from an in-memory
>>>>>> datasource as inner to an rdf/xml as inner. I didn't get why you made
>>>>>> that move, was that intentional?
>>>>> Hi Axel,
>>>>> Thank you for your answer.
>>>>> To begin, you can grab my component source code here, with the "second
>>>>> design" implementation (with inner):
>>>>> http://pastebin.mozilla.org/319272
>>>>> And the xul tree that should show my results look quite simple :
>>>>> <tree id="itemtypes-tree" flex="1"
>>>>>         datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list">
>>>>>   <treecols>
>>>>>     <treecol id="col-name" primary="true" label="Name" flex="1"/>
>>>>>   </treecols>
>>>>>   <template>
>>>>>     <treechildren>
>>>>>       <treeitem uri="rdf:*">
>>>>>         <treerow>
>>>>>           <treecell label="rdf:*" />
>>>>>         </treerow>
>>>>>       </treeitem>
>>>>>     </treechildren>
>>>>>   </template>
>>>>> </tree>
>>>>> Hum. yes, the move was partially intentional :
>>>>>  * My first try with an in-memory datasource was with the instance set
>>>>> as __proto__ property in the prototype of my component. That is to
>>>>> say, that it was not with the "inner" design.
>>>>> The main problem with this design was that i could not extends my
>>>>> component by implementing other public interface : the QI function of
>>>>> my component was never called, nor any method that i though they
>>>>> overrode existing methods of the in-mem. The only thing that i could
>>>>> improve in this design was the init phase of my component (by filling
>>>>> in-mem with XMLHttpRequest) nothing else.
>>>>> Is it normal that with the following code, the QueryInterface method
>>>>> is never called, that's why i cant implement any other interfaces ? (i
>>>>> think that the __proto__ QI is called instead).
>>>>> function myComponentImplementation() {
>>>>> }
>>>>> myComponentImplementation.prototype {
>>>>>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
>>>>> name=in-memory-datasource"]
>>>>>                          .createInstance(Components.interfaces.nsIRDFDataSource),
>>>>>     QueryInterface : function(iid) {
>>>>>         if (!iid.equals(C_i.nsIDOMEventListener) &&
>>>>>             !iid.equals(C_i.nsIRDFDataSource) &&
>>>>>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
>>>>>             !iid.equals(C_i.nsISupports))
>>>>>             throw Components.results.NS_ERROR_NO_INTERFACE;
>>>>>         ConsoleService.logStringMessage("QI called:" + iid);
>>>>>         return this;
>>>>>     }
>>>>> }
>>>>>  * With the "inner" design, i immediatly use a xml-datasource, just
>>>>> like the nsLocalStore implementation. With that, i could load a cached
>>>>> version of the rdf file from disk, and then update it with
>>>>> XMLHttpRequest only if it really needed.
>>>>> Since, you are thinking that the problem can come from the xml-
>>>>> datasource, i took the same component, and just replaced the xml-
>>>>> datasource inner, with an in-memory-datasource.
>>>>> Indeed, it seems there is no major failure with initialization, i can
>>>>> register the datasource, but the content that i downloaded with
>>>>> XMLHttpRequest and that i put in the ds is not reflected in my chrome
>>>>> xul tree, nor i can query my datasource for any target that sould
>>>>> exists.
>>>>> More precisely, about any errors, i had to create the container (the
>>>>> one to wich I append downloaded resources) with this.mInner (the in-
>>>>> mem ds) and not my component. Is it normal ?
>>>>> Look:
>>>>> this._container = RDFContainer.MakeSeq(this.mInner,
>>>>> RDF.GetResource(this._struct.ref));
>>>>> Even though my component should implement nsIRDFDataSource, that's why
>>>>> i thought i could do that :
>>>>> this._container = RDFContainer.MakeSeq(this,
>>>>> RDF.GetResource(this._struct.ref));
>>>>> But it seems that append does not work anyway.
>>>>> * Finally, why I made the move to xml-datasource ?
>>>>> (I thought) I could parse a local rdf file at init, and flushes the
>>>>> modified results at destruction. I even could observe the download
>>>>> progress from chrome (eg: with a progressbar), etc.
>>>>> So any clue ?
>>>>> What do you think is the best implementation ?
>>>>> The first design could be perfect if i could override and extends
>>>>> methods and interfaces of the __proto__ instance.
>>>>> Thank you for reading me.
>>>> I suspect that something in your implementation is broken. There ishttp://developer.mozilla.org/en/docs/Aggregating_the_In-Memory_Dataso...,
>>>> but that hasn't been maintained in years, same goes for its sibling
>>>> documents.
>>> Yes, i know this document, and tried some months ago to agregate a xml-
>>> datasource (for another project) and gave up when i saw that xml-
>>> datasource cant be aggregated ;-)
>>> Maybe i should give another try with the in-mem datasource.
>>> But can you confirm me that i could try that with a javascript
>>> implementation ?
>>>> Sorry, no better idea, maybe if you post parts of your code there's
>>>> better chances.
>>> Héhé. The whole component is too long / time consuming for you to take
>>> a look ?
>>> I understand.
>>> So first question, that i previously asked. WIth a component
>>> implementation below, is it normal that I cant override public methods
>>> of the __proto__. In fact, I can only add private method, that cant be
>>> accessed by the chrome ?
>>> function myComponentImplementation() {
>>> }
>>> myComponentImplementation.prototype {
>>>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
>>> name=in-memory-datasource"]
>>>                          .createInstance(Components.interfaces.nsIRDFDataSource),
>>>     QueryInterface : function(iid) {
>>>         if (!iid.equals(C_i.nsIDOMEventListener) &&
>>>             !iid.equals(C_i.nsIRDFDataSource) &&
>>>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
>>>             !iid.equals(C_i.nsISupports))
>>>             throw Components.results.NS_ERROR_NO_INTERFACE;
>>>         ConsoleService.logStringMessage("QI called:" + iid);
>>>         return this;
>>>     }
>>> }
>> That is more of a js/xpconnect question. Trying
>>
>> function A(){this.bar=3;}
>> function B(){this.__proto__ = new A();this.foo=6};
>> b=new B()
>> [object Object]
>> props(b)
>> Fields: foo
>> Fields of prototype: bar
>> Methods of prototype of prototype of prototype: extend
>> b.bar
>> 3
>> b.foo
>> 6
>>
>> makes me think that you should set the __proto__ to a new instance of
>> the in-mem ds in the Constructor. Which makes sense, as you don't want
>> to share the in-mem ds across all instances of
>> myComponentImplementation, right?
>
> Good point.
>
> I just tried that :
>
> function myDataSourceImplementation(struct)
> {
>     this.__proto__ = Components.classes["@mozilla.org/rdf/datasource;1?
> name=in-memory-datasource"]
>                          .createInstance(Components.interfaces.nsIRDFDataSource);
>
>     this.init = function() {
>        // load data with XMLHttpRequest
>     };
>
>    this.QueryInterface = function(iid) {
>         ConsoleService.logStringMessage("QI called:" + iid);
>         if (!iid.equals(Components.interfaces.nsIDOMEventListener) &&
>             !iid.equals(Components.interfaces.nsIRDFDataSource) &&
>             !iid.equals(Components.interfaces.nsIRDFRemoteDataSource)
> &&
>             !iid.equals(Components.interfaces.nsISupports))
>             throw Components.results.NS_ERROR_NO_INTERFACE;
>         return this;
>     };
>
>     this.init();
>
> }
>
> As you can see, i'm compelled to binds new methods in the constructor
> since, the prototype is overriden by "this.__proto__". Not a real
> problem.
> Code works (i see the data in the chrome).
>
> But my new QI is never called, like before, and prevents me from
> implementing other interfaces :-(
>
>> But I guess for real questions on this, you should try .js-engine.
>
> Maybe.
> This evening, I'll try XPCOM aggregation (like in "Aggregating In
> Memory Datasource"), and will ask .js-engine for any clues.
> I'll post back here any progress about this subject.
>
> Thanks for your time.
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

mcben
In reply to this post by mcben
>
> Good point.
>
> I just tried that :
>
> function myDataSourceImplementation(struct)
> {
>     this.__proto__ = Components.classes["@mozilla.org/rdf/datasource;1?
> name=in-memory-datasource"]
>                          .createInstance(Components.interfaces.nsIRDFDataSource);
>
>     this.init = function() {
>        // load data with XMLHttpRequest
>     };
>
>    this.QueryInterface = function(iid) {
>         ConsoleService.logStringMessage("QI called:" + iid);
>         if (!iid.equals(Components.interfaces.nsIDOMEventListener) &&
>             !iid.equals(Components.interfaces.nsIRDFDataSource) &&
>             !iid.equals(Components.interfaces.nsIRDFRemoteDataSource)
> &&
>             !iid.equals(Components.interfaces.nsISupports))
>             throw Components.results.NS_ERROR_NO_INTERFACE;
>         return this;
>     };
>
>     this.init();
>
> }
>
> As you can see, i'm compelled to binds new methods in the constructor
> since, the prototype is overriden by "this.__proto__". Not a real
> problem.
> Code works (i see the data in the chrome).
>
> But my new QI is never called, like before, and prevents me from
> implementing other interfaces :-(
>
>> But I guess for real questions on this, you should try .js-engine.
>
> Maybe.
> This evening, I'll try XPCOM aggregation (like in "Aggregating In
> Memory Datasource"),

I'm back :)

In fact, I already try to aggregate an in-memory datasource, that was
not with xml datasource.
See here my post (without replies :[) to .xpcom:
http://groups.google.com/group/mozilla.dev.tech.xpcom/browse_frm/thread/38aeabcf8bfef28c/6d12b03fa5010e7b?lnk=st&q=Javascript%2C+RDF+in-mem+datasource+and+XPCOM+Aggregation#6d12b03fa5010e7b

My new tries is same as previous ones of today :
  in the chrome, i cant QI to another interface the datasource that i
get from RDFService.GetDataSource(), nor if i directly call my component
with Components.classes.

The asked interface is not forwarded to the outter object, eg: my own
component.

Here is the code:

function MyDataSourceImplementation(struct)
{
   this.mInner = Components
     .classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
     .createInstance(Components.interfaces.nsIRDFDataSource,
                     this,
                     Components.interfaces.nsISupports);
}
MyDataSourceImplementation.prototype = {
     mInner:null,

     QueryInterface : function MDSI_QueryInterface(iid) {
         if(iid.equals(Components.interfaces.nsIRDFDataSource))
             return this.mInner;

         if (iid.equals(Components.interfaces.nsIDOMEventListener) ||
             iid.equals(Components.interfaces.nsIRDFRemoteDataSource) ||
             iid.equals(Components.interfaces.nsISupports))
             return this;

         throw Components.results.NS_ERROR_NO_INTERFACE;
     }
}

It'worse, if I replace the mInner initialization with :

this.mInner = Components
                 .manager
                 .createInstance(inMemDsCID,
                            this, Components.interfaces.nsISupports);

The datasource if filled, that's fine, but with some QI errors, but
crashses with a Segmentation fault 15 seconde later.
The QI also does not work.

I can't find any XPCOM aggregation with javascript example :(

Are my parameters right for createInstance ?
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: this.__proto__ = Ci[].createInstance and QueryInterface calling problem

mcben
In reply to this post by Axel Hecht-2
Axel Hecht a écrit :
> Asking js-engine for some xpconnect help.
>
> I left all the context in, I guess it's best to read from the bottom up
> for those in js-engine.
>
> Axel

Thank you Axel.
And (far.. far..) below is my last reply (that i sent to .rdf before
the X-Post) with XPCOM aggregation with Javascript tries.

>
> mcben wrote:
>> On 4 fév, 15:47, Axel Hecht <[hidden email]> wrote:
>>> mcben wrote:
>>>> On 4 fév, 14:52, Axel Hecht <[hidden email]> wrote:
>>>>> mcben wrote:
>>>>>> On 4 fév, 09:27, Axel Hecht <[hidden email]> wrote:
>>>>>>> mcben wrote:
>>>>>>>> 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.
>>>>>>> I suspect that it has something to do with your move from an
>>>>>>> in-memory
>>>>>>> datasource as inner to an rdf/xml as inner. I didn't get why you
>>>>>>> made
>>>>>>> that move, was that intentional?
>>>>>> Hi Axel,
>>>>>> Thank you for your answer.
>>>>>> To begin, you can grab my component source code here, with the
>>>>>> "second
>>>>>> design" implementation (with inner):
>>>>>> http://pastebin.mozilla.org/319272
>>>>>> And the xul tree that should show my results look quite simple :
>>>>>> <tree id="itemtypes-tree" flex="1"
>>>>>>         datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list">
>>>>>>   <treecols>
>>>>>>     <treecol id="col-name" primary="true" label="Name" flex="1"/>
>>>>>>   </treecols>
>>>>>>   <template>
>>>>>>     <treechildren>
>>>>>>       <treeitem uri="rdf:*">
>>>>>>         <treerow>
>>>>>>           <treecell label="rdf:*" />
>>>>>>         </treerow>
>>>>>>       </treeitem>
>>>>>>     </treechildren>
>>>>>>   </template>
>>>>>> </tree>
>>>>>> Hum. yes, the move was partially intentional :
>>>>>>  * My first try with an in-memory datasource was with the instance
>>>>>> set
>>>>>> as __proto__ property in the prototype of my component. That is to
>>>>>> say, that it was not with the "inner" design.
>>>>>> The main problem with this design was that i could not extends my
>>>>>> component by implementing other public interface : the QI function of
>>>>>> my component was never called, nor any method that i though they
>>>>>> overrode existing methods of the in-mem. The only thing that i could
>>>>>> improve in this design was the init phase of my component (by filling
>>>>>> in-mem with XMLHttpRequest) nothing else.
>>>>>> Is it normal that with the following code, the QueryInterface method
>>>>>> is never called, that's why i cant implement any other interfaces
>>>>>> ? (i
>>>>>> think that the __proto__ QI is called instead).
>>>>>> function myComponentImplementation() {
>>>>>> }
>>>>>> myComponentImplementation.prototype {
>>>>>>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
>>>>>> name=in-memory-datasource"]
>>>>>>                          
>>>>>> .createInstance(Components.interfaces.nsIRDFDataSource),
>>>>>>     QueryInterface : function(iid) {
>>>>>>         if (!iid.equals(C_i.nsIDOMEventListener) &&
>>>>>>             !iid.equals(C_i.nsIRDFDataSource) &&
>>>>>>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
>>>>>>             !iid.equals(C_i.nsISupports))
>>>>>>             throw Components.results.NS_ERROR_NO_INTERFACE;
>>>>>>         ConsoleService.logStringMessage("QI called:" + iid);
>>>>>>         return this;
>>>>>>     }
>>>>>> }
>>>>>>  * With the "inner" design, i immediatly use a xml-datasource, just
>>>>>> like the nsLocalStore implementation. With that, i could load a
>>>>>> cached
>>>>>> version of the rdf file from disk, and then update it with
>>>>>> XMLHttpRequest only if it really needed.
>>>>>> Since, you are thinking that the problem can come from the xml-
>>>>>> datasource, i took the same component, and just replaced the xml-
>>>>>> datasource inner, with an in-memory-datasource.
>>>>>> Indeed, it seems there is no major failure with initialization, i can
>>>>>> register the datasource, but the content that i downloaded with
>>>>>> XMLHttpRequest and that i put in the ds is not reflected in my chrome
>>>>>> xul tree, nor i can query my datasource for any target that sould
>>>>>> exists.
>>>>>> More precisely, about any errors, i had to create the container (the
>>>>>> one to wich I append downloaded resources) with this.mInner (the in-
>>>>>> mem ds) and not my component. Is it normal ?
>>>>>> Look:
>>>>>> this._container = RDFContainer.MakeSeq(this.mInner,
>>>>>> RDF.GetResource(this._struct.ref));
>>>>>> Even though my component should implement nsIRDFDataSource, that's
>>>>>> why
>>>>>> i thought i could do that :
>>>>>> this._container = RDFContainer.MakeSeq(this,
>>>>>> RDF.GetResource(this._struct.ref));
>>>>>> But it seems that append does not work anyway.
>>>>>> * Finally, why I made the move to xml-datasource ?
>>>>>> (I thought) I could parse a local rdf file at init, and flushes the
>>>>>> modified results at destruction. I even could observe the download
>>>>>> progress from chrome (eg: with a progressbar), etc.
>>>>>> So any clue ?
>>>>>> What do you think is the best implementation ?
>>>>>> The first design could be perfect if i could override and extends
>>>>>> methods and interfaces of the __proto__ instance.
>>>>>> Thank you for reading me.
>>>>> I suspect that something in your implementation is broken. There
>>>>> ishttp://developer.mozilla.org/en/docs/Aggregating_the_In-Memory_Dataso...,
>>>>>
>>>>> but that hasn't been maintained in years, same goes for its sibling
>>>>> documents.
>>>> Yes, i know this document, and tried some months ago to agregate a xml-
>>>> datasource (for another project) and gave up when i saw that xml-
>>>> datasource cant be aggregated ;-)
>>>> Maybe i should give another try with the in-mem datasource.
>>>> But can you confirm me that i could try that with a javascript
>>>> implementation ?
>>>>> Sorry, no better idea, maybe if you post parts of your code there's
>>>>> better chances.
>>>> Héhé. The whole component is too long / time consuming for you to take
>>>> a look ?
>>>> I understand.
>>>> So first question, that i previously asked. WIth a component
>>>> implementation below, is it normal that I cant override public methods
>>>> of the __proto__. In fact, I can only add private method, that cant be
>>>> accessed by the chrome ?
>>>> function myComponentImplementation() {
>>>> }
>>>> myComponentImplementation.prototype {
>>>>     __proto__ : Components.classes["@mozilla.org/rdf/datasource;1?
>>>> name=in-memory-datasource"]
>>>>                          
>>>> .createInstance(Components.interfaces.nsIRDFDataSource),
>>>>     QueryInterface : function(iid) {
>>>>         if (!iid.equals(C_i.nsIDOMEventListener) &&
>>>>             !iid.equals(C_i.nsIRDFDataSource) &&
>>>>             !iid.equals(C_i.nsIRDFRemoteDataSource) &&
>>>>             !iid.equals(C_i.nsISupports))
>>>>             throw Components.results.NS_ERROR_NO_INTERFACE;
>>>>         ConsoleService.logStringMessage("QI called:" + iid);
>>>>         return this;
>>>>     }
>>>> }
>>> That is more of a js/xpconnect question. Trying
>>>
>>> function A(){this.bar=3;}
>>> function B(){this.__proto__ = new A();this.foo=6};
>>> b=new B()
>>> [object Object]
>>> props(b)
>>> Fields: foo
>>> Fields of prototype: bar
>>> Methods of prototype of prototype of prototype: extend
>>> b.bar
>>> 3
>>> b.foo
>>> 6
>>>
>>> makes me think that you should set the __proto__ to a new instance of
>>> the in-mem ds in the Constructor. Which makes sense, as you don't want
>>> to share the in-mem ds across all instances of
>>> myComponentImplementation, right?
>>
>> Good point.
>>
>> I just tried that :
>>
>> function myDataSourceImplementation(struct)
>> {
>>     this.__proto__ = Components.classes["@mozilla.org/rdf/datasource;1?
>> name=in-memory-datasource"]
>>                          
>> .createInstance(Components.interfaces.nsIRDFDataSource);
>>
>>     this.init = function() {
>>        // load data with XMLHttpRequest
>>     };
>>
>>    this.QueryInterface = function(iid) {
>>         ConsoleService.logStringMessage("QI called:" + iid);
>>         if (!iid.equals(Components.interfaces.nsIDOMEventListener) &&
>>             !iid.equals(Components.interfaces.nsIRDFDataSource) &&
>>             !iid.equals(Components.interfaces.nsIRDFRemoteDataSource)
>> &&
>>             !iid.equals(Components.interfaces.nsISupports))
>>             throw Components.results.NS_ERROR_NO_INTERFACE;
>>         return this;
>>     };
>>
>>     this.init();
>>
>> }
>>
>> As you can see, i'm compelled to binds new methods in the constructor
>> since, the prototype is overriden by "this.__proto__". Not a real
>> problem.
>> Code works (i see the data in the chrome).
>>
>> But my new QI is never called, like before, and prevents me from
>> implementing other interfaces :-(
>>
>>> But I guess for real questions on this, you should try .js-engine.
>>
>> Maybe.
>> This evening, I'll try XPCOM aggregation (like in "Aggregating In
>> Memory Datasource"), and will ask .js-engine for any clues.
>> I'll post back here any progress about this subject.
>>
>> Thanks for your time.

In fact, I already try to aggregate an in-memory datasource, that was
not with xml datasource.
See here my post (without replies :[) to .xpcom:
http://groups.google.com/group/mozilla.dev.tech.xpcom/browse_frm/thread/38aeabcf8bfef28c/6d12b03fa5010e7b?lnk=st&q=Javascript%2C+RDF+in-mem+datasource+and+XPCOM+Aggregation#6d12b03fa5010e7b

My new tries is same as previous ones of today :
  in the chrome, i cant QI to another interface the datasource that i
get from RDFService.GetDataSource(), nor if i directly call my component
with Components.classes.

The asked interface is not forwarded to the outter object, eg: my own
component.

Here is the code:

function MyDataSourceImplementation(struct)
{
   this.mInner = Components
     .classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
     .createInstance(Components.interfaces.nsIRDFDataSource,
                     this,
                     Components.interfaces.nsISupports);
}
MyDataSourceImplementation.prototype = {
     mInner:null,

     QueryInterface : function MDSI_QueryInterface(iid) {
         if(iid.equals(Components.interfaces.nsIRDFDataSource))
             return this.mInner;

         if (iid.equals(Components.interfaces.nsIDOMEventListener) ||
             iid.equals(Components.interfaces.nsIRDFRemoteDataSource) ||
             iid.equals(Components.interfaces.nsISupports))
             return this;

         throw Components.results.NS_ERROR_NO_INTERFACE;
     }
}

It'worse, if I replace the mInner initialization with :

this.mInner = Components
                 .manager
                 .createInstance(inMemDsCID,
                            this, Components.interfaces.nsISupports);

The datasource if filled, that's fine, but with some QI errors, but
crashses with a Segmentation fault 15 seconde later.
The QI also does not work.

I can't find any XPCOM aggregation with javascript example :(

Are my parameters right for createInstance ?
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: Cannot call RegisterDataSource on a own datasource

Neil-4
In reply to this post by mcben
mcben wrote:

>     QueryInterface : function MDSI_QueryInterface(iid) {
>         if (iid.equals(Components.interfaces.nsIRDFDataSource))
>             return this.mInner;
>
>         if (iid.equals(Components.interfaces.nsIDOMEventListener) ||
>             iid.equals(Components.interfaces.nsIRDFRemoteDataSource) ||
>             iid.equals(Components.interfaces.nsISupports))
>             return this;
>
>         throw Components.results.NS_ERROR_NO_INTERFACE;
>     }

This won't work; any object you return from QueryInterface must return
the original object when queried back to nsISupports, which mInner
clearly won't do.

--
Warning: May contain traces of nuts.
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf
Reply | Threaded
Open this post in threaded view
|

Re: this.__proto__ = Ci[].createInstance and QueryInterface calling problem

mcben
In reply to this post by Axel Hecht-2
On 4 fév, 18:53, Axel Hecht <[hidden email]> wrote:
> Asking js-engine for some xpconnect help.
>
> I left all the context in, I guess it's best to read from the bottom up
> for those in js-engine.
>

Anybody there that could help me ? :(

In fact, i never thought that i could set a xpcom instance as a
prototype of a js object.
But according to this thread :
http://groups.google.fr/group/mozilla.dev.tech.xpcom/browse_thread/thread/b44471fb71569447/e3146a7288feec1d?lnk=gst&q=inheritance#e3146a7288feec1d
And both last replies of Boris Zbarsky and Honza T_, it should works !
Quote :
"Just create an instance and set it as your prototype in your
constructor
function.... "

So how can i properly set it as my prototype in my constructor, and
then adds new methods and implements new interfaces ?
_______________________________________________
dev-tech-rdf mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-rdf