bug 259119, rdf/xml serializer needs to be less memory consuming, first steps of the new APIs, r=bsmedberg, sr=shaver, a=bsmedberg

This commit is contained in:
axel%pike.org 2005-06-24 07:49:44 +00:00
parent b5a19bd671
commit 39c3c8adf5
16 changed files with 1014 additions and 179 deletions

View File

@ -46,6 +46,9 @@ MODULE = rdf
GRE_MODULE = 1
XPIDLSRCS = \
rdfIDataSource.idl \
rdfITripleVisitor.idl \
rdfISerializer.idl \
nsIRDFCompositeDataSource.idl \
nsIRDFContainer.idl \
nsIRDFContainerUtils.idl \

View File

@ -0,0 +1,71 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <bsmedberg@covad.net>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface rdfITripleVisitor;
/**
* Interface used in RDF to describe data sources.
*
* @status PLASMA
*/
[scriptable, uuid(ebce86bd-1568-4a34-a808-9ccf9cde8087)]
interface rdfIDataSource : nsISupports
{
/**
* Visit all the subject resources in the datasource. The order is
* intederminate and may change from one invocation to the next.
* The subjects will be in the aSubject argument in calls into
* aVisitor, aPredicate and aObject will be null.
* @note Implementations may throw NS_ERROR_NOT_IMPLEMENTED for
* this method, but in this case RDF serializations of this
* datasource will not be possible.
*/
void visitAllSubjects(in rdfITripleVisitor aVisitor);
/**
* Visit all the triples in the datasource. The order is
* intederminate and may change from one invocation to the next.
* @note Implementations may throw NS_ERROR_NOT_IMPLEMENTED for
* this method, but in this case RDF serializations of this
* datasource will not be possible.
*/
void visitAllTriples(in rdfITripleVisitor aVisitor);
};

View File

@ -0,0 +1,63 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Axel Hecht <axel@pike.org>.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface rdfIDataSource;
interface nsIOutputStream;
/**
* Interface used to serialize RDF.
*
* @status PLASMA
*/
[scriptable, uuid(f0edfcdd-8bca-4d32-9226-7421001396a4)]
interface rdfISerializer : nsISupports
{
/**
* Synchronously serialize the given datasource to the outputstream.
*
* Implementations are not required to implement any buffering or
* other stream-based optimizations.
*
* @param aDataSource The RDF data source to be serialized.
* @param aOut The output stream to use.
*/
void serialize(in rdfIDataSource aDataSource, in nsIOutputStream aOut);
};

View File

@ -0,0 +1,64 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <bsmedberg@covad.net>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIRDFResource;
interface nsIRDFNode;
/**
* Interface used in RDF to enumerate triples.
* Also used by rdfIDataSource::getAllSubjects, then aPredicate,
* aObject and aTruthValue are ignored.
*
* @status PLASMA
*/
[scriptable, function, uuid(aafea151-c271-4505-9978-a100d292800c)]
interface rdfITripleVisitor : nsISupports
{
/**
* Callback function for returning query results.
*
* @param aSubject, aPredicate, aObject describe the (sub-)arc
* @returnCode NS_RDF_STOP_VISIT to stop iterating over the query result.
* Any error code will stop the iteration as well.
*/
void visit(in nsIRDFNode aSubject, in nsIRDFResource aPredicate,
in nsIRDFNode aObject, in boolean aTruthValue);
};

View File

@ -95,6 +95,9 @@ static const char kURI##prefix##_##name[] = ns #name
willing to record the statement. */
#define NS_RDF_ASSERTION_REJECTED NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_RDF, 3)
/* Return this from rdfITripleVisitor to stop cycling */
#define NS_RDF_STOP_VISIT NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_RDF, 4)
/* ContractID prefixes for RDF DLL registration. */
@ -105,6 +108,8 @@ static const char kURI##prefix##_##name[] = ns #name
#define NS_RDF_RESOURCE_FACTORY_CONTRACTID_PREFIX NS_RDF_RESOURCE_FACTORY_CONTRACTID "?name="
#define NS_RDF_INFER_DATASOURCE_CONTRACTID_PREFIX NS_RDF_CONTRACTID "/infer-datasource;1?engine="
#define NS_RDF_SERIALIZER NS_RDF_CONTRACTID "/serializer;1?format="
// contract ID is in the form
// @mozilla.org/rdf/delegate-factory;1?key=<key>&scheme=<scheme>
#define NS_RDF_DELEGATEFACTORY_CONTRACTID "@mozilla.org/rdf/delegate-factory;1"

View File

@ -56,6 +56,7 @@ REQUIRES = xpcom \
$(NULL)
CPPSRCS = \
rdfTriplesSerializer.cpp \
nsCompositeDataSource.cpp \
nsContainerEnumerator.cpp \
nsDefaultResourceFactory.cpp \

View File

