зеркало из https://github.com/mozilla/pjs.git
Factor interfaces into individual .idl files. Add purge support and re-load support to RDF/XML datasource.
This commit is contained in:
Родитель
35b16ac48a
Коммит
73fd36d322
|
@ -1111,45 +1111,60 @@ CompositeDataSourceImpl::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSource
|
|||
// need to add the observers of the CompositeDataSourceImpl to the new data source.
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* source)
|
||||
CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
NS_ASSERTION(source != nsnull, "null ptr");
|
||||
if (! source)
|
||||
NS_ASSERTION(aDataSource != nsnull, "null ptr");
|
||||
if (! aDataSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mDataSources.InsertElementAt(source, 0);
|
||||
source->AddObserver(this);
|
||||
NS_ADDREF(source);
|
||||
mDataSources.AppendElement(aDataSource);
|
||||
aDataSource->AddObserver(this);
|
||||
NS_ADDREF(aDataSource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::RemoveDataSource(nsIRDFDataSource* source)
|
||||
CompositeDataSourceImpl::RemoveDataSource(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
NS_ASSERTION(source != nsnull, "null ptr");
|
||||
if (! source)
|
||||
NS_ASSERTION(aDataSource != nsnull, "null ptr");
|
||||
if (! aDataSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
||||
if (mDataSources.IndexOf(source) >= 0) {
|
||||
mDataSources.RemoveElement(source);
|
||||
source->RemoveObserver(this);
|
||||
NS_RELEASE(source);
|
||||
if (mDataSources.IndexOf(aDataSource) >= 0) {
|
||||
mDataSources.RemoveElement(aDataSource);
|
||||
aDataSource->RemoveObserver(this);
|
||||
NS_RELEASE(aDataSource);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::OnAssert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object)
|
||||
CompositeDataSourceImpl::OnAssert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget)
|
||||
{
|
||||
// Make sure that the assertion isn't masked by another
|
||||
// datasource.
|
||||
//
|
||||
// XXX We could make this more efficient if we knew _which_
|
||||
// datasource actually served up the OnAssert(): we could use
|
||||
// HasAssertionN() to only search datasources _before_ the
|
||||
// datasource that coughed up the assertion.
|
||||
nsresult rv;
|
||||
PRBool hasAssertion;
|
||||
rv = HasAssertion(aSource, aProperty, aTarget, PR_TRUE, &hasAssertion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasAssertion)
|
||||
return NS_OK;
|
||||
|
||||
if (mObservers) {
|
||||
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnAssert(subject, predicate, object);
|
||||
obs->OnAssert(aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
}
|
||||
|
@ -1157,14 +1172,31 @@ CompositeDataSourceImpl::OnAssert(nsIRDFResource* subject,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::OnUnassert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object)
|
||||
CompositeDataSourceImpl::OnUnassert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget)
|
||||
{
|
||||
// Make sure that the un-assertion doesn't just unmask the
|
||||
// same assertion in a different datasource.
|
||||
//
|
||||
// XXX We could make this more efficient if we knew _which_
|
||||
// datasource actually served up the OnAssert(): we could use
|
||||
// HasAssertionN() to only search datasources _before_ the
|
||||
// datasource that coughed up the assertion.
|
||||
//
|
||||
// XXX What if the unassertion
|
||||
nsresult rv;
|
||||
PRBool hasAssertion;
|
||||
rv = HasAssertion(aSource, aProperty, aTarget, PR_TRUE, &hasAssertion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (hasAssertion)
|
||||
return NS_OK;
|
||||
|
||||
if (mObservers) {
|
||||
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnUnassert(subject, predicate, object);
|
||||
obs->OnUnassert(aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
|
|
|
@ -39,8 +39,10 @@
|
|||
#include "nscore.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFLiteral.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFPurgeableDataSource.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsAutoLock.h"
|
||||
|
@ -69,15 +71,61 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|||
|
||||
// This struct is used as the slot value in the forward and reverse
|
||||
// arcs hash tables.
|
||||
struct Assertion
|
||||
class Assertion
|
||||
{
|
||||
nsIRDFResource* mSource;
|
||||
nsIRDFResource* mProperty;
|
||||
nsIRDFNode* mTarget;
|
||||
PRBool mTruthValue;
|
||||
public:
|
||||
Assertion(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool aTruthValue);
|
||||
|
||||
~Assertion();
|
||||
|
||||
// public for now, because I'm too lazy to go thru and clean this up.
|
||||
nsIRDFResource* mSource; // OWNER
|
||||
nsIRDFResource* mProperty; // OWNER
|
||||
nsIRDFNode* mTarget; // OWNER
|
||||
Assertion* mNext;
|
||||
Assertion* mInvNext;
|
||||
PRBool mTruthValue;
|
||||
|
||||
// For nsIRDFPurgeableDataSource
|
||||
void Mark() { mMarked = PR_TRUE; }
|
||||
PRBool IsMarked() { return mMarked; }
|
||||
void Unmark() { mMarked = PR_FALSE; }
|
||||
|
||||
private:
|
||||
PRBool mMarked;
|
||||
PRInt16 mRefCnt; // XXX not used yet: to be used for threadsafety
|
||||
};
|
||||
|
||||
|
||||
Assertion::Assertion(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool aTruthValue)
|
||||
: mSource(aSource),
|
||||
mProperty(aProperty),
|
||||
mTarget(aTarget),
|
||||
mNext(nsnull),
|
||||
mInvNext(nsnull),
|
||||
mTruthValue(aTruthValue),
|
||||
mMarked(PR_FALSE),
|
||||
mRefCnt(0)
|
||||
{
|
||||
NS_ADDREF(mSource);
|
||||
NS_ADDREF(mProperty);
|
||||
NS_ADDREF(mTarget);
|
||||
}
|
||||
|
||||
Assertion::~Assertion()
|
||||
{
|
||||
NS_RELEASE(mSource);
|
||||
NS_RELEASE(mProperty);
|
||||
NS_RELEASE(mTarget);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Utility routines
|
||||
|
@ -101,12 +149,12 @@ rdf_CompareNodes(const void* v1, const void* v2)
|
|||
return (PRIntn) result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// InMemoryDataSource
|
||||
class InMemoryResourceEnumeratorImpl;
|
||||
|
||||
class InMemoryDataSource : public nsIRDFDataSource
|
||||
class InMemoryDataSource : public nsIRDFDataSource,
|
||||
public nsIRDFPurgeableDataSource
|
||||
{
|
||||
protected:
|
||||
char* mURL;
|
||||
|
@ -213,12 +261,33 @@ public:
|
|||
nsIRDFResource* aCommand,
|
||||
nsISupportsArray/*<nsIRDFResource>*/* aArguments);
|
||||
|
||||
// nsIRDFPurgeableDataSource methods
|
||||
NS_IMETHOD Mark(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool aTruthValue,
|
||||
PRBool* aDidMark);
|
||||
|
||||
NS_IMETHOD Sweep();
|
||||
|
||||
protected:
|
||||
static PRIntn SweepForwardArcsEntries(PLHashEntry* he, PRIntn index, void* arg);
|
||||
|
||||
public:
|
||||
// Implemenatation methods
|
||||
Assertion* GetForwardArcs(nsIRDFResource* u);
|
||||
Assertion* GetReverseArcs(nsIRDFNode* v);
|
||||
void SetForwardArcs(nsIRDFResource* u, Assertion* as);
|
||||
void SetReverseArcs(nsIRDFNode* v, Assertion* as);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
void
|
||||
LogOperation(const char* aOperation,
|
||||
nsIRDFResource* asource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool aTruthValue = PR_TRUE);
|
||||
#endif
|
||||
|
||||
// This datasource's monitor object.
|
||||
PRLock* mLock;
|
||||
|
@ -510,19 +579,24 @@ NS_IMPL_RELEASE(InMemoryDataSource);
|
|||
NS_IMETHODIMP
|
||||
InMemoryDataSource::QueryInterface(REFNSIID iid, void** result)
|
||||
{
|
||||
NS_PRECONDITION(result != nsnull, "null ptr");
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kISupportsIID) ||
|
||||
iid.Equals(nsIRDFDataSource::GetIID())) {
|
||||
*result = NS_STATIC_CAST(nsIRDFDataSource*, this);
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
else if (iid.Equals(nsIRDFPurgeableDataSource::GetIID())) {
|
||||
*result = NS_STATIC_CAST(nsIRDFPurgeableDataSource*, this);
|
||||
}
|
||||
else {
|
||||
*result = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
InMemoryDataSource::InMemoryDataSource(void)
|
||||
|
@ -589,10 +663,6 @@ InMemoryDataSource::DeleteForwardArcsEntry(PLHashEntry* he, PRIntn index, void*
|
|||
while (as) {
|
||||
Assertion* doomed = as;
|
||||
as = as->mNext;
|
||||
|
||||
NS_RELEASE(doomed->mSource);
|
||||
NS_RELEASE(doomed->mProperty);
|
||||
NS_RELEASE(doomed->mTarget);
|
||||
delete doomed;
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
|
@ -637,6 +707,59 @@ InMemoryDataSource::SetReverseArcs(nsIRDFNode* v, Assertion* as)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
void
|
||||
InMemoryDataSource::LogOperation(const char* aOperation,
|
||||
nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool aTruthValue)
|
||||
{
|
||||
if (! PR_LOG_TEST(gLog, PR_LOG_ALWAYS))
|
||||
return;
|
||||
|
||||
nsXPIDLCString uri;
|
||||
aSource->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("InMemoryDataSource(%s): %s", mURL, aOperation));
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" [(%p)%s]--", aSource, (const char*) uri));
|
||||
|
||||
aProperty->GetValue(getter_Copies(uri));
|
||||
|
||||
char tv = (aTruthValue ? '-' : '!');
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" --%c[(%p)%s]--", tv, aProperty, (const char*) uri));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
nsCOMPtr<nsIRDFLiteral> literal;
|
||||
|
||||
if ((resource = do_QueryInterface(aTarget)) != nsnull) {
|
||||
resource->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->[(%p)%s]", aTarget, (const char*) uri));
|
||||
}
|
||||
else if ((literal = do_QueryInterface(aTarget)) != nsnull) {
|
||||
nsXPIDLString value;
|
||||
literal->GetValue(getter_Copies(value));
|
||||
nsAutoString valueStr(value);
|
||||
char* valueCStr = valueStr.ToNewCString();
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->(\"%s\")\n", valueCStr));
|
||||
|
||||
delete[] valueCStr;
|
||||
}
|
||||
else {
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->(unknown-type)\n"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
InMemoryDataSource::Init(const char* uri)
|
||||
{
|
||||
|
@ -682,21 +805,12 @@ InMemoryDataSource::GetSource(nsIRDFResource* property,
|
|||
|
||||
NS_AUTOLOCK(mLock);
|
||||
|
||||
nsresult rv;
|
||||
for (Assertion* as = GetReverseArcs(target); as != nsnull; as = as->mNext) {
|
||||
PRBool eq;
|
||||
if (NS_FAILED(rv = property->EqualsResource(as->mProperty, &eq)))
|
||||
return rv;
|
||||
|
||||
if (! eq)
|
||||
continue;
|
||||
|
||||
if (as->mTruthValue != tv)
|
||||
continue;
|
||||
|
||||
*source = as->mSource;
|
||||
NS_ADDREF(as->mSource);
|
||||
return NS_OK;
|
||||
if ((property == as->mProperty) && (as->mTruthValue == tv)) {
|
||||
*source = as->mSource;
|
||||
NS_ADDREF(as->mSource);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
*source = nsnull;
|
||||
return NS_RDF_NO_VALUE;
|
||||
|
@ -722,21 +836,12 @@ InMemoryDataSource::GetTarget(nsIRDFResource* source,
|
|||
|
||||
NS_AUTOLOCK(mLock);
|
||||
|
||||
nsresult rv;
|
||||
for (Assertion* as = GetForwardArcs(source); as != nsnull; as = as->mNext) {
|
||||
PRBool eq;
|
||||
if (NS_FAILED(rv = property->EqualsResource(as->mProperty, &eq)))
|
||||
return rv;
|
||||
|
||||
if (! eq)
|
||||
continue;
|
||||
|
||||
if (as->mTruthValue != tv)
|
||||
continue;
|
||||
|
||||
*target = as->mTarget;
|
||||
NS_ADDREF(as->mTarget);
|
||||
return NS_OK;
|
||||
if ((property == as->mProperty) && (as->mTruthValue == tv)) {
|
||||
*target = as->mTarget;
|
||||
NS_ADDREF(as->mTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, then there was no target with for the specified
|
||||
|
@ -769,10 +874,7 @@ InMemoryDataSource::HasAssertion(nsIRDFResource* source,
|
|||
nsresult rv;
|
||||
for (Assertion* as = GetForwardArcs(source); as != nsnull; as = as->mNext) {
|
||||
PRBool eq;
|
||||
if (NS_FAILED(rv = property->EqualsResource(as->mProperty, &eq)))
|
||||
return rv;
|
||||
|
||||
if (! eq)
|
||||
if (property != as->mProperty)
|
||||
continue;
|
||||
|
||||
if (NS_FAILED(rv = target->EqualsNode(as->mTarget, &eq)))
|
||||
|
@ -868,43 +970,7 @@ InMemoryDataSource::SafeAssert(nsIRDFResource* source,
|
|||
NS_AUTOLOCK(mLock);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_ALWAYS)) {
|
||||
nsXPIDLCString uri;
|
||||
source->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("InMemoryDataSource(%s):", mURL));
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("ASSERT [(%p)%s]--", source, (const char*) uri));
|
||||
|
||||
property->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" --%c[(%p)%s]--", (tv ? '-' : '!'), property, (const char*) uri));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
nsCOMPtr<nsIRDFLiteral> literal;
|
||||
|
||||
if ((resource = do_QueryInterface(target)) != nsnull) {
|
||||
resource->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->[(%p)%s]", target, (const char*) uri));
|
||||
}
|
||||
else if ((literal = do_QueryInterface(target)) != nsnull) {
|
||||
nsXPIDLString value;
|
||||
literal->GetValue(getter_Copies(value));
|
||||
nsAutoString valueStr(value);
|
||||
char* valueCStr = valueStr.ToNewCString();
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->(\"%s\")\n", valueCStr));
|
||||
|
||||
delete[] valueCStr;
|
||||
}
|
||||
else {
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->(unknown-type)\n"));
|
||||
}
|
||||
}
|
||||
LogOperation("ASSERT", source, property, target, tv);
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
|
@ -915,12 +981,8 @@ InMemoryDataSource::SafeAssert(nsIRDFResource* source,
|
|||
// Walk to the end of the linked list.
|
||||
// XXX shouldn't we just keep a pointer to the end, or insert at the front???
|
||||
while (next) {
|
||||
PRBool eq;
|
||||
|
||||
if (NS_FAILED(rv = property->EqualsResource(next->mProperty, &eq)))
|
||||
return rv;
|
||||
|
||||
if (eq) {
|
||||
if (property == next->mProperty) {
|
||||
PRBool eq;
|
||||
if (NS_FAILED(rv = target->EqualsNode(next->mTarget, &eq)))
|
||||
return rv;
|
||||
|
||||
|
@ -936,23 +998,10 @@ InMemoryDataSource::SafeAssert(nsIRDFResource* source,
|
|||
next = next->mNext;
|
||||
}
|
||||
|
||||
as = new Assertion;
|
||||
as = new Assertion(source, property, target, tv);
|
||||
if (! as)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(source);
|
||||
as->mSource = source;
|
||||
|
||||
NS_ADDREF(property);
|
||||
as->mProperty = property;
|
||||
|
||||
NS_ADDREF(target);
|
||||
as->mTarget = target;
|
||||
|
||||
as->mTruthValue = tv;
|
||||
as->mNext = nsnull;
|
||||
as->mInvNext = nsnull;
|
||||
|
||||
// Link it in to the "forward arcs" table
|
||||
if (!prev) {
|
||||
SetForwardArcs(source, as);
|
||||
|
@ -1012,43 +1061,7 @@ InMemoryDataSource::SafeUnassert(nsIRDFResource* source,
|
|||
NS_AUTOLOCK(mLock);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_ALWAYS)) {
|
||||
nsXPIDLCString uri;
|
||||
source->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("InMemoryDataSource(%s):", mURL));
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("UNASSERT [(%p)%s]--", source, (const char*) uri));
|
||||
|
||||
property->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" ---[(%p)%s]--", property, (const char*) uri));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
nsCOMPtr<nsIRDFLiteral> literal;
|
||||
|
||||
if ((resource = do_QueryInterface(target)) != nsnull) {
|
||||
resource->GetValue(getter_Copies(uri));
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->[(%p)%s]", target, (const char*) uri));
|
||||
}
|
||||
else if ((literal = do_QueryInterface(target)) != nsnull) {
|
||||
nsXPIDLString value;
|
||||
literal->GetValue(getter_Copies(value));
|
||||
nsAutoString valueStr(value);
|
||||
char* valueCStr = valueStr.ToNewCString();
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->(\"%s\")\n", valueCStr));
|
||||
|
||||
delete[] valueCStr;
|
||||
}
|
||||
else {
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
(" -->(unknown-type)\n"));
|
||||
}
|
||||
}
|
||||
LogOperation("UNASSERT", source, property, target);
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
|
@ -1057,12 +1070,8 @@ InMemoryDataSource::SafeUnassert(nsIRDFResource* source,
|
|||
Assertion* as = nsnull;
|
||||
|
||||
while (next) {
|
||||
PRBool eq;
|
||||
|
||||
if (NS_FAILED(rv = property->EqualsResource(next->mProperty, &eq)))
|
||||
return rv;
|
||||
|
||||
if (eq) {
|
||||
if (property == next->mProperty) {
|
||||
PRBool eq;
|
||||
if (NS_FAILED(rv = target->EqualsNode(next->mTarget, &eq)))
|
||||
return rv;
|
||||
|
||||
|
@ -1111,9 +1120,6 @@ InMemoryDataSource::SafeUnassert(nsIRDFResource* source,
|
|||
#endif
|
||||
|
||||
// Delete the assertion struct & release resources
|
||||
NS_RELEASE(as->mSource);
|
||||
NS_RELEASE(as->mProperty);
|
||||
NS_RELEASE(as->mTarget);
|
||||
delete as;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1298,6 +1304,174 @@ InMemoryDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFPurgeableDataSource methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
InMemoryDataSource::Mark(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool aTruthValue,
|
||||
PRBool* aDidMark)
|
||||
{
|
||||
NS_PRECONDITION(aSource != nsnull, "null ptr");
|
||||
if (! aSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aProperty != nsnull, "null ptr");
|
||||
if (! aProperty)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aTarget != nsnull, "null ptr");
|
||||
if (! aTarget)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_AUTOLOCK(mLock);
|
||||
|
||||
nsresult rv;
|
||||
for (Assertion* as = GetForwardArcs(aSource); as != nsnull; as = as->mNext) {
|
||||
PRBool eq;
|
||||
if (aProperty != as->mProperty)
|
||||
continue;
|
||||
|
||||
if (NS_FAILED(rv = aTarget->EqualsNode(as->mTarget, &eq)))
|
||||
return rv;
|
||||
|
||||
if (! eq)
|
||||
continue;
|
||||
|
||||
if (as->mTruthValue != aTruthValue)
|
||||
continue;
|
||||
|
||||
// found it! so mark it.
|
||||
as->Mark();
|
||||
*aDidMark = PR_TRUE;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
LogOperation("MARK", aSource, aProperty, aTarget, aTruthValue);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we get here, we couldn't find the assertion
|
||||
*aDidMark = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
struct SweepInfo {
|
||||
Assertion* mUnassertList;
|
||||
PLHashTable* mReverseArcs;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
InMemoryDataSource::Sweep()
|
||||
{
|
||||
SweepInfo info = { nsnull, mReverseArcs };
|
||||
|
||||
{
|
||||
// Remove all the assertions while holding the lock, but don't notify anyone.
|
||||
NS_AUTOLOCK(mLock);
|
||||
PL_HashTableEnumerateEntries(mForwardArcs, SweepForwardArcsEntries, &info);
|
||||
}
|
||||
|
||||
// Now we've left the autolock. Do the notification.
|
||||
Assertion* as = info.mUnassertList;
|
||||
while (as) {
|
||||
#ifdef PR_LOGGING
|
||||
LogOperation("SWEEP", as->mSource, as->mProperty, as->mTarget, as->mTruthValue);
|
||||
#endif
|
||||
|
||||
if (mObservers) {
|
||||
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnUnassert(as->mSource, as->mProperty, as->mTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
}
|
||||
|
||||
Assertion* doomed = as;
|
||||
as = as->mNext;
|
||||
delete doomed;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRIntn
|
||||
InMemoryDataSource::SweepForwardArcsEntries(PLHashEntry* he, PRIntn index, void* arg)
|
||||
{
|
||||
SweepInfo* info = (SweepInfo*) arg;
|
||||
|
||||
Assertion* as = (Assertion*) he->value;
|
||||
Assertion* prev = nsnull;
|
||||
while (as) {
|
||||
if (as->IsMarked()) {
|
||||
prev = as;
|
||||
as->Unmark();
|
||||
as = as->mNext;
|
||||
}
|
||||
else {
|
||||
// remove from the list of assertions in the datasource
|
||||
Assertion* next = as->mNext;
|
||||
if (prev) {
|
||||
prev->mNext = next;
|
||||
}
|
||||
else {
|
||||
// it's the first one. update the hashtable entry.
|
||||
he->value = next;
|
||||
}
|
||||
|
||||
// remove from the reverse arcs
|
||||
PLHashEntry** hep =
|
||||
PL_HashTableRawLookup(info->mReverseArcs,
|
||||
(PLHashNumber) as->mTarget, // because we know we're using rdf_HashPointer()
|
||||
as->mTarget);
|
||||
|
||||
Assertion* ras = (Assertion*) ((*hep)->value);
|
||||
NS_ASSERTION(ras != nsnull, "no assertion in reverse arcs");
|
||||
Assertion* rprev = nsnull;
|
||||
while (ras) {
|
||||
if (ras == as) {
|
||||
if (rprev) {
|
||||
rprev->mInvNext = ras->mInvNext;
|
||||
}
|
||||
else {
|
||||
// it's the first one. update the hashtable entry.
|
||||
(*hep)->value = ras->mInvNext;
|
||||
}
|
||||
as->mInvNext = nsnull; // for my sanity.
|
||||
break;
|
||||
}
|
||||
rprev = ras;
|
||||
ras = ras->mInvNext;
|
||||
}
|
||||
|
||||
// Wow, it was the _only_ one. Unhash it.
|
||||
if (! (*hep)->value)
|
||||
PL_HashTableRawRemove(info->mReverseArcs, hep, *hep);
|
||||
|
||||
|
||||
// add to the list of assertions to unassert
|
||||
as->mNext = info->mUnassertList;
|
||||
info->mUnassertList = as;
|
||||
|
||||
// Advance to the next assertion
|
||||
as = next;
|
||||
}
|
||||
}
|
||||
|
||||
PRIntn result = HT_ENUMERATE_NEXT;
|
||||
|
||||
// if no more assertions exist for this resource, then unhash it.
|
||||
if (! he->value)
|
||||
result |= HT_ENUMERATE_REMOVE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult NS_NewRDFInMemoryDataSource(nsIRDFDataSource** result);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "nsINameSpace.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFContentSink.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
|
@ -243,8 +244,6 @@ protected:
|
|||
|
||||
nsIURL* mDocumentURL;
|
||||
PRUint32 mGenSym; // for generating anonymous resources
|
||||
|
||||
PRBool mHaveSetRootResource;
|
||||
};
|
||||
|
||||
PRInt32 RDFContentSinkImpl::gRefCnt = 0;
|
||||
|
@ -276,8 +275,7 @@ RDFContentSinkImpl::RDFContentSinkImpl()
|
|||
mText(nsnull),
|
||||
mTextLength(0),
|
||||
mTextSize(0),
|
||||
mConstrainSize(PR_TRUE),
|
||||
mHaveSetRootResource(PR_FALSE)
|
||||
mConstrainSize(PR_TRUE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
|
@ -591,67 +589,11 @@ RDFContentSinkImpl::AddComment(const nsIParserNode& aNode)
|
|||
NS_IMETHODIMP
|
||||
RDFContentSinkImpl::AddProcessingInstruction(const nsIParserNode& aNode)
|
||||
{
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("rdfxml: ignoring processing instruction at line %d",
|
||||
aNode.GetSourceLineNumber()));
|
||||
|
||||
static const char kStyleSheetPI[] = "<?xml-stylesheet";
|
||||
static const char kCSSType[] = "text/css";
|
||||
|
||||
static const char kDataSourcePI[] = "<?rdf-datasource";
|
||||
static const char kContentModelBuilderPI[] = "<?rdf-builder";
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
FlushText();
|
||||
|
||||
if (! mDataSource)
|
||||
return NS_OK;
|
||||
|
||||
// XXX For now, we don't add the PI to the content model.
|
||||
// We just check for a style sheet PI
|
||||
const nsString& text = aNode.GetText();
|
||||
|
||||
// If it's a stylesheet PI...
|
||||
if (0 == text.Find(kStyleSheetPI)) {
|
||||
nsAutoString href;
|
||||
if (NS_FAILED(rv = nsRDFParserUtils::GetQuotedAttributeValue(text, "href", href)))
|
||||
return rv;
|
||||
|
||||
// If there was an error or there's no href, we can't do
|
||||
// anything with this PI
|
||||
if (! href.Length())
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString type;
|
||||
if (NS_FAILED(rv = nsRDFParserUtils::GetQuotedAttributeValue(text, "type", type)))
|
||||
return rv;
|
||||
|
||||
if (! type.Equals(kCSSType))
|
||||
return NS_OK;
|
||||
|
||||
nsIURL* url = nsnull;
|
||||
nsAutoString absURL;
|
||||
nsAutoString emptyURL;
|
||||
emptyURL.Truncate();
|
||||
if (NS_FAILED(rv = NS_MakeAbsoluteURL(mDocumentURL, emptyURL, href, absURL)))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewURL(&url, absURL)))
|
||||
return rv;
|
||||
|
||||
rv = mDataSource->AddCSSStyleSheetURL(url);
|
||||
NS_RELEASE(url);
|
||||
}
|
||||
else if (0 == text.Find(kDataSourcePI)) {
|
||||
nsAutoString href;
|
||||
rv = nsRDFParserUtils::GetQuotedAttributeValue(text, "href", href);
|
||||
if (NS_FAILED(rv) || (0 == href.Length()))
|
||||
return rv;
|
||||
|
||||
char uri[256];
|
||||
href.ToCString(uri, sizeof(uri));
|
||||
|
||||
rv = mDataSource->AddNamedDataSourceURI(uri);
|
||||
}
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1246,13 +1188,7 @@ RDFContentSinkImpl::OpenObject(const nsIParserNode& aNode)
|
|||
|
||||
AddProperties(aNode, rdfResource);
|
||||
|
||||
if (mDataSource && !mHaveSetRootResource) {
|
||||
mHaveSetRootResource = PR_TRUE;
|
||||
mDataSource->SetRootResource(rdfResource);
|
||||
}
|
||||
|
||||
NS_RELEASE(rdfResource);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,19 +37,36 @@ PRUnichar
|
|||
nsRDFParserUtils::EntityToUnicode(const char* buf)
|
||||
{
|
||||
if ((buf[0] == 'g' || buf[0] == 'G') &&
|
||||
(buf[1] == 't' || buf[1] == 'T'))
|
||||
(buf[1] == 't' || buf[1] == 'T') &&
|
||||
(buf[2] == '\0'))
|
||||
return PRUnichar('>');
|
||||
|
||||
if ((buf[0] == 'l' || buf[0] == 'L') &&
|
||||
(buf[1] == 't' || buf[1] == 'T'))
|
||||
(buf[1] == 't' || buf[1] == 'T') &&
|
||||
(buf[2] == '\0'))
|
||||
return PRUnichar('<');
|
||||
|
||||
if ((buf[0] == 'a' || buf[0] == 'A') &&
|
||||
(buf[1] == 'm' || buf[1] == 'M') &&
|
||||
(buf[2] == 'p' || buf[2] == 'P'))
|
||||
(buf[2] == 'p' || buf[2] == 'P') &&
|
||||
(buf[3] == '\0'))
|
||||
return PRUnichar('&');
|
||||
|
||||
NS_NOTYETIMPLEMENTED("this is a named entity that I can't handle...");
|
||||
if ((buf[0] == 'a' || buf[0] == 'A') &&
|
||||
(buf[1] == 'p' || buf[1] == 'P') &&
|
||||
(buf[2] == 'o' || buf[2] == 'O') &&
|
||||
(buf[3] == 's' || buf[3] == 'S') &&
|
||||
(buf[4] == '\0'))
|
||||
return PRUnichar('\'');
|
||||
|
||||
if ((buf[0] == 'q' || buf[0] == 'Q') &&
|
||||
(buf[1] == 'u' || buf[1] == 'U') &&
|
||||
(buf[2] == 'o' || buf[2] == 'O') &&
|
||||
(buf[3] == 't' || buf[3] == 'T') &&
|
||||
(buf[4] == '\0'))
|
||||
return PRUnichar('"');
|
||||
|
||||
NS_NOTYETIMPLEMENTED("look this up in the declared-entity table");
|
||||
return PRUnichar('?');
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "nsIComponentManager.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFResourceFactory.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFXMLDataSource.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
@ -846,17 +845,20 @@ ServiceImpl::GetDataSource(const char* uri, nsIRDFDataSource** aDataSource)
|
|||
{
|
||||
// First, check the cache to see if we already have this
|
||||
// datasource loaded and initialized.
|
||||
nsIRDFDataSource* ds =
|
||||
NS_STATIC_CAST(nsIRDFDataSource*, PL_HashTableLookup(mNamedDataSources, uri));
|
||||
{
|
||||
nsIRDFDataSource* cached =
|
||||
NS_STATIC_CAST(nsIRDFDataSource*, PL_HashTableLookup(mNamedDataSources, uri));
|
||||
|
||||
if (ds) {
|
||||
NS_ADDREF(ds);
|
||||
*aDataSource = ds;
|
||||
return NS_OK;
|
||||
if (cached) {
|
||||
NS_ADDREF(cached);
|
||||
*aDataSource = cached;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Nope. So go to the repository to try to create it.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIRDFDataSource> ds;
|
||||
nsAutoString rdfName(uri);
|
||||
static const char kRDFPrefix[] = "rdf:";
|
||||
PRInt32 pos = rdfName.Find(kRDFPrefix);
|
||||
|
@ -881,9 +883,15 @@ ServiceImpl::GetDataSource(const char* uri, nsIRDFDataSource** aDataSource)
|
|||
|
||||
rv = nsComponentManager::CreateInstance(progID, nsnull,
|
||||
nsIRDFDataSource::GetIID(),
|
||||
(void**)&ds);
|
||||
getter_AddRefs(ds));
|
||||
|
||||
if (progID != buf)
|
||||
delete[] progID;
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = ds->Init(uri);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
// Try to load this as an RDF/XML data source
|
||||
|
@ -892,32 +900,24 @@ ServiceImpl::GetDataSource(const char* uri, nsIRDFDataSource** aDataSource)
|
|||
nsIRDFDataSource::GetIID(),
|
||||
(void**) &ds);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = ds->Init(uri);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX hack for now: make sure that the data source is
|
||||
// synchronously loaded. In the long run, we should factor out
|
||||
// the "loading" from the "creating". See nsRDFXMLDataSource::Init().
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIRDFXMLDataSource> rdfxmlDataSource(do_QueryInterface(ds));
|
||||
NS_ASSERTION(rdfxmlDataSource, "not an RDF/XML data source!");
|
||||
if (rdfxmlDataSource) {
|
||||
rv = rdfxmlDataSource->SetSynchronous(PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to make RDF/XML data source synchronous");
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIRDFXMLDataSource> rdfxmlDataSource(do_QueryInterface(ds));
|
||||
NS_ASSERTION(rdfxmlDataSource, "not an RDF/XML data source!");
|
||||
if (! rdfxmlDataSource) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = rdfxmlDataSource->Open(PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX only a warning, because the URI may have been ill-formed.
|
||||
NS_WARNING("unable to create data source");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = ds->Init(uri);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(ds);
|
||||
NS_ERROR("unable to initialize data source");
|
||||
return rv;
|
||||
}
|
||||
*aDataSource = ds;
|
||||
NS_ADDREF(*aDataSource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "nsFileSpec.h"
|
||||
#include "nsFileStream.h"
|
||||
#include "nsIDTD.h"
|
||||
#include "nsIRDFPurgeableDataSource.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIOutputStream.h"
|
||||
|
@ -124,7 +125,7 @@ public:
|
|||
*aLength = mSize - mIndex;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount) {
|
||||
PRUint32 readCount = 0;
|
||||
while (mIndex < mSize && aCount > 0) {
|
||||
|
@ -161,18 +162,13 @@ protected:
|
|||
NameSpaceMap* Next;
|
||||
};
|
||||
|
||||
nsIRDFDataSource* mInner;
|
||||
PRBool mIsSynchronous; // true if the document should be loaded synchronously
|
||||
nsIRDFDataSource* mInner; // OWNER
|
||||
PRBool mIsWritable; // true if the document can be written back
|
||||
PRBool mIsDirty; // true if the document should be written back
|
||||
nsVoidArray mObservers;
|
||||
char** mNamedDataSourceURIs;
|
||||
PRInt32 mNumNamedDataSourceURIs;
|
||||
nsIURL** mCSSStyleSheetURLs;
|
||||
PRInt32 mNumCSSStyleSheetURLs;
|
||||
nsIRDFResource* mRootResource;
|
||||
PRBool mIsLoading; // true while the document is loading
|
||||
nsVoidArray mObservers; // WEAK REFERENCES
|
||||
PRBool mIsLoading; // true while the document is loading
|
||||
NameSpaceMap* mNameSpaces;
|
||||
nsCOMPtr<nsIURL> mURL;
|
||||
|
||||
// pseudo-constants
|
||||
static PRInt32 gRefCnt;
|
||||
|
@ -224,9 +220,9 @@ public:
|
|||
return mInner->GetTargets(source, property, tv, targets);
|
||||
}
|
||||
|
||||
NS_IMETHOD Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
NS_IMETHOD Assert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool tv);
|
||||
|
||||
NS_IMETHOD Unassert(nsIRDFResource* source,
|
||||
|
@ -286,18 +282,13 @@ public:
|
|||
}
|
||||
|
||||
// nsIRDFXMLDataSource interface
|
||||
NS_IMETHOD SetSynchronous(PRBool aIsSynchronous);
|
||||
NS_IMETHOD GetReadOnly(PRBool* aIsReadOnly);
|
||||
NS_IMETHOD SetReadOnly(PRBool aIsReadOnly);
|
||||
NS_IMETHOD Open(PRBool aBlocking);
|
||||
NS_IMETHOD BeginLoad(void);
|
||||
NS_IMETHOD Interrupt(void);
|
||||
NS_IMETHOD Resume(void);
|
||||
NS_IMETHOD EndLoad(void);
|
||||
NS_IMETHOD SetRootResource(nsIRDFResource* aResource);
|
||||
NS_IMETHOD GetRootResource(nsIRDFResource** aResource);
|
||||
NS_IMETHOD AddCSSStyleSheetURL(nsIURL* aStyleSheetURL);
|
||||
NS_IMETHOD GetCSSStyleSheetURLs(nsIURL*** aStyleSheetURLs, PRInt32* aCount);
|
||||
NS_IMETHOD AddNamedDataSourceURI(const char* aNamedDataSourceURI);
|
||||
NS_IMETHOD GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount);
|
||||
NS_IMETHOD AddNameSpace(nsIAtom* aPrefix, const nsString& aURI);
|
||||
NS_IMETHOD AddXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver);
|
||||
NS_IMETHOD RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver);
|
||||
|
@ -367,14 +358,8 @@ NS_NewRDFXMLDataSource(nsIRDFXMLDataSource** result)
|
|||
|
||||
RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
|
||||
: mInner(nsnull),
|
||||
mIsSynchronous(PR_FALSE),
|
||||
mIsWritable(PR_TRUE),
|
||||
mIsDirty(PR_FALSE),
|
||||
mNamedDataSourceURIs(nsnull),
|
||||
mNumNamedDataSourceURIs(0),
|
||||
mCSSStyleSheetURLs(nsnull),
|
||||
mNumCSSStyleSheetURLs(0),
|
||||
mRootResource(nsnull),
|
||||
mIsLoading(PR_FALSE),
|
||||
mNameSpaces(nsnull)
|
||||
{
|
||||
|
@ -422,18 +407,6 @@ RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void)
|
|||
|
||||
Flush();
|
||||
|
||||
while (mNumNamedDataSourceURIs-- > 0) {
|
||||
delete mNamedDataSourceURIs[mNumNamedDataSourceURIs];
|
||||
}
|
||||
|
||||
delete mNamedDataSourceURIs;
|
||||
|
||||
while (mNumCSSStyleSheetURLs-- > 0) {
|
||||
NS_RELEASE(mCSSStyleSheetURLs[mNumCSSStyleSheetURLs]);
|
||||
}
|
||||
|
||||
delete mCSSStyleSheetURLs;
|
||||
|
||||
while (mNameSpaces) {
|
||||
NameSpaceMap* doomed = mNameSpaces;
|
||||
mNameSpaces = mNameSpaces->Next;
|
||||
|
@ -442,7 +415,6 @@ RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void)
|
|||
delete doomed;
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mRootResource);
|
||||
NS_RELEASE(mInner);
|
||||
|
||||
if (--gRefCnt == 0) {
|
||||
|
@ -516,7 +488,7 @@ rdf_BlockingParse(nsIURL* aURL, nsIStreamListener* aConsumer)
|
|||
break; // eof
|
||||
|
||||
proxy->SetBuffer(buf, readCount);
|
||||
|
||||
|
||||
// XXX shouldn't netlib be doing this???
|
||||
if (NS_FAILED(rv = aConsumer->OnDataAvailable(aURL, proxy, readCount)))
|
||||
break;
|
||||
|
@ -538,7 +510,6 @@ RDFXMLDataSourceImpl::Init(const char* uri)
|
|||
{
|
||||
static const char kFileURIPrefix[] = "file:";
|
||||
static const char kResourceURIPrefix[] = "resource:";
|
||||
nsAutoString utf8("UTF-8");
|
||||
|
||||
NS_PRECONDITION(mInner != nsnull, "not initialized");
|
||||
if (! mInner)
|
||||
|
@ -546,134 +517,85 @@ static const char kResourceURIPrefix[] = "resource:";
|
|||
|
||||
nsresult rv;
|
||||
|
||||
nsIRDFService* rdfService = nsnull;
|
||||
nsINameSpaceManager* ns = nsnull;
|
||||
nsIRDFContentSink* sink = nsnull;
|
||||
nsIParser* parser = nsnull;
|
||||
nsIDTD* dtd = nsnull;
|
||||
nsIStreamListener* lsnr = nsnull;
|
||||
nsIURL* url = nsnull;
|
||||
const char* realURL;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewURL(&url, uri)))
|
||||
goto done;
|
||||
rv = NS_NewURL(getter_AddRefs(mURL), uri);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX this is a hack: any "file:" URI is considered writable. All
|
||||
// others are considered read-only.
|
||||
url->GetSpec(&realURL);
|
||||
const char* realURL;
|
||||
mURL->GetSpec(&realURL);
|
||||
if ((PL_strncmp(realURL, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) &&
|
||||
(PL_strncmp(realURL, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) {
|
||||
mIsWritable = PR_FALSE;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv = mInner->Init(realURL)))
|
||||
goto done;
|
||||
rv = mInner->Init(realURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &rdfService)))
|
||||
goto done;
|
||||
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (NS_FAILED(rv = rdfService->RegisterDataSource(this, PR_FALSE)))
|
||||
goto done;
|
||||
rv = rdf->RegisterDataSource(this, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (NS_FAILED(rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID,
|
||||
nsnull,
|
||||
kINameSpaceManagerIID,
|
||||
(void**) &ns)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nsComponentManager::CreateInstance(kRDFContentSinkCID,
|
||||
nsnull,
|
||||
kIRDFContentSinkIID,
|
||||
(void**) &sink)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(sink->Init(url, ns)))
|
||||
goto done;
|
||||
|
||||
// We set the content sink's data source directly to our in-memory
|
||||
// store. This allows the initial content to be generated "directly".
|
||||
if (NS_FAILED(rv = sink->SetDataSource(this)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nsComponentManager::CreateInstance(kParserCID,
|
||||
nsnull,
|
||||
kIParserIID,
|
||||
(void**) &parser)))
|
||||
goto done;
|
||||
|
||||
parser->SetDocumentCharset(utf8, kCharsetFromDocTypeDefault);
|
||||
|
||||
parser->SetContentSink(sink);
|
||||
|
||||
// XXX this should eventually be kRDFDTDCID (oh boy, that's a
|
||||
// pretty identifier). The RDF DTD will be a much more
|
||||
// RDF-resilient parser.
|
||||
if (NS_FAILED(rv = nsComponentManager::CreateInstance(kWellFormedDTDCID,
|
||||
nsnull,
|
||||
kIDTDIID,
|
||||
(void**) &dtd)))
|
||||
goto done;
|
||||
|
||||
parser->RegisterDTD(dtd);
|
||||
|
||||
if (NS_FAILED(rv = parser->QueryInterface(kIStreamListenerIID, (void**) &lsnr)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(parser->Parse(url)))
|
||||
goto done;
|
||||
|
||||
// XXX Yet another hack to get the registry stuff
|
||||
// bootstrapped. Force "file:" and "resource:" URIs to be loaded
|
||||
// by a blocking read. Maybe there needs to be a distinct
|
||||
// interface for stream data sources?
|
||||
if (mIsSynchronous) {
|
||||
rv = rdf_BlockingParse(url, lsnr);
|
||||
}
|
||||
else {
|
||||
rv = NS_OpenURL(url, lsnr);
|
||||
}
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(lsnr);
|
||||
NS_IF_RELEASE(dtd);
|
||||
NS_IF_RELEASE(parser);
|
||||
NS_IF_RELEASE(sink);
|
||||
if (rdfService) {
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
|
||||
rdfService = nsnull;
|
||||
}
|
||||
NS_IF_RELEASE(url);
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv)
|
||||
RDFXMLDataSourceImpl::Assert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
PRBool aTruthValue)
|
||||
{
|
||||
// We don't accept assertions unless we're writable (except in the
|
||||
// case that we're actually _reading_ the datasource in).
|
||||
if (!mIsLoading && !mIsWritable)
|
||||
return NS_RDF_ASSERTION_REJECTED;
|
||||
nsresult rv;
|
||||
|
||||
nsresult rv = mInner->Assert(source, property, target, tv);
|
||||
if (mIsLoading) {
|
||||
PRBool hasAssertion = PR_FALSE;
|
||||
|
||||
if (rv == NS_RDF_ASSERTION_ACCEPTED) {
|
||||
if (!mIsLoading)
|
||||
mIsDirty = PR_TRUE;
|
||||
nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner);
|
||||
if (gcable) {
|
||||
rv = gcable->Mark(aSource, aProperty, aTarget, aTruthValue, &hasAssertion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = NS_RDF_ASSERTION_ACCEPTED;
|
||||
|
||||
if (! hasAssertion) {
|
||||
rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && gcable) {
|
||||
// Now mark the new assertion, so it doesn't get
|
||||
// removed when we sweep. Ignore rv, because we want
|
||||
// to return what mInner->Assert() gave us.
|
||||
PRBool didMark;
|
||||
(void) gcable->Mark(aSource, aProperty, aTarget, aTruthValue, &didMark);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
else if (mIsWritable) {
|
||||
rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
|
||||
|
||||
return rv;
|
||||
if (rv == NS_RDF_ASSERTION_ACCEPTED)
|
||||
mIsDirty = PR_TRUE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
return NS_RDF_ASSERTION_REJECTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
RDFXMLDataSourceImpl::Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target)
|
||||
{
|
||||
// We don't accept assertions unless we're writable (except in the
|
||||
|
@ -724,12 +646,13 @@ done:
|
|||
// nsIRDFXMLDataSource methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::SetSynchronous(PRBool aIsSynchronous)
|
||||
RDFXMLDataSourceImpl::GetReadOnly(PRBool* aIsReadOnly)
|
||||
{
|
||||
mIsSynchronous = aIsSynchronous;
|
||||
*aIsReadOnly = !mIsWritable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::SetReadOnly(PRBool aIsReadOnly)
|
||||
{
|
||||
|
@ -739,6 +662,76 @@ RDFXMLDataSourceImpl::SetReadOnly(PRBool aIsReadOnly)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Open(PRBool aBlocking)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsINameSpaceManager> nsmgr;
|
||||
rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID,
|
||||
nsnull,
|
||||
kINameSpaceManagerIID,
|
||||
getter_AddRefs(nsmgr));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFContentSink> sink;
|
||||
rv = nsComponentManager::CreateInstance(kRDFContentSinkCID,
|
||||
nsnull,
|
||||
kIRDFContentSinkIID,
|
||||
getter_AddRefs(sink));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = sink->Init(mURL, nsmgr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// We set the content sink's data source directly to our in-memory
|
||||
// store. This allows the initial content to be generated "directly".
|
||||
rv = sink->SetDataSource(this);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIParser> parser;
|
||||
rv = nsComponentManager::CreateInstance(kParserCID,
|
||||
nsnull,
|
||||
kIParserIID,
|
||||
getter_AddRefs(parser));
|
||||
|
||||
nsAutoString utf8("UTF-8");
|
||||
parser->SetDocumentCharset(utf8, kCharsetFromDocTypeDefault);
|
||||
|
||||
parser->SetContentSink(sink);
|
||||
|
||||
// XXX this should eventually be kRDFDTDCID (oh boy, that's a
|
||||
// pretty identifier). The RDF DTD will be a much more
|
||||
// RDF-resilient parser.
|
||||
nsCOMPtr<nsIDTD> dtd;
|
||||
rv = nsComponentManager::CreateInstance(kWellFormedDTDCID,
|
||||
nsnull,
|
||||
kIDTDIID,
|
||||
getter_AddRefs(dtd));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
parser->RegisterDTD(dtd);
|
||||
|
||||
|
||||
nsCOMPtr<nsIStreamListener> lsnr;
|
||||
rv = parser->QueryInterface(kIStreamListenerIID, getter_AddRefs(lsnr));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = parser->Parse(mURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aBlocking) {
|
||||
rv = rdf_BlockingParse(mURL, lsnr);
|
||||
}
|
||||
else {
|
||||
rv = NS_OpenURL(mURL, lsnr);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::BeginLoad(void)
|
||||
{
|
||||
|
@ -774,6 +767,11 @@ NS_IMETHODIMP
|
|||
RDFXMLDataSourceImpl::EndLoad(void)
|
||||
{
|
||||
mIsLoading = PR_FALSE;
|
||||
nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner);
|
||||
if (gcable) {
|
||||
gcable->Sweep();
|
||||
}
|
||||
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnEndLoad(this);
|
||||
|
@ -781,113 +779,6 @@ RDFXMLDataSourceImpl::EndLoad(void)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::SetRootResource(nsIRDFResource* aResource)
|
||||
{
|
||||
NS_PRECONDITION(aResource != nsnull, "null ptr");
|
||||
if (! aResource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_IF_RELEASE(mRootResource);
|
||||
mRootResource = aResource;
|
||||
NS_IF_ADDREF(mRootResource);
|
||||
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnRootResourceFound(this, mRootResource);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::GetRootResource(nsIRDFResource** aResource)
|
||||
{
|
||||
NS_IF_ADDREF(mRootResource);
|
||||
*aResource = mRootResource;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::AddCSSStyleSheetURL(nsIURL* aCSSStyleSheetURL)
|
||||
{
|
||||
NS_PRECONDITION(aCSSStyleSheetURL != nsnull, "null ptr");
|
||||
if (! aCSSStyleSheetURL)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsIURL** p = new nsIURL*[mNumCSSStyleSheetURLs + 1];
|
||||
if (! p)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PRInt32 i;
|
||||
for (i = mNumCSSStyleSheetURLs - 1; i >= 0; --i)
|
||||
p[i] = mCSSStyleSheetURLs[i];
|
||||
|
||||
NS_ADDREF(aCSSStyleSheetURL);
|
||||
p[mNumCSSStyleSheetURLs] = aCSSStyleSheetURL;
|
||||
|
||||
++mNumCSSStyleSheetURLs;
|
||||
mCSSStyleSheetURLs = p;
|
||||
|
||||
for (i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnCSSStyleSheetAdded(this, aCSSStyleSheetURL);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::GetCSSStyleSheetURLs(nsIURL*** aCSSStyleSheetURLs, PRInt32* aCount)
|
||||
{
|
||||
*aCSSStyleSheetURLs = mCSSStyleSheetURLs;
|
||||
*aCount = mNumCSSStyleSheetURLs;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::AddNamedDataSourceURI(const char* aNamedDataSourceURI)
|
||||
{
|
||||
NS_PRECONDITION(aNamedDataSourceURI != nsnull, "null ptr");
|
||||
if (! aNamedDataSourceURI)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
char** p = new char*[mNumNamedDataSourceURIs + 1];
|
||||
if (! p)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PRInt32 i;
|
||||
for (i = mNumNamedDataSourceURIs - 1; i >= 0; --i)
|
||||
p[i] = mNamedDataSourceURIs[i];
|
||||
|
||||
PRInt32 len = PL_strlen(aNamedDataSourceURI);
|
||||
char* buf = new char[len + 1];
|
||||
if (! buf) {
|
||||
delete p;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
PL_strcpy(buf, aNamedDataSourceURI);
|
||||
p[mNumNamedDataSourceURIs] = buf;
|
||||
|
||||
++mNumNamedDataSourceURIs;
|
||||
mNamedDataSourceURIs = p;
|
||||
|
||||
for (i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnNamedDataSourceAdded(this, aNamedDataSourceURI);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount)
|
||||
{
|
||||
*aNamedDataSourceURIs = mNamedDataSourceURIs;
|
||||
*aCount = mNumNamedDataSourceURIs;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::AddNameSpace(nsIAtom* aPrefix, const nsString& aURI)
|
||||
{
|
||||
|
@ -1384,7 +1275,7 @@ static const char kRDFAlt[] = "RDF:Alt";
|
|||
else if (property == kRDF_instanceOf) {
|
||||
// don't serialize instanceOf -- it's implicit in the tag
|
||||
}
|
||||
else if (property == kRDF_nextVal) {
|
||||
else if (property == kRDF_nextVal) {
|
||||
// don't serialize nextVal -- it's internal state
|
||||
}
|
||||
else {
|
||||
|
@ -1414,30 +1305,6 @@ static const char kXMLNS[] = "\n xmlns";
|
|||
|
||||
rdf_BlockingWrite(aStream, kXMLVersion, sizeof(kXMLVersion) - 1);
|
||||
|
||||
PRInt32 i;
|
||||
|
||||
// Write out style sheet processing instructions
|
||||
for (i = 0; i < mNumCSSStyleSheetURLs; ++i) {
|
||||
static const char kCSSStyleSheet1[] = "<?xml-stylesheet href=\"";
|
||||
static const char kCSSStyleSheet2[] = "\" type=\"text/css\"?>\n";
|
||||
|
||||
const char* url;
|
||||
mCSSStyleSheetURLs[i]->GetSpec(&url);
|
||||
rdf_BlockingWrite(aStream, kCSSStyleSheet1, sizeof(kCSSStyleSheet1) - 1);
|
||||
rdf_BlockingWrite(aStream, url);
|
||||
rdf_BlockingWrite(aStream, kCSSStyleSheet2, sizeof(kCSSStyleSheet2) - 1);
|
||||
}
|
||||
|
||||
// Write out named data source processing instructions
|
||||
for (i = 0; i < mNumNamedDataSourceURIs; ++i) {
|
||||
static const char kNamedDataSource1[] = "<?rdf-datasource href=\"";
|
||||
static const char kNamedDataSource2[] = "\"?>\n";
|
||||
|
||||
rdf_BlockingWrite(aStream, kNamedDataSource1, sizeof(kNamedDataSource1) - 1);
|
||||
rdf_BlockingWrite(aStream, mNamedDataSourceURIs[i]);
|
||||
rdf_BlockingWrite(aStream, kNamedDataSource2, sizeof(kNamedDataSource2) - 1);
|
||||
}
|
||||
|
||||
// global name space declarations
|
||||
rdf_BlockingWrite(aStream, kOpenRDF, sizeof(kOpenRDF) - 1);
|
||||
for (NameSpaceMap* entry = mNameSpaces; entry != nsnull; entry = entry->Next) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче