Add experimental support for RDF delegates.

This commit is contained in:
waterson%netscape.com 1999-11-24 20:51:39 +00:00
Родитель 25ec09fbb0
Коммит 7615b7ebff
4 изменённых файлов: 138 добавлений и 2 удалений

Просмотреть файл

@ -33,7 +33,7 @@ interface nsIRDFResource;
/**
* This interface should be implemented by an XPCOM factory that
* is registered to handle "component:/rdf/delegate/[key]/[scheme]"
* is registered to handle "component:/rdf/delegate-factory/[key]/[scheme]"
* ProgIDs.
*
* The factory will be invoked to create delegate objects from

Просмотреть файл

@ -20,6 +20,7 @@
* Contributor(s):
*/
#include "nsrootidl.idl"
#include "nsIRDFNode.idl"
@ -51,5 +52,39 @@ interface nsIRDFResource : nsIRDFNode {
* Determine if the resource has the given URI.
*/
boolean EqualsString(in string aURI);
/**
* Retrieve the "delegate" object for this resource. A resource
* may have several delegate objects, each of whose lifetimes is
* bound to the life of the resource object.
*
* This method will return the delegate for the given key after
* QueryInterface()-ing it to the requested IID.
*
* If no delegate exists for the specified key, this method will
* attempt to create one using the component manager. Specifically,
* it will combine aKey with the resource's URI scheme to produce
* a ProgID as follows:
*
* component:/rdf/delegate-factory/[key]/[scheme]
*
* This ProgID will be used to locate a factory using the
* FindFactory() method of nsIComponentManager. If the nsIFactory
* exists, it will be used to create a "delegate factory"; that
* is, an object that supports nsIRDFDelegateFactory. The delegate
* factory will be used to construct the delegate object.
*/
void GetDelegate(in string aKey, in nsIIDRef aIID,
[iid_is(aIID),retval] out nsQIResult aResult);
/**
* Force a delegate to be "unbound" from the resource.
*
* Normally, a delegate object's lifetime will be identical to
* that of the resource to which it is bound; this method allows a
* delegate to unlink itself from an RDF resource prematurely.
*/
void ReleaseDelegate(in string aKey);
};

Просмотреть файл

@ -23,9 +23,11 @@
#ifndef nsRDFResource_h__
#define nsRDFResource_h__
#include "nsCOMPtr.h"
#include "nsIRDFNode.h"
#include "nsIRDFResource.h"
#include "nscore.h"
#include "nsString.h"
#include "rdf.h"
class nsIRDFService;
@ -46,6 +48,8 @@ public:
NS_IMETHOD GetValue(char* *aURI);
NS_IMETHOD GetValueConst(const char** aURI);
NS_IMETHOD EqualsString(const char* aURI, PRBool* aResult);
NS_IMETHOD GetDelegate(const char* aKey, REFNSIID aIID, void** aResult);
NS_IMETHOD ReleaseDelegate(const char* aKey);
// nsRDFResource methods:
nsRDFResource(void);
@ -57,6 +61,14 @@ protected:
protected:
char* mURI;
struct DelegateEntry {
nsCString mKey;
nsCOMPtr<nsISupports> mDelegate;
DelegateEntry* mNext;
};
DelegateEntry* mDelegates;
};
#endif // nsRDFResource_h__

Просмотреть файл

@ -23,6 +23,7 @@
#include "nsRDFResource.h"
#include "nsCRT.h"
#include "nsIServiceManager.h"
#include "nsIRDFDelegateFactory.h"
#include "nsIRDFService.h"
#include "nsRDFCID.h"
#include "nsXPIDLString.h"
@ -37,13 +38,20 @@ nsrefcnt nsRDFResource::gRDFServiceRefCnt = 0;
////////////////////////////////////////////////////////////////////////////////
nsRDFResource::nsRDFResource(void)
: mURI(nsnull)
: mURI(nsnull), mDelegates(nsnull)
{
NS_INIT_REFCNT();
}
nsRDFResource::~nsRDFResource(void)
{
// Release all of the delegate objects
while (mDelegates) {
DelegateEntry* doomed = mDelegates;
mDelegates = mDelegates->mNext;
delete doomed;
}
gRDFService->UnregisterResource(this);
// N.B. that we need to free the URI *after* we un-cache the resource,
@ -166,4 +174,85 @@ nsRDFResource::EqualsString(const char* aURI, PRBool* aResult)
return NS_OK;
}
NS_IMETHODIMP
nsRDFResource::GetDelegate(const char* aKey, REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aKey != nsnull, "null ptr");
if (! aKey)
return NS_ERROR_NULL_POINTER;
nsresult rv;
*aResult = nsnull;
DelegateEntry* entry = mDelegates;
while (entry) {
if (entry->mKey == aKey) {
rv = entry->mDelegate->QueryInterface(aIID, aResult);
return rv;
}
entry = entry->mNext;
}
// Construct a ProgID of the form "component:/rdf/delegate/[key]/[scheme]
nsCAutoString progID("component://rdf/delegate-factory/");
progID.Append(aKey);
progID.Append("/");
for (const char* p = mURI; *p && *p != ':'; ++p)
progID.Append(*p);
nsCOMPtr<nsIRDFDelegateFactory> delegateFactory;
rv = nsComponentManager::CreateInstance(progID,
nsnull,
NS_GET_IID(nsIRDFDelegateFactory),
getter_AddRefs(delegateFactory));
if (NS_FAILED(rv)) return rv;
rv = delegateFactory->CreateDelegate(this, aKey, aIID, aResult);
if (NS_FAILED(rv)) return rv;
// Okay, we've successfully created a delegate. Let's remember it.
entry = new DelegateEntry;
if (! entry) {
NS_RELEASE(*NS_REINTERPRET_CAST(nsISupports**, aResult));
return NS_ERROR_OUT_OF_MEMORY;
}
entry->mKey = aKey;
entry->mDelegate = do_QueryInterface(*NS_REINTERPRET_CAST(nsISupports**, aResult));
entry->mNext = mDelegates;
mDelegates = entry;
return NS_OK;
}
NS_IMETHODIMP
nsRDFResource::ReleaseDelegate(const char* aKey)
{
NS_PRECONDITION(aKey != nsnull, "null ptr");
if (! aKey)
return NS_ERROR_NULL_POINTER;
DelegateEntry* entry = mDelegates;
DelegateEntry** link = &mDelegates;
while (entry) {
if (entry->mKey == aKey) {
*link = entry->mNext;
delete entry;
return NS_OK;
}
link = &(entry->mNext);
entry = entry->mNext;
}
NS_WARNING("nsRDFResource::ReleaseDelegate() no delegate found");
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////