@ -99,6 +99,8 @@
#include "prlog.h"
#include "rdf.h"
#include "rdfIDataSource.h"
#include "rdfITripleVisitor.h"
#ifdef PR_LOGGING
static PRLogModuleInfo* gLog = nsnull;
@ -293,7 +295,8 @@ class InMemoryResourceEnumeratorImpl;
class InMemoryDataSource : public nsIRDFDataSource,
public nsIRDFInMemoryDataSource,
public nsIRDFPropagatableDataSource,
public nsIRDFPurgeableDataSource
public nsIRDFPurgeableDataSource,
public rdfIDataSource
{
protected:
nsFixedSizeAllocator mAllocator;
@ -309,6 +312,10 @@ protected:
nsCOMArray<nsIRDFObserver> mObservers;
PRUint32 mNumObservers;
// VisitFoo needs to block writes, [Un]Assert only allowed
// during mReadCount == 0
PRUint32 mReadCount;
static PLDHashOperator PR_CALLBACK
DeleteForwardArcsEntry(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg);
@ -355,6 +362,9 @@ public:
// nsIRDFPurgeableDataSource methods
NS_DECL_NSIRDFPURGEABLEDATASOURCE
// rdfIDataSource methods
NS_DECL_RDFIDATASOURCE
protected:
static PLDHashOperator PR_CALLBACK
SweepForwardArcsEntries(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
@ -867,7 +877,7 @@ NS_NewRDFInMemoryDataSource(nsISupports* aOuter, const nsIID& aIID, void** aResu
InMemoryDataSource::InMemoryDataSource(nsISupports* aOuter)
: mNumObservers(0)
: mNumObservers(0), mReadCount(0)
{
NS_INIT_AGGREGATED(aOuter);
@ -988,6 +998,9 @@ InMemoryDataSource::AggregatedQueryInterface(REFNSIID aIID, void** aResult)
else if (aIID.Equals(NS_GET_IID(nsIRDFPurgeableDataSource))) {
*aResult = NS_STATIC_CAST(nsIRDFPurgeableDataSource*, this);
}
else if (aIID.Equals(NS_GET_IID(rdfIDataSource))) {
*aResult = NS_STATIC_CAST(rdfIDataSource*, this);
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
@ -1373,6 +1386,11 @@ InMemoryDataSource::Assert(nsIRDFResource* aSource,
if (! aTarget)
return NS_ERROR_NULL_POINTER;
if (mReadCount) {
NS_WARNING("Writing to InMemoryDataSource during read\n");
return NS_RDF_ASSERTION_REJECTED;
}
nsresult rv;
rv = LockedAssert(aSource, aProperty, aTarget, aTruthValue);
if (NS_FAILED(rv)) return rv;
@ -1527,6 +1545,11 @@ InMemoryDataSource::Unassert(nsIRDFResource* aSource,
if (! aTarget)
return NS_ERROR_NULL_POINTER;
if (mReadCount) {
NS_WARNING("Writing to InMemoryDataSource during read\n");
return NS_RDF_ASSERTION_REJECTED;
}
nsresult rv;
rv = LockedUnassert(aSource, aProperty, aTarget);
@ -1571,6 +1594,11 @@ InMemoryDataSource::Change(nsIRDFResource* aSource,
if (! aNewTarget)
return NS_ERROR_NULL_POINTER;
if (mReadCount) {
NS_WARNING("Writing to InMemoryDataSource during read\n");
return NS_RDF_ASSERTION_REJECTED;
}
nsresult rv;
// XXX We can implement LockedChange() if we decide that this
@ -1621,6 +1649,11 @@ InMemoryDataSource::Move(nsIRDFResource* aOldSource,
if (! aTarget)
return NS_ERROR_NULL_POINTER;
if (mReadCount) {
NS_WARNING("Writing to InMemoryDataSource during read\n");
return NS_RDF_ASSERTION_REJECTED;
}
nsresult rv;
// XXX We can implement LockedMove() if we decide that this
@ -2117,4 +2150,130 @@ InMemoryDataSource::SweepForwardArcsEntries(PLDHashTable* aTable,
}
////////////////////////////////////////////////////////////////////////
// rdfIDataSource methods
class VisitorClosure
{
public:
VisitorClosure(rdfITripleVisitor* aVisitor) :
mVisitor(aVisitor),
mRv(NS_OK)
{};
rdfITripleVisitor* mVisitor;
nsresult mRv;
};
PLDHashOperator PR_CALLBACK
SubjectEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg) {
Entry* entry = NS_REINTERPRET_CAST(Entry*, aHdr);
VisitorClosure* closure = NS_STATIC_CAST(VisitorClosure*, aArg);
nsresult rv;
nsCOMPtr<nsIRDFNode> subject = do_QueryInterface(entry->mNode, &rv);
NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
closure->mRv = closure->mVisitor->Visit(subject, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(closure->mRv) || closure->mRv == NS_RDF_STOP_VISIT)
return PL_DHASH_STOP;
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
InMemoryDataSource::VisitAllSubjects(rdfITripleVisitor *aVisitor)
{
// Lock datasource against writes
++mReadCount;
// Enumerate all of our entries into an nsISupportsArray.
VisitorClosure cls(aVisitor);
PL_DHashTableEnumerate(&mForwardArcs, SubjectEnumerator, &cls);
// Unlock datasource
--mReadCount;
return cls.mRv;
}
class TriplesInnerClosure
{
public:
TriplesInnerClosure(nsIRDFNode* aSubject, VisitorClosure* aClosure) :
mSubject(aSubject), mOuter(aClosure) {};
nsIRDFNode* mSubject;
VisitorClosure* mOuter;
};
PLDHashOperator PR_CALLBACK
TriplesInnerEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg) {
Entry* entry = NS_REINTERPRET_CAST(Entry*, aHdr);
Assertion* assertion = entry->mAssertions;
TriplesInnerClosure* closure =
NS_STATIC_CAST(TriplesInnerClosure*, aArg);
while (assertion) {
NS_ASSERTION(!assertion->mHashEntry, "shouldn't have to hashes");
VisitorClosure* cls = closure->mOuter;
cls->mRv = cls->mVisitor->Visit(closure->mSubject,
assertion->u.as.mProperty,
assertion->u.as.mTarget,
assertion->u.as.mTruthValue);
if (NS_FAILED(cls->mRv) || cls->mRv == NS_RDF_STOP_VISIT) {
return PL_DHASH_STOP;
}
assertion = assertion->mNext;
}
return PL_DHASH_NEXT;
}
PLDHashOperator PR_CALLBACK
TriplesEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg) {
Entry* entry = NS_REINTERPRET_CAST(Entry*, aHdr);
VisitorClosure* closure = NS_STATIC_CAST(VisitorClosure*, aArg);
nsresult rv;
nsCOMPtr<nsIRDFNode> subject = do_QueryInterface(entry->mNode, &rv);
NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
if (entry->mAssertions->mHashEntry) {
TriplesInnerClosure cls(subject, closure);
PL_DHashTableEnumerate(entry->mAssertions->u.hash.mPropertyHash,
TriplesInnerEnumerator, &cls);
if (NS_FAILED(closure->mRv)) {
return PL_DHASH_STOP;
}
return PL_DHASH_NEXT;
}
Assertion* assertion = entry->mAssertions;
while (assertion) {
NS_ASSERTION(!assertion->mHashEntry, "shouldn't have to hashes");
closure->mRv = closure->mVisitor->Visit(subject,
assertion->u.as.mProperty,
assertion->u.as.mTarget,
assertion->u.as.mTruthValue);
if (NS_FAILED(closure->mRv) || closure->mRv == NS_RDF_STOP_VISIT) {
return PL_DHASH_STOP;
}
assertion = assertion->mNext;
}
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
InMemoryDataSource::VisitAllTriples(rdfITripleVisitor *aVisitor)
{
// Lock datasource against writes
++mReadCount;
// Enumerate all of our entries into an nsISupportsArray.
VisitorClosure cls(aVisitor);
PL_DHashTableEnumerate(&mForwardArcs, TriplesEnumerator, &cls);
// Unlock datasource
--mReadCount;
return cls.mRv;
}
////////////////////////////////////////////////////////////////////////

View File

@ -123,6 +123,8 @@
#include "nsNameSpaceMap.h"
#include "nsCRT.h"
#include "rdfIDataSource.h"
//----------------------------------------------------------------------
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
@ -215,7 +217,8 @@ class RDFXMLDataSourceImpl : public nsIRDFDataSource,
public nsIRDFRemoteDataSource,
public nsIRDFXMLSink,
public nsIRDFXMLSource,
public nsIStreamListener
public nsIStreamListener,
public rdfIDataSource
{
protected:
enum LoadState {
@ -386,6 +389,21 @@ public:
// nsIStreamListener
NS_DECL_NSISTREAMLISTENER
// rdfIDataSource
NS_IMETHOD VisitAllSubjects(rdfITripleVisitor *aVisitor) {
nsresult rv;
nsCOMPtr<rdfIDataSource> rdfds = do_QueryInterface(mInner, &rv);
if (NS_FAILED(rv)) return rv;
return rdfds->VisitAllSubjects(aVisitor);
}
NS_IMETHOD VisitAllTriples(rdfITripleVisitor *aVisitor) {
nsresult rv;
nsCOMPtr<rdfIDataSource> rdfds = do_QueryInterface(mInner, &rv);
if (NS_FAILED(rv)) return rv;
return rdfds->VisitAllTriples(aVisitor);
}
// Implementation methods
PRBool
MakeQName(nsIRDFResource* aResource,
@ -519,13 +537,14 @@ RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void)
}
NS_IMPL_ISUPPORTS6(RDFXMLDataSourceImpl,
NS_IMPL_ISUPPORTS7(RDFXMLDataSourceImpl,
nsIRDFDataSource,
nsIRDFRemoteDataSource,
nsIRDFXMLSink,
nsIRDFXMLSource,
nsIRequestObserver,
nsIStreamListener)
nsIStreamListener,
rdfIDataSource)
nsresult

View File

@ -22,6 +22,7 @@
*
* Contributor(s):
* Chris Waterson <waterson@netscape.com>
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -50,6 +51,10 @@
#include "rdf.h"
#include "rdfutil.h"
#include "rdfIDataSource.h"
#include "nsITimelineService.h"
PRInt32 nsRDFXMLSerializer::gRefCnt = 0;
nsIRDFContainerUtils* nsRDFXMLSerializer::gRDFC;
nsIRDFResource* nsRDFXMLSerializer::kRDF_instanceOf;
@ -161,13 +166,25 @@ nsRDFXMLSerializer::Init(nsIRDFDataSource* aDataSource)
prefix = do_GetAtom("NC");
AddNameSpace(prefix, NS_LITERAL_STRING("http://home.netscape.com/NC-rdf#"));
mQNames.Init();
mPrefixID = 0;
return NS_OK;
}
NS_IMETHODIMP
nsRDFXMLSerializer::AddNameSpace(nsIAtom* aPrefix, const nsAString& aURI)
{
mNameSpaces.Put(aURI, aPrefix);
nsCOMPtr<nsIAtom> prefix = aPrefix;
if (!prefix) {
// Make up a prefix, we don't want default namespaces, so
// that we can use QNames for elements and attributes alike.
nsCAutoString pref;
pref.AssignLiteral("NS");
pref.AppendInt(++mPrefixID, 10);
prefix = do_GetAtom(pref);
}
mNameSpaces.Put(aURI, prefix);
return NS_OK;
}
@ -203,31 +220,24 @@ rdf_BlockingWrite(nsIOutputStream* stream, const nsAString& s)
}
// 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#").
// "http://www.w3.org/TR/WD-rdf-syntax#Description") into a QName
// ("RDF:Description"), and registers the namespace, if it's made up.
PRBool
nsRDFXMLSerializer::MakeQName(nsIRDFResource* aResource,
nsCString& aProperty,
nsCString& aNameSpacePrefix,
nsCString& aNameSpaceURI)
nsresult
nsRDFXMLSerializer::RegisterQName(nsIRDFResource* aResource)
{
nsCAutoString uri;
nsCAutoString uri, qname;
aResource->GetValueUTF8(uri);
nsNameSpaceMap::const_iterator iter = mNameSpaces.GetNameSpaceOf(uri);
if (iter != mNameSpaces.last()) {
if (iter->mPrefix)
iter->mPrefix->ToUTF8String(aNameSpacePrefix);
else
aNameSpacePrefix.Truncate();
aNameSpaceURI = iter->mURI;
uri.Right(aProperty, uri.Length() - aNameSpaceURI.Length());
return PR_TRUE;
NS_ENSURE_TRUE(iter->mPrefix, NS_ERROR_UNEXPECTED);
iter->mPrefix->ToUTF8String(qname);
qname.Append(':');
qname += StringTail(uri, uri.Length() - iter->mURI.Length());
return mQNames.Put(aResource, qname) ? NS_OK : NS_ERROR_FAILURE;
}
// Okay, so we don't have it in our map. Try to make one up. This
// is very bogus.
PRInt32 i = uri.RFindChar('#'); // first try a '#'
@ -236,30 +246,29 @@ nsRDFXMLSerializer::MakeQName(nsIRDFResource* aResource,
if (i == -1) {
// Okay, just punt and assume there is _no_ namespace on
// this thing...
aNameSpaceURI.Truncate();
aNameSpacePrefix.Truncate();
aProperty = uri;
return PR_TRUE;
return mQNames.Put(aResource, uri) ? NS_OK : NS_ERROR_FAILURE;
}
}
// Take whatever is to the right of the '#' and call it the
// property.
aProperty.Truncate();
uri.Right(aProperty, uri.Length() - (i + 1));
// Take whatever is to the right of the '#' or '/' and call it the
// local name, make up a prefix.
qname.AssignLiteral("NS");
qname.AppendInt(++mPrefixID, 10);
{
nsCOMPtr<nsIAtom> prefix = do_GetAtom(qname);
mNameSpaces.Put(StringHead(uri, i+1), prefix);
}
qname.Append(':');
qname += StringTail(uri, uri.Length() - (i + 1));
// Truncate the namespace URI down to the string up to and
// including the '#'.
aNameSpaceURI = uri;
aNameSpaceURI.Truncate(i + 1);
// Just generate a random prefix
static PRInt32 gPrefixID = 0;
aNameSpacePrefix.AssignLiteral("NS");
aNameSpacePrefix.AppendInt(++gPrefixID, 10);
return PR_FALSE;
return mQNames.Put(aResource, qname) ? NS_OK : NS_ERROR_FAILURE;
}
nsresult
nsRDFXMLSerializer::GetQName(nsIRDFResource* aResource, nsCString& aQName)
{
return mQNames.Get(aResource, &aQName) ? NS_OK : NS_ERROR_UNEXPECTED;
}
PRBool
nsRDFXMLSerializer::IsContainerProperty(nsIRDFResource* aProperty)
@ -370,42 +379,24 @@ nsRDFXMLSerializer::SerializeInlineAssertion(nsIOutputStream* aStream,
nsIRDFResource* aProperty,
nsIRDFLiteral* aValue)
{
nsCAutoString property, nameSpacePrefix, nameSpaceURI;
nsCAutoString attr;
PRBool wasDefinedAtGlobalScope =
MakeQName(aProperty, property, nameSpacePrefix, nameSpaceURI);
if (nameSpacePrefix.Length()) {
attr.Append(nameSpacePrefix);
attr.Append(':');
}
attr.Append(property);
nsresult rv;
nsCString qname;
rv = GetQName(aProperty, qname);
NS_ENSURE_SUCCESS(rv, rv);
rv = rdf_BlockingWrite(aStream,
NS_LITERAL_CSTRING("\n "));
if (NS_FAILED(rv)) return rv;
if (!wasDefinedAtGlobalScope && nameSpacePrefix.Length()) {
nsCAutoString nsutf8 =
NS_LITERAL_CSTRING("xmlns:") +
nameSpacePrefix +
NS_LITERAL_CSTRING("=\"") +
nameSpaceURI +
NS_LITERAL_CSTRING("\" ");
rv = rdf_BlockingWrite(aStream, nsutf8);
if (NS_FAILED(rv)) return rv;
}
const PRUnichar* value;
aValue->GetValueConst(&value);
NS_ConvertUTF16toUTF8 s(value);
rdf_EscapeAttributeValue(s);
attr.AppendLiteral("=\"");
rv = rdf_BlockingWrite(aStream, attr);
rv = rdf_BlockingWrite(aStream, qname);
if (NS_FAILED(rv)) return rv;
rv = rdf_BlockingWrite(aStream, "=\"", 2);
if (NS_FAILED(rv)) return rv;
s.Append('"');
return rdf_BlockingWrite(aStream, s);
@ -417,33 +408,15 @@ nsRDFXMLSerializer::SerializeChildAssertion(nsIOutputStream* aStream,
nsIRDFResource* aProperty,
nsIRDFNode* aValue)
{
nsCAutoString property, nameSpacePrefix, nameSpaceURI;
nsCAutoString tag;
nsCString qname;
nsresult rv = GetQName(aProperty, qname);
NS_ENSURE_SUCCESS(rv, rv);
PRBool wasDefinedAtGlobalScope =
MakeQName(aProperty, property, nameSpacePrefix, nameSpaceURI);
if (nameSpacePrefix.Length()) {
tag.Append(nameSpacePrefix);
tag.Append(':');
}
tag.Append(property);
nsresult rv = rdf_BlockingWrite(aStream, " <", 5);
rv = rdf_BlockingWrite(aStream, " <", 5);
if (NS_FAILED(rv)) return rv;
rv = rdf_BlockingWrite(aStream, tag);
rv = rdf_BlockingWrite(aStream, qname);
if (NS_FAILED(rv)) return rv;
if (!wasDefinedAtGlobalScope && nameSpacePrefix.Length()) {
nsCAutoString out = NS_LITERAL_CSTRING(" xmlns:") +
nameSpacePrefix +
NS_LITERAL_CSTRING("=\"") +
nameSpaceURI +
NS_LITERAL_CSTRING("\"");
rv = rdf_BlockingWrite(aStream, out);
if (NS_FAILED(rv)) return rv;
}
nsCOMPtr<nsIRDFResource> resource;
nsCOMPtr<nsIRDFLiteral> literal;
nsCOMPtr<nsIRDFInt> number;
@ -516,8 +489,9 @@ nsRDFXMLSerializer::SerializeChildAssertion(nsIOutputStream* aStream,
rv = rdf_BlockingWrite(aStream, "</", 2);
if (NS_FAILED(rv)) return rv;
tag.AppendLiteral(">\n");
return rdf_BlockingWrite(aStream, tag);
rv = rdf_BlockingWrite(aStream, qname);
if (NS_FAILED(rv)) return rv;
return rdf_BlockingWrite(aStream, ">\n", 2);
no_close_tag:
return NS_OK;
@ -600,7 +574,7 @@ nsRDFXMLSerializer::SerializeDescription(nsIOutputStream* aStream,
nsresult rv;
PRBool isTypedNode = PR_FALSE;
nsCAutoString nodeName, nameSpacePrefix, nameSpaceURI;
nsCString typeQName;
nsCOMPtr<nsIRDFNode> typeNode;
mDataSource->GetTarget(aResource, kRDF_type, PR_TRUE, getter_AddRefs(typeNode));
@ -611,8 +585,7 @@ nsRDFXMLSerializer::SerializeDescription(nsIOutputStream* aStream,
// just treat the description as if it weren't a typed node
// after all and emit rdf:type as a normal property. This
// seems preferable to using a bogus (invented) prefix.
isTypedNode = MakeQName(type, nodeName,
nameSpacePrefix, nameSpaceURI);
isTypedNode = NS_SUCCEEDED(GetQName(type, typeQName));
}
}
@ -628,12 +601,7 @@ nsRDFXMLSerializer::SerializeDescription(nsIOutputStream* aStream,
rv = rdf_BlockingWrite(aStream, NS_LITERAL_STRING(" <"));
if (NS_FAILED(rv)) return rv;
// Watch out for the default namespace!
if (!nameSpacePrefix.IsEmpty()) {
nameSpacePrefix.Append(':');
rv = rdf_BlockingWrite(aStream, nameSpacePrefix);
if (NS_FAILED(rv)) return rv;
}
rv = rdf_BlockingWrite(aStream, nodeName);
rv = rdf_BlockingWrite(aStream, typeQName);
if (NS_FAILED(rv)) return rv;
}
else {
@ -747,13 +715,9 @@ nsRDFXMLSerializer::SerializeDescription(nsIOutputStream* aStream,
rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(" </"));
if (NS_FAILED(rv)) return rv;
// Watch out for the default namespace!
if (!nameSpacePrefix.IsEmpty()) {
// ':' already appended above
rv = rdf_BlockingWrite(aStream, nameSpacePrefix);
if (NS_FAILED(rv)) return rv;
}
nodeName.Append(">\n", 2);
rdf_BlockingWrite(aStream, nodeName);
rdf_BlockingWrite(aStream, typeQName);
if (NS_FAILED(rv)) return rv;
rdf_BlockingWrite(aStream, ">\n", 2);
if (NS_FAILED(rv)) return rv;
}
else {
@ -1057,76 +1021,61 @@ nsRDFXMLSerializer::SerializeEpilogue(nsIOutputStream* aStream)
return rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("</RDF:RDF>\n"));
}
class QNameCollector : public rdfITripleVisitor {
public:
NS_DECL_ISUPPORTS
NS_DECL_RDFITRIPLEVISITOR
QNameCollector(nsRDFXMLSerializer* aParent)
: mParent(aParent){}
private:
nsRDFXMLSerializer* mParent;
};
NS_IMPL_ISUPPORTS1(QNameCollector, rdfITripleVisitor)
nsresult
nsRDFXMLSerializer::CollectNamespaces()
QNameCollector::Visit(nsIRDFNode* aSubject, nsIRDFResource* aPredicate,
nsIRDFNode* aObject, PRBool aTruthValue)
{
// Iterate through all the resources in the datasource, and all of
// the arcs-out of each, to collect the set of namespaces in use
nsCOMPtr<nsISimpleEnumerator> resources;
mDataSource->GetAllResources(getter_AddRefs(resources));
if (! resources)
return NS_ERROR_FAILURE;
while (1) {
PRBool hasMore = PR_FALSE;
resources->HasMoreElements(&hasMore);
if (! hasMore)
break;
nsCOMPtr<nsISupports> isupports;
resources->GetNext(getter_AddRefs(isupports));
nsCOMPtr<nsIRDFResource> resource =
do_QueryInterface(isupports);
if (! resource)
continue;
nsCOMPtr<nsISimpleEnumerator> arcs;
mDataSource->ArcLabelsOut(resource, getter_AddRefs(arcs));
if (! arcs)
continue;
while (1) {
hasMore = PR_FALSE;
arcs->HasMoreElements(&hasMore);
if (! hasMore)
break;
arcs->GetNext(getter_AddRefs(isupports));
nsCOMPtr<nsIRDFResource> property =
do_QueryInterface(isupports);
if (! property)
continue;
EnsureNameSpaceFor(property);
if (aPredicate == mParent->kRDF_type) {
// try to get a type QName for aObject, should be a resource
nsCOMPtr<nsIRDFResource> resType = do_QueryInterface(aObject);
if (!resType) {
// ignore error
return NS_OK;
}
if (mParent->mQNames.Get(resType, nsnull)) {
return NS_OK;
}
mParent->RegisterQName(resType);
return NS_OK;
}
if (mParent->mQNames.Get(aPredicate, nsnull)) {
return NS_OK;
}
if (aPredicate == mParent->kRDF_instanceOf ||
aPredicate == mParent->kRDF_nextVal)
return NS_OK;
PRBool isOrdinal = PR_FALSE;
mParent->gRDFC->IsOrdinalProperty(aPredicate, &isOrdinal);
if (isOrdinal)
return NS_OK;
mParent->RegisterQName(aPredicate);
return NS_OK;
}
nsresult
nsRDFXMLSerializer::EnsureNameSpaceFor(nsIRDFResource* aResource)
nsRDFXMLSerializer::CollectNamespaces()
{
nsCAutoString property;
nsCAutoString nameSpacePrefix;
nsCAutoString nameSpaceURI;
if (! MakeQName(aResource, property, nameSpacePrefix, nameSpaceURI)) {
#ifdef DEBUG_waterson
const char* s;
aResource->GetValueConst(&s);
printf("*** Creating namespace for %s\n", s);
#endif
nsCOMPtr<nsIAtom> prefix = do_GetAtom(nameSpacePrefix);
mNameSpaces.Put(nameSpaceURI, prefix);
}
return NS_OK;
// Iterate over all Triples to get namespaces for subject resource types
// and Predicates and cache all the QNames we want to use.
nsCOMPtr<rdfITripleVisitor> collector =
new QNameCollector(this);
nsCOMPtr<rdfIDataSource> ds = do_QueryInterface(mDataSource); // XXX API
NS_ENSURE_TRUE(collector && ds, NS_ERROR_FAILURE);
return ds->VisitAllTriples(collector);
}
//----------------------------------------------------------------------
@ -1135,6 +1084,7 @@ NS_IMETHODIMP
nsRDFXMLSerializer::Serialize(nsIOutputStream* aStream)
{
nsresult rv;
NS_TIMELINE_START_TIMER("rdf/xml-ser");
rv = CollectNamespaces();
if (NS_FAILED(rv)) return rv;
@ -1173,7 +1123,11 @@ nsRDFXMLSerializer::Serialize(nsIOutputStream* aStream)
break;
}
return SerializeEpilogue(aStream);
rv = SerializeEpilogue(aStream);
NS_TIMELINE_STOP_TIMER("rdf/xml-ser");
NS_TIMELINE_MARK("rdf/xml-ser");
return rv;
}

View File

@ -22,6 +22,7 @@
*
* Contributor(s):
* Chris Waterson <waterson@netscape.com>
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -46,6 +47,9 @@
#include "nsNameSpaceMap.h"
#include "nsXPIDLString.h"
#include "nsDataHashtable.h"
#include "rdfITripleVisitor.h"
class nsString;
class nsIOutputStream;
class nsIRDFContainerUtils;
@ -71,11 +75,10 @@ protected:
virtual ~nsRDFXMLSerializer();
// Implementation methods
PRBool
MakeQName(nsIRDFResource* aResource,
nsCString& aPproperty,
nsCString& aNameSpacePrefix,
nsCString& aNameSpaceURI);
nsresult
RegisterQName(nsIRDFResource* aResource);
nsresult
GetQName(nsIRDFResource* aResource, nsCString& aQName);
nsresult
SerializeInlineAssertion(nsIOutputStream* aStream,
@ -121,9 +124,6 @@ protected:
nsresult
CollectNamespaces();
nsresult
EnsureNameSpaceFor(nsIRDFResource* aResource);
PRBool
IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType);
@ -131,6 +131,12 @@ protected:
nsNameSpaceMap mNameSpaces;
nsXPIDLCString mBaseURLSpec;
// hash mapping resources to utf8-encoded QNames
nsDataHashtable<nsISupportsHashKey, nsCString> mQNames;
friend class QNameCollector;
PRUint32 mPrefixID;
static PRInt32 gRefCnt;
static nsIRDFResource* kRDF_instanceOf;
static nsIRDFResource* kRDF_type;

View File

@ -0,0 +1,183 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIOutputStream.h"
#include "nsReadableUtils.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsPrintfCString.h"
#include "nsIBufferedStreams.h"
#include "nsNetCID.h"
#include "nsComponentManagerUtils.h"
#include "rdfISerializer.h"
#include "rdfIDataSource.h"
#include "rdfITripleVisitor.h"
#include "nsIRDFResource.h"
#include "nsIRDFLiteral.h"
class TriplesVisitor : public rdfITripleVisitor
{
public:
TriplesVisitor(nsIOutputStream* aOut) : mOut(aOut) {};
NS_DECL_RDFITRIPLEVISITOR
NS_DECL_ISUPPORTS
protected:
nsresult writeResource(nsIRDFResource* aResource);
nsIOutputStream* mOut;
};
NS_IMPL_ISUPPORTS1(TriplesVisitor, rdfITripleVisitor)
nsresult
TriplesVisitor::writeResource(nsIRDFResource *aResource)
{
nsCString res;
PRUint32 writeCount, wroteCount;
mOut->Write("<", 1, &wroteCount);
NS_ENSURE_TRUE(wroteCount == 1, NS_ERROR_FAILURE);
nsresult rv = aResource->GetValueUTF8(res);
NS_ENSURE_SUCCESS(rv, rv);
writeCount = res.Length();
mOut->Write(res.get(), writeCount, &wroteCount);
NS_ENSURE_TRUE(writeCount == wroteCount, NS_ERROR_FAILURE);
mOut->Write("> ", 2, &wroteCount);
NS_ENSURE_TRUE(wroteCount == 2, NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMETHODIMP
TriplesVisitor::Visit(nsIRDFNode *aSubject, nsIRDFResource *aPredicate,
nsIRDFNode *aObject, PRBool aTruthValue)
{
nsCOMPtr<nsIRDFResource> subjectRes = do_QueryInterface(aSubject);
nsresult rv = NS_OK;
if (subjectRes) {
rv = writeResource(subjectRes);
}
if (NS_FAILED(rv)) {
return rv;
}
rv = writeResource(aPredicate);
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIRDFResource> res = do_QueryInterface(aObject);
nsCOMPtr<nsIRDFLiteral> lit;
nsCOMPtr<nsIRDFInt> intLit;
PRUint32 wroteCount;
if (res) {
rv = writeResource(res);
} else if ((lit = do_QueryInterface(aObject)) != nsnull) {
const PRUnichar *value;
lit->GetValueConst(&value);
nsCAutoString object;
object.AppendLiteral("\"");
AppendUTF16toUTF8(value, object);
object.AppendLiteral("\" ");
PRUint32 writeCount = object.Length();
rv = mOut->Write(object.get(), writeCount, &wroteCount);
NS_ENSURE_TRUE(writeCount == wroteCount, NS_ERROR_FAILURE);
} else if ((intLit = do_QueryInterface(aObject)) != nsnull) {
PRInt32 value;
intLit->GetValue(&value);
nsPrintfCString
object(128,
"\"%i\"^^<http://www.w3.org/2001/XMLSchema#integer> ",
value);
PRUint32 writeCount = object.Length();
rv = mOut->Write(object.get(), writeCount, &wroteCount);
NS_ENSURE_TRUE(writeCount == wroteCount, NS_ERROR_FAILURE);
}
NS_ENSURE_SUCCESS(rv, rv);
return mOut->Write(".\n", 2, &wroteCount);
}
class rdfTriplesSerializer : public rdfISerializer
{
public:
NS_DECL_ISUPPORTS
NS_DECL_RDFISERIALIZER
rdfTriplesSerializer();
private:
~rdfTriplesSerializer();
};
nsresult
NS_NewTriplesSerializer(rdfISerializer** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
*aResult = new rdfTriplesSerializer();
if (! *aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMPL_ISUPPORTS1(rdfTriplesSerializer, rdfISerializer)
rdfTriplesSerializer::rdfTriplesSerializer()
{
}
rdfTriplesSerializer::~rdfTriplesSerializer()
{
}
NS_IMETHODIMP
rdfTriplesSerializer::Serialize(rdfIDataSource *aDataSource,
nsIOutputStream *aOut)
{
nsresult rv;
nsCOMPtr<nsIBufferedOutputStream> bufout =
do_CreateInstance(NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = bufout->Init(aOut, 1024);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<rdfITripleVisitor> tv = new TriplesVisitor(bufout);
NS_ENSURE_TRUE(tv, NS_ERROR_OUT_OF_MEMORY);
return aDataSource->VisitAllTriples(tv);
}

View File

@ -105,4 +105,8 @@
#define NS_RDFXMLPARSER_CID \
{ 0xa4048e94, 0x1dd1, 0x11b2, { 0xa6, 0x76, 0x8a, 0x06, 0xc0, 0x86, 0xcc, 0x7d } }
// {0a5cd734-eb65-4d14-88a0-9f0bb2aba206}
#define NS_RDFNTRIPLES_SERIALIZER_CID \
{ 0x0a5cd734, 0xeb65, 0x4d14, { 0x88, 0xa0, 0x9f, 0x0b, 0xb2, 0xab, 0xa2, 0x06 } }
#endif // nsRDFCID_h__

View File

@ -57,6 +57,8 @@
#include "nsRDFXMLParser.h"
#include "nsRDFXMLSerializer.h"
#include "rdfISerializer.h"
//----------------------------------------------------------------------
// Functions used to create new instances of a given object by the
@ -101,6 +103,36 @@ MAKE_CTOR(RDFContainerUtils,RDFContainerUtils,RDFContainerUtils)
MAKE_CTOR(RDFContentSink,RDFContentSink,RDFContentSink)
MAKE_CTOR(RDFDefaultResource,DefaultResource,RDFResource)
#define MAKE_RDF_CTOR(_func,_new,_ifname) \
static NS_IMETHODIMP \
CreateNew##_func(nsISupports* aOuter, REFNSIID aIID, void **aResult) \
{ \
if (!aResult) { \
return NS_ERROR_INVALID_POINTER; \
} \
if (aOuter) { \
*aResult = nsnull; \
return NS_ERROR_NO_AGGREGATION; \
} \
rdfI##_ifname* inst; \
nsresult rv = NS_New##_new(&inst); \
if (NS_FAILED(rv)) { \
*aResult = nsnull; \
return rv; \
} \
rv = inst->QueryInterface(aIID, aResult); \
if (NS_FAILED(rv)) { \
*aResult = nsnull; \
} \
NS_RELEASE(inst); /* get rid of extra refcnt */ \
return rv; \
}
extern nsresult
NS_NewTriplesSerializer(rdfISerializer** aResult);
MAKE_RDF_CTOR(TriplesSerializer, TriplesSerializer, Serializer)
// The list of components we register
static const nsModuleComponentInfo components[] =
{ // register our build-in datasources:
@ -175,6 +207,12 @@ static const nsModuleComponentInfo components[] =
nsRDFXMLSerializer::Create
},
{ "RDF/NTriples Serializer",
NS_RDFNTRIPLES_SERIALIZER_CID,
NS_RDF_SERIALIZER "ntriples",
CreateNewTriplesSerializer
},
// XXX move this to XPFE at some point.
{ "Local Store", NS_LOCALSTORE_CID,
NS_LOCALSTORE_CONTRACTID, NS_NewLocalStore },

View File

@ -42,7 +42,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = rdfcat rdfpoll
DIRS = rdfcat rdfpoll triplescat
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,66 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla 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/MPL/
#
# 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.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <axel@pike.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
PROGRAM = triplescat$(BIN_SUFFIX)
CPPSRCS = triplescat.cpp
REQUIRES = xpcom \
rdf \
necko \
string \
$(NULL)
LIBS = \
$(LIBS_DIR) \
$(XPCOM_LIBS) \
$(NSPR_LIBS) \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
MAPFILE=triplescat.map
endif
include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS)

View File

@ -0,0 +1,199 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
* Chase Tingley <tingley@sundell.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* A simple test program that reads in RDF/XML into an in-memory data
* source, then serializes NTriples format back to stdout (or none).
*
* The program takes a single parameter: the URL from which to read,
* plus an optional parameter -q
*/
#include <stdio.h>
#include "nsXPCOM.h"
#include "nsCOMPtr.h"
//#include "nsString.h"
#include "nsIComponentManager.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsIEventQueueService.h"
#include "nsIIOService.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFNode.h"
#include "nsIRDFRemoteDataSource.h"
#include "nsIRDFService.h"
#include "nsIRDFXMLSource.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsIURL.h"
#include "nsRDFCID.h"
#include "plevent.h"
#include "plstr.h"
#include "prio.h"
#include "prthread.h"
#include "rdf.h"
#include "rdfIDataSource.h"
#include "rdfITripleVisitor.h"
#include "rdfISerializer.h"
////////////////////////////////////////////////////////////////////////
// Blatantly stolen from netwerk/test/
#define RETURN_IF_FAILED(rv, step) \
PR_BEGIN_MACRO \
if (NS_FAILED(rv)) { \
printf(">>> %s failed: rv=%x\n", step, rv); \
return rv;\
} \
PR_END_MACRO
////////////////////////////////////////////////////////////////////////
class ConsoleOutputStreamImpl : public nsIOutputStream
{
public:
ConsoleOutputStreamImpl(void) {}
virtual ~ConsoleOutputStreamImpl(void) {}
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIBaseStream interface
NS_IMETHOD Close(void) {
return NS_OK;
}
// nsIOutputStream interface
NS_IMETHOD Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount) {
PR_Write(PR_GetSpecialFD(PR_StandardOutput), aBuf, aCount);
*aWriteCount = aCount;
return NS_OK;
}
NS_IMETHOD
WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval) {
NS_NOTREACHED("WriteFrom");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD
WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval) {
NS_NOTREACHED("WriteSegments");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD
IsNonBlocking(PRBool *aNonBlocking) {
NS_NOTREACHED("IsNonBlocking");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD Flush(void) {
PR_Sync(PR_GetSpecialFD(PR_StandardOutput));
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(ConsoleOutputStreamImpl, nsIOutputStream)
////////////////////////////////////////////////////////////////////////
int
main(int argc, char** argv)
{
nsresult rv;
if (argc < 2) {
fprintf(stderr, "usage: %s <url>\n", argv[0]);
return 1;
}
NS_InitXPCOM2(nsnull, nsnull, nsnull);
// Get netlib off the floor...
nsCOMPtr<nsIEventQueueService> theEventQueueService =
do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
RETURN_IF_FAILED(rv, "EventQueueService");
nsIEventQueue* eq = nsnull;
rv = theEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, &eq);
RETURN_IF_FAILED(rv, "GetThreadEventQueue");
// Create a stream data source and initialize it on argv[1], which
// is hopefully a "file:" URL.
nsCOMPtr<nsIRDFDataSource> ds =
do_CreateInstance(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "xml-datasource",
&rv);
RETURN_IF_FAILED(rv, "RDF/XML datasource creation");
nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(ds, &rv);
RETURN_IF_FAILED(rv, "QI to nsIRDFRemoteDataSource");
rv = remote->Init(argv[1]);
RETURN_IF_FAILED(rv, "datasource initialization");
// Okay, this should load the XML file...
rv = remote->Refresh(PR_FALSE);
RETURN_IF_FAILED(rv, "datasource refresh");
// Pump events until the load is finished
PRBool done = PR_FALSE;
while (!done) {
eq->ProcessPendingEvents();
remote->GetLoaded(&done);
}
nsCOMPtr<rdfIDataSource> rdfds = do_QueryInterface(ds, &rv);
RETURN_IF_FAILED(rv, "QI to rdIDataSource");
{
nsCOMPtr<nsIOutputStream> out = new ConsoleOutputStreamImpl();
nsCOMPtr<rdfISerializer> ser =
do_CreateInstance(NS_RDF_SERIALIZER "ntriples", &rv);
RETURN_IF_FAILED(rv, "Creation of NTriples Serializer");
rv = ser->Serialize(rdfds, out);
RETURN_IF_FAILED(rv, "Serialization to NTriples");
out->Close();
}
theEventQueueService->DestroyThreadEventQueue();
return NS_OK;
}