Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / rdf / base / src / nsRDFService.cpp
blobe71e475198989beb9d853a0914a85be9a98a580f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Benjamin Smedberg <benjamin@smedbergs.us>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK *****
41 * This Original Code has been modified by IBM Corporation.
42 * Modifications made by IBM described herein are
43 * Copyright (c) International Business Machines
44 * Corporation, 2000
46 * Modifications to Mozilla code or documentation
47 * identified per MPL Section 3.3
49 * Date Modified by Description of modification
50 * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
51 * use in OS2
56 This file provides the implementation for the RDF service manager.
58 TO DO
59 -----
61 1) Implement the CreateDataBase() methods.
63 2) Cache date and int literals.
67 #include "nsRDFService.h"
68 #include "nsCOMPtr.h"
69 #include "nsAutoPtr.h"
70 #include "nsMemory.h"
71 #include "nsIAtom.h"
72 #include "nsIComponentManager.h"
73 #include "nsIRDFDataSource.h"
74 #include "nsIRDFNode.h"
75 #include "nsIRDFRemoteDataSource.h"
76 #include "nsIServiceManager.h"
77 #include "nsIFactory.h"
78 #include "nsRDFCID.h"
79 #include "nsString.h"
80 #include "nsXPIDLString.h"
81 #include "nsNetUtil.h"
82 #include "pldhash.h"
83 #include "plhash.h"
84 #include "plstr.h"
85 #include "prlog.h"
86 #include "prprf.h"
87 #include "prmem.h"
88 #include "rdf.h"
89 #include "nsCRT.h"
90 #include "nsCRTGlue.h"
91 #include "prbit.h"
93 ////////////////////////////////////////////////////////////////////////
95 static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
96 static NS_DEFINE_CID(kRDFDefaultResourceCID, NS_RDFDEFAULTRESOURCE_CID);
98 static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
99 static NS_DEFINE_IID(kIRDFDateIID, NS_IRDFDATE_IID);
100 static NS_DEFINE_IID(kIRDFIntIID, NS_IRDFINT_IID);
101 static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
102 static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
104 #ifdef PR_LOGGING
105 static PRLogModuleInfo* gLog = nsnull;
106 #endif
108 class BlobImpl;
110 // These functions are copied from nsprpub/lib/ds/plhash.c, with one
111 // change to free the key in DataSourceFreeEntry.
112 // XXX sigh, why were DefaultAllocTable et. al. declared static, anyway?
114 static void *
115 DataSourceAllocTable(void *pool, PRSize size)
117 #if defined(XP_MAC)
118 #pragma unused (pool)
119 #endif
121 return PR_MALLOC(size);
124 static void
125 DataSourceFreeTable(void *pool, void *item)
127 #if defined(XP_MAC)
128 #pragma unused (pool)
129 #endif
131 PR_Free(item);
134 static PLHashEntry *
135 DataSourceAllocEntry(void *pool, const void *key)
137 #if defined(XP_MAC)
138 #pragma unused (pool,key)
139 #endif
141 return PR_NEW(PLHashEntry);
144 static void
145 DataSourceFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
147 #if defined(XP_MAC)
148 #pragma unused (pool)
149 #endif
151 if (flag == HT_FREE_ENTRY) {
152 PL_strfree((char*) he->key);
153 PR_Free(he);
157 static PLHashAllocOps dataSourceHashAllocOps = {
158 DataSourceAllocTable, DataSourceFreeTable,
159 DataSourceAllocEntry, DataSourceFreeEntry
162 //----------------------------------------------------------------------
164 // For the mResources hashtable.
167 struct ResourceHashEntry : public PLDHashEntryHdr {
168 const char *mKey;
169 nsIRDFResource *mResource;
171 static PLDHashNumber
172 HashKey(PLDHashTable *table, const void *key)
174 return nsCRT::HashCode(static_cast<const char *>(key));
177 static PRBool
178 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
179 const void *key)
181 const ResourceHashEntry *entry =
182 static_cast<const ResourceHashEntry *>(hdr);
184 return 0 == nsCRT::strcmp(static_cast<const char *>(key),
185 entry->mKey);
189 static PLDHashTableOps gResourceTableOps = {
190 PL_DHashAllocTable,
191 PL_DHashFreeTable,
192 ResourceHashEntry::HashKey,
193 ResourceHashEntry::MatchEntry,
194 PL_DHashMoveEntryStub,
195 PL_DHashClearEntryStub,
196 PL_DHashFinalizeStub,
197 nsnull
200 // ----------------------------------------------------------------------
202 // For the mLiterals hashtable.
205 struct LiteralHashEntry : public PLDHashEntryHdr {
206 nsIRDFLiteral *mLiteral;
207 const PRUnichar *mKey;
209 static PLDHashNumber
210 HashKey(PLDHashTable *table, const void *key)
212 return nsCRT::HashCode(static_cast<const PRUnichar *>(key));
215 static PRBool
216 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
217 const void *key)
219 const LiteralHashEntry *entry =
220 static_cast<const LiteralHashEntry *>(hdr);
222 return 0 == nsCRT::strcmp(static_cast<const PRUnichar *>(key),
223 entry->mKey);
227 static PLDHashTableOps gLiteralTableOps = {
228 PL_DHashAllocTable,
229 PL_DHashFreeTable,
230 LiteralHashEntry::HashKey,
231 LiteralHashEntry::MatchEntry,
232 PL_DHashMoveEntryStub,
233 PL_DHashClearEntryStub,
234 PL_DHashFinalizeStub,
235 nsnull
238 // ----------------------------------------------------------------------
240 // For the mInts hashtable.
243 struct IntHashEntry : public PLDHashEntryHdr {
244 nsIRDFInt *mInt;
245 PRInt32 mKey;
247 static PLDHashNumber
248 HashKey(PLDHashTable *table, const void *key)
250 return PLDHashNumber(*static_cast<const PRInt32 *>(key));
253 static PRBool
254 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
255 const void *key)
257 const IntHashEntry *entry =
258 static_cast<const IntHashEntry *>(hdr);
260 return *static_cast<const PRInt32 *>(key) == entry->mKey;
264 static PLDHashTableOps gIntTableOps = {
265 PL_DHashAllocTable,
266 PL_DHashFreeTable,
267 IntHashEntry::HashKey,
268 IntHashEntry::MatchEntry,
269 PL_DHashMoveEntryStub,
270 PL_DHashClearEntryStub,
271 PL_DHashFinalizeStub,
272 nsnull
275 // ----------------------------------------------------------------------
277 // For the mDates hashtable.
280 struct DateHashEntry : public PLDHashEntryHdr {
281 nsIRDFDate *mDate;
282 PRTime mKey;
284 static PLDHashNumber
285 HashKey(PLDHashTable *table, const void *key)
287 // xor the low 32 bits with the high 32 bits.
288 PRTime t = *static_cast<const PRTime *>(key);
289 PRInt64 h64, l64;
290 LL_USHR(h64, t, 32);
291 l64 = LL_INIT(0, 0xffffffff);
292 LL_AND(l64, l64, t);
293 PRInt32 h32, l32;
294 LL_L2I(h32, h64);
295 LL_L2I(l32, l64);
296 return PLDHashNumber(l32 ^ h32);
299 static PRBool
300 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
301 const void *key)
303 const DateHashEntry *entry =
304 static_cast<const DateHashEntry *>(hdr);
306 return LL_EQ(*static_cast<const PRTime *>(key), entry->mKey);
310 static PLDHashTableOps gDateTableOps = {
311 PL_DHashAllocTable,
312 PL_DHashFreeTable,
313 DateHashEntry::HashKey,
314 DateHashEntry::MatchEntry,
315 PL_DHashMoveEntryStub,
316 PL_DHashClearEntryStub,
317 PL_DHashFinalizeStub,
318 nsnull
321 class BlobImpl : public nsIRDFBlob
323 public:
324 struct Data {
325 PRInt32 mLength;
326 PRUint8 *mBytes;
329 BlobImpl(const PRUint8 *aBytes, PRInt32 aLength)
331 mData.mLength = aLength;
332 mData.mBytes = new PRUint8[aLength];
333 memcpy(mData.mBytes, aBytes, aLength);
334 NS_ADDREF(RDFServiceImpl::gRDFService);
335 RDFServiceImpl::gRDFService->RegisterBlob(this);
338 virtual ~BlobImpl()
340 RDFServiceImpl::gRDFService->UnregisterBlob(this);
341 // Use NS_RELEASE2() here, because we want to decrease the
342 // refcount, but not null out the gRDFService pointer (which is
343 // what a vanilla NS_RELEASE() would do).
344 nsrefcnt refcnt;
345 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
346 delete[] mData.mBytes;
349 NS_DECL_ISUPPORTS
350 NS_DECL_NSIRDFNODE
351 NS_DECL_NSIRDFBLOB
353 Data mData;
356 NS_IMPL_ISUPPORTS2(BlobImpl, nsIRDFNode, nsIRDFBlob)
358 NS_IMETHODIMP
359 BlobImpl::EqualsNode(nsIRDFNode *aNode, PRBool *aEquals)
361 nsCOMPtr<nsIRDFBlob> blob = do_QueryInterface(aNode);
362 if (blob) {
363 PRInt32 length;
364 blob->GetLength(&length);
366 if (length == mData.mLength) {
367 const PRUint8 *bytes;
368 blob->GetValue(&bytes);
370 if (0 == memcmp(bytes, mData.mBytes, length)) {
371 *aEquals = PR_TRUE;
372 return NS_OK;
377 *aEquals = PR_FALSE;
378 return NS_OK;
381 NS_IMETHODIMP
382 BlobImpl::GetValue(const PRUint8 **aResult)
384 *aResult = mData.mBytes;
385 return NS_OK;
388 NS_IMETHODIMP
389 BlobImpl::GetLength(PRInt32 *aResult)
391 *aResult = mData.mLength;
392 return NS_OK;
395 // ----------------------------------------------------------------------
397 // For the mBlobs hashtable.
400 struct BlobHashEntry : public PLDHashEntryHdr {
401 BlobImpl *mBlob;
403 static PLDHashNumber
404 HashKey(PLDHashTable *table, const void *key)
406 const BlobImpl::Data *data =
407 static_cast<const BlobImpl::Data *>(key);
409 const PRUint8 *p = data->mBytes, *limit = p + data->mLength;
410 PLDHashNumber h = 0;
411 for ( ; p < limit; ++p)
412 h = PR_ROTATE_LEFT32(h, 4) ^ *p;
413 return h;
416 static PRBool
417 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
418 const void *key)
420 const BlobHashEntry *entry =
421 static_cast<const BlobHashEntry *>(hdr);
423 const BlobImpl::Data *left = &entry->mBlob->mData;
425 const BlobImpl::Data *right =
426 static_cast<const BlobImpl::Data *>(key);
428 return (left->mLength == right->mLength)
429 && 0 == memcmp(left->mBytes, right->mBytes, right->mLength);
433 static PLDHashTableOps gBlobTableOps = {
434 PL_DHashAllocTable,
435 PL_DHashFreeTable,
436 BlobHashEntry::HashKey,
437 BlobHashEntry::MatchEntry,
438 PL_DHashMoveEntryStub,
439 PL_DHashClearEntryStub,
440 PL_DHashFinalizeStub,
441 nsnull
444 ////////////////////////////////////////////////////////////////////////
445 // LiteralImpl
447 // Currently, all literals are implemented exactly the same way;
448 // i.e., there is are no resource factories to allow you to generate
449 // customer resources. I doubt that makes sense, anyway.
451 class LiteralImpl : public nsIRDFLiteral {
452 public:
453 static nsresult
454 Create(const PRUnichar* aValue, nsIRDFLiteral** aResult);
456 // nsISupports
457 NS_DECL_ISUPPORTS
459 // nsIRDFNode
460 NS_DECL_NSIRDFNODE
462 // nsIRDFLiteral
463 NS_DECL_NSIRDFLITERAL
465 protected:
466 LiteralImpl(const PRUnichar* s);
467 virtual ~LiteralImpl();
469 const PRUnichar* GetValue() const {
470 size_t objectSize = ((sizeof(LiteralImpl) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
471 return reinterpret_cast<const PRUnichar*>(reinterpret_cast<const unsigned char*>(this) + objectSize);
476 nsresult
477 LiteralImpl::Create(const PRUnichar* aValue, nsIRDFLiteral** aResult)
479 // Goofy math to get alignment right. Copied from nsSharedString.h.
480 size_t objectSize = ((sizeof(LiteralImpl) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
481 size_t stringLen = nsCharTraits<PRUnichar>::length(aValue);
482 size_t stringSize = (stringLen + 1) * sizeof(PRUnichar);
484 void* objectPtr = operator new(objectSize + stringSize);
485 if (! objectPtr)
486 return NS_ERROR_NULL_POINTER;
488 PRUnichar* buf = reinterpret_cast<PRUnichar*>(static_cast<unsigned char*>(objectPtr) + objectSize);
489 nsCharTraits<PRUnichar>::copy(buf, aValue, stringLen + 1);
491 NS_ADDREF(*aResult = new (objectPtr) LiteralImpl(buf));
492 return NS_OK;
496 LiteralImpl::LiteralImpl(const PRUnichar* s)
498 RDFServiceImpl::gRDFService->RegisterLiteral(this);
499 NS_ADDREF(RDFServiceImpl::gRDFService);
502 LiteralImpl::~LiteralImpl()
504 RDFServiceImpl::gRDFService->UnregisterLiteral(this);
506 // Use NS_RELEASE2() here, because we want to decrease the
507 // refcount, but not null out the gRDFService pointer (which is
508 // what a vanilla NS_RELEASE() would do).
509 nsrefcnt refcnt;
510 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
513 NS_IMPL_THREADSAFE_ADDREF(LiteralImpl)
514 NS_IMPL_THREADSAFE_RELEASE(LiteralImpl)
516 nsresult
517 LiteralImpl::QueryInterface(REFNSIID iid, void** result)
519 if (! result)
520 return NS_ERROR_NULL_POINTER;
522 *result = nsnull;
523 if (iid.Equals(kIRDFLiteralIID) ||
524 iid.Equals(kIRDFNodeIID) ||
525 iid.Equals(kISupportsIID)) {
526 *result = static_cast<nsIRDFLiteral*>(this);
527 AddRef();
528 return NS_OK;
530 return NS_NOINTERFACE;
533 NS_IMETHODIMP
534 LiteralImpl::EqualsNode(nsIRDFNode* aNode, PRBool* aResult)
536 nsresult rv;
537 nsIRDFLiteral* literal;
538 rv = aNode->QueryInterface(kIRDFLiteralIID, (void**) &literal);
539 if (NS_SUCCEEDED(rv)) {
540 *aResult = (static_cast<nsIRDFLiteral*>(this) == literal);
541 NS_RELEASE(literal);
542 return NS_OK;
544 else if (rv == NS_NOINTERFACE) {
545 *aResult = PR_FALSE;
546 return NS_OK;
548 else {
549 return rv;
553 NS_IMETHODIMP
554 LiteralImpl::GetValue(PRUnichar* *value)
556 NS_ASSERTION(value, "null ptr");
557 if (! value)
558 return NS_ERROR_NULL_POINTER;
560 const PRUnichar *temp = GetValue();
561 *value = temp? NS_strdup(temp) : 0;
562 return NS_OK;
566 NS_IMETHODIMP
567 LiteralImpl::GetValueConst(const PRUnichar** aValue)
569 *aValue = GetValue();
570 return NS_OK;
573 ////////////////////////////////////////////////////////////////////////
574 // DateImpl
577 class DateImpl : public nsIRDFDate {
578 public:
579 DateImpl(const PRTime s);
580 virtual ~DateImpl();
582 // nsISupports
583 NS_DECL_ISUPPORTS
585 // nsIRDFNode
586 NS_DECL_NSIRDFNODE
588 // nsIRDFDate
589 NS_IMETHOD GetValue(PRTime *value);
591 private:
592 nsresult EqualsDate(nsIRDFDate* date, PRBool* result);
593 PRTime mValue;
597 DateImpl::DateImpl(const PRTime s)
598 : mValue(s)
600 RDFServiceImpl::gRDFService->RegisterDate(this);
601 NS_ADDREF(RDFServiceImpl::gRDFService);
604 DateImpl::~DateImpl()
606 RDFServiceImpl::gRDFService->UnregisterDate(this);
608 // Use NS_RELEASE2() here, because we want to decrease the
609 // refcount, but not null out the gRDFService pointer (which is
610 // what a vanilla NS_RELEASE() would do).
611 nsrefcnt refcnt;
612 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
615 NS_IMPL_ADDREF(DateImpl)
616 NS_IMPL_RELEASE(DateImpl)
618 nsresult
619 DateImpl::QueryInterface(REFNSIID iid, void** result)
621 if (! result)
622 return NS_ERROR_NULL_POINTER;
624 *result = nsnull;
625 if (iid.Equals(kIRDFDateIID) ||
626 iid.Equals(kIRDFNodeIID) ||
627 iid.Equals(kISupportsIID)) {
628 *result = static_cast<nsIRDFDate*>(this);
629 AddRef();
630 return NS_OK;
632 return NS_NOINTERFACE;
635 NS_IMETHODIMP
636 DateImpl::EqualsNode(nsIRDFNode* node, PRBool* result)
638 nsresult rv;
639 nsIRDFDate* date;
640 if (NS_SUCCEEDED(node->QueryInterface(kIRDFDateIID, (void**) &date))) {
641 rv = EqualsDate(date, result);
642 NS_RELEASE(date);
644 else {
645 *result = PR_FALSE;
646 rv = NS_OK;
648 return rv;
651 NS_IMETHODIMP
652 DateImpl::GetValue(PRTime *value)
654 NS_ASSERTION(value, "null ptr");
655 if (! value)
656 return NS_ERROR_NULL_POINTER;
658 *value = mValue;
659 return NS_OK;
663 nsresult
664 DateImpl::EqualsDate(nsIRDFDate* date, PRBool* result)
666 NS_ASSERTION(date && result, "null ptr");
667 if (!date || !result)
668 return NS_ERROR_NULL_POINTER;
670 nsresult rv;
671 PRTime p;
672 if (NS_FAILED(rv = date->GetValue(&p)))
673 return rv;
675 *result = LL_EQ(p, mValue);
676 return NS_OK;
679 ////////////////////////////////////////////////////////////////////////
680 // IntImpl
683 class IntImpl : public nsIRDFInt {
684 public:
685 IntImpl(PRInt32 s);
686 virtual ~IntImpl();
688 // nsISupports
689 NS_DECL_ISUPPORTS
691 // nsIRDFNode
692 NS_DECL_NSIRDFNODE
694 // nsIRDFInt
695 NS_IMETHOD GetValue(PRInt32 *value);
697 private:
698 nsresult EqualsInt(nsIRDFInt* value, PRBool* result);
699 PRInt32 mValue;
703 IntImpl::IntImpl(PRInt32 s)
704 : mValue(s)
706 RDFServiceImpl::gRDFService->RegisterInt(this);
707 NS_ADDREF(RDFServiceImpl::gRDFService);
710 IntImpl::~IntImpl()
712 RDFServiceImpl::gRDFService->UnregisterInt(this);
714 // Use NS_RELEASE2() here, because we want to decrease the
715 // refcount, but not null out the gRDFService pointer (which is
716 // what a vanilla NS_RELEASE() would do).
717 nsrefcnt refcnt;
718 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
721 NS_IMPL_ADDREF(IntImpl)
722 NS_IMPL_RELEASE(IntImpl)
724 nsresult
725 IntImpl::QueryInterface(REFNSIID iid, void** result)
727 if (! result)
728 return NS_ERROR_NULL_POINTER;
730 *result = nsnull;
731 if (iid.Equals(kIRDFIntIID) ||
732 iid.Equals(kIRDFNodeIID) ||
733 iid.Equals(kISupportsIID)) {
734 *result = static_cast<nsIRDFInt*>(this);
735 AddRef();
736 return NS_OK;
738 return NS_NOINTERFACE;
741 NS_IMETHODIMP
742 IntImpl::EqualsNode(nsIRDFNode* node, PRBool* result)
744 nsresult rv;
745 nsIRDFInt* intValue;
746 if (NS_SUCCEEDED(node->QueryInterface(kIRDFIntIID, (void**) &intValue))) {
747 rv = EqualsInt(intValue, result);
748 NS_RELEASE(intValue);
750 else {
751 *result = PR_FALSE;
752 rv = NS_OK;
754 return rv;
757 NS_IMETHODIMP
758 IntImpl::GetValue(PRInt32 *value)
760 NS_ASSERTION(value, "null ptr");
761 if (! value)
762 return NS_ERROR_NULL_POINTER;
764 *value = mValue;
765 return NS_OK;
769 nsresult
770 IntImpl::EqualsInt(nsIRDFInt* intValue, PRBool* result)
772 NS_ASSERTION(intValue && result, "null ptr");
773 if (!intValue || !result)
774 return NS_ERROR_NULL_POINTER;
776 nsresult rv;
777 PRInt32 p;
778 if (NS_FAILED(rv = intValue->GetValue(&p)))
779 return rv;
781 *result = (p == mValue);
782 return NS_OK;
785 ////////////////////////////////////////////////////////////////////////
786 // RDFServiceImpl
788 RDFServiceImpl*
789 RDFServiceImpl::gRDFService;
791 RDFServiceImpl::RDFServiceImpl()
792 : mNamedDataSources(nsnull)
794 mResources.ops = nsnull;
795 mLiterals.ops = nsnull;
796 mInts.ops = nsnull;
797 mDates.ops = nsnull;
798 mBlobs.ops = nsnull;
799 gRDFService = this;
802 nsresult
803 RDFServiceImpl::Init()
805 nsresult rv;
807 mNamedDataSources = PL_NewHashTable(23,
808 PL_HashString,
809 PL_CompareStrings,
810 PL_CompareValues,
811 &dataSourceHashAllocOps, nsnull);
813 if (! mNamedDataSources)
814 return NS_ERROR_OUT_OF_MEMORY;
816 if (!PL_DHashTableInit(&mResources, &gResourceTableOps, nsnull,
817 sizeof(ResourceHashEntry), PL_DHASH_MIN_SIZE)) {
818 mResources.ops = nsnull;
819 return NS_ERROR_OUT_OF_MEMORY;
821 if (!PL_DHashTableInit(&mLiterals, &gLiteralTableOps, nsnull,
822 sizeof(LiteralHashEntry), PL_DHASH_MIN_SIZE)) {
823 mLiterals.ops = nsnull;
824 return NS_ERROR_OUT_OF_MEMORY;
826 if (!PL_DHashTableInit(&mInts, &gIntTableOps, nsnull,
827 sizeof(IntHashEntry), PL_DHASH_MIN_SIZE)) {
828 mInts.ops = nsnull;
829 return NS_ERROR_OUT_OF_MEMORY;
831 if (!PL_DHashTableInit(&mDates, &gDateTableOps, nsnull,
832 sizeof(DateHashEntry), PL_DHASH_MIN_SIZE)) {
833 mDates.ops = nsnull;
834 return NS_ERROR_OUT_OF_MEMORY;
836 if (!PL_DHashTableInit(&mBlobs, &gBlobTableOps, nsnull,
837 sizeof(BlobHashEntry), PL_DHASH_MIN_SIZE)) {
838 mBlobs.ops = nsnull;
839 return NS_ERROR_OUT_OF_MEMORY;
841 mDefaultResourceFactory = do_GetClassObject(kRDFDefaultResourceCID, &rv);
842 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get default resource factory");
843 if (NS_FAILED(rv)) return rv;
845 #ifdef PR_LOGGING
846 if (! gLog)
847 gLog = PR_NewLogModule("nsRDFService");
848 #endif
850 return NS_OK;
854 RDFServiceImpl::~RDFServiceImpl()
856 if (mNamedDataSources) {
857 PL_HashTableDestroy(mNamedDataSources);
858 mNamedDataSources = nsnull;
860 if (mResources.ops)
861 PL_DHashTableFinish(&mResources);
862 if (mLiterals.ops)
863 PL_DHashTableFinish(&mLiterals);
864 if (mInts.ops)
865 PL_DHashTableFinish(&mInts);
866 if (mDates.ops)
867 PL_DHashTableFinish(&mDates);
868 if (mBlobs.ops)
869 PL_DHashTableFinish(&mBlobs);
870 gRDFService = nsnull;
874 // static
875 nsresult
876 RDFServiceImpl::CreateSingleton(nsISupports* aOuter,
877 const nsIID& aIID, void **aResult)
879 NS_ENSURE_NO_AGGREGATION(aOuter);
881 if (gRDFService) {
882 NS_ERROR("Trying to create RDF serviec twice.");
883 return gRDFService->QueryInterface(aIID, aResult);
886 nsRefPtr<RDFServiceImpl> serv = new RDFServiceImpl();
887 if (!serv)
888 return NS_ERROR_OUT_OF_MEMORY;
890 nsresult rv = serv->Init();
891 if (NS_FAILED(rv))
892 return rv;
894 return serv->QueryInterface(aIID, aResult);
897 NS_IMPL_THREADSAFE_ISUPPORTS2(RDFServiceImpl, nsIRDFService, nsISupportsWeakReference)
899 // Per RFC2396.
900 static const PRUint8
901 kLegalSchemeChars[] = {
902 // ASCII Bits Ordered Hex
903 // 01234567 76543210
904 0x00, // 00-07
905 0x00, // 08-0F
906 0x00, // 10-17
907 0x00, // 18-1F
908 0x00, // 20-27 !"#$%&' 00000000 00000000
909 0x28, // 28-2F ()*+,-./ 00010100 00101000 0x28
910 0xff, // 30-37 01234567 11111111 11111111 0xFF
911 0x03, // 38-3F 89:;<=>? 11000000 00000011 0x03
912 0xfe, // 40-47 @ABCDEFG 01111111 11111110 0xFE
913 0xff, // 48-4F HIJKLMNO 11111111 11111111 0xFF
914 0xff, // 50-57 PQRSTUVW 11111111 11111111 0xFF
915 0x87, // 58-5F XYZ[\]^_ 11100001 10000111 0x87
916 0xfe, // 60-67 `abcdefg 01111111 11111110 0xFE
917 0xff, // 68-6F hijklmno 11111111 11111111 0xFF
918 0xff, // 70-77 pqrstuvw 11111111 11111111 0xFF
919 0x07, // 78-7F xyz{|}~ 11100000 00000111 0x07
920 0x00, 0x00, 0x00, 0x00, // >= 80
921 0x00, 0x00, 0x00, 0x00,
922 0x00, 0x00, 0x00, 0x00,
923 0x00, 0x00, 0x00, 0x00
926 static inline PRBool
927 IsLegalSchemeCharacter(const char aChar)
929 PRUint8 mask = kLegalSchemeChars[aChar >> 3];
930 PRUint8 bit = PR_BIT(aChar & 0x7);
931 return PRBool((mask & bit) != 0);
935 NS_IMETHODIMP
936 RDFServiceImpl::GetResource(const nsACString& aURI, nsIRDFResource** aResource)
938 // Sanity checks
939 NS_PRECONDITION(aResource != nsnull, "null ptr");
940 NS_PRECONDITION(!aURI.IsEmpty(), "URI is empty");
941 if (! aResource)
942 return NS_ERROR_NULL_POINTER;
943 if (aURI.IsEmpty())
944 return NS_ERROR_INVALID_ARG;
946 const nsAFlatCString& flatURI = PromiseFlatCString(aURI);
947 PR_LOG(gLog, PR_LOG_DEBUG, ("rdfserv get-resource %s", flatURI.get()));
949 // First, check the cache to see if we've already created and
950 // registered this thing.
951 PLDHashEntryHdr *hdr =
952 PL_DHashTableOperate(&mResources, flatURI.get(), PL_DHASH_LOOKUP);
954 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
955 ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
956 NS_ADDREF(*aResource = entry->mResource);
957 return NS_OK;
960 // Nope. So go to the repository to create it.
962 // Compute the scheme of the URI. Scan forward until we either:
964 // 1. Reach the end of the string
965 // 2. Encounter a non-alpha character
966 // 3. Encouter a colon.
968 // If we encounter a colon _before_ encountering a non-alpha
969 // character, then assume it's the scheme.
971 // XXX Although it's really not correct, we'll allow underscore
972 // characters ('_'), too.
973 nsACString::const_iterator p, end;
974 aURI.BeginReading(p);
975 aURI.EndReading(end);
976 while (p != end && IsLegalSchemeCharacter(*p))
977 ++p;
979 nsresult rv;
980 nsCOMPtr<nsIFactory> factory;
982 nsACString::const_iterator begin;
983 aURI.BeginReading(begin);
984 if (*p == ':') {
985 // There _was_ a scheme. First see if it's the same scheme
986 // that we just tried to use...
987 if (mLastFactory && mLastURIPrefix.Equals(Substring(begin, p)))
988 factory = mLastFactory;
989 else {
990 // Try to find a factory using the component manager.
991 nsACString::const_iterator begin;
992 aURI.BeginReading(begin);
993 nsCAutoString contractID;
994 contractID = NS_LITERAL_CSTRING(NS_RDF_RESOURCE_FACTORY_CONTRACTID_PREFIX) +
995 Substring(begin, p);
997 factory = do_GetClassObject(contractID.get());
998 if (factory) {
999 // Store the factory in our one-element cache.
1000 if (p != begin) {
1001 mLastFactory = factory;
1002 mLastURIPrefix = Substring(begin, p);
1008 if (! factory) {
1009 // fall through to using the "default" resource factory if either:
1011 // 1. The URI didn't have a scheme, or
1012 // 2. There was no resource factory registered for the scheme.
1013 factory = mDefaultResourceFactory;
1015 // Store the factory in our one-element cache.
1016 if (p != begin) {
1017 mLastFactory = factory;
1018 mLastURIPrefix = Substring(begin, p);
1022 nsIRDFResource *result;
1023 rv = factory->CreateInstance(nsnull, NS_GET_IID(nsIRDFResource), (void**) &result);
1024 if (NS_FAILED(rv)) return rv;
1026 // Now initialize it with its URI. At this point, the resource
1027 // implementation should register itself with the RDF service.
1028 rv = result->Init(flatURI.get());
1029 if (NS_FAILED(rv)) {
1030 NS_ERROR("unable to initialize resource");
1031 NS_RELEASE(result);
1032 return rv;
1035 *aResource = result; // already refcounted from repository
1036 return rv;
1039 NS_IMETHODIMP
1040 RDFServiceImpl::GetUnicodeResource(const nsAString& aURI, nsIRDFResource** aResource)
1042 return GetResource(NS_ConvertUTF16toUTF8(aURI), aResource);
1046 NS_IMETHODIMP
1047 RDFServiceImpl::GetAnonymousResource(nsIRDFResource** aResult)
1049 static PRUint32 gCounter = 0;
1050 static char gChars[] = "0123456789abcdef"
1051 "ghijklmnopqrstuv"
1052 "wxyzABCDEFGHIJKL"
1053 "MNOPQRSTUVWXYZ.+";
1055 static PRInt32 kMask = 0x003f;
1056 static PRInt32 kShift = 6;
1058 if (! gCounter) {
1059 // Start it at a semi-unique value, just to minimize the
1060 // chance that we get into a situation where
1062 // 1. An anonymous resource gets serialized out in a graph
1063 // 2. Reboot
1064 // 3. The same anonymous resource gets requested, and refers
1065 // to something completely different.
1066 // 4. The serialization is read back in.
1067 LL_L2UI(gCounter, PR_Now());
1070 nsresult rv;
1071 nsCAutoString s;
1073 do {
1074 // Ugh, this is a really sloppy way to do this; I copied the
1075 // implementation from the days when it lived outside the RDF
1076 // service. Now that it's a member we can be more cleverer.
1078 s.Truncate();
1079 s.Append("rdf:#$");
1081 PRUint32 id = ++gCounter;
1082 while (id) {
1083 char ch = gChars[(id & kMask)];
1084 s.Append(ch);
1085 id >>= kShift;
1088 nsIRDFResource* resource;
1089 rv = GetResource(s, &resource);
1090 if (NS_FAILED(rv)) return rv;
1092 // XXX an ugly but effective way to make sure that this
1093 // resource is really unique in the world.
1094 resource->AddRef();
1095 nsrefcnt refcnt = resource->Release();
1097 if (refcnt == 1) {
1098 *aResult = resource;
1099 break;
1102 NS_RELEASE(resource);
1103 } while (1);
1105 return NS_OK;
1109 NS_IMETHODIMP
1110 RDFServiceImpl::GetLiteral(const PRUnichar* aValue, nsIRDFLiteral** aLiteral)
1112 NS_PRECONDITION(aValue != nsnull, "null ptr");
1113 if (! aValue)
1114 return NS_ERROR_NULL_POINTER;
1116 NS_PRECONDITION(aLiteral != nsnull, "null ptr");
1117 if (! aLiteral)
1118 return NS_ERROR_NULL_POINTER;
1120 // See if we have one already cached
1121 PLDHashEntryHdr *hdr =
1122 PL_DHashTableOperate(&mLiterals, aValue, PL_DHASH_LOOKUP);
1124 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
1125 LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
1126 NS_ADDREF(*aLiteral = entry->mLiteral);
1127 return NS_OK;
1130 // Nope. Create a new one
1131 return LiteralImpl::Create(aValue, aLiteral);
1134 NS_IMETHODIMP
1135 RDFServiceImpl::GetDateLiteral(PRTime aTime, nsIRDFDate** aResult)
1137 // See if we have one already cached
1138 PLDHashEntryHdr *hdr =
1139 PL_DHashTableOperate(&mDates, &aTime, PL_DHASH_LOOKUP);
1141 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
1142 DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
1143 NS_ADDREF(*aResult = entry->mDate);
1144 return NS_OK;
1147 DateImpl* result = new DateImpl(aTime);
1148 if (! result)
1149 return NS_ERROR_OUT_OF_MEMORY;
1151 NS_ADDREF(*aResult = result);
1152 return NS_OK;
1155 NS_IMETHODIMP
1156 RDFServiceImpl::GetIntLiteral(PRInt32 aInt, nsIRDFInt** aResult)
1158 // See if we have one already cached
1159 PLDHashEntryHdr *hdr =
1160 PL_DHashTableOperate(&mInts, &aInt, PL_DHASH_LOOKUP);
1162 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
1163 IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
1164 NS_ADDREF(*aResult = entry->mInt);
1165 return NS_OK;
1168 IntImpl* result = new IntImpl(aInt);
1169 if (! result)
1170 return NS_ERROR_OUT_OF_MEMORY;
1172 NS_ADDREF(*aResult = result);
1173 return NS_OK;
1176 NS_IMETHODIMP
1177 RDFServiceImpl::GetBlobLiteral(const PRUint8 *aBytes, PRInt32 aLength,
1178 nsIRDFBlob **aResult)
1180 BlobImpl::Data key = { aLength, const_cast<PRUint8 *>(aBytes) };
1182 PLDHashEntryHdr *hdr =
1183 PL_DHashTableOperate(&mBlobs, &key, PL_DHASH_LOOKUP);
1185 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
1186 BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
1187 NS_ADDREF(*aResult = entry->mBlob);
1188 return NS_OK;
1191 BlobImpl *result = new BlobImpl(aBytes, aLength);
1192 if (! result)
1193 return NS_ERROR_OUT_OF_MEMORY;
1195 NS_ADDREF(*aResult = result);
1196 return NS_OK;
1199 NS_IMETHODIMP
1200 RDFServiceImpl::IsAnonymousResource(nsIRDFResource* aResource, PRBool* _result)
1202 NS_PRECONDITION(aResource != nsnull, "null ptr");
1203 if (! aResource)
1204 return NS_ERROR_NULL_POINTER;
1206 nsresult rv;
1208 const char* uri;
1209 rv = aResource->GetValueConst(&uri);
1210 if (NS_FAILED(rv)) return rv;
1212 if ((uri[0] == 'r') &&
1213 (uri[1] == 'd') &&
1214 (uri[2] == 'f') &&
1215 (uri[3] == ':') &&
1216 (uri[4] == '#') &&
1217 (uri[5] == '$')) {
1218 *_result = PR_TRUE;
1220 else {
1221 *_result = PR_FALSE;
1224 return NS_OK;
1227 NS_IMETHODIMP
1228 RDFServiceImpl::RegisterResource(nsIRDFResource* aResource, PRBool aReplace)
1230 NS_PRECONDITION(aResource != nsnull, "null ptr");
1231 if (! aResource)
1232 return NS_ERROR_NULL_POINTER;
1234 nsresult rv;
1236 const char* uri;
1237 rv = aResource->GetValueConst(&uri);
1238 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get URI from resource");
1239 if (NS_FAILED(rv)) return rv;
1241 NS_ASSERTION(uri != nsnull, "resource has no URI");
1242 if (! uri)
1243 return NS_ERROR_NULL_POINTER;
1245 PLDHashEntryHdr *hdr =
1246 PL_DHashTableOperate(&mResources, uri, PL_DHASH_LOOKUP);
1248 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
1249 if (!aReplace) {
1250 NS_WARNING("resource already registered, and replace not specified");
1251 return NS_ERROR_FAILURE; // already registered
1254 // N.B., we do _not_ release the original resource because we
1255 // only ever held a weak reference to it. We simply replace
1256 // it.
1258 PR_LOG(gLog, PR_LOG_DEBUG,
1259 ("rdfserv replace-resource [%p] <-- [%p] %s",
1260 static_cast<ResourceHashEntry *>(hdr)->mResource,
1261 aResource, (const char*) uri));
1263 else {
1264 hdr = PL_DHashTableOperate(&mResources, uri, PL_DHASH_ADD);
1265 if (! hdr)
1266 return NS_ERROR_OUT_OF_MEMORY;
1268 PR_LOG(gLog, PR_LOG_DEBUG,
1269 ("rdfserv register-resource [%p] %s",
1270 aResource, (const char*) uri));
1273 // N.B., we only hold a weak reference to the resource: that way,
1274 // the resource can be destroyed when the last refcount goes
1275 // away. The single addref that the CreateResource() call made
1276 // will be owned by the callee.
1277 ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
1278 entry->mResource = aResource;
1279 entry->mKey = uri;
1281 return NS_OK;
1284 NS_IMETHODIMP
1285 RDFServiceImpl::UnregisterResource(nsIRDFResource* aResource)
1287 NS_PRECONDITION(aResource != nsnull, "null ptr");
1288 if (! aResource)
1289 return NS_ERROR_NULL_POINTER;
1291 nsresult rv;
1293 const char* uri;
1294 rv = aResource->GetValueConst(&uri);
1295 if (NS_FAILED(rv)) return rv;
1297 NS_ASSERTION(uri != nsnull, "resource has no URI");
1298 if (! uri)
1299 return NS_ERROR_UNEXPECTED;
1301 PR_LOG(gLog, PR_LOG_DEBUG,
1302 ("rdfserv unregister-resource [%p] %s",
1303 aResource, (const char*) uri));
1305 #ifdef DEBUG
1306 if (PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mResources, uri, PL_DHASH_LOOKUP)))
1307 NS_WARNING("resource was never registered");
1308 #endif
1310 PL_DHashTableOperate(&mResources, uri, PL_DHASH_REMOVE);
1311 return NS_OK;
1314 NS_IMETHODIMP
1315 RDFServiceImpl::RegisterDataSource(nsIRDFDataSource* aDataSource, PRBool aReplace)
1317 NS_PRECONDITION(aDataSource != nsnull, "null ptr");
1318 if (! aDataSource)
1319 return NS_ERROR_NULL_POINTER;
1321 nsresult rv;
1323 nsXPIDLCString uri;
1324 rv = aDataSource->GetURI(getter_Copies(uri));
1325 if (NS_FAILED(rv)) return rv;
1327 PLHashEntry** hep =
1328 PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
1330 if (*hep) {
1331 if (! aReplace)
1332 return NS_ERROR_FAILURE; // already registered
1334 // N.B., we only hold a weak reference to the datasource, so
1335 // just replace the old with the new and don't touch any
1336 // refcounts.
1337 PR_LOG(gLog, PR_LOG_NOTICE,
1338 ("rdfserv replace-datasource [%p] <-- [%p] %s",
1339 (*hep)->value, aDataSource, (const char*) uri));
1341 (*hep)->value = aDataSource;
1343 else {
1344 const char* key = PL_strdup(uri);
1345 if (! key)
1346 return NS_ERROR_OUT_OF_MEMORY;
1348 PL_HashTableAdd(mNamedDataSources, key, aDataSource);
1350 PR_LOG(gLog, PR_LOG_NOTICE,
1351 ("rdfserv register-datasource [%p] %s",
1352 aDataSource, (const char*) uri));
1354 // N.B., we only hold a weak reference to the datasource, so don't
1355 // addref.
1358 return NS_OK;
1361 NS_IMETHODIMP
1362 RDFServiceImpl::UnregisterDataSource(nsIRDFDataSource* aDataSource)
1364 NS_PRECONDITION(aDataSource != nsnull, "null ptr");
1365 if (! aDataSource)
1366 return NS_ERROR_NULL_POINTER;
1368 nsresult rv;
1370 nsXPIDLCString uri;
1371 rv = aDataSource->GetURI(getter_Copies(uri));
1372 if (NS_FAILED(rv)) return rv;
1374 //NS_ASSERTION(uri != nsnull, "datasource has no URI");
1375 if (! uri)
1376 return NS_ERROR_UNEXPECTED;
1378 PLHashEntry** hep =
1379 PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
1381 // It may well be that this datasource was never registered. If
1382 // so, don't unregister it.
1383 if (! *hep || ((*hep)->value != aDataSource))
1384 return NS_OK;
1386 // N.B., we only held a weak reference to the datasource, so we
1387 // don't release here.
1388 PL_HashTableRawRemove(mNamedDataSources, hep, *hep);
1390 PR_LOG(gLog, PR_LOG_NOTICE,
1391 ("rdfserv unregister-datasource [%p] %s",
1392 aDataSource, (const char*) uri));
1394 return NS_OK;
1397 NS_IMETHODIMP
1398 RDFServiceImpl::GetDataSource(const char* aURI, nsIRDFDataSource** aDataSource)
1400 // Use the other GetDataSource and ask for a non-blocking Refresh.
1401 // If you wanted it loaded synchronously, then you should've tried to do it
1402 // yourself, or used GetDataSourceBlocking.
1403 return GetDataSource( aURI, PR_FALSE, aDataSource );
1406 NS_IMETHODIMP
1407 RDFServiceImpl::GetDataSourceBlocking(const char* aURI, nsIRDFDataSource** aDataSource)
1409 // Use GetDataSource and ask for a blocking Refresh.
1410 return GetDataSource( aURI, PR_TRUE, aDataSource );
1413 nsresult
1414 RDFServiceImpl::GetDataSource(const char* aURI, PRBool aBlock, nsIRDFDataSource** aDataSource)
1416 NS_PRECONDITION(aURI != nsnull, "null ptr");
1417 if (! aURI)
1418 return NS_ERROR_NULL_POINTER;
1420 nsresult rv;
1422 // Attempt to canonify the URI before we look for it in the
1423 // cache. We won't bother doing this on `rdf:' URIs to avoid
1424 // useless (and expensive) protocol handler lookups.
1425 nsCAutoString spec(aURI);
1427 if (!StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
1428 nsCOMPtr<nsIURI> uri;
1429 NS_NewURI(getter_AddRefs(uri), spec);
1430 if (uri)
1431 uri->GetSpec(spec);
1434 // First, check the cache to see if we already have this
1435 // datasource loaded and initialized.
1437 nsIRDFDataSource* cached =
1438 static_cast<nsIRDFDataSource*>(PL_HashTableLookup(mNamedDataSources, spec.get()));
1440 if (cached) {
1441 NS_ADDREF(cached);
1442 *aDataSource = cached;
1443 return NS_OK;
1447 // Nope. So go to the repository to try to create it.
1448 nsCOMPtr<nsIRDFDataSource> ds;
1449 if (StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
1450 // It's a built-in data source. Convert it to a contract ID.
1451 nsCAutoString contractID(
1452 NS_LITERAL_CSTRING(NS_RDF_DATASOURCE_CONTRACTID_PREFIX) +
1453 Substring(spec, 4, spec.Length() - 4));
1455 // Strip params to get ``base'' contractID for data source.
1456 PRInt32 p = contractID.FindChar(PRUnichar('&'));
1457 if (p >= 0)
1458 contractID.Truncate(p);
1460 ds = do_GetService(contractID.get(), &rv);
1461 if (NS_FAILED(rv)) return rv;
1463 nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(ds);
1464 if (remote) {
1465 rv = remote->Init(spec.get());
1466 if (NS_FAILED(rv)) return rv;
1469 else {
1470 // Try to load this as an RDF/XML data source
1471 ds = do_CreateInstance(kRDFXMLDataSourceCID, &rv);
1472 if (NS_FAILED(rv)) return rv;
1474 nsCOMPtr<nsIRDFRemoteDataSource> remote(do_QueryInterface(ds));
1475 NS_ASSERTION(remote, "not a remote RDF/XML data source!");
1476 if (! remote) return NS_ERROR_UNEXPECTED;
1478 rv = remote->Init(spec.get());
1479 if (NS_FAILED(rv)) return rv;
1481 rv = remote->Refresh(aBlock);
1482 if (NS_FAILED(rv)) return rv;
1485 *aDataSource = ds;
1486 NS_ADDREF(*aDataSource);
1487 return NS_OK;
1490 ////////////////////////////////////////////////////////////////////////
1492 nsresult
1493 RDFServiceImpl::RegisterLiteral(nsIRDFLiteral* aLiteral)
1495 const PRUnichar* value;
1496 aLiteral->GetValueConst(&value);
1498 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mLiterals,
1499 value,
1500 PL_DHASH_LOOKUP)),
1501 "literal already registered");
1503 PLDHashEntryHdr *hdr =
1504 PL_DHashTableOperate(&mLiterals, value, PL_DHASH_ADD);
1506 if (! hdr)
1507 return NS_ERROR_OUT_OF_MEMORY;
1509 LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
1511 // N.B., we only hold a weak reference to the literal: that
1512 // way, the literal can be destroyed when the last refcount
1513 // goes away. The single addref that the CreateLiteral() call
1514 // made will be owned by the callee.
1515 entry->mLiteral = aLiteral;
1516 entry->mKey = value;
1518 PR_LOG(gLog, PR_LOG_DEBUG,
1519 ("rdfserv register-literal [%p] %s",
1520 aLiteral, (const PRUnichar*) value));
1522 return NS_OK;
1526 nsresult
1527 RDFServiceImpl::UnregisterLiteral(nsIRDFLiteral* aLiteral)
1529 const PRUnichar* value;
1530 aLiteral->GetValueConst(&value);
1532 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mLiterals,
1533 value,
1534 PL_DHASH_LOOKUP)),
1535 "literal was never registered");
1537 PL_DHashTableOperate(&mLiterals, value, PL_DHASH_REMOVE);
1539 // N.B. that we _don't_ release the literal: we only held a weak
1540 // reference to it in the hashtable.
1541 PR_LOG(gLog, PR_LOG_DEBUG,
1542 ("rdfserv unregister-literal [%p] %s",
1543 aLiteral, (const PRUnichar*) value));
1545 return NS_OK;
1548 //----------------------------------------------------------------------
1550 nsresult
1551 RDFServiceImpl::RegisterInt(nsIRDFInt* aInt)
1553 PRInt32 value;
1554 aInt->GetValue(&value);
1556 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mInts,
1557 &value,
1558 PL_DHASH_LOOKUP)),
1559 "int already registered");
1561 PLDHashEntryHdr *hdr =
1562 PL_DHashTableOperate(&mInts, &value, PL_DHASH_ADD);
1564 if (! hdr)
1565 return NS_ERROR_OUT_OF_MEMORY;
1567 IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
1569 // N.B., we only hold a weak reference to the literal: that
1570 // way, the literal can be destroyed when the last refcount
1571 // goes away. The single addref that the CreateInt() call
1572 // made will be owned by the callee.
1573 entry->mInt = aInt;
1574 entry->mKey = value;
1576 PR_LOG(gLog, PR_LOG_DEBUG,
1577 ("rdfserv register-int [%p] %d",
1578 aInt, value));
1580 return NS_OK;
1584 nsresult
1585 RDFServiceImpl::UnregisterInt(nsIRDFInt* aInt)
1587 PRInt32 value;
1588 aInt->GetValue(&value);
1590 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mInts,
1591 &value,
1592 PL_DHASH_LOOKUP)),
1593 "int was never registered");
1595 PL_DHashTableOperate(&mInts, &value, PL_DHASH_REMOVE);
1597 // N.B. that we _don't_ release the literal: we only held a weak
1598 // reference to it in the hashtable.
1599 PR_LOG(gLog, PR_LOG_DEBUG,
1600 ("rdfserv unregister-int [%p] %d",
1601 aInt, value));
1603 return NS_OK;
1606 //----------------------------------------------------------------------
1608 nsresult
1609 RDFServiceImpl::RegisterDate(nsIRDFDate* aDate)
1611 PRTime value;
1612 aDate->GetValue(&value);
1614 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mDates,
1615 &value,
1616 PL_DHASH_LOOKUP)),
1617 "date already registered");
1619 PLDHashEntryHdr *hdr =
1620 PL_DHashTableOperate(&mDates, &value, PL_DHASH_ADD);
1622 if (! hdr)
1623 return NS_ERROR_OUT_OF_MEMORY;
1625 DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
1627 // N.B., we only hold a weak reference to the literal: that
1628 // way, the literal can be destroyed when the last refcount
1629 // goes away. The single addref that the CreateDate() call
1630 // made will be owned by the callee.
1631 entry->mDate = aDate;
1632 entry->mKey = value;
1634 PR_LOG(gLog, PR_LOG_DEBUG,
1635 ("rdfserv register-date [%p] %ld",
1636 aDate, value));
1638 return NS_OK;
1642 nsresult
1643 RDFServiceImpl::UnregisterDate(nsIRDFDate* aDate)
1645 PRTime value;
1646 aDate->GetValue(&value);
1648 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mDates,
1649 &value,
1650 PL_DHASH_LOOKUP)),
1651 "date was never registered");
1653 PL_DHashTableOperate(&mDates, &value, PL_DHASH_REMOVE);
1655 // N.B. that we _don't_ release the literal: we only held a weak
1656 // reference to it in the hashtable.
1657 PR_LOG(gLog, PR_LOG_DEBUG,
1658 ("rdfserv unregister-date [%p] %ld",
1659 aDate, value));
1661 return NS_OK;
1664 nsresult
1665 RDFServiceImpl::RegisterBlob(BlobImpl *aBlob)
1667 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mBlobs,
1668 &aBlob->mData,
1669 PL_DHASH_LOOKUP)),
1670 "blob already registered");
1672 PLDHashEntryHdr *hdr =
1673 PL_DHashTableOperate(&mBlobs, &aBlob->mData, PL_DHASH_ADD);
1675 if (! hdr)
1676 return NS_ERROR_OUT_OF_MEMORY;
1678 BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
1680 // N.B., we only hold a weak reference to the literal: that
1681 // way, the literal can be destroyed when the last refcount
1682 // goes away. The single addref that the CreateInt() call
1683 // made will be owned by the callee.
1684 entry->mBlob = aBlob;
1686 PR_LOG(gLog, PR_LOG_DEBUG,
1687 ("rdfserv register-blob [%p] %s",
1688 aBlob, aBlob->mData.mBytes));
1690 return NS_OK;
1693 nsresult
1694 RDFServiceImpl::UnregisterBlob(BlobImpl *aBlob)
1696 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mBlobs,
1697 &aBlob->mData,
1698 PL_DHASH_LOOKUP)),
1699 "blob was never registered");
1701 PL_DHashTableOperate(&mBlobs, &aBlob->mData, PL_DHASH_REMOVE);
1703 // N.B. that we _don't_ release the literal: we only held a weak
1704 // reference to it in the hashtable.
1705 PR_LOG(gLog, PR_LOG_DEBUG,
1706 ("rdfserv unregister-blob [%p] %s",
1707 aBlob, aBlob->mData.mBytes));
1709 return NS_OK;