1999-01-19 02:42:30 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
*
|
1999-11-06 03:43:54 +00:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/NPL/
|
1999-01-19 02:42:30 +00:00
|
|
|
*
|
1999-11-06 03:43:54 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1999-01-19 02:42:30 +00:00
|
|
|
*
|
1999-11-06 03:43:54 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1999-01-19 02:42:30 +00:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 03:43:54 +00:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
2000-01-11 20:49:15 +00:00
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
1999-01-19 02:42:30 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
A data source that can read itself from and write itself to an
|
|
|
|
RDF/XML stream.
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
For more information on the RDF/XML syntax,
|
|
|
|
see http://www.w3.org/TR/REC-rdf-syntax/.
|
|
|
|
|
|
|
|
This code is based on the final W3C Recommendation,
|
|
|
|
http://www.w3.org/TR/1999/REC-rdf-syntax-19990222.
|
|
|
|
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
TO DO
|
|
|
|
-----
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
1) Right now, the only kind of stream data sources that are _really_
|
1999-06-20 00:19:23 +00:00
|
|
|
writable are "file:" URIs. (In fact, _all_ "file:" URIs are
|
2000-03-28 04:53:57 +00:00
|
|
|
writable, modulo file system permissions; this may lead to some
|
1999-06-20 00:19:23 +00:00
|
|
|
surprising behavior.) Eventually, it'd be great if we could open
|
|
|
|
an arbitrary nsIOutputStream on *any* URL, and Netlib could just
|
|
|
|
do the magic.
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-01-22 06:48:25 +00:00
|
|
|
2) Implement a more terse output for "typed" nodes; that is, instead
|
1999-04-21 00:09:41 +00:00
|
|
|
of "RDF:Description type='ns:foo'", just output "ns:foo".
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
3) When re-serializing, we "cheat" for Descriptions that talk about
|
|
|
|
inline resources (i.e.., using the `ID' attribute specified in
|
|
|
|
[6.21]). Instead of writing an `ID="foo"' for the first instance,
|
|
|
|
and then `about="#foo"' for each subsequent instance, we just
|
|
|
|
_always_ write `about="#foo"'.
|
1999-01-26 01:24:34 +00:00
|
|
|
|
1999-06-20 00:19:23 +00:00
|
|
|
We do this so that we can handle the case where an RDF container
|
|
|
|
has been assigned arbitrary properties: the spec says we can't
|
|
|
|
dangle the attributes directly off the container, so we need to
|
|
|
|
refer to it. Of course, with a little cleverness, we could fix
|
|
|
|
this. But who cares?
|
|
|
|
|
|
|
|
4) When re-serializing containers. We have to cheat on some
|
|
|
|
containers, and use an illegal "about=" construct. We do this to
|
|
|
|
handle containers that have been assigned URIs outside of the
|
|
|
|
local document.
|
1999-06-16 05:11:05 +00:00
|
|
|
|
2001-02-16 20:34:30 +00:00
|
|
|
|
|
|
|
Logging
|
|
|
|
-------
|
|
|
|
|
|
|
|
To turn on logging for this module, set
|
|
|
|
|
|
|
|
NSPR_LOG_MODULES=nsRDFXMLDataSource:5
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nsFileSpec.h"
|
|
|
|
#include "nsFileStream.h"
|
|
|
|
#include "nsIDTD.h"
|
1999-05-05 03:09:12 +00:00
|
|
|
#include "nsIRDFPurgeableDataSource.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
#include "nsIInputStream.h"
|
|
|
|
#include "nsIOutputStream.h"
|
|
|
|
#include "nsIParser.h"
|
1999-04-27 05:54:18 +00:00
|
|
|
#include "nsIRDFContainerUtils.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
#include "nsIRDFContentSink.h"
|
|
|
|
#include "nsIRDFNode.h"
|
1999-06-24 00:22:58 +00:00
|
|
|
#include "nsIRDFRemoteDataSource.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
#include "nsIRDFService.h"
|
1999-06-24 00:22:58 +00:00
|
|
|
#include "nsIRDFXMLSink.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
#include "nsIRDFXMLSource.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIStreamListener.h"
|
|
|
|
#include "nsIURL.h"
|
1999-11-30 04:50:42 +00:00
|
|
|
#include "nsNetUtil.h"
|
1999-07-02 06:15:00 +00:00
|
|
|
#include "nsIChannel.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
#include "nsLayoutCID.h" // for NS_NAMESPACEMANAGER_CID.
|
|
|
|
#include "nsParserCIID.h"
|
|
|
|
#include "nsRDFCID.h"
|
1999-06-24 00:22:58 +00:00
|
|
|
#include "nsRDFBaseDataSources.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
#include "nsVoidArray.h"
|
1999-03-29 19:52:54 +00:00
|
|
|
#include "nsXPIDLString.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
#include "plstr.h"
|
|
|
|
#include "prio.h"
|
|
|
|
#include "prthread.h"
|
1999-04-22 03:16:55 +00:00
|
|
|
#include "rdf.h"
|
1999-01-21 22:24:32 +00:00
|
|
|
#include "rdfutil.h"
|
1999-03-09 09:44:27 +00:00
|
|
|
#include "prlog.h"
|
1999-01-19 02:42:30 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
//----------------------------------------------------------------------
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
|
|
|
|
static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID);
|
|
|
|
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
|
|
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
|
|
|
|
|
|
static NS_DEFINE_CID(kParserCID, NS_PARSER_IID); // XXX
|
|
|
|
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
|
1999-04-27 05:54:18 +00:00
|
|
|
static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
|
1999-01-19 02:42:30 +00:00
|
|
|
static NS_DEFINE_CID(kRDFContentSinkCID, NS_RDFCONTENTSINK_CID);
|
|
|
|
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID);
|
|
|
|
|
1999-10-13 08:00:14 +00:00
|
|
|
#ifdef PR_LOGGING
|
|
|
|
static PRLogModuleInfo* gLog;
|
|
|
|
#endif
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// ProxyStream
|
|
|
|
//
|
|
|
|
// A silly little stub class that lets us do blocking parses
|
|
|
|
//
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
class ProxyStream : public nsIInputStream
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
const char* mBuffer;
|
|
|
|
PRUint32 mSize;
|
|
|
|
PRUint32 mIndex;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ProxyStream(void) : mBuffer(nsnull)
|
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~ProxyStream(void) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsISupports
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIBaseStream
|
|
|
|
NS_IMETHOD Close(void) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsIInputStream
|
1999-09-09 22:05:05 +00:00
|
|
|
NS_IMETHOD Available(PRUint32 *aLength) {
|
1999-01-19 02:42:30 +00:00
|
|
|
*aLength = mSize - mIndex;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-05-05 03:09:12 +00:00
|
|
|
|
1999-03-05 22:53:56 +00:00
|
|
|
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount) {
|
2000-12-12 21:58:13 +00:00
|
|
|
PRUint32 readCount = PR_MIN(aCount, (mSize-mIndex));
|
|
|
|
|
|
|
|
nsCRT::memcpy(aBuf, mBuffer+mIndex, readCount);
|
|
|
|
mIndex += readCount;
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
*aReadCount = readCount;
|
2000-12-12 21:58:13 +00:00
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-08-22 07:03:33 +00:00
|
|
|
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval) {
|
2000-12-12 21:58:13 +00:00
|
|
|
PRUint32 readCount = PR_MIN(count, (mSize-mIndex));
|
|
|
|
|
|
|
|
*_retval = 0;
|
|
|
|
nsresult rv = writer (this, closure, mBuffer+mIndex, mIndex, readCount, _retval);
|
|
|
|
mIndex += *_retval;
|
|
|
|
|
|
|
|
return rv;
|
2000-08-22 07:03:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking) {
|
|
|
|
NS_NOTREACHED("GetNonBlocking");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD GetObserver(nsIInputStreamObserver * *aObserver) {
|
|
|
|
NS_NOTREACHED("GetObserver");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD SetObserver(nsIInputStreamObserver * aObserver) {
|
|
|
|
NS_NOTREACHED("SetObserver");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
// Implementation
|
|
|
|
void SetBuffer(const char* aBuffer, PRUint32 aSize) {
|
|
|
|
mBuffer = aBuffer;
|
|
|
|
mSize = aSize;
|
|
|
|
mIndex = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2000-11-17 20:54:21 +00:00
|
|
|
NS_IMPL_ISUPPORTS1(ProxyStream, nsIInputStream);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
1999-01-19 02:42:30 +00:00
|
|
|
// RDFXMLDataSourceImpl
|
2000-01-27 02:24:20 +00:00
|
|
|
//
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-06-24 00:22:58 +00:00
|
|
|
class RDFXMLDataSourceImpl : public nsIRDFDataSource,
|
|
|
|
public nsIRDFRemoteDataSource,
|
|
|
|
public nsIRDFXMLSink,
|
2000-01-27 02:24:20 +00:00
|
|
|
public nsIRDFXMLSource,
|
|
|
|
public nsIStreamListener
|
1999-01-19 02:42:30 +00:00
|
|
|
{
|
|
|
|
protected:
|
1999-01-21 22:24:32 +00:00
|
|
|
struct NameSpaceMap {
|
|
|
|
nsString URI;
|
|
|
|
nsIAtom* Prefix;
|
|
|
|
NameSpaceMap* Next;
|
|
|
|
};
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
enum LoadState {
|
|
|
|
eLoadState_Unloaded,
|
|
|
|
eLoadState_Pending,
|
|
|
|
eLoadState_Loading,
|
|
|
|
eLoadState_Loaded
|
|
|
|
};
|
|
|
|
|
|
|
|
nsIRDFDataSource* mInner; // OWNER
|
|
|
|
PRPackedBool mIsWritable; // true if the document can be written back
|
|
|
|
PRPackedBool mIsDirty; // true if the document should be written back
|
|
|
|
LoadState mLoadState; // what we're doing now
|
|
|
|
nsVoidArray mObservers; // OWNER
|
|
|
|
NameSpaceMap* mNameSpaces;
|
|
|
|
nsCOMPtr<nsIURI> mURL;
|
|
|
|
nsCOMPtr<nsIStreamListener> mParser;
|
|
|
|
char* mURLSpec;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-04-22 03:16:55 +00:00
|
|
|
// pseudo-constants
|
|
|
|
static PRInt32 gRefCnt;
|
1999-06-09 08:29:51 +00:00
|
|
|
static nsIRDFContainerUtils* gRDFC;
|
1999-08-06 20:24:29 +00:00
|
|
|
static nsIRDFService* gRDFService;
|
1999-04-22 03:16:55 +00:00
|
|
|
static nsIRDFResource* kRDF_instanceOf;
|
|
|
|
static nsIRDFResource* kRDF_nextVal;
|
1999-04-27 05:54:18 +00:00
|
|
|
static nsIRDFResource* kRDF_Bag;
|
|
|
|
static nsIRDFResource* kRDF_Seq;
|
|
|
|
static nsIRDFResource* kRDF_Alt;
|
1999-04-22 03:16:55 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
nsresult Init();
|
1999-01-19 02:42:30 +00:00
|
|
|
RDFXMLDataSourceImpl(void);
|
|
|
|
virtual ~RDFXMLDataSourceImpl(void);
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
friend nsresult
|
1999-06-24 00:22:58 +00:00
|
|
|
NS_NewRDFXMLDataSource(nsIRDFDataSource** aResult);
|
1999-06-09 08:29:51 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
inline PRBool IsLoading() {
|
|
|
|
return (mLoadState == eLoadState_Pending) ||
|
|
|
|
(mLoadState == eLoadState_Loading);
|
|
|
|
}
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
public:
|
1999-01-19 02:42:30 +00:00
|
|
|
// nsISupports
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIRDFDataSource
|
1999-06-24 00:22:58 +00:00
|
|
|
NS_IMETHOD GetURI(char* *uri);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
NS_IMETHOD GetSource(nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFResource** source) {
|
|
|
|
return mInner->GetSource(property, target, tv, source);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD GetSources(nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
1999-04-24 02:41:02 +00:00
|
|
|
nsISimpleEnumerator** sources) {
|
1999-01-19 02:42:30 +00:00
|
|
|
return mInner->GetSources(property, target, tv, sources);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD GetTarget(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFNode** target) {
|
|
|
|
return mInner->GetTarget(source, property, tv, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD GetTargets(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
PRBool tv,
|
1999-04-24 02:41:02 +00:00
|
|
|
nsISimpleEnumerator** targets) {
|
1999-01-19 02:42:30 +00:00
|
|
|
return mInner->GetTargets(source, property, tv, targets);
|
|
|
|
}
|
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
NS_IMETHOD Assert(nsIRDFResource* aSource,
|
|
|
|
nsIRDFResource* aProperty,
|
|
|
|
nsIRDFNode* aTarget,
|
1999-01-19 02:42:30 +00:00
|
|
|
PRBool tv);
|
|
|
|
|
|
|
|
NS_IMETHOD Unassert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target);
|
|
|
|
|
1999-06-24 00:22:58 +00:00
|
|
|
NS_IMETHOD Change(nsIRDFResource* aSource,
|
|
|
|
nsIRDFResource* aProperty,
|
|
|
|
nsIRDFNode* aOldTarget,
|
|
|
|
nsIRDFNode* aNewTarget);
|
|
|
|
|
|
|
|
NS_IMETHOD Move(nsIRDFResource* aOldSource,
|
|
|
|
nsIRDFResource* aNewSource,
|
|
|
|
nsIRDFResource* aProperty,
|
|
|
|
nsIRDFNode* aTarget);
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
NS_IMETHOD HasAssertion(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
PRBool* hasAssertion) {
|
|
|
|
return mInner->HasAssertion(source, property, target, tv, hasAssertion);
|
|
|
|
}
|
|
|
|
|
1999-07-06 23:36:44 +00:00
|
|
|
NS_IMETHOD AddObserver(nsIRDFObserver* aObserver) {
|
|
|
|
return mInner->AddObserver(aObserver);
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
|
1999-07-06 23:36:44 +00:00
|
|
|
NS_IMETHOD RemoveObserver(nsIRDFObserver* aObserver) {
|
|
|
|
return mInner->RemoveObserver(aObserver);
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
|
2000-07-19 03:58:25 +00:00
|
|
|
NS_IMETHOD HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *_retval) {
|
|
|
|
return mInner->HasArcIn(aNode, aArc, _retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, PRBool *_retval) {
|
|
|
|
return mInner->HasArcOut(aSource, aArc, _retval);
|
|
|
|
}
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
|
1999-04-24 02:41:02 +00:00
|
|
|
nsISimpleEnumerator** labels) {
|
1999-01-19 02:42:30 +00:00
|
|
|
return mInner->ArcLabelsIn(node, labels);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
|
1999-04-24 02:41:02 +00:00
|
|
|
nsISimpleEnumerator** labels) {
|
1999-01-19 02:42:30 +00:00
|
|
|
return mInner->ArcLabelsOut(source, labels);
|
|
|
|
}
|
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult) {
|
|
|
|
return mInner->GetAllResources(aResult);
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
1999-03-12 21:28:34 +00:00
|
|
|
NS_IMETHOD GetAllCommands(nsIRDFResource* source,
|
|
|
|
nsIEnumerator/*<nsIRDFResource>*/** commands) {
|
|
|
|
return mInner->GetAllCommands(source, commands);
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
|
1999-06-26 01:09:02 +00:00
|
|
|
NS_IMETHOD GetAllCmds(nsIRDFResource* source,
|
|
|
|
nsISimpleEnumerator/*<nsIRDFResource>*/** commands) {
|
|
|
|
return mInner->GetAllCmds(source, commands);
|
|
|
|
}
|
|
|
|
|
1999-03-12 21:28:34 +00:00
|
|
|
NS_IMETHOD IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|
|
|
nsIRDFResource* aCommand,
|
1999-03-29 19:52:54 +00:00
|
|
|
nsISupportsArray/*<nsIRDFResource>*/* aArguments,
|
|
|
|
PRBool* aResult) {
|
|
|
|
return mInner->IsCommandEnabled(aSources, aCommand, aArguments, aResult);
|
1999-03-12 21:28:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
1999-03-11 10:01:25 +00:00
|
|
|
nsIRDFResource* aCommand,
|
1999-03-12 21:28:34 +00:00
|
|
|
nsISupportsArray/*<nsIRDFResource>*/* aArguments) {
|
1999-01-19 02:42:30 +00:00
|
|
|
// XXX Uh oh, this could cause problems wrt. the "dirty" flag
|
|
|
|
// if it changes the in-memory store's internal state.
|
1999-03-11 10:01:25 +00:00
|
|
|
return mInner->DoCommand(aSources, aCommand, aArguments);
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
|
1999-06-24 00:22:58 +00:00
|
|
|
// nsIRDFRemoteDataSource interface
|
1999-08-24 09:11:48 +00:00
|
|
|
NS_DECL_NSIRDFREMOTEDATASOURCE
|
1999-06-24 00:22:58 +00:00
|
|
|
|
|
|
|
// nsIRDFXMLSink interface
|
1999-08-24 09:11:48 +00:00
|
|
|
NS_DECL_NSIRDFXMLSINK
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
// nsIRDFXMLSource interface
|
1999-08-24 09:11:48 +00:00
|
|
|
NS_DECL_NSIRDFXMLSOURCE
|
1999-01-19 02:42:30 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
// nsIStreamObserver
|
|
|
|
NS_DECL_NSISTREAMOBSERVER
|
|
|
|
|
|
|
|
// nsIStreamListener
|
|
|
|
NS_DECL_NSISTREAMLISTENER
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
// Implementation methods
|
1999-01-21 22:24:32 +00:00
|
|
|
PRBool
|
|
|
|
MakeQName(nsIRDFResource* aResource,
|
|
|
|
nsString& property,
|
|
|
|
nsString& nameSpacePrefix,
|
|
|
|
nsString& nameSpaceURI);
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SerializeAssertion(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aResource,
|
|
|
|
nsIRDFResource* aProperty,
|
|
|
|
nsIRDFNode* aValue);
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SerializeProperty(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aResource,
|
|
|
|
nsIRDFResource* aProperty);
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
PRBool
|
|
|
|
IsContainerProperty(nsIRDFResource* aProperty);
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
nsresult
|
|
|
|
SerializeDescription(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aResource);
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SerializeMember(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aContainer,
|
1999-06-09 08:29:51 +00:00
|
|
|
nsIRDFNode* aMember);
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
SerializeContainer(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aContainer);
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SerializePrologue(nsIOutputStream* aStream);
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SerializeEpilogue(nsIOutputStream* aStream);
|
1999-09-01 00:50:01 +00:00
|
|
|
|
|
|
|
PRBool
|
|
|
|
IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType);
|
1999-01-19 02:42:30 +00:00
|
|
|
};
|
|
|
|
|
1999-04-22 03:16:55 +00:00
|
|
|
PRInt32 RDFXMLDataSourceImpl::gRefCnt = 0;
|
1999-08-06 20:24:29 +00:00
|
|
|
nsIRDFService* RDFXMLDataSourceImpl::gRDFService;
|
1999-06-09 08:29:51 +00:00
|
|
|
nsIRDFContainerUtils* RDFXMLDataSourceImpl::gRDFC;
|
1999-04-22 03:16:55 +00:00
|
|
|
nsIRDFResource* RDFXMLDataSourceImpl::kRDF_instanceOf;
|
|
|
|
nsIRDFResource* RDFXMLDataSourceImpl::kRDF_nextVal;
|
1999-04-27 05:54:18 +00:00
|
|
|
nsIRDFResource* RDFXMLDataSourceImpl::kRDF_Bag;
|
|
|
|
nsIRDFResource* RDFXMLDataSourceImpl::kRDF_Seq;
|
|
|
|
nsIRDFResource* RDFXMLDataSourceImpl::kRDF_Alt;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
//----------------------------------------------------------------------
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
nsresult
|
1999-06-24 00:22:58 +00:00
|
|
|
NS_NewRDFXMLDataSource(nsIRDFDataSource** aResult)
|
1999-01-19 02:42:30 +00:00
|
|
|
{
|
1999-06-09 08:29:51 +00:00
|
|
|
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
|
|
|
if (! aResult)
|
1999-01-19 02:42:30 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
RDFXMLDataSourceImpl* datasource = new RDFXMLDataSourceImpl();
|
|
|
|
if (! datasource)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
rv = datasource->Init();
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
delete datasource;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ADDREF(datasource);
|
|
|
|
*aResult = datasource;
|
1999-01-19 02:42:30 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
|
1999-02-02 07:06:56 +00:00
|
|
|
: mInner(nsnull),
|
1999-01-20 19:56:34 +00:00
|
|
|
mIsWritable(PR_TRUE),
|
1999-01-20 01:42:13 +00:00
|
|
|
mIsDirty(PR_FALSE),
|
2000-01-27 02:24:20 +00:00
|
|
|
mLoadState(eLoadState_Unloaded),
|
1999-06-24 00:22:58 +00:00
|
|
|
mNameSpaces(nsnull),
|
|
|
|
mURLSpec(nsnull)
|
1999-01-19 02:42:30 +00:00
|
|
|
{
|
1999-04-22 03:16:55 +00:00
|
|
|
NS_INIT_REFCNT();
|
1999-10-13 08:00:14 +00:00
|
|
|
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
if (! gLog)
|
|
|
|
gLog = PR_NewLogModule("nsRDFXMLDataSource");
|
|
|
|
#endif
|
1999-06-09 08:29:51 +00:00
|
|
|
}
|
|
|
|
|
1999-04-22 03:16:55 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::Init()
|
|
|
|
{
|
1999-01-19 02:42:30 +00:00
|
|
|
nsresult rv;
|
1999-06-09 08:29:51 +00:00
|
|
|
rv = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID,
|
|
|
|
nsnull,
|
2000-01-11 20:49:15 +00:00
|
|
|
NS_GET_IID(nsIRDFDataSource),
|
1999-06-09 08:29:51 +00:00
|
|
|
(void**) &mInner);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
// Initialize the name space stuff to know about any "standard"
|
|
|
|
// namespaces that we want to look the same in all the RDF/XML we
|
|
|
|
// generate.
|
1999-01-22 06:48:25 +00:00
|
|
|
//
|
|
|
|
// XXX this is a bit of a hack, because technically, the document
|
|
|
|
// should've defined the RDF namespace to be _something_, and we
|
|
|
|
// should just look at _that_ and use it. Oh well.
|
1999-10-02 01:32:38 +00:00
|
|
|
nsIAtom* rdfPrefix = NS_NewAtom("RDF");
|
2000-07-20 20:15:08 +00:00
|
|
|
AddNameSpace(rdfPrefix, NS_ConvertASCIItoUCS2(RDF_NAMESPACE_URI));
|
1999-10-02 01:32:38 +00:00
|
|
|
NS_IF_RELEASE(rdfPrefix);
|
1999-04-22 03:16:55 +00:00
|
|
|
|
|
|
|
if (gRefCnt++ == 0) {
|
1999-08-06 20:24:29 +00:00
|
|
|
rv = nsServiceManager::GetService(kRDFServiceCID,
|
2000-01-11 20:49:15 +00:00
|
|
|
NS_GET_IID(nsIRDFService),
|
1999-08-06 20:24:29 +00:00
|
|
|
NS_REINTERPRET_CAST(nsISupports**, &gRDFService));
|
|
|
|
|
1999-04-22 03:16:55 +00:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
|
1999-06-09 08:29:51 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-04-22 03:16:55 +00:00
|
|
|
|
1999-08-06 20:24:29 +00:00
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_instanceOf);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "nextVal", &kRDF_nextVal);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "Bag", &kRDF_Bag);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "Seq", &kRDF_Seq);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "Alt", &kRDF_Alt);
|
1999-06-09 08:29:51 +00:00
|
|
|
|
|
|
|
rv = nsServiceManager::GetService(kRDFContainerUtilsCID,
|
2000-01-11 20:49:15 +00:00
|
|
|
NS_GET_IID(nsIRDFContainerUtils),
|
1999-06-09 08:29:51 +00:00
|
|
|
(nsISupports**) &gRDFC);
|
|
|
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get container utils");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-04-22 03:16:55 +00:00
|
|
|
}
|
1999-06-09 08:29:51 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void)
|
|
|
|
{
|
1999-05-13 20:53:07 +00:00
|
|
|
nsresult rv;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-08-06 20:24:29 +00:00
|
|
|
// Unregister first so that nobody else tries to get us.
|
|
|
|
rv = gRDFService->UnregisterDataSource(this);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-08-06 20:24:29 +00:00
|
|
|
// Now flush contents
|
|
|
|
rv = Flush();
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
// Release RDF/XML sink observers
|
|
|
|
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
|
|
|
nsIRDFXMLSinkObserver* obs = NS_STATIC_CAST(nsIRDFXMLSinkObserver*, mObservers[i]);
|
|
|
|
NS_RELEASE(obs);
|
|
|
|
}
|
|
|
|
|
1999-08-06 20:24:29 +00:00
|
|
|
if (mURLSpec)
|
|
|
|
PL_strfree(mURLSpec);
|
1999-07-03 04:26:04 +00:00
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
while (mNameSpaces) {
|
|
|
|
NameSpaceMap* doomed = mNameSpaces;
|
|
|
|
mNameSpaces = mNameSpaces->Next;
|
|
|
|
|
1999-03-26 04:42:29 +00:00
|
|
|
NS_IF_RELEASE(doomed->Prefix);
|
1999-01-21 22:24:32 +00:00
|
|
|
delete doomed;
|
|
|
|
}
|
1999-02-02 07:06:56 +00:00
|
|
|
|
|
|
|
NS_RELEASE(mInner);
|
1999-04-22 03:16:55 +00:00
|
|
|
|
|
|
|
if (--gRefCnt == 0) {
|
1999-06-09 08:29:51 +00:00
|
|
|
NS_IF_RELEASE(kRDF_Bag);
|
|
|
|
NS_IF_RELEASE(kRDF_Seq);
|
|
|
|
NS_IF_RELEASE(kRDF_Alt);
|
1999-04-22 03:16:55 +00:00
|
|
|
NS_IF_RELEASE(kRDF_instanceOf);
|
|
|
|
NS_IF_RELEASE(kRDF_nextVal);
|
1999-08-06 20:24:29 +00:00
|
|
|
|
|
|
|
if (gRDFC) {
|
|
|
|
nsServiceManager::ReleaseService(kRDFContainerUtilsCID, gRDFC);
|
|
|
|
gRDFC = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gRDFService) {
|
|
|
|
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
|
|
|
|
gRDFService = nsnull;
|
|
|
|
}
|
1999-04-22 03:16:55 +00:00
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
NS_IMPL_ISUPPORTS6(RDFXMLDataSourceImpl,
|
|
|
|
nsIRDFDataSource,
|
|
|
|
nsIRDFRemoteDataSource,
|
|
|
|
nsIRDFXMLSink,
|
|
|
|
nsIRDFXMLSource,
|
|
|
|
nsIStreamObserver,
|
|
|
|
nsIStreamListener);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
static nsresult
|
1999-06-23 03:29:44 +00:00
|
|
|
rdf_BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
|
1999-01-19 02:42:30 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-01-20 01:42:13 +00:00
|
|
|
// XXX I really hate the way that we're spoon-feeding this stuff
|
|
|
|
// to the parser: it seems like this is something that netlib
|
|
|
|
// should be able to do by itself.
|
2001-02-10 00:16:26 +00:00
|
|
|
|
2001-02-12 03:14:23 +00:00
|
|
|
nsCOMPtr<nsIChannel> channel;
|
1999-08-26 22:45:55 +00:00
|
|
|
// Null LoadGroup ?
|
|
|
|
rv = NS_OpenURI(getter_AddRefs(channel), aURL, nsnull);
|
1999-11-22 20:53:09 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
2001-02-12 03:14:23 +00:00
|
|
|
|
1999-07-02 06:15:00 +00:00
|
|
|
nsIInputStream* in;
|
|
|
|
PRUint32 sourceOffset = 0;
|
2001-02-12 03:14:23 +00:00
|
|
|
rv = channel->OpenInputStream(&in);
|
1999-11-22 20:53:09 +00:00
|
|
|
|
|
|
|
// If we couldn't open the channel, then just return.
|
|
|
|
if (NS_FAILED(rv)) return NS_OK;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-03-27 00:28:08 +00:00
|
|
|
NS_ASSERTION(in != nsnull, "no input stream");
|
|
|
|
if (! in) return NS_ERROR_FAILURE;
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
ProxyStream* proxy = new ProxyStream();
|
|
|
|
if (! proxy)
|
|
|
|
goto done;
|
|
|
|
|
2001-02-12 03:14:23 +00:00
|
|
|
aConsumer->OnStartRequest(channel, nsnull);
|
1999-01-19 02:42:30 +00:00
|
|
|
while (PR_TRUE) {
|
|
|
|
char buf[1024];
|
|
|
|
PRUint32 readCount;
|
|
|
|
|
1999-03-05 22:53:56 +00:00
|
|
|
if (NS_FAILED(rv = in->Read(buf, sizeof(buf), &readCount)))
|
1999-09-09 22:05:05 +00:00
|
|
|
break; // error
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
if (readCount == 0)
|
|
|
|
break; // eof
|
|
|
|
|
|
|
|
proxy->SetBuffer(buf, readCount);
|
1999-05-05 03:09:12 +00:00
|
|
|
|
2001-02-12 03:14:23 +00:00
|
|
|
rv = aConsumer->OnDataAvailable(channel, nsnull, proxy, sourceOffset, readCount);
|
1999-07-02 06:15:00 +00:00
|
|
|
sourceOffset += readCount;
|
1999-06-26 06:36:26 +00:00
|
|
|
if (NS_FAILED(rv))
|
1999-01-19 02:42:30 +00:00
|
|
|
break;
|
|
|
|
}
|
2000-01-28 00:29:42 +00:00
|
|
|
|
2001-02-12 03:14:23 +00:00
|
|
|
aConsumer->OnStopRequest(channel, nsnull, rv, nsnull);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-08-05 20:10:08 +00:00
|
|
|
// don't leak proxy!
|
|
|
|
proxy->Close();
|
|
|
|
delete proxy;
|
|
|
|
proxy = nsnull;
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
done:
|
|
|
|
NS_RELEASE(in);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::GetLoaded(PRBool* _result)
|
|
|
|
{
|
|
|
|
*_result = (mLoadState == eLoadState_Loaded);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::Init(const char* uri)
|
|
|
|
{
|
|
|
|
static const char kFileURIPrefix[] = "file:";
|
|
|
|
static const char kResourceURIPrefix[] = "resource:";
|
|
|
|
|
|
|
|
NS_PRECONDITION(mInner != nsnull, "not initialized");
|
|
|
|
if (! mInner)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-06-26 06:36:26 +00:00
|
|
|
rv = NS_NewURI(getter_AddRefs(mURL), uri);
|
1999-05-05 03:09:12 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-04-10 08:18:20 +00:00
|
|
|
// XXX this is a hack: any "file:" URI is considered writable. All
|
|
|
|
// others are considered read-only.
|
2000-01-14 22:01:56 +00:00
|
|
|
char* realURL;
|
1999-05-05 03:09:12 +00:00
|
|
|
mURL->GetSpec(&realURL);
|
1999-04-10 08:18:20 +00:00
|
|
|
if ((PL_strncmp(realURL, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) &&
|
|
|
|
(PL_strncmp(realURL, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) {
|
|
|
|
mIsWritable = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-06-24 00:22:58 +00:00
|
|
|
// XXX Keep a 'cached' copy of the URL; opening it may cause the
|
|
|
|
// spec to be re-written.
|
|
|
|
if (mURLSpec)
|
|
|
|
PL_strfree(mURLSpec);
|
|
|
|
|
|
|
|
mURLSpec = PL_strdup(realURL);
|
1999-06-26 06:36:26 +00:00
|
|
|
nsCRT::free(realURL);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-08-06 20:24:29 +00:00
|
|
|
rv = gRDFService->RegisterDataSource(this, PR_FALSE);
|
1999-05-05 03:09:12 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
|
1999-06-24 00:22:58 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::GetURI(char* *aURI)
|
|
|
|
{
|
|
|
|
*aURI = nsnull;
|
|
|
|
if (mURLSpec) {
|
|
|
|
// XXX We don't use the mURL, because it might get re-written
|
|
|
|
// when it's actually opened.
|
|
|
|
*aURI = nsXPIDLCString::Copy(mURLSpec);
|
|
|
|
if (! *aURI)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
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).
|
|
|
|
nsresult rv;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
if (IsLoading()) {
|
1999-05-05 03:09:12 +00:00
|
|
|
PRBool hasAssertion = PR_FALSE;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner);
|
|
|
|
if (gcable) {
|
|
|
|
rv = gcable->Mark(aSource, aProperty, aTarget, aTruthValue, &hasAssertion);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
rv = NS_RDF_ASSERTION_ACCEPTED;
|
1999-04-27 21:33:36 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
if (! hasAssertion) {
|
|
|
|
rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
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);
|
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
else if (mIsWritable) {
|
|
|
|
rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
if (rv == NS_RDF_ASSERTION_ACCEPTED)
|
|
|
|
mIsDirty = PR_TRUE;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
return rv;
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
else {
|
1999-04-07 06:29:41 +00:00
|
|
|
return NS_RDF_ASSERTION_REJECTED;
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-05 03:09:12 +00:00
|
|
|
RDFXMLDataSourceImpl::Unassert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
1999-01-19 02:42:30 +00:00
|
|
|
nsIRDFNode* target)
|
|
|
|
{
|
1999-04-07 06:29:41 +00:00
|
|
|
// We don't accept assertions unless we're writable (except in the
|
|
|
|
// case that we're actually _reading_ the datasource in).
|
1999-01-19 02:42:30 +00:00
|
|
|
nsresult rv;
|
1999-09-29 20:25:41 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
if (IsLoading() || mIsWritable) {
|
1999-09-29 20:25:41 +00:00
|
|
|
rv = mInner->Unassert(source, property, target);
|
2000-01-27 02:24:20 +00:00
|
|
|
if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED)
|
1999-01-19 02:42:30 +00:00
|
|
|
mIsDirty = PR_TRUE;
|
|
|
|
}
|
1999-09-29 20:25:41 +00:00
|
|
|
else {
|
|
|
|
rv = NS_RDF_ASSERTION_REJECTED;
|
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-06-24 00:22:58 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::Change(nsIRDFResource* aSource,
|
|
|
|
nsIRDFResource* aProperty,
|
|
|
|
nsIRDFNode* aOldTarget,
|
|
|
|
nsIRDFNode* aNewTarget)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
if (IsLoading() || mIsWritable) {
|
1999-06-24 00:22:58 +00:00
|
|
|
rv = mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED)
|
1999-06-24 00:22:58 +00:00
|
|
|
mIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
1999-09-29 20:25:41 +00:00
|
|
|
rv = NS_RDF_ASSERTION_REJECTED;
|
1999-06-24 00:22:58 +00:00
|
|
|
}
|
1999-09-29 20:25:41 +00:00
|
|
|
|
|
|
|
return rv;
|
1999-06-24 00:22:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::Move(nsIRDFResource* aOldSource,
|
|
|
|
nsIRDFResource* aNewSource,
|
|
|
|
nsIRDFResource* aProperty,
|
|
|
|
nsIRDFNode* aTarget)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
if (IsLoading() || mIsWritable) {
|
1999-06-24 00:22:58 +00:00
|
|
|
rv = mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
|
2000-01-27 02:24:20 +00:00
|
|
|
if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED)
|
1999-06-24 00:22:58 +00:00
|
|
|
mIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
1999-09-29 20:25:41 +00:00
|
|
|
rv = NS_RDF_ASSERTION_REJECTED;
|
1999-06-24 00:22:58 +00:00
|
|
|
}
|
1999-09-29 20:25:41 +00:00
|
|
|
|
|
|
|
return rv;
|
1999-06-24 00:22:58 +00:00
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::Flush(void)
|
|
|
|
{
|
1999-01-20 19:56:34 +00:00
|
|
|
if (!mIsWritable || !mIsDirty)
|
1999-01-19 02:42:30 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
1999-07-03 03:19:28 +00:00
|
|
|
NS_PRECONDITION(mURLSpec != nsnull, "not initialized");
|
|
|
|
if (! mURLSpec)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-10-13 08:00:14 +00:00
|
|
|
PR_LOG(gLog, PR_LOG_ALWAYS,
|
2000-01-28 00:29:42 +00:00
|
|
|
("rdfxml[%p] flush(%s)", this, mURLSpec));
|
1999-10-13 08:00:14 +00:00
|
|
|
|
1999-07-03 03:19:28 +00:00
|
|
|
nsresult rv;
|
1999-01-19 02:42:30 +00:00
|
|
|
|
2000-08-30 00:57:59 +00:00
|
|
|
{
|
|
|
|
// Quick and dirty check to see if we're in XPCOM shutdown. If
|
|
|
|
// we are, we're screwed: it's too late to serialize because
|
|
|
|
// many of the services that we'll need to acquire to properly
|
|
|
|
// write the file will be unaquirable.
|
|
|
|
nsCOMPtr<nsIRDFService> dummy = do_GetService(kRDFServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("unable to Flush() diry datasource during XPCOM shutdown");
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-03 03:19:28 +00:00
|
|
|
// XXX Replace this with channels someday soon...
|
2000-05-16 03:09:34 +00:00
|
|
|
nsFileURL url(mURLSpec, PR_TRUE);
|
1999-02-25 20:58:10 +00:00
|
|
|
nsFileSpec path(url);
|
1999-01-19 02:42:30 +00:00
|
|
|
|
2000-08-07 22:59:40 +00:00
|
|
|
nsOutputFileStream out(path);
|
1999-02-25 20:58:10 +00:00
|
|
|
if (! out.is_open())
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-01-22 22:04:04 +00:00
|
|
|
|
1999-02-25 20:58:10 +00:00
|
|
|
nsCOMPtr<nsIOutputStream> outIStream = out.GetIStream();
|
|
|
|
if (NS_FAILED(rv = Serialize(outIStream)))
|
1999-01-19 02:42:30 +00:00
|
|
|
goto done;
|
|
|
|
|
|
|
|
mIsDirty = PR_FALSE;
|
|
|
|
|
|
|
|
done:
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
1999-01-19 02:42:30 +00:00
|
|
|
// nsIRDFXMLDataSource methods
|
2000-01-27 02:24:20 +00:00
|
|
|
//
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-01-20 01:42:13 +00:00
|
|
|
NS_IMETHODIMP
|
1999-05-05 03:09:12 +00:00
|
|
|
RDFXMLDataSourceImpl::GetReadOnly(PRBool* aIsReadOnly)
|
1999-01-20 01:42:13 +00:00
|
|
|
{
|
1999-05-05 03:09:12 +00:00
|
|
|
*aIsReadOnly = !mIsWritable;
|
1999-01-20 01:42:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
|
1999-01-20 01:42:13 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::SetReadOnly(PRBool aIsReadOnly)
|
|
|
|
{
|
1999-01-20 19:56:34 +00:00
|
|
|
if (mIsWritable && aIsReadOnly)
|
|
|
|
mIsWritable = PR_FALSE;
|
|
|
|
|
1999-01-20 01:42:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
NS_IMETHODIMP
|
1999-06-24 00:22:58 +00:00
|
|
|
RDFXMLDataSourceImpl::Refresh(PRBool aBlocking)
|
1999-05-05 03:09:12 +00:00
|
|
|
{
|
1999-10-13 08:00:14 +00:00
|
|
|
PR_LOG(gLog, PR_LOG_ALWAYS,
|
|
|
|
("rdfxml[%p] refresh(%s) %sblocking", this, mURLSpec, (aBlocking ? "" : "non")));
|
|
|
|
|
1999-09-24 19:52:42 +00:00
|
|
|
// If an asynchronous load is already pending, then just let it do
|
|
|
|
// the honors.
|
2000-01-27 02:24:20 +00:00
|
|
|
if (IsLoading()) {
|
1999-10-13 08:00:14 +00:00
|
|
|
PR_LOG(gLog, PR_LOG_ALWAYS,
|
|
|
|
("rdfxml[%p] refresh(%s) a load was pending", this, mURLSpec));
|
|
|
|
|
1999-09-24 19:52:42 +00:00
|
|
|
if (aBlocking) {
|
|
|
|
NS_WARNING("blocking load requested when async load pending");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-05-05 03:09:12 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRDFContentSink> sink;
|
|
|
|
rv = nsComponentManager::CreateInstance(kRDFContentSinkCID,
|
|
|
|
nsnull,
|
2000-01-11 20:49:15 +00:00
|
|
|
NS_GET_IID(nsIRDFContentSink),
|
1999-05-05 03:09:12 +00:00
|
|
|
getter_AddRefs(sink));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2000-07-26 14:08:05 +00:00
|
|
|
rv = sink->Init(mURL);
|
1999-05-05 03:09:12 +00:00
|
|
|
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));
|
1999-08-10 05:35:09 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-05-05 03:09:12 +00:00
|
|
|
|
2000-07-20 19:49:47 +00:00
|
|
|
nsAutoString charset(NS_LITERAL_STRING("UTF-8"));
|
2000-04-17 17:51:01 +00:00
|
|
|
parser->SetDocumentCharset(charset, kCharsetFromDocTypeDefault);
|
1999-05-05 03:09:12 +00:00
|
|
|
parser->SetContentSink(sink);
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
rv = parser->QueryInterface(NS_GET_IID(nsIStreamListener), getter_AddRefs(mParser));
|
1999-05-05 03:09:12 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = parser->Parse(mURL);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
if (aBlocking) {
|
2000-01-27 02:24:20 +00:00
|
|
|
rv = rdf_BlockingParse(mURL, this);
|
|
|
|
|
2000-01-28 00:29:42 +00:00
|
|
|
mParser = nsnull; // release the parser
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-05-05 03:09:12 +00:00
|
|
|
}
|
|
|
|
else {
|
1999-08-26 22:45:55 +00:00
|
|
|
// Null LoadGroup ?
|
2000-01-27 02:24:20 +00:00
|
|
|
rv = NS_OpenURI(this, nsnull, mURL, nsnull);
|
1999-09-24 19:52:42 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
// So we don't try to issue two asynchronous loads at once.
|
2000-01-27 02:24:20 +00:00
|
|
|
mLoadState = eLoadState_Pending;
|
1999-05-05 03:09:12 +00:00
|
|
|
}
|
|
|
|
|
1999-09-24 19:52:42 +00:00
|
|
|
return NS_OK;
|
1999-05-05 03:09:12 +00:00
|
|
|
}
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::BeginLoad(void)
|
|
|
|
{
|
1999-10-13 08:00:14 +00:00
|
|
|
PR_LOG(gLog, PR_LOG_ALWAYS,
|
|
|
|
("rdfxml[%p] begin-load(%s)", this, mURLSpec));
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
mLoadState = eLoadState_Loading;
|
1999-01-19 02:42:30 +00:00
|
|
|
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
1999-06-24 00:22:58 +00:00
|
|
|
nsIRDFXMLSinkObserver* obs = (nsIRDFXMLSinkObserver*) mObservers[i];
|
1999-01-19 02:42:30 +00:00
|
|
|
obs->OnBeginLoad(this);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::Interrupt(void)
|
|
|
|
{
|
1999-10-13 08:00:14 +00:00
|
|
|
PR_LOG(gLog, PR_LOG_ALWAYS,
|
|
|
|
("rdfxml[%p] interrupt(%s)", this, mURLSpec));
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
1999-06-24 00:22:58 +00:00
|
|
|
nsIRDFXMLSinkObserver* obs = (nsIRDFXMLSinkObserver*) mObservers[i];
|
1999-01-19 02:42:30 +00:00
|
|
|
obs->OnInterrupt(this);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::Resume(void)
|
|
|
|
{
|
1999-10-13 08:00:14 +00:00
|
|
|
PR_LOG(gLog, PR_LOG_ALWAYS,
|
|
|
|
("rdfxml[%p] resume(%s)", this, mURLSpec));
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
1999-06-24 00:22:58 +00:00
|
|
|
nsIRDFXMLSinkObserver* obs = (nsIRDFXMLSinkObserver*) mObservers[i];
|
1999-01-19 02:42:30 +00:00
|
|
|
obs->OnResume(this);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::EndLoad(void)
|
|
|
|
{
|
1999-10-13 08:00:14 +00:00
|
|
|
PR_LOG(gLog, PR_LOG_ALWAYS,
|
|
|
|
("rdfxml[%p] end-load(%s)", this, mURLSpec));
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
mLoadState = eLoadState_Loaded;
|
|
|
|
|
|
|
|
// Clear out any unmarked assertions from the datasource.
|
1999-05-05 03:09:12 +00:00
|
|
|
nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner);
|
|
|
|
if (gcable) {
|
|
|
|
gcable->Sweep();
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
// Notify load observers
|
1999-01-19 02:42:30 +00:00
|
|
|
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
1999-06-24 00:22:58 +00:00
|
|
|
nsIRDFXMLSinkObserver* obs = (nsIRDFXMLSinkObserver*) mObservers[i];
|
1999-05-05 03:09:12 +00:00
|
|
|
obs->OnEndLoad(this);
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RDFXMLDataSourceImpl::AddNameSpace(nsIAtom* aPrefix, const nsString& aURI)
|
|
|
|
{
|
|
|
|
NameSpaceMap* entry;
|
|
|
|
|
|
|
|
// ensure that URIs are unique
|
|
|
|
for (entry = mNameSpaces; entry != nsnull; entry = entry->Next) {
|
|
|
|
if (aURI.Equals(entry->URI))
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// okay, it's a new one: let's add it.
|
|
|
|
entry = new NameSpaceMap;
|
|
|
|
if (! entry)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
1999-03-26 04:42:29 +00:00
|
|
|
NS_IF_ADDREF(aPrefix);
|
1999-01-21 22:24:32 +00:00
|
|
|
entry->Prefix = aPrefix;
|
|
|
|
entry->URI = aURI;
|
|
|
|
entry->Next = mNameSpaces;
|
|
|
|
mNameSpaces = entry;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-01-19 02:42:30 +00:00
|
|
|
|
|
|
|
|
1999-02-01 22:34:51 +00:00
|
|
|
NS_IMETHODIMP
|
1999-06-24 00:22:58 +00:00
|
|
|
RDFXMLDataSourceImpl::AddXMLSinkObserver(nsIRDFXMLSinkObserver* aObserver)
|
1999-02-01 22:34:51 +00:00
|
|
|
{
|
2000-01-27 02:24:20 +00:00
|
|
|
if (! aObserver)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_ADDREF(aObserver);
|
1999-02-01 22:34:51 +00:00
|
|
|
mObservers.AppendElement(aObserver);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-06-24 00:22:58 +00:00
|
|
|
RDFXMLDataSourceImpl::RemoveXMLSinkObserver(nsIRDFXMLSinkObserver* aObserver)
|
1999-02-01 22:34:51 +00:00
|
|
|
{
|
2000-01-27 02:24:20 +00:00
|
|
|
if (! aObserver)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
if (mObservers.RemoveElement(aObserver)) {
|
|
|
|
// RemoveElement() returns PR_TRUE if it was actually there...
|
|
|
|
NS_RELEASE(aObserver);
|
|
|
|
}
|
|
|
|
|
1999-02-01 22:34:51 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// nsIStreamObserver
|
|
|
|
//
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-02-12 03:14:23 +00:00
|
|
|
RDFXMLDataSourceImpl::OnStartRequest(nsIChannel *channel, nsISupports *ctxt)
|
2000-01-27 02:24:20 +00:00
|
|
|
{
|
2001-02-12 03:14:23 +00:00
|
|
|
return mParser->OnStartRequest(channel, ctxt);
|
2000-01-27 02:24:20 +00:00
|
|
|
}
|
1999-02-01 22:34:51 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
NS_IMETHODIMP
|
2001-02-12 03:14:23 +00:00
|
|
|
RDFXMLDataSourceImpl::OnStopRequest(nsIChannel *channel,
|
2000-01-27 02:24:20 +00:00
|
|
|
nsISupports *ctxt,
|
|
|
|
nsresult status,
|
|
|
|
const PRUnichar *errorMsg)
|
|
|
|
{
|
|
|
|
if (NS_FAILED(status)) {
|
2000-01-28 00:29:42 +00:00
|
|
|
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
|
|
|
nsIRDFXMLSinkObserver* obs = (nsIRDFXMLSinkObserver*) mObservers[i];
|
|
|
|
(void) obs->OnError(this, status, errorMsg);
|
|
|
|
}
|
2000-01-27 02:24:20 +00:00
|
|
|
}
|
|
|
|
|
2000-01-27 06:17:13 +00:00
|
|
|
nsresult rv;
|
2001-02-12 03:14:23 +00:00
|
|
|
rv = mParser->OnStopRequest(channel, ctxt, status, errorMsg);
|
2000-01-27 06:17:13 +00:00
|
|
|
|
|
|
|
mParser = nsnull; // release the parser
|
|
|
|
|
|
|
|
return rv;
|
2000-01-27 02:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// nsIStreamListener
|
|
|
|
//
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-02-12 03:14:23 +00:00
|
|
|
RDFXMLDataSourceImpl::OnDataAvailable(nsIChannel *channel,
|
2000-01-27 02:24:20 +00:00
|
|
|
nsISupports *ctxt,
|
|
|
|
nsIInputStream *inStr,
|
|
|
|
PRUint32 sourceOffset,
|
|
|
|
PRUint32 count)
|
|
|
|
{
|
2001-02-12 03:14:23 +00:00
|
|
|
return mParser->OnDataAvailable(channel, ctxt, inStr, sourceOffset, count);
|
2000-01-27 02:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
1999-01-19 02:42:30 +00:00
|
|
|
// nsIRDFXMLSource methods
|
2000-01-27 02:24:20 +00:00
|
|
|
//
|
1999-01-19 02:42:30 +00:00
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
static nsresult
|
|
|
|
rdf_BlockingWrite(nsIOutputStream* stream, const char* buf, PRUint32 size)
|
|
|
|
{
|
|
|
|
PRUint32 written = 0;
|
|
|
|
PRUint32 remaining = size;
|
|
|
|
while (remaining > 0) {
|
|
|
|
nsresult rv;
|
|
|
|
PRUint32 cb;
|
|
|
|
|
1999-03-05 22:53:56 +00:00
|
|
|
if (NS_FAILED(rv = stream->Write(buf + written, remaining, &cb)))
|
1999-01-21 22:24:32 +00:00
|
|
|
return rv;
|
|
|
|
|
|
|
|
written += cb;
|
|
|
|
remaining -= cb;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsresult
|
|
|
|
rdf_BlockingWrite(nsIOutputStream* stream, const nsString& s)
|
|
|
|
{
|
2000-03-18 05:22:42 +00:00
|
|
|
nsresult rv;
|
|
|
|
char* utf8 = s.ToNewUTF8String();
|
2000-03-18 06:24:19 +00:00
|
|
|
if (! utf8)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
// Be sure to grab the UTF-8 encoded string's length, because it
|
|
|
|
// may be longer than the length of the unencoded string.
|
2000-03-18 05:22:42 +00:00
|
|
|
PRInt32 len = PL_strlen(utf8);
|
|
|
|
rv = rdf_BlockingWrite(stream, utf8, len);
|
2000-03-18 06:24:19 +00:00
|
|
|
|
2000-03-18 05:22:42 +00:00
|
|
|
nsCRT::free(utf8);
|
1999-01-21 22:24:32 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This converts a property resource (like
|
|
|
|
// "http://www.w3.org/TR/WD-rdf-syntax#Description") into a property
|
|
|
|
// ("Description"), a namespace prefix ("RDF"), and a namespace URI
|
|
|
|
// ("http://www.w3.org/TR/WD-rdf-syntax#").
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
RDFXMLDataSourceImpl::MakeQName(nsIRDFResource* resource,
|
|
|
|
nsString& property,
|
|
|
|
nsString& nameSpacePrefix,
|
|
|
|
nsString& nameSpaceURI)
|
|
|
|
{
|
1999-03-29 19:52:54 +00:00
|
|
|
nsXPIDLCString s;
|
|
|
|
resource->GetValue(getter_Copies(s));
|
2000-07-20 19:49:47 +00:00
|
|
|
nsAutoString uri = NS_ConvertUTF8toUCS2(s);
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
for (NameSpaceMap* entry = mNameSpaces; entry != nsnull; entry = entry->Next) {
|
|
|
|
if (uri.Find(entry->URI) == 0) {
|
|
|
|
nameSpaceURI = entry->URI;
|
1999-03-26 04:42:29 +00:00
|
|
|
if (entry->Prefix) {
|
|
|
|
entry->Prefix->ToString(nameSpacePrefix);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nameSpacePrefix.Truncate();
|
|
|
|
}
|
1999-01-21 22:24:32 +00:00
|
|
|
uri.Right(property, uri.Length() - nameSpaceURI.Length());
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-05-16 05:58:48 +00:00
|
|
|
// Okay, so we don't have it in our map. Try to make one up. This
|
|
|
|
// is very bogus.
|
1999-07-19 03:29:56 +00:00
|
|
|
PRInt32 i = uri.RFindChar('#'); // first try a '#'
|
1999-06-24 00:22:58 +00:00
|
|
|
if (i == -1) {
|
1999-07-19 03:29:56 +00:00
|
|
|
i = uri.RFindChar('/');
|
1999-06-24 00:22:58 +00:00
|
|
|
if (i == -1) {
|
1999-01-21 22:24:32 +00:00
|
|
|
// Okay, just punt and assume there is _no_ namespace on
|
|
|
|
// this thing...
|
|
|
|
nameSpaceURI.Truncate();
|
|
|
|
nameSpacePrefix.Truncate();
|
|
|
|
property = uri;
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Take whatever is to the right of the '#' and call it the
|
|
|
|
// property.
|
|
|
|
property.Truncate();
|
1999-07-06 23:36:44 +00:00
|
|
|
uri.Right(property, uri.Length() - (i + 1));
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
// Truncate the namespace URI down to the string up to and
|
|
|
|
// including the '#'.
|
|
|
|
nameSpaceURI = uri;
|
1999-06-24 00:22:58 +00:00
|
|
|
nameSpaceURI.Truncate(i + 1);
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
// Just generate a random prefix
|
|
|
|
static PRInt32 gPrefixID = 0;
|
2000-07-20 19:49:47 +00:00
|
|
|
nameSpacePrefix = NS_LITERAL_STRING("NS");
|
2000-04-17 14:30:23 +00:00
|
|
|
nameSpacePrefix.AppendInt(++gPrefixID, 10);
|
1999-01-21 22:24:32 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
|
|
|
|
PRBool
|
|
|
|
RDFXMLDataSourceImpl::IsContainerProperty(nsIRDFResource* aProperty)
|
|
|
|
{
|
|
|
|
// Return `true' if the property is an internal property related
|
|
|
|
// to being a container.
|
|
|
|
if (aProperty == kRDF_instanceOf)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
if (aProperty == kRDF_nextVal)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
PRBool isOrdinal = PR_FALSE;
|
|
|
|
gRDFC->IsOrdinalProperty(aProperty, &isOrdinal);
|
|
|
|
if (isOrdinal)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
// convert '<' and '>' into '<' and '>', respectively.
|
|
|
|
static void
|
|
|
|
rdf_EscapeAngleBrackets(nsString& s)
|
|
|
|
{
|
1999-06-24 00:22:58 +00:00
|
|
|
PRInt32 i;
|
1999-07-26 00:47:36 +00:00
|
|
|
while ((i = s.FindChar('<')) != -1) {
|
1999-06-24 00:22:58 +00:00
|
|
|
s.SetCharAt('&', i);
|
2000-07-20 19:49:47 +00:00
|
|
|
s.Insert(NS_LITERAL_STRING("lt;"), i + 1);
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
1999-07-26 00:47:36 +00:00
|
|
|
while ((i = s.FindChar('>')) != -1) {
|
1999-06-24 00:22:58 +00:00
|
|
|
s.SetCharAt('&', i);
|
2000-07-20 19:49:47 +00:00
|
|
|
s.Insert(NS_LITERAL_STRING("gt;"), i + 1);
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rdf_EscapeAmpersands(nsString& s)
|
|
|
|
{
|
1999-06-24 00:22:58 +00:00
|
|
|
PRInt32 i = 0;
|
1999-07-26 00:47:36 +00:00
|
|
|
while ((i = s.FindChar('&', PR_FALSE,i)) != -1) {
|
1999-06-24 00:22:58 +00:00
|
|
|
s.SetCharAt('&', i);
|
2000-07-20 19:49:47 +00:00
|
|
|
s.Insert(NS_LITERAL_STRING("amp;"), i + 1);
|
1999-06-24 00:22:58 +00:00
|
|
|
i += 4;
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-05-16 05:58:48 +00:00
|
|
|
static void
|
|
|
|
rdf_EscapeQuotes(nsString& s)
|
|
|
|
{
|
|
|
|
PRInt32 i = 0;
|
|
|
|
while ((i = s.FindChar('"', PR_FALSE, i)) != -1) {
|
|
|
|
s.SetCharAt('&', i);
|
2000-07-20 19:49:47 +00:00
|
|
|
s.Insert(NS_LITERAL_STRING("quot;"), i + 1);
|
2000-05-16 05:58:48 +00:00
|
|
|
i += 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rdf_EscapeAttributeValue(nsString& s)
|
|
|
|
{
|
|
|
|
rdf_EscapeAmpersands(s);
|
|
|
|
rdf_EscapeAngleBrackets(s);
|
|
|
|
rdf_EscapeQuotes(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::SerializeAssertion(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aResource,
|
|
|
|
nsIRDFResource* aProperty,
|
|
|
|
nsIRDFNode* aValue)
|
|
|
|
{
|
|
|
|
nsAutoString property, nameSpacePrefix, nameSpaceURI;
|
|
|
|
nsAutoString tag;
|
|
|
|
|
|
|
|
PRBool wasDefinedAtGlobalScope =
|
|
|
|
MakeQName(aProperty, property, nameSpacePrefix, nameSpaceURI);
|
|
|
|
|
|
|
|
if (nameSpacePrefix.Length()) {
|
|
|
|
tag.Append(nameSpacePrefix);
|
2000-04-17 14:30:23 +00:00
|
|
|
tag.AppendWithConversion(':');
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
tag.Append(property);
|
|
|
|
|
|
|
|
rdf_BlockingWrite(aStream, " <", 5);
|
|
|
|
rdf_BlockingWrite(aStream, tag);
|
|
|
|
|
|
|
|
if (!wasDefinedAtGlobalScope && nameSpacePrefix.Length()) {
|
|
|
|
rdf_BlockingWrite(aStream, " xmlns:", 7);
|
|
|
|
rdf_BlockingWrite(aStream, nameSpacePrefix);
|
|
|
|
rdf_BlockingWrite(aStream, "=\"", 2);
|
|
|
|
rdf_BlockingWrite(aStream, nameSpaceURI);
|
|
|
|
rdf_BlockingWrite(aStream, "\"", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIRDFResource* resource;
|
|
|
|
nsIRDFLiteral* literal;
|
|
|
|
|
2000-01-11 20:49:15 +00:00
|
|
|
if (NS_SUCCEEDED(aValue->QueryInterface(NS_GET_IID(nsIRDFResource), (void**) &resource))) {
|
1999-03-29 19:52:54 +00:00
|
|
|
nsXPIDLCString s;
|
|
|
|
resource->GetValue(getter_Copies(s));
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-03-29 19:52:54 +00:00
|
|
|
nsXPIDLCString docURI;
|
1999-01-22 06:48:25 +00:00
|
|
|
|
2000-07-20 19:49:47 +00:00
|
|
|
nsAutoString uri = NS_ConvertUTF8toUCS2(s);
|
|
|
|
rdf_MakeRelativeRef(NS_ConvertUTF8toUCS2(mURLSpec), uri);
|
2000-05-16 05:58:48 +00:00
|
|
|
rdf_EscapeAttributeValue(uri);
|
1999-01-26 01:24:34 +00:00
|
|
|
|
1999-04-21 00:09:41 +00:00
|
|
|
static const char kRDFResource1[] = " resource=\"";
|
1999-01-26 01:24:34 +00:00
|
|
|
static const char kRDFResource2[] = "\"/>\n";
|
|
|
|
rdf_BlockingWrite(aStream, kRDFResource1, sizeof(kRDFResource1) - 1);
|
|
|
|
rdf_BlockingWrite(aStream, uri);
|
|
|
|
rdf_BlockingWrite(aStream, kRDFResource2, sizeof(kRDFResource2) - 1);
|
1999-01-22 06:48:25 +00:00
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
NS_RELEASE(resource);
|
|
|
|
}
|
2000-01-11 20:49:15 +00:00
|
|
|
else if (NS_SUCCEEDED(aValue->QueryInterface(NS_GET_IID(nsIRDFLiteral), (void**) &literal))) {
|
1999-03-29 19:52:54 +00:00
|
|
|
nsXPIDLString value;
|
|
|
|
literal->GetValue(getter_Copies(value));
|
|
|
|
nsAutoString s((const PRUnichar*) value);
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
rdf_EscapeAmpersands(s); // do these first!
|
|
|
|
rdf_EscapeAngleBrackets(s);
|
|
|
|
|
1999-01-22 06:48:25 +00:00
|
|
|
rdf_BlockingWrite(aStream, ">", 1);
|
1999-01-21 22:24:32 +00:00
|
|
|
rdf_BlockingWrite(aStream, s);
|
1999-01-22 06:48:25 +00:00
|
|
|
rdf_BlockingWrite(aStream, "</", 2);
|
|
|
|
rdf_BlockingWrite(aStream, tag);
|
|
|
|
rdf_BlockingWrite(aStream, ">\n", 2);
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
NS_RELEASE(literal);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// XXX it doesn't support nsIRDFResource _or_ nsIRDFLiteral???
|
2000-08-30 00:57:59 +00:00
|
|
|
// We should serialize nsIRDFInt, nsIRDFDate, etc...
|
|
|
|
NS_ERROR("not an nsIRDFResource or nsIRDFLiteral?");
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::SerializeProperty(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aResource,
|
|
|
|
nsIRDFResource* aProperty)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
nsCOMPtr<nsISimpleEnumerator> assertions;
|
1999-03-30 02:30:16 +00:00
|
|
|
if (NS_FAILED(rv = mInner->GetTargets(aResource, aProperty, PR_TRUE, getter_AddRefs(assertions))))
|
1999-01-21 22:24:32 +00:00
|
|
|
return rv;
|
|
|
|
|
1999-03-30 02:30:16 +00:00
|
|
|
while (1) {
|
1999-04-24 02:41:02 +00:00
|
|
|
PRBool hasMore;
|
|
|
|
rv = assertions->HasMoreElements(&hasMore);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-03-30 02:30:16 +00:00
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
if (! hasMore)
|
1999-03-30 02:30:16 +00:00
|
|
|
break;
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
nsIRDFNode* value;
|
1999-04-24 02:41:02 +00:00
|
|
|
rv = assertions->GetNext((nsISupports**) &value);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
rv = SerializeAssertion(aStream, aResource, aProperty, value);
|
|
|
|
NS_RELEASE(value);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-03-30 02:30:16 +00:00
|
|
|
return NS_OK;
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::SerializeDescription(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aResource)
|
|
|
|
{
|
2000-05-16 05:58:48 +00:00
|
|
|
static const char kRDFDescriptionAbout[] = " <RDF:Description about=\"";
|
|
|
|
static const char kRDFDescriptionID[] = " <RDF:Description ID=\"";
|
1999-01-21 22:24:32 +00:00
|
|
|
static const char kRDFDescription2[] = "\">\n";
|
|
|
|
static const char kRDFDescription3[] = " </RDF:Description>\n";
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// XXX Look for an "RDF:type" property: if one exists, then output
|
|
|
|
// as a "typed node" instead of the more verbose "RDF:Description
|
1999-04-21 00:09:41 +00:00
|
|
|
// type='...'".
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-03-29 19:52:54 +00:00
|
|
|
nsXPIDLCString s;
|
|
|
|
rv = aResource->GetValue(getter_Copies(s));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
2000-07-20 19:49:47 +00:00
|
|
|
nsAutoString uri = NS_ConvertUTF8toUCS2(s);
|
|
|
|
rdf_MakeRelativeRef(NS_ConvertUTF8toUCS2(mURLSpec), uri);
|
2000-05-16 05:58:48 +00:00
|
|
|
rdf_EscapeAttributeValue(uri);
|
|
|
|
|
|
|
|
if (uri[0] == PRUnichar('#')) {
|
|
|
|
uri.Cut(0, 1);
|
|
|
|
rdf_BlockingWrite(aStream, kRDFDescriptionID, sizeof(kRDFDescriptionID) - 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rdf_BlockingWrite(aStream, kRDFDescriptionAbout, sizeof(kRDFDescriptionAbout) - 1);
|
|
|
|
}
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-01-26 01:24:34 +00:00
|
|
|
rdf_BlockingWrite(aStream, uri);
|
1999-01-21 22:24:32 +00:00
|
|
|
rdf_BlockingWrite(aStream, kRDFDescription2, sizeof(kRDFDescription2) - 1);
|
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
nsCOMPtr<nsISimpleEnumerator> arcs;
|
2000-08-30 00:57:59 +00:00
|
|
|
nsCOMPtr<nsISupportsArray> array;
|
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
rv = mInner->ArcLabelsOut(aResource, getter_AddRefs(arcs));
|
2000-08-30 00:57:59 +00:00
|
|
|
if (NS_FAILED(rv)) goto done;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
2000-03-18 05:28:53 +00:00
|
|
|
rv = NS_NewISupportsArray(getter_AddRefs(array));
|
2000-08-30 00:57:59 +00:00
|
|
|
if (NS_FAILED(rv)) goto done;
|
2000-03-18 05:28:53 +00:00
|
|
|
|
1999-03-30 02:30:16 +00:00
|
|
|
while (1) {
|
1999-04-24 02:41:02 +00:00
|
|
|
PRBool hasMore;
|
|
|
|
rv = arcs->HasMoreElements(&hasMore);
|
2000-08-30 00:57:59 +00:00
|
|
|
if (NS_FAILED(rv)) break;
|
1999-03-30 02:30:16 +00:00
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
if (! hasMore)
|
1999-03-30 02:30:16 +00:00
|
|
|
break;
|
|
|
|
|
2000-04-18 04:40:56 +00:00
|
|
|
nsCOMPtr<nsISupports> isupports;
|
|
|
|
rv = arcs->GetNext(getter_AddRefs(isupports));
|
1999-04-24 02:41:02 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
2000-04-18 04:40:56 +00:00
|
|
|
nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
|
|
|
|
NS_ASSERTION(property != nsnull, "not an nsIRDFResource!");
|
|
|
|
if (! property)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// have we already seen this resource? If so, don't write it out again
|
|
|
|
if (array->IndexOf(property) >= 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
array->AppendElement(property);
|
2000-03-18 05:28:53 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
if (! IsContainerProperty(property)) {
|
|
|
|
// Ignore properties that pertain to containers; we may be
|
|
|
|
// called from SerializeContainer() if the container
|
|
|
|
// resource has been assigned non-container properties.
|
|
|
|
rv = SerializeProperty(aStream, aResource, property);
|
|
|
|
}
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-08-30 00:57:59 +00:00
|
|
|
rv = NS_OK;
|
|
|
|
|
|
|
|
done:
|
1999-01-21 22:24:32 +00:00
|
|
|
rdf_BlockingWrite(aStream, kRDFDescription3, sizeof(kRDFDescription3) - 1);
|
2000-08-30 00:57:59 +00:00
|
|
|
return rv;
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::SerializeMember(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aContainer,
|
1999-06-09 08:29:51 +00:00
|
|
|
nsIRDFNode* aMember)
|
1999-01-21 22:24:32 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
// If it's a resource, then output a "<RDF:li resource=... />"
|
|
|
|
// tag, because we'll be dumping the resource separately. (We
|
|
|
|
// iterate thru all the resources in the datasource,
|
|
|
|
// remember?) Otherwise, output the literal value.
|
1999-03-30 02:30:16 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
nsIRDFResource* resource = nsnull;
|
|
|
|
nsIRDFLiteral* literal = nsnull;
|
1999-03-30 02:30:16 +00:00
|
|
|
|
2000-01-11 20:49:15 +00:00
|
|
|
if (NS_SUCCEEDED(rv = aMember->QueryInterface(NS_GET_IID(nsIRDFResource), (void**) &resource))) {
|
1999-06-09 08:29:51 +00:00
|
|
|
nsXPIDLCString s;
|
|
|
|
if (NS_SUCCEEDED(rv = resource->GetValue( getter_Copies(s) ))) {
|
1999-04-21 00:09:41 +00:00
|
|
|
static const char kRDFLIResource1[] = " <RDF:li resource=\"";
|
1999-01-26 01:24:34 +00:00
|
|
|
static const char kRDFLIResource2[] = "\"/>\n";
|
|
|
|
|
2000-07-20 19:49:47 +00:00
|
|
|
nsAutoString uri = NS_ConvertUTF8toUCS2(s);
|
|
|
|
rdf_MakeRelativeRef(NS_ConvertUTF8toUCS2(mURLSpec), uri);
|
2000-05-16 05:58:48 +00:00
|
|
|
rdf_EscapeAttributeValue(uri);
|
1999-01-26 01:24:34 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
rdf_BlockingWrite(aStream, kRDFLIResource1, sizeof(kRDFLIResource1) - 1);
|
|
|
|
rdf_BlockingWrite(aStream, uri);
|
|
|
|
rdf_BlockingWrite(aStream, kRDFLIResource2, sizeof(kRDFLIResource2) - 1);
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
1999-06-09 08:29:51 +00:00
|
|
|
NS_RELEASE(resource);
|
|
|
|
}
|
2000-01-11 20:49:15 +00:00
|
|
|
else if (NS_SUCCEEDED(rv = aMember->QueryInterface(NS_GET_IID(nsIRDFLiteral), (void**) &literal))) {
|
1999-06-09 08:29:51 +00:00
|
|
|
nsXPIDLString value;
|
|
|
|
if (NS_SUCCEEDED(rv = literal->GetValue( getter_Copies(value) ))) {
|
1999-01-26 01:24:34 +00:00
|
|
|
static const char kRDFLILiteral1[] = " <RDF:li>";
|
|
|
|
static const char kRDFLILiteral2[] = "</RDF:li>\n";
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
rdf_BlockingWrite(aStream, kRDFLILiteral1, sizeof(kRDFLILiteral1) - 1);
|
2000-10-20 00:55:55 +00:00
|
|
|
|
|
|
|
nsAutoString s(value);
|
|
|
|
rdf_EscapeAmpersands(s); // do these first!
|
|
|
|
rdf_EscapeAngleBrackets(s);
|
|
|
|
|
|
|
|
rdf_BlockingWrite(aStream, s);
|
1999-06-09 08:29:51 +00:00
|
|
|
rdf_BlockingWrite(aStream, kRDFLILiteral2, sizeof(kRDFLILiteral2) - 1);
|
|
|
|
}
|
|
|
|
NS_RELEASE(literal);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_ASSERTION(PR_FALSE, "uhh -- it's not a literal or a resource?");
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
1999-03-30 02:30:16 +00:00
|
|
|
return NS_OK;
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::SerializeContainer(nsIOutputStream* aStream,
|
|
|
|
nsIRDFResource* aContainer)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2000-07-21 19:59:39 +00:00
|
|
|
nsAutoString tag;
|
1999-01-22 06:48:25 +00:00
|
|
|
|
|
|
|
// Decide if it's a sequence, bag, or alternation, and print the
|
|
|
|
// appropriate tag-open sequence
|
|
|
|
|
1999-09-01 00:50:01 +00:00
|
|
|
if (IsA(mInner, aContainer, kRDF_Bag)) {
|
2000-07-20 20:15:08 +00:00
|
|
|
tag = NS_LITERAL_STRING("RDF:Bag");
|
1999-01-22 06:48:25 +00:00
|
|
|
}
|
1999-09-01 00:50:01 +00:00
|
|
|
else if (IsA(mInner, aContainer, kRDF_Seq)) {
|
2000-07-20 20:15:08 +00:00
|
|
|
tag = NS_LITERAL_STRING("RDF:Seq");
|
1999-01-22 06:48:25 +00:00
|
|
|
}
|
1999-09-01 00:50:01 +00:00
|
|
|
else if (IsA(mInner, aContainer, kRDF_Alt)) {
|
2000-07-20 20:15:08 +00:00
|
|
|
tag = NS_LITERAL_STRING("RDF:Alt");
|
1999-01-22 06:48:25 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_ASSERTION(PR_FALSE, "huh? this is _not_ a container.");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdf_BlockingWrite(aStream, " <", 3);
|
2000-07-20 19:49:47 +00:00
|
|
|
rdf_BlockingWrite(aStream, tag);
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
|
1999-01-22 06:48:25 +00:00
|
|
|
// Unfortunately, we always need to print out the identity of the
|
|
|
|
// resource, even if was constructed "anonymously". We need to do
|
|
|
|
// this because we never really know who else might be referring
|
|
|
|
// to it...
|
|
|
|
|
1999-03-29 19:52:54 +00:00
|
|
|
nsXPIDLCString s;
|
|
|
|
if (NS_SUCCEEDED(aContainer->GetValue( getter_Copies(s) ))) {
|
2000-07-20 19:49:47 +00:00
|
|
|
nsAutoString uri = NS_ConvertUTF8toUCS2(s);
|
|
|
|
rdf_MakeRelativeRef(NS_ConvertUTF8toUCS2(mURLSpec), uri);
|
1999-06-20 00:19:23 +00:00
|
|
|
|
2000-05-16 05:58:48 +00:00
|
|
|
rdf_EscapeAttributeValue(uri);
|
1999-06-20 00:19:23 +00:00
|
|
|
|
|
|
|
if (uri.First() == PRUnichar('#')) {
|
|
|
|
// Okay, it's actually identified as an element in the
|
|
|
|
// current document, not trying to decorate some absolute
|
|
|
|
// URI. We can use the 'ID=' attribute...
|
|
|
|
static const char kIDEquals[] = " ID=\"";
|
|
|
|
|
|
|
|
uri.Cut(0, 1); // chop the '#'
|
|
|
|
rdf_BlockingWrite(aStream, kIDEquals, sizeof(kIDEquals) - 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// We need to cheat and spit out an illegal 'about=' on
|
|
|
|
// the sequence.
|
|
|
|
static const char kAboutEquals[] = " about=\"";
|
|
|
|
rdf_BlockingWrite(aStream, kAboutEquals, sizeof(kAboutEquals) - 1);
|
|
|
|
}
|
|
|
|
|
1999-01-22 06:48:25 +00:00
|
|
|
rdf_BlockingWrite(aStream, uri);
|
|
|
|
rdf_BlockingWrite(aStream, "\"", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
rdf_BlockingWrite(aStream, ">\n", 2);
|
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
// First iterate through each of the ordinal elements (the RDF/XML
|
|
|
|
// syntax doesn't allow us to place properties on RDF container
|
|
|
|
// elements).
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> elements;
|
|
|
|
rv = NS_NewContainerEnumerator(mInner, aContainer, getter_AddRefs(elements));
|
|
|
|
|
2000-08-30 00:57:59 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
while (1) {
|
|
|
|
PRBool hasMore;
|
|
|
|
rv = elements->HasMoreElements(&hasMore);
|
|
|
|
if (NS_FAILED(rv)) break;
|
1999-06-09 08:29:51 +00:00
|
|
|
|
2000-08-30 00:57:59 +00:00
|
|
|
if (! hasMore)
|
|
|
|
break;
|
1999-06-09 08:29:51 +00:00
|
|
|
|
2000-08-30 00:57:59 +00:00
|
|
|
nsCOMPtr<nsISupports> isupports;
|
|
|
|
elements->GetNext(getter_AddRefs(isupports));
|
1999-06-09 08:29:51 +00:00
|
|
|
|
2000-08-30 00:57:59 +00:00
|
|
|
nsCOMPtr<nsIRDFNode> element = do_QueryInterface(isupports);
|
|
|
|
NS_ASSERTION(element != nsnull, "not an nsIRDFNode");
|
|
|
|
if (! element)
|
|
|
|
continue;
|
1999-06-09 08:29:51 +00:00
|
|
|
|
2000-08-30 00:57:59 +00:00
|
|
|
SerializeMember(aStream, aContainer, element);
|
|
|
|
}
|
1999-06-09 08:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// close the container tag
|
|
|
|
rdf_BlockingWrite(aStream, " </", 4);
|
2000-07-20 19:49:47 +00:00
|
|
|
rdf_BlockingWrite(aStream, tag);
|
1999-06-09 08:29:51 +00:00
|
|
|
rdf_BlockingWrite(aStream, ">\n", 2);
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
// Now, we iterate through _all_ of the arcs, in case someone has
|
|
|
|
// applied properties to the bag itself. These'll be placed in a
|
|
|
|
// separate RDF:Description element.
|
1999-04-24 02:41:02 +00:00
|
|
|
nsCOMPtr<nsISimpleEnumerator> arcs;
|
2000-08-30 00:57:59 +00:00
|
|
|
mInner->ArcLabelsOut(aContainer, getter_AddRefs(arcs));
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-06-09 08:29:51 +00:00
|
|
|
PRBool wroteDescription = PR_FALSE;
|
|
|
|
while (! wroteDescription) {
|
2000-08-30 00:57:59 +00:00
|
|
|
PRBool hasMore = PR_FALSE;
|
1999-04-24 02:41:02 +00:00
|
|
|
rv = arcs->HasMoreElements(&hasMore);
|
2000-08-30 00:57:59 +00:00
|
|
|
if (NS_FAILED(rv)) break;
|
1999-03-30 02:30:16 +00:00
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
if (! hasMore)
|
1999-03-30 02:30:16 +00:00
|
|
|
break;
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
nsIRDFResource* property;
|
1999-04-24 02:41:02 +00:00
|
|
|
rv = arcs->GetNext((nsISupports**) &property);
|
2000-08-30 00:57:59 +00:00
|
|
|
if (NS_FAILED(rv)) break;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
// If it's a membership property, then output a "LI"
|
|
|
|
// tag. Otherwise, output a property.
|
1999-06-09 08:29:51 +00:00
|
|
|
if (! IsContainerProperty(property)) {
|
|
|
|
rv = SerializeDescription(aStream, aContainer);
|
|
|
|
wroteDescription = PR_TRUE;
|
1999-01-22 06:48:25 +00:00
|
|
|
}
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
NS_RELEASE(property);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-03-30 02:30:16 +00:00
|
|
|
return NS_OK;
|
1999-01-21 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::SerializePrologue(nsIOutputStream* aStream)
|
|
|
|
{
|
|
|
|
static const char kXMLVersion[] = "<?xml version=\"1.0\"?>\n";
|
|
|
|
static const char kOpenRDF[] = "<RDF:RDF";
|
1999-04-01 05:17:05 +00:00
|
|
|
static const char kXMLNS[] = "\n xmlns";
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
rdf_BlockingWrite(aStream, kXMLVersion, sizeof(kXMLVersion) - 1);
|
|
|
|
|
|
|
|
// global name space declarations
|
|
|
|
rdf_BlockingWrite(aStream, kOpenRDF, sizeof(kOpenRDF) - 1);
|
|
|
|
for (NameSpaceMap* entry = mNameSpaces; entry != nsnull; entry = entry->Next) {
|
|
|
|
rdf_BlockingWrite(aStream, kXMLNS, sizeof(kXMLNS) - 1);
|
|
|
|
|
1999-04-01 05:17:05 +00:00
|
|
|
if (entry->Prefix) {
|
|
|
|
rdf_BlockingWrite(aStream, ":", 1);
|
|
|
|
nsAutoString prefix;
|
|
|
|
entry->Prefix->ToString(prefix);
|
|
|
|
rdf_BlockingWrite(aStream, prefix);
|
|
|
|
}
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
rdf_BlockingWrite(aStream, "=\"", 2);
|
|
|
|
rdf_BlockingWrite(aStream, entry->URI);
|
|
|
|
rdf_BlockingWrite(aStream, "\"", 1);
|
|
|
|
}
|
|
|
|
rdf_BlockingWrite(aStream, ">\n", 2);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
RDFXMLDataSourceImpl::SerializeEpilogue(nsIOutputStream* aStream)
|
|
|
|
{
|
2000-08-19 22:46:00 +00:00
|
|
|
// can't use |NS_LITERAL_STRING| here until |rdf_BlockingWrite| is fixed to accept readables
|
|
|
|
rdf_BlockingWrite(aStream, NS_ConvertASCIItoUCS2("</RDF:RDF>\n"));
|
1999-01-21 22:24:32 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-01-19 02:42:30 +00:00
|
|
|
NS_IMETHODIMP
|
1999-01-21 22:24:32 +00:00
|
|
|
RDFXMLDataSourceImpl::Serialize(nsIOutputStream* aStream)
|
1999-01-19 02:42:30 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
1999-04-24 02:41:02 +00:00
|
|
|
nsCOMPtr<nsISimpleEnumerator> resources;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-03-30 02:30:16 +00:00
|
|
|
rv = mInner->GetAllResources(getter_AddRefs(resources));
|
1999-04-24 02:41:02 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-03-30 02:30:16 +00:00
|
|
|
rv = SerializePrologue(aStream);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
while (1) {
|
1999-04-24 02:41:02 +00:00
|
|
|
PRBool hasMore;
|
|
|
|
rv = resources->HasMoreElements(&hasMore);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-03-30 02:30:16 +00:00
|
|
|
|
1999-04-24 02:41:02 +00:00
|
|
|
if (! hasMore)
|
1999-03-30 02:30:16 +00:00
|
|
|
break;
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
nsIRDFResource* resource;
|
1999-04-24 02:41:02 +00:00
|
|
|
rv = resources->GetNext((nsISupports**) &resource);
|
|
|
|
if (NS_FAILED(rv))
|
1999-01-21 22:24:32 +00:00
|
|
|
break;
|
|
|
|
|
1999-09-01 00:50:01 +00:00
|
|
|
if (IsA(mInner, resource, kRDF_Bag) ||
|
|
|
|
IsA(mInner, resource, kRDF_Seq) ||
|
|
|
|
IsA(mInner, resource, kRDF_Alt)) {
|
1999-01-21 22:24:32 +00:00
|
|
|
rv = SerializeContainer(aStream, resource);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rv = SerializeDescription(aStream, resource);
|
|
|
|
}
|
|
|
|
NS_RELEASE(resource);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
1999-01-19 02:42:30 +00:00
|
|
|
}
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
rv = SerializeEpilogue(aStream);
|
1999-01-19 02:42:30 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
|
1999-09-01 00:50:01 +00:00
|
|
|
PRBool
|
|
|
|
RDFXMLDataSourceImpl::IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
PRBool result;
|
|
|
|
rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, aType, PR_TRUE, &result);
|
|
|
|
if (NS_FAILED(rv)) return PR_FALSE;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
1999-09-29 20:25:41 +00:00
|
|
|
|
2000-01-27 02:24:20 +00:00
|
|
|
|