Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 : *
7 : *
8 : * This Original Code has been modified by IBM Corporation.
9 : * Modifications made by IBM described herein are
10 : * Copyright (c) International Business Machines
11 : * Corporation, 2000
12 : *
13 : * Modifications to Mozilla code or documentation
14 : * identified per MPL Section 3.3
15 : *
16 : * Date Modified by Description of modification
17 : * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
18 : * use in OS2
19 : */
20 :
21 : /*
22 :
23 : This file provides the implementation for the RDF service manager.
24 :
25 : TO DO
26 : -----
27 :
28 : 1) Implement the CreateDataBase() methods.
29 :
30 : 2) Cache date and int literals.
31 :
32 : */
33 :
34 : #include "nsRDFService.h"
35 : #include "nsCOMPtr.h"
36 : #include "nsAutoPtr.h"
37 : #include "nsMemory.h"
38 : #include "nsIAtom.h"
39 : #include "nsIComponentManager.h"
40 : #include "nsIRDFDataSource.h"
41 : #include "nsIRDFNode.h"
42 : #include "nsIRDFRemoteDataSource.h"
43 : #include "nsIServiceManager.h"
44 : #include "nsIFactory.h"
45 : #include "nsRDFCID.h"
46 : #include "nsString.h"
47 : #include "nsXPIDLString.h"
48 : #include "nsNetUtil.h"
49 : #include "nsIURI.h"
50 : #include "PLDHashTable.h"
51 : #include "plhash.h"
52 : #include "plstr.h"
53 : #include "mozilla/Logging.h"
54 : #include "prprf.h"
55 : #include "rdf.h"
56 : #include "nsCRT.h"
57 : #include "nsCRTGlue.h"
58 : #include "mozilla/HashFunctions.h"
59 : #include "mozilla/IntegerPrintfMacros.h"
60 :
61 : using namespace mozilla;
62 :
63 : ////////////////////////////////////////////////////////////////////////
64 :
65 : static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
66 : static NS_DEFINE_CID(kRDFDefaultResourceCID, NS_RDFDEFAULTRESOURCE_CID);
67 :
68 : static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
69 : static NS_DEFINE_IID(kIRDFDateIID, NS_IRDFDATE_IID);
70 : static NS_DEFINE_IID(kIRDFIntIID, NS_IRDFINT_IID);
71 : static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
72 : static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
73 :
74 : static LazyLogModule gLog("nsRDFService");
75 :
76 : class BlobImpl;
77 :
78 : // These functions are copied from nsprpub/lib/ds/plhash.c, with one
79 : // change to free the key in DataSourceFreeEntry.
80 : // XXX sigh, why were DefaultAllocTable et. al. declared static, anyway?
81 :
82 : static void *
83 6 : DataSourceAllocTable(void *pool, size_t size)
84 : {
85 6 : return malloc(size);
86 : }
87 :
88 : static void
89 0 : DataSourceFreeTable(void *pool, void *item)
90 : {
91 0 : free(item);
92 0 : }
93 :
94 : static PLHashEntry *
95 0 : DataSourceAllocEntry(void *pool, const void *key)
96 : {
97 0 : return (PLHashEntry*) malloc(sizeof(PLHashEntry));
98 : }
99 :
100 : static void
101 0 : DataSourceFreeEntry(void *pool, PLHashEntry *he, unsigned flag)
102 : {
103 0 : if (flag == HT_FREE_ENTRY) {
104 0 : PL_strfree((char*) he->key);
105 0 : free(he);
106 : }
107 0 : }
108 :
109 : static PLHashAllocOps dataSourceHashAllocOps = {
110 : DataSourceAllocTable, DataSourceFreeTable,
111 : DataSourceAllocEntry, DataSourceFreeEntry
112 : };
113 :
114 : //----------------------------------------------------------------------
115 : //
116 : // For the mResources hashtable.
117 : //
118 :
119 : struct ResourceHashEntry : public PLDHashEntryHdr {
120 : const char *mKey;
121 : nsIRDFResource *mResource;
122 :
123 : static PLDHashNumber
124 102 : HashKey(const void *key)
125 : {
126 102 : return HashString(static_cast<const char *>(key));
127 : }
128 :
129 : static bool
130 3 : MatchEntry(const PLDHashEntryHdr *hdr, const void *key)
131 : {
132 : const ResourceHashEntry *entry =
133 3 : static_cast<const ResourceHashEntry *>(hdr);
134 :
135 3 : return 0 == nsCRT::strcmp(static_cast<const char *>(key),
136 6 : entry->mKey);
137 : }
138 : };
139 :
140 : static const PLDHashTableOps gResourceTableOps = {
141 : ResourceHashEntry::HashKey,
142 : ResourceHashEntry::MatchEntry,
143 : PLDHashTable::MoveEntryStub,
144 : PLDHashTable::ClearEntryStub,
145 : nullptr
146 : };
147 :
148 : // ----------------------------------------------------------------------
149 : //
150 : // For the mLiterals hashtable.
151 : //
152 :
153 : struct LiteralHashEntry : public PLDHashEntryHdr {
154 : nsIRDFLiteral *mLiteral;
155 : const char16_t *mKey;
156 :
157 : static PLDHashNumber
158 18 : HashKey(const void *key)
159 : {
160 18 : return HashString(static_cast<const char16_t *>(key));
161 : }
162 :
163 : static bool
164 0 : MatchEntry(const PLDHashEntryHdr *hdr, const void *key)
165 : {
166 : const LiteralHashEntry *entry =
167 0 : static_cast<const LiteralHashEntry *>(hdr);
168 :
169 0 : return 0 == nsCRT::strcmp(static_cast<const char16_t *>(key),
170 0 : entry->mKey);
171 : }
172 : };
173 :
174 : static const PLDHashTableOps gLiteralTableOps = {
175 : LiteralHashEntry::HashKey,
176 : LiteralHashEntry::MatchEntry,
177 : PLDHashTable::MoveEntryStub,
178 : PLDHashTable::ClearEntryStub,
179 : nullptr
180 : };
181 :
182 : // ----------------------------------------------------------------------
183 : //
184 : // For the mInts hashtable.
185 : //
186 :
187 : struct IntHashEntry : public PLDHashEntryHdr {
188 : nsIRDFInt *mInt;
189 : int32_t mKey;
190 :
191 : static PLDHashNumber
192 0 : HashKey(const void *key)
193 : {
194 0 : return PLDHashNumber(*static_cast<const int32_t *>(key));
195 : }
196 :
197 : static bool
198 0 : MatchEntry(const PLDHashEntryHdr *hdr, const void *key)
199 : {
200 : const IntHashEntry *entry =
201 0 : static_cast<const IntHashEntry *>(hdr);
202 :
203 0 : return *static_cast<const int32_t *>(key) == entry->mKey;
204 : }
205 : };
206 :
207 : static const PLDHashTableOps gIntTableOps = {
208 : IntHashEntry::HashKey,
209 : IntHashEntry::MatchEntry,
210 : PLDHashTable::MoveEntryStub,
211 : PLDHashTable::ClearEntryStub,
212 : nullptr
213 : };
214 :
215 : // ----------------------------------------------------------------------
216 : //
217 : // For the mDates hashtable.
218 : //
219 :
220 : struct DateHashEntry : public PLDHashEntryHdr {
221 : nsIRDFDate *mDate;
222 : PRTime mKey;
223 :
224 : static PLDHashNumber
225 0 : HashKey(const void *key)
226 : {
227 : // xor the low 32 bits with the high 32 bits.
228 0 : PRTime t = *static_cast<const PRTime *>(key);
229 0 : int32_t h32 = int32_t(t >> 32);
230 0 : int32_t l32 = int32_t(0xffffffff & t);
231 0 : return PLDHashNumber(l32 ^ h32);
232 : }
233 :
234 : static bool
235 0 : MatchEntry(const PLDHashEntryHdr *hdr, const void *key)
236 : {
237 : const DateHashEntry *entry =
238 0 : static_cast<const DateHashEntry *>(hdr);
239 :
240 0 : return *static_cast<const PRTime *>(key) == entry->mKey;
241 : }
242 : };
243 :
244 : static const PLDHashTableOps gDateTableOps = {
245 : DateHashEntry::HashKey,
246 : DateHashEntry::MatchEntry,
247 : PLDHashTable::MoveEntryStub,
248 : PLDHashTable::ClearEntryStub,
249 : nullptr
250 : };
251 :
252 : class BlobImpl : public nsIRDFBlob
253 : {
254 : public:
255 : struct Data {
256 : int32_t mLength;
257 : uint8_t *mBytes;
258 : };
259 :
260 0 : BlobImpl(const uint8_t *aBytes, int32_t aLength)
261 0 : {
262 0 : mData.mLength = aLength;
263 0 : mData.mBytes = new uint8_t[aLength];
264 0 : memcpy(mData.mBytes, aBytes, aLength);
265 0 : NS_ADDREF(RDFServiceImpl::gRDFService);
266 0 : RDFServiceImpl::gRDFService->RegisterBlob(this);
267 0 : }
268 :
269 : protected:
270 0 : virtual ~BlobImpl()
271 0 : {
272 0 : RDFServiceImpl::gRDFService->UnregisterBlob(this);
273 : // Use NS_RELEASE2() here, because we want to decrease the
274 : // refcount, but not null out the gRDFService pointer (which is
275 : // what a vanilla NS_RELEASE() would do).
276 : nsrefcnt refcnt;
277 0 : NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
278 0 : delete[] mData.mBytes;
279 0 : }
280 :
281 : public:
282 : NS_DECL_ISUPPORTS
283 : NS_DECL_NSIRDFNODE
284 : NS_DECL_NSIRDFBLOB
285 :
286 : Data mData;
287 : };
288 :
289 0 : NS_IMPL_ISUPPORTS(BlobImpl, nsIRDFNode, nsIRDFBlob)
290 :
291 : NS_IMETHODIMP
292 0 : BlobImpl::EqualsNode(nsIRDFNode *aNode, bool *aEquals)
293 : {
294 0 : nsCOMPtr<nsIRDFBlob> blob = do_QueryInterface(aNode);
295 0 : if (blob) {
296 : int32_t length;
297 0 : blob->GetLength(&length);
298 :
299 0 : if (length == mData.mLength) {
300 : const uint8_t *bytes;
301 0 : blob->GetValue(&bytes);
302 :
303 0 : if (0 == memcmp(bytes, mData.mBytes, length)) {
304 0 : *aEquals = true;
305 0 : return NS_OK;
306 : }
307 : }
308 : }
309 :
310 0 : *aEquals = false;
311 0 : return NS_OK;
312 : }
313 :
314 : NS_IMETHODIMP
315 0 : BlobImpl::GetValue(const uint8_t **aResult)
316 : {
317 0 : *aResult = mData.mBytes;
318 0 : return NS_OK;
319 : }
320 :
321 : NS_IMETHODIMP
322 0 : BlobImpl::GetLength(int32_t *aResult)
323 : {
324 0 : *aResult = mData.mLength;
325 0 : return NS_OK;
326 : }
327 :
328 : // ----------------------------------------------------------------------
329 : //
330 : // For the mBlobs hashtable.
331 : //
332 :
333 : struct BlobHashEntry : public PLDHashEntryHdr {
334 : BlobImpl *mBlob;
335 :
336 : static PLDHashNumber
337 0 : HashKey(const void *key)
338 : {
339 : const BlobImpl::Data *data =
340 0 : static_cast<const BlobImpl::Data *>(key);
341 0 : return HashBytes(data->mBytes, data->mLength);
342 : }
343 :
344 : static bool
345 0 : MatchEntry(const PLDHashEntryHdr *hdr, const void *key)
346 : {
347 : const BlobHashEntry *entry =
348 0 : static_cast<const BlobHashEntry *>(hdr);
349 :
350 0 : const BlobImpl::Data *left = &entry->mBlob->mData;
351 :
352 : const BlobImpl::Data *right =
353 0 : static_cast<const BlobImpl::Data *>(key);
354 :
355 0 : return (left->mLength == right->mLength)
356 0 : && 0 == memcmp(left->mBytes, right->mBytes, right->mLength);
357 : }
358 : };
359 :
360 : static const PLDHashTableOps gBlobTableOps = {
361 : BlobHashEntry::HashKey,
362 : BlobHashEntry::MatchEntry,
363 : PLDHashTable::MoveEntryStub,
364 : PLDHashTable::ClearEntryStub,
365 : nullptr
366 : };
367 :
368 : ////////////////////////////////////////////////////////////////////////
369 : // LiteralImpl
370 : //
371 : // Currently, all literals are implemented exactly the same way;
372 : // i.e., there is are no resource factories to allow you to generate
373 : // customer resources. I doubt that makes sense, anyway.
374 : //
375 : class LiteralImpl : public nsIRDFLiteral {
376 : public:
377 : static nsresult
378 : Create(const char16_t* aValue, nsIRDFLiteral** aResult);
379 :
380 : // nsISupports
381 : NS_DECL_THREADSAFE_ISUPPORTS
382 :
383 : // nsIRDFNode
384 : NS_DECL_NSIRDFNODE
385 :
386 : // nsIRDFLiteral
387 : NS_DECL_NSIRDFLITERAL
388 :
389 : protected:
390 : explicit LiteralImpl(const char16_t* s);
391 : virtual ~LiteralImpl();
392 :
393 9 : const char16_t* GetValue() const {
394 9 : size_t objectSize = ((sizeof(LiteralImpl) + sizeof(char16_t) - 1) / sizeof(char16_t)) * sizeof(char16_t);
395 9 : return reinterpret_cast<const char16_t*>(reinterpret_cast<const unsigned char*>(this) + objectSize);
396 : }
397 : };
398 :
399 :
400 : nsresult
401 8 : LiteralImpl::Create(const char16_t* aValue, nsIRDFLiteral** aResult)
402 : {
403 : // Goofy math to get alignment right. Copied from nsSharedString.h.
404 8 : size_t objectSize = ((sizeof(LiteralImpl) + sizeof(char16_t) - 1) / sizeof(char16_t)) * sizeof(char16_t);
405 8 : size_t stringLen = nsCharTraits<char16_t>::length(aValue);
406 8 : size_t stringSize = (stringLen + 1) * sizeof(char16_t);
407 :
408 16 : void* objectPtr = operator new(objectSize + stringSize);
409 8 : if (! objectPtr)
410 0 : return NS_ERROR_NULL_POINTER;
411 :
412 8 : char16_t* buf = reinterpret_cast<char16_t*>(static_cast<unsigned char*>(objectPtr) + objectSize);
413 8 : nsCharTraits<char16_t>::copy(buf, aValue, stringLen + 1);
414 :
415 8 : NS_ADDREF(*aResult = new (objectPtr) LiteralImpl(buf));
416 8 : return NS_OK;
417 : }
418 :
419 :
420 8 : LiteralImpl::LiteralImpl(const char16_t* s)
421 : {
422 8 : RDFServiceImpl::gRDFService->RegisterLiteral(this);
423 8 : NS_ADDREF(RDFServiceImpl::gRDFService);
424 8 : }
425 :
426 0 : LiteralImpl::~LiteralImpl()
427 : {
428 0 : RDFServiceImpl::gRDFService->UnregisterLiteral(this);
429 :
430 : // Use NS_RELEASE2() here, because we want to decrease the
431 : // refcount, but not null out the gRDFService pointer (which is
432 : // what a vanilla NS_RELEASE() would do).
433 : nsrefcnt refcnt;
434 0 : NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
435 0 : }
436 :
437 19 : NS_IMPL_ADDREF(LiteralImpl)
438 9 : NS_IMPL_RELEASE(LiteralImpl)
439 :
440 : nsresult
441 5 : LiteralImpl::QueryInterface(REFNSIID iid, void** result)
442 : {
443 5 : if (! result)
444 0 : return NS_ERROR_NULL_POINTER;
445 :
446 5 : *result = nullptr;
447 11 : if (iid.Equals(kIRDFLiteralIID) ||
448 5 : iid.Equals(kIRDFNodeIID) ||
449 0 : iid.Equals(kISupportsIID)) {
450 5 : *result = static_cast<nsIRDFLiteral*>(this);
451 5 : AddRef();
452 5 : return NS_OK;
453 : }
454 0 : return NS_NOINTERFACE;
455 : }
456 :
457 : NS_IMETHODIMP
458 0 : LiteralImpl::EqualsNode(nsIRDFNode* aNode, bool* aResult)
459 : {
460 : nsresult rv;
461 : nsIRDFLiteral* literal;
462 0 : rv = aNode->QueryInterface(kIRDFLiteralIID, (void**) &literal);
463 0 : if (NS_SUCCEEDED(rv)) {
464 0 : *aResult = (static_cast<nsIRDFLiteral*>(this) == literal);
465 0 : NS_RELEASE(literal);
466 0 : return NS_OK;
467 : }
468 0 : else if (rv == NS_NOINTERFACE) {
469 0 : *aResult = false;
470 0 : return NS_OK;
471 : }
472 : else {
473 0 : return rv;
474 : }
475 : }
476 :
477 : NS_IMETHODIMP
478 0 : LiteralImpl::GetValue(char16_t* *value)
479 : {
480 0 : NS_ASSERTION(value, "null ptr");
481 0 : if (! value)
482 0 : return NS_ERROR_NULL_POINTER;
483 :
484 0 : const char16_t *temp = GetValue();
485 0 : *value = temp? NS_strdup(temp) : 0;
486 0 : return NS_OK;
487 : }
488 :
489 :
490 : NS_IMETHODIMP
491 9 : LiteralImpl::GetValueConst(const char16_t** aValue)
492 : {
493 9 : *aValue = GetValue();
494 9 : return NS_OK;
495 : }
496 :
497 : ////////////////////////////////////////////////////////////////////////
498 : // DateImpl
499 : //
500 :
501 : class DateImpl : public nsIRDFDate {
502 : public:
503 : explicit DateImpl(const PRTime s);
504 :
505 : // nsISupports
506 : NS_DECL_ISUPPORTS
507 :
508 : // nsIRDFNode
509 : NS_DECL_NSIRDFNODE
510 :
511 : // nsIRDFDate
512 : NS_IMETHOD GetValue(PRTime *value) override;
513 :
514 : private:
515 : virtual ~DateImpl();
516 :
517 : nsresult EqualsDate(nsIRDFDate* date, bool* result);
518 : PRTime mValue;
519 : };
520 :
521 :
522 0 : DateImpl::DateImpl(const PRTime s)
523 0 : : mValue(s)
524 : {
525 0 : RDFServiceImpl::gRDFService->RegisterDate(this);
526 0 : NS_ADDREF(RDFServiceImpl::gRDFService);
527 0 : }
528 :
529 0 : DateImpl::~DateImpl()
530 : {
531 0 : RDFServiceImpl::gRDFService->UnregisterDate(this);
532 :
533 : // Use NS_RELEASE2() here, because we want to decrease the
534 : // refcount, but not null out the gRDFService pointer (which is
535 : // what a vanilla NS_RELEASE() would do).
536 : nsrefcnt refcnt;
537 0 : NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
538 0 : }
539 :
540 0 : NS_IMPL_ADDREF(DateImpl)
541 0 : NS_IMPL_RELEASE(DateImpl)
542 :
543 : nsresult
544 0 : DateImpl::QueryInterface(REFNSIID iid, void** result)
545 : {
546 0 : if (! result)
547 0 : return NS_ERROR_NULL_POINTER;
548 :
549 0 : *result = nullptr;
550 0 : if (iid.Equals(kIRDFDateIID) ||
551 0 : iid.Equals(kIRDFNodeIID) ||
552 0 : iid.Equals(kISupportsIID)) {
553 0 : *result = static_cast<nsIRDFDate*>(this);
554 0 : AddRef();
555 0 : return NS_OK;
556 : }
557 0 : return NS_NOINTERFACE;
558 : }
559 :
560 : NS_IMETHODIMP
561 0 : DateImpl::EqualsNode(nsIRDFNode* node, bool* result)
562 : {
563 : nsresult rv;
564 : nsIRDFDate* date;
565 0 : if (NS_SUCCEEDED(node->QueryInterface(kIRDFDateIID, (void**) &date))) {
566 0 : rv = EqualsDate(date, result);
567 0 : NS_RELEASE(date);
568 : }
569 : else {
570 0 : *result = false;
571 0 : rv = NS_OK;
572 : }
573 0 : return rv;
574 : }
575 :
576 : NS_IMETHODIMP
577 0 : DateImpl::GetValue(PRTime *value)
578 : {
579 0 : NS_ASSERTION(value, "null ptr");
580 0 : if (! value)
581 0 : return NS_ERROR_NULL_POINTER;
582 :
583 0 : *value = mValue;
584 0 : return NS_OK;
585 : }
586 :
587 :
588 : nsresult
589 0 : DateImpl::EqualsDate(nsIRDFDate* date, bool* result)
590 : {
591 0 : NS_ASSERTION(date && result, "null ptr");
592 0 : if (!date || !result)
593 0 : return NS_ERROR_NULL_POINTER;
594 :
595 : nsresult rv;
596 : PRTime p;
597 0 : if (NS_FAILED(rv = date->GetValue(&p)))
598 0 : return rv;
599 :
600 0 : *result = p == mValue;
601 0 : return NS_OK;
602 : }
603 :
604 : ////////////////////////////////////////////////////////////////////////
605 : // IntImpl
606 : //
607 :
608 : class IntImpl : public nsIRDFInt {
609 : public:
610 : explicit IntImpl(int32_t s);
611 :
612 : // nsISupports
613 : NS_DECL_ISUPPORTS
614 :
615 : // nsIRDFNode
616 : NS_DECL_NSIRDFNODE
617 :
618 : // nsIRDFInt
619 : NS_IMETHOD GetValue(int32_t *value) override;
620 :
621 : private:
622 : virtual ~IntImpl();
623 :
624 : nsresult EqualsInt(nsIRDFInt* value, bool* result);
625 : int32_t mValue;
626 : };
627 :
628 :
629 0 : IntImpl::IntImpl(int32_t s)
630 0 : : mValue(s)
631 : {
632 0 : RDFServiceImpl::gRDFService->RegisterInt(this);
633 0 : NS_ADDREF(RDFServiceImpl::gRDFService);
634 0 : }
635 :
636 0 : IntImpl::~IntImpl()
637 : {
638 0 : RDFServiceImpl::gRDFService->UnregisterInt(this);
639 :
640 : // Use NS_RELEASE2() here, because we want to decrease the
641 : // refcount, but not null out the gRDFService pointer (which is
642 : // what a vanilla NS_RELEASE() would do).
643 : nsrefcnt refcnt;
644 0 : NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
645 0 : }
646 :
647 0 : NS_IMPL_ADDREF(IntImpl)
648 0 : NS_IMPL_RELEASE(IntImpl)
649 :
650 : nsresult
651 0 : IntImpl::QueryInterface(REFNSIID iid, void** result)
652 : {
653 0 : if (! result)
654 0 : return NS_ERROR_NULL_POINTER;
655 :
656 0 : *result = nullptr;
657 0 : if (iid.Equals(kIRDFIntIID) ||
658 0 : iid.Equals(kIRDFNodeIID) ||
659 0 : iid.Equals(kISupportsIID)) {
660 0 : *result = static_cast<nsIRDFInt*>(this);
661 0 : AddRef();
662 0 : return NS_OK;
663 : }
664 0 : return NS_NOINTERFACE;
665 : }
666 :
667 : NS_IMETHODIMP
668 0 : IntImpl::EqualsNode(nsIRDFNode* node, bool* result)
669 : {
670 : nsresult rv;
671 : nsIRDFInt* intValue;
672 0 : if (NS_SUCCEEDED(node->QueryInterface(kIRDFIntIID, (void**) &intValue))) {
673 0 : rv = EqualsInt(intValue, result);
674 0 : NS_RELEASE(intValue);
675 : }
676 : else {
677 0 : *result = false;
678 0 : rv = NS_OK;
679 : }
680 0 : return rv;
681 : }
682 :
683 : NS_IMETHODIMP
684 0 : IntImpl::GetValue(int32_t *value)
685 : {
686 0 : NS_ASSERTION(value, "null ptr");
687 0 : if (! value)
688 0 : return NS_ERROR_NULL_POINTER;
689 :
690 0 : *value = mValue;
691 0 : return NS_OK;
692 : }
693 :
694 :
695 : nsresult
696 0 : IntImpl::EqualsInt(nsIRDFInt* intValue, bool* result)
697 : {
698 0 : NS_ASSERTION(intValue && result, "null ptr");
699 0 : if (!intValue || !result)
700 0 : return NS_ERROR_NULL_POINTER;
701 :
702 : nsresult rv;
703 : int32_t p;
704 0 : if (NS_FAILED(rv = intValue->GetValue(&p)))
705 0 : return rv;
706 :
707 0 : *result = (p == mValue);
708 0 : return NS_OK;
709 : }
710 :
711 : ////////////////////////////////////////////////////////////////////////
712 : // RDFServiceImpl
713 :
714 : RDFServiceImpl*
715 : RDFServiceImpl::gRDFService;
716 :
717 3 : RDFServiceImpl::RDFServiceImpl()
718 : : mNamedDataSources(nullptr)
719 : , mResources(&gResourceTableOps, sizeof(ResourceHashEntry))
720 : , mLiterals(&gLiteralTableOps, sizeof(LiteralHashEntry))
721 : , mInts(&gIntTableOps, sizeof(IntHashEntry))
722 : , mDates(&gDateTableOps, sizeof(DateHashEntry))
723 3 : , mBlobs(&gBlobTableOps, sizeof(BlobHashEntry))
724 : {
725 3 : gRDFService = this;
726 3 : }
727 :
728 : nsresult
729 3 : RDFServiceImpl::Init()
730 : {
731 : nsresult rv;
732 :
733 3 : mNamedDataSources = PL_NewHashTable(23,
734 : PL_HashString,
735 : PL_CompareStrings,
736 : PL_CompareValues,
737 : &dataSourceHashAllocOps, nullptr);
738 :
739 3 : if (! mNamedDataSources)
740 0 : return NS_ERROR_OUT_OF_MEMORY;
741 :
742 3 : mDefaultResourceFactory = do_GetClassObject(kRDFDefaultResourceCID, &rv);
743 3 : NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get default resource factory");
744 3 : if (NS_FAILED(rv)) return rv;
745 :
746 3 : return NS_OK;
747 : }
748 :
749 :
750 0 : RDFServiceImpl::~RDFServiceImpl()
751 : {
752 0 : if (mNamedDataSources) {
753 0 : PL_HashTableDestroy(mNamedDataSources);
754 0 : mNamedDataSources = nullptr;
755 : }
756 0 : gRDFService = nullptr;
757 0 : }
758 :
759 :
760 : // static
761 : nsresult
762 3 : RDFServiceImpl::CreateSingleton(nsISupports* aOuter,
763 : const nsIID& aIID, void **aResult)
764 : {
765 3 : NS_ENSURE_NO_AGGREGATION(aOuter);
766 :
767 3 : if (gRDFService) {
768 0 : NS_ERROR("Trying to create RDF serviec twice.");
769 0 : return gRDFService->QueryInterface(aIID, aResult);
770 : }
771 :
772 6 : RefPtr<RDFServiceImpl> serv = new RDFServiceImpl();
773 3 : nsresult rv = serv->Init();
774 3 : if (NS_FAILED(rv))
775 0 : return rv;
776 :
777 3 : return serv->QueryInterface(aIID, aResult);
778 : }
779 :
780 56 : NS_IMPL_ISUPPORTS(RDFServiceImpl, nsIRDFService, nsISupportsWeakReference)
781 :
782 : // Per RFC2396.
783 : static const uint8_t
784 : kLegalSchemeChars[] = {
785 : // ASCII Bits Ordered Hex
786 : // 01234567 76543210
787 : 0x00, // 00-07
788 : 0x00, // 08-0F
789 : 0x00, // 10-17
790 : 0x00, // 18-1F
791 : 0x00, // 20-27 !"#$%&' 00000000 00000000
792 : 0x28, // 28-2F ()*+,-./ 00010100 00101000 0x28
793 : 0xff, // 30-37 01234567 11111111 11111111 0xFF
794 : 0x03, // 38-3F 89:;<=>? 11000000 00000011 0x03
795 : 0xfe, // 40-47 @ABCDEFG 01111111 11111110 0xFE
796 : 0xff, // 48-4F HIJKLMNO 11111111 11111111 0xFF
797 : 0xff, // 50-57 PQRSTUVW 11111111 11111111 0xFF
798 : 0x87, // 58-5F XYZ[\]^_ 11100001 10000111 0x87
799 : 0xfe, // 60-67 `abcdefg 01111111 11111110 0xFE
800 : 0xff, // 68-6F hijklmno 11111111 11111111 0xFF
801 : 0xff, // 70-77 pqrstuvw 11111111 11111111 0xFF
802 : 0x07, // 78-7F xyz{|}~ 11100000 00000111 0x07
803 : 0x00, 0x00, 0x00, 0x00, // >= 80
804 : 0x00, 0x00, 0x00, 0x00,
805 : 0x00, 0x00, 0x00, 0x00,
806 : 0x00, 0x00, 0x00, 0x00
807 : };
808 :
809 : static inline bool
810 172 : IsLegalSchemeCharacter(const char aChar)
811 : {
812 172 : uint8_t mask = kLegalSchemeChars[aChar >> 3];
813 172 : uint8_t bit = 1u << (aChar & 0x7);
814 172 : return bool((mask & bit) != 0);
815 : }
816 :
817 :
818 : NS_IMETHODIMP
819 38 : RDFServiceImpl::GetResource(const nsACString& aURI, nsIRDFResource** aResource)
820 : {
821 : // Sanity checks
822 38 : NS_PRECONDITION(aResource != nullptr, "null ptr");
823 38 : NS_PRECONDITION(!aURI.IsEmpty(), "URI is empty");
824 38 : if (! aResource)
825 0 : return NS_ERROR_NULL_POINTER;
826 38 : if (aURI.IsEmpty())
827 0 : return NS_ERROR_INVALID_ARG;
828 :
829 76 : const nsCString& flatURI = PromiseFlatCString(aURI);
830 38 : MOZ_LOG(gLog, LogLevel::Debug, ("rdfserv get-resource %s", flatURI.get()));
831 :
832 : // First, check the cache to see if we've already created and
833 : // registered this thing.
834 38 : PLDHashEntryHdr *hdr = mResources.Search(flatURI.get());
835 38 : if (hdr) {
836 3 : ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
837 3 : NS_ADDREF(*aResource = entry->mResource);
838 3 : return NS_OK;
839 : }
840 :
841 : // Nope. So go to the repository to create it.
842 :
843 : // Compute the scheme of the URI. Scan forward until we either:
844 : //
845 : // 1. Reach the end of the string
846 : // 2. Encounter a non-alpha character
847 : // 3. Encouter a colon.
848 : //
849 : // If we encounter a colon _before_ encountering a non-alpha
850 : // character, then assume it's the scheme.
851 : //
852 : // XXX Although it's really not correct, we'll allow underscore
853 : // characters ('_'), too.
854 35 : nsACString::const_iterator p, end;
855 35 : aURI.BeginReading(p);
856 35 : aURI.EndReading(end);
857 311 : while (p != end && IsLegalSchemeCharacter(*p))
858 138 : ++p;
859 :
860 : nsresult rv;
861 70 : nsCOMPtr<nsIFactory> factory;
862 :
863 35 : nsACString::const_iterator begin;
864 35 : aURI.BeginReading(begin);
865 35 : if (*p == ':') {
866 : // There _was_ a scheme. First see if it's the same scheme
867 : // that we just tried to use...
868 34 : if (mLastFactory && mLastURIPrefix.Equals(Substring(begin, p)))
869 24 : factory = mLastFactory;
870 : else {
871 : // Try to find a factory using the component manager.
872 10 : nsACString::const_iterator begin;
873 10 : aURI.BeginReading(begin);
874 20 : nsAutoCString contractID;
875 30 : contractID = NS_LITERAL_CSTRING(NS_RDF_RESOURCE_FACTORY_CONTRACTID_PREFIX) +
876 40 : Substring(begin, p);
877 :
878 10 : factory = do_GetClassObject(contractID.get());
879 10 : if (factory) {
880 : // Store the factory in our one-element cache.
881 0 : if (p != begin) {
882 0 : mLastFactory = factory;
883 0 : mLastURIPrefix = Substring(begin, p);
884 : }
885 : }
886 : }
887 : }
888 :
889 35 : if (! factory) {
890 : // fall through to using the "default" resource factory if either:
891 : //
892 : // 1. The URI didn't have a scheme, or
893 : // 2. There was no resource factory registered for the scheme.
894 11 : factory = mDefaultResourceFactory;
895 :
896 : // Store the factory in our one-element cache.
897 11 : if (p != begin) {
898 11 : mLastFactory = factory;
899 11 : mLastURIPrefix = Substring(begin, p);
900 : }
901 : }
902 :
903 : nsIRDFResource *result;
904 35 : rv = factory->CreateInstance(nullptr, NS_GET_IID(nsIRDFResource), (void**) &result);
905 35 : if (NS_FAILED(rv)) return rv;
906 :
907 : // Now initialize it with its URI. At this point, the resource
908 : // implementation should register itself with the RDF service.
909 35 : rv = result->Init(flatURI.get());
910 35 : if (NS_FAILED(rv)) {
911 0 : NS_ERROR("unable to initialize resource");
912 0 : NS_RELEASE(result);
913 0 : return rv;
914 : }
915 :
916 35 : *aResource = result; // already refcounted from repository
917 35 : return rv;
918 : }
919 :
920 : NS_IMETHODIMP
921 0 : RDFServiceImpl::GetUnicodeResource(const nsAString& aURI, nsIRDFResource** aResource)
922 : {
923 0 : return GetResource(NS_ConvertUTF16toUTF8(aURI), aResource);
924 : }
925 :
926 :
927 : NS_IMETHODIMP
928 0 : RDFServiceImpl::GetAnonymousResource(nsIRDFResource** aResult)
929 : {
930 : static uint32_t gCounter = 0;
931 : static char gChars[] = "0123456789abcdef"
932 : "ghijklmnopqrstuv"
933 : "wxyzABCDEFGHIJKL"
934 : "MNOPQRSTUVWXYZ.+";
935 :
936 : static int32_t kMask = 0x003f;
937 : static int32_t kShift = 6;
938 :
939 0 : if (! gCounter) {
940 : // Start it at a semi-unique value, just to minimize the
941 : // chance that we get into a situation where
942 : //
943 : // 1. An anonymous resource gets serialized out in a graph
944 : // 2. Reboot
945 : // 3. The same anonymous resource gets requested, and refers
946 : // to something completely different.
947 : // 4. The serialization is read back in.
948 0 : gCounter = uint32_t(PR_Now());
949 : }
950 :
951 : nsresult rv;
952 0 : nsAutoCString s;
953 :
954 : do {
955 : // Ugh, this is a really sloppy way to do this; I copied the
956 : // implementation from the days when it lived outside the RDF
957 : // service. Now that it's a member we can be more cleverer.
958 :
959 0 : s.Truncate();
960 0 : s.AppendLiteral("rdf:#$");
961 :
962 0 : uint32_t id = ++gCounter;
963 0 : while (id) {
964 0 : char ch = gChars[(id & kMask)];
965 0 : s.Append(ch);
966 0 : id >>= kShift;
967 : }
968 :
969 : nsIRDFResource* resource;
970 0 : rv = GetResource(s, &resource);
971 0 : if (NS_FAILED(rv)) return rv;
972 :
973 : // XXX an ugly but effective way to make sure that this
974 : // resource is really unique in the world.
975 0 : resource->AddRef();
976 0 : nsrefcnt refcnt = resource->Release();
977 :
978 0 : if (refcnt == 1) {
979 0 : *aResult = resource;
980 0 : break;
981 : }
982 :
983 0 : NS_RELEASE(resource);
984 : } while (1);
985 :
986 0 : return NS_OK;
987 : }
988 :
989 :
990 : NS_IMETHODIMP
991 8 : RDFServiceImpl::GetLiteral(const char16_t* aValue, nsIRDFLiteral** aLiteral)
992 : {
993 8 : NS_PRECONDITION(aValue != nullptr, "null ptr");
994 8 : if (! aValue)
995 0 : return NS_ERROR_NULL_POINTER;
996 :
997 8 : NS_PRECONDITION(aLiteral != nullptr, "null ptr");
998 8 : if (! aLiteral)
999 0 : return NS_ERROR_NULL_POINTER;
1000 :
1001 : // See if we have one already cached
1002 8 : PLDHashEntryHdr *hdr = mLiterals.Search(aValue);
1003 8 : if (hdr) {
1004 0 : LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
1005 0 : NS_ADDREF(*aLiteral = entry->mLiteral);
1006 0 : return NS_OK;
1007 : }
1008 :
1009 : // Nope. Create a new one
1010 8 : return LiteralImpl::Create(aValue, aLiteral);
1011 : }
1012 :
1013 : NS_IMETHODIMP
1014 0 : RDFServiceImpl::GetDateLiteral(PRTime aTime, nsIRDFDate** aResult)
1015 : {
1016 : // See if we have one already cached
1017 0 : PLDHashEntryHdr *hdr = mDates.Search(&aTime);
1018 0 : if (hdr) {
1019 0 : DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
1020 0 : NS_ADDREF(*aResult = entry->mDate);
1021 0 : return NS_OK;
1022 : }
1023 :
1024 0 : DateImpl* result = new DateImpl(aTime);
1025 0 : if (! result)
1026 0 : return NS_ERROR_OUT_OF_MEMORY;
1027 :
1028 0 : NS_ADDREF(*aResult = result);
1029 0 : return NS_OK;
1030 : }
1031 :
1032 : NS_IMETHODIMP
1033 0 : RDFServiceImpl::GetIntLiteral(int32_t aInt, nsIRDFInt** aResult)
1034 : {
1035 : // See if we have one already cached
1036 0 : PLDHashEntryHdr *hdr = mInts.Search(&aInt);
1037 0 : if (hdr) {
1038 0 : IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
1039 0 : NS_ADDREF(*aResult = entry->mInt);
1040 0 : return NS_OK;
1041 : }
1042 :
1043 0 : IntImpl* result = new IntImpl(aInt);
1044 0 : if (! result)
1045 0 : return NS_ERROR_OUT_OF_MEMORY;
1046 :
1047 0 : NS_ADDREF(*aResult = result);
1048 0 : return NS_OK;
1049 : }
1050 :
1051 : NS_IMETHODIMP
1052 0 : RDFServiceImpl::GetBlobLiteral(const uint8_t *aBytes, int32_t aLength,
1053 : nsIRDFBlob **aResult)
1054 : {
1055 0 : BlobImpl::Data key = { aLength, const_cast<uint8_t *>(aBytes) };
1056 :
1057 0 : PLDHashEntryHdr *hdr = mBlobs.Search(&key);
1058 0 : if (hdr) {
1059 0 : BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
1060 0 : NS_ADDREF(*aResult = entry->mBlob);
1061 0 : return NS_OK;
1062 : }
1063 :
1064 0 : BlobImpl *result = new BlobImpl(aBytes, aLength);
1065 0 : if (! result)
1066 0 : return NS_ERROR_OUT_OF_MEMORY;
1067 :
1068 0 : NS_ADDREF(*aResult = result);
1069 0 : return NS_OK;
1070 : }
1071 :
1072 : NS_IMETHODIMP
1073 0 : RDFServiceImpl::IsAnonymousResource(nsIRDFResource* aResource, bool* _result)
1074 : {
1075 0 : NS_PRECONDITION(aResource != nullptr, "null ptr");
1076 0 : if (! aResource)
1077 0 : return NS_ERROR_NULL_POINTER;
1078 :
1079 : nsresult rv;
1080 :
1081 : const char* uri;
1082 0 : rv = aResource->GetValueConst(&uri);
1083 0 : if (NS_FAILED(rv)) return rv;
1084 :
1085 0 : if ((uri[0] == 'r') &&
1086 0 : (uri[1] == 'd') &&
1087 0 : (uri[2] == 'f') &&
1088 0 : (uri[3] == ':') &&
1089 0 : (uri[4] == '#') &&
1090 0 : (uri[5] == '$')) {
1091 0 : *_result = true;
1092 : }
1093 : else {
1094 0 : *_result = false;
1095 : }
1096 :
1097 0 : return NS_OK;
1098 : }
1099 :
1100 : NS_IMETHODIMP
1101 35 : RDFServiceImpl::RegisterResource(nsIRDFResource* aResource, bool aReplace)
1102 : {
1103 35 : NS_PRECONDITION(aResource != nullptr, "null ptr");
1104 35 : if (! aResource)
1105 0 : return NS_ERROR_NULL_POINTER;
1106 :
1107 : nsresult rv;
1108 :
1109 : const char* uri;
1110 35 : rv = aResource->GetValueConst(&uri);
1111 35 : NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get URI from resource");
1112 35 : if (NS_FAILED(rv)) return rv;
1113 :
1114 35 : NS_ASSERTION(uri != nullptr, "resource has no URI");
1115 35 : if (! uri)
1116 0 : return NS_ERROR_NULL_POINTER;
1117 :
1118 35 : PLDHashEntryHdr *hdr = mResources.Search(uri);
1119 35 : if (hdr) {
1120 0 : if (!aReplace) {
1121 0 : NS_WARNING("resource already registered, and replace not specified");
1122 0 : return NS_ERROR_FAILURE; // already registered
1123 : }
1124 :
1125 : // N.B., we do _not_ release the original resource because we
1126 : // only ever held a weak reference to it. We simply replace
1127 : // it.
1128 :
1129 0 : MOZ_LOG(gLog, LogLevel::Debug,
1130 : ("rdfserv replace-resource [%p] <-- [%p] %s",
1131 : static_cast<ResourceHashEntry *>(hdr)->mResource,
1132 : aResource, (const char*) uri));
1133 : }
1134 : else {
1135 35 : hdr = mResources.Add(uri, fallible);
1136 35 : if (! hdr)
1137 0 : return NS_ERROR_OUT_OF_MEMORY;
1138 :
1139 35 : MOZ_LOG(gLog, LogLevel::Debug,
1140 : ("rdfserv register-resource [%p] %s",
1141 : aResource, (const char*) uri));
1142 : }
1143 :
1144 : // N.B., we only hold a weak reference to the resource: that way,
1145 : // the resource can be destroyed when the last refcount goes
1146 : // away. The single addref that the CreateResource() call made
1147 : // will be owned by the callee.
1148 35 : ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
1149 35 : entry->mResource = aResource;
1150 35 : entry->mKey = uri;
1151 :
1152 35 : return NS_OK;
1153 : }
1154 :
1155 : NS_IMETHODIMP
1156 0 : RDFServiceImpl::UnregisterResource(nsIRDFResource* aResource)
1157 : {
1158 0 : NS_PRECONDITION(aResource != nullptr, "null ptr");
1159 0 : if (! aResource)
1160 0 : return NS_ERROR_NULL_POINTER;
1161 :
1162 : nsresult rv;
1163 :
1164 : const char* uri;
1165 0 : rv = aResource->GetValueConst(&uri);
1166 0 : if (NS_FAILED(rv)) return rv;
1167 :
1168 0 : NS_ASSERTION(uri != nullptr, "resource has no URI");
1169 0 : if (! uri)
1170 0 : return NS_ERROR_UNEXPECTED;
1171 :
1172 0 : MOZ_LOG(gLog, LogLevel::Debug,
1173 : ("rdfserv unregister-resource [%p] %s",
1174 : aResource, (const char*) uri));
1175 :
1176 : #ifdef DEBUG
1177 0 : if (!mResources.Search(uri))
1178 0 : NS_WARNING("resource was never registered");
1179 : #endif
1180 :
1181 0 : mResources.Remove(uri);
1182 0 : return NS_OK;
1183 : }
1184 :
1185 : NS_IMETHODIMP
1186 0 : RDFServiceImpl::RegisterDataSource(nsIRDFDataSource* aDataSource, bool aReplace)
1187 : {
1188 0 : NS_PRECONDITION(aDataSource != nullptr, "null ptr");
1189 0 : if (! aDataSource)
1190 0 : return NS_ERROR_NULL_POINTER;
1191 :
1192 : nsresult rv;
1193 :
1194 0 : nsXPIDLCString uri;
1195 0 : rv = aDataSource->GetURI(getter_Copies(uri));
1196 0 : if (NS_FAILED(rv)) return rv;
1197 :
1198 : PLHashEntry** hep =
1199 0 : PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
1200 :
1201 0 : if (*hep) {
1202 0 : if (! aReplace)
1203 0 : return NS_ERROR_FAILURE; // already registered
1204 :
1205 : // N.B., we only hold a weak reference to the datasource, so
1206 : // just replace the old with the new and don't touch any
1207 : // refcounts.
1208 0 : MOZ_LOG(gLog, LogLevel::Debug,
1209 : ("rdfserv replace-datasource [%p] <-- [%p] %s",
1210 : (*hep)->value, aDataSource, (const char*) uri));
1211 :
1212 0 : (*hep)->value = aDataSource;
1213 : }
1214 : else {
1215 0 : const char* key = PL_strdup(uri);
1216 0 : if (! key)
1217 0 : return NS_ERROR_OUT_OF_MEMORY;
1218 :
1219 0 : PL_HashTableAdd(mNamedDataSources, key, aDataSource);
1220 :
1221 0 : MOZ_LOG(gLog, LogLevel::Debug,
1222 : ("rdfserv register-datasource [%p] %s",
1223 : aDataSource, (const char*) uri));
1224 :
1225 : // N.B., we only hold a weak reference to the datasource, so don't
1226 : // addref.
1227 : }
1228 :
1229 0 : return NS_OK;
1230 : }
1231 :
1232 : NS_IMETHODIMP
1233 0 : RDFServiceImpl::UnregisterDataSource(nsIRDFDataSource* aDataSource)
1234 : {
1235 0 : NS_PRECONDITION(aDataSource != nullptr, "null ptr");
1236 0 : if (! aDataSource)
1237 0 : return NS_ERROR_NULL_POINTER;
1238 :
1239 : nsresult rv;
1240 :
1241 0 : nsXPIDLCString uri;
1242 0 : rv = aDataSource->GetURI(getter_Copies(uri));
1243 0 : if (NS_FAILED(rv)) return rv;
1244 :
1245 : //NS_ASSERTION(uri != nullptr, "datasource has no URI");
1246 0 : if (! uri)
1247 0 : return NS_ERROR_UNEXPECTED;
1248 :
1249 : PLHashEntry** hep =
1250 0 : PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
1251 :
1252 : // It may well be that this datasource was never registered. If
1253 : // so, don't unregister it.
1254 0 : if (! *hep || ((*hep)->value != aDataSource))
1255 0 : return NS_OK;
1256 :
1257 : // N.B., we only held a weak reference to the datasource, so we
1258 : // don't release here.
1259 0 : PL_HashTableRawRemove(mNamedDataSources, hep, *hep);
1260 :
1261 0 : MOZ_LOG(gLog, LogLevel::Debug,
1262 : ("rdfserv unregister-datasource [%p] %s",
1263 : aDataSource, (const char*) uri));
1264 :
1265 0 : return NS_OK;
1266 : }
1267 :
1268 : NS_IMETHODIMP
1269 0 : RDFServiceImpl::GetDataSource(const char* aURI, nsIRDFDataSource** aDataSource)
1270 : {
1271 : // Use the other GetDataSource and ask for a non-blocking Refresh.
1272 : // If you wanted it loaded synchronously, then you should've tried to do it
1273 : // yourself, or used GetDataSourceBlocking.
1274 0 : return GetDataSource( aURI, false, aDataSource );
1275 : }
1276 :
1277 : NS_IMETHODIMP
1278 0 : RDFServiceImpl::GetDataSourceBlocking(const char* aURI, nsIRDFDataSource** aDataSource)
1279 : {
1280 : // Use GetDataSource and ask for a blocking Refresh.
1281 0 : return GetDataSource( aURI, true, aDataSource );
1282 : }
1283 :
1284 : nsresult
1285 0 : RDFServiceImpl::GetDataSource(const char* aURI, bool aBlock, nsIRDFDataSource** aDataSource)
1286 : {
1287 0 : NS_PRECONDITION(aURI != nullptr, "null ptr");
1288 0 : if (! aURI)
1289 0 : return NS_ERROR_NULL_POINTER;
1290 :
1291 : nsresult rv;
1292 :
1293 : // Attempt to canonify the URI before we look for it in the
1294 : // cache. We won't bother doing this on `rdf:' URIs to avoid
1295 : // useless (and expensive) protocol handler lookups.
1296 0 : nsAutoCString spec(aURI);
1297 :
1298 0 : if (!StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
1299 0 : nsCOMPtr<nsIURI> uri;
1300 0 : NS_NewURI(getter_AddRefs(uri), spec);
1301 0 : if (uri) {
1302 0 : rv = uri->GetSpec(spec);
1303 0 : if (NS_FAILED(rv)) return rv;
1304 : }
1305 : }
1306 :
1307 : // First, check the cache to see if we already have this
1308 : // datasource loaded and initialized.
1309 : {
1310 : nsIRDFDataSource* cached =
1311 0 : static_cast<nsIRDFDataSource*>(PL_HashTableLookup(mNamedDataSources, spec.get()));
1312 :
1313 0 : if (cached) {
1314 0 : NS_ADDREF(cached);
1315 0 : *aDataSource = cached;
1316 0 : return NS_OK;
1317 : }
1318 : }
1319 :
1320 : // Nope. So go to the repository to try to create it.
1321 0 : nsCOMPtr<nsIRDFDataSource> ds;
1322 0 : if (StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
1323 : // It's a built-in data source. Convert it to a contract ID.
1324 : nsAutoCString contractID(
1325 0 : NS_LITERAL_CSTRING(NS_RDF_DATASOURCE_CONTRACTID_PREFIX) +
1326 0 : Substring(spec, 4, spec.Length() - 4));
1327 :
1328 : // Strip params to get ``base'' contractID for data source.
1329 0 : int32_t p = contractID.FindChar(char16_t('&'));
1330 0 : if (p >= 0)
1331 0 : contractID.Truncate(p);
1332 :
1333 0 : ds = do_GetService(contractID.get(), &rv);
1334 0 : if (NS_FAILED(rv)) return rv;
1335 :
1336 0 : nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(ds);
1337 0 : if (remote) {
1338 0 : rv = remote->Init(spec.get());
1339 0 : if (NS_FAILED(rv)) return rv;
1340 : }
1341 : }
1342 : else {
1343 : // Try to load this as an RDF/XML data source
1344 0 : ds = do_CreateInstance(kRDFXMLDataSourceCID, &rv);
1345 0 : if (NS_FAILED(rv)) return rv;
1346 :
1347 0 : nsCOMPtr<nsIRDFRemoteDataSource> remote(do_QueryInterface(ds));
1348 0 : NS_ASSERTION(remote, "not a remote RDF/XML data source!");
1349 0 : if (! remote) return NS_ERROR_UNEXPECTED;
1350 :
1351 0 : rv = remote->Init(spec.get());
1352 0 : if (NS_FAILED(rv)) return rv;
1353 :
1354 0 : rv = remote->Refresh(aBlock);
1355 0 : if (NS_FAILED(rv)) return rv;
1356 : }
1357 :
1358 0 : *aDataSource = ds;
1359 0 : NS_ADDREF(*aDataSource);
1360 0 : return NS_OK;
1361 : }
1362 :
1363 : ////////////////////////////////////////////////////////////////////////
1364 :
1365 : nsresult
1366 8 : RDFServiceImpl::RegisterLiteral(nsIRDFLiteral* aLiteral)
1367 : {
1368 : const char16_t* value;
1369 8 : aLiteral->GetValueConst(&value);
1370 :
1371 8 : NS_ASSERTION(!mLiterals.Search(value), "literal already registered");
1372 :
1373 8 : PLDHashEntryHdr *hdr = mLiterals.Add(value, fallible);
1374 8 : if (! hdr)
1375 0 : return NS_ERROR_OUT_OF_MEMORY;
1376 :
1377 8 : LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
1378 :
1379 : // N.B., we only hold a weak reference to the literal: that
1380 : // way, the literal can be destroyed when the last refcount
1381 : // goes away. The single addref that the CreateLiteral() call
1382 : // made will be owned by the callee.
1383 8 : entry->mLiteral = aLiteral;
1384 8 : entry->mKey = value;
1385 :
1386 8 : MOZ_LOG(gLog, LogLevel::Debug,
1387 : ("rdfserv register-literal [%p] %s",
1388 : aLiteral, NS_ConvertUTF16toUTF8(value).get()));
1389 :
1390 8 : return NS_OK;
1391 : }
1392 :
1393 :
1394 : nsresult
1395 0 : RDFServiceImpl::UnregisterLiteral(nsIRDFLiteral* aLiteral)
1396 : {
1397 : const char16_t* value;
1398 0 : aLiteral->GetValueConst(&value);
1399 :
1400 0 : NS_ASSERTION(mLiterals.Search(value), "literal was never registered");
1401 :
1402 0 : mLiterals.Remove(value);
1403 :
1404 : // N.B. that we _don't_ release the literal: we only held a weak
1405 : // reference to it in the hashtable.
1406 0 : MOZ_LOG(gLog, LogLevel::Debug,
1407 : ("rdfserv unregister-literal [%p] %s",
1408 : aLiteral, NS_ConvertUTF16toUTF8(value).get()));
1409 :
1410 0 : return NS_OK;
1411 : }
1412 :
1413 : //----------------------------------------------------------------------
1414 :
1415 : nsresult
1416 0 : RDFServiceImpl::RegisterInt(nsIRDFInt* aInt)
1417 : {
1418 : int32_t value;
1419 0 : aInt->GetValue(&value);
1420 :
1421 0 : NS_ASSERTION(!mInts.Search(&value), "int already registered");
1422 :
1423 0 : PLDHashEntryHdr *hdr = mInts.Add(&value, fallible);
1424 0 : if (! hdr)
1425 0 : return NS_ERROR_OUT_OF_MEMORY;
1426 :
1427 0 : IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
1428 :
1429 : // N.B., we only hold a weak reference to the literal: that
1430 : // way, the literal can be destroyed when the last refcount
1431 : // goes away. The single addref that the CreateInt() call
1432 : // made will be owned by the callee.
1433 0 : entry->mInt = aInt;
1434 0 : entry->mKey = value;
1435 :
1436 0 : MOZ_LOG(gLog, LogLevel::Debug,
1437 : ("rdfserv register-int [%p] %d",
1438 : aInt, value));
1439 :
1440 0 : return NS_OK;
1441 : }
1442 :
1443 :
1444 : nsresult
1445 0 : RDFServiceImpl::UnregisterInt(nsIRDFInt* aInt)
1446 : {
1447 : int32_t value;
1448 0 : aInt->GetValue(&value);
1449 :
1450 0 : NS_ASSERTION(mInts.Search(&value), "int was never registered");
1451 :
1452 0 : mInts.Remove(&value);
1453 :
1454 : // N.B. that we _don't_ release the literal: we only held a weak
1455 : // reference to it in the hashtable.
1456 0 : MOZ_LOG(gLog, LogLevel::Debug,
1457 : ("rdfserv unregister-int [%p] %d",
1458 : aInt, value));
1459 :
1460 0 : return NS_OK;
1461 : }
1462 :
1463 : //----------------------------------------------------------------------
1464 :
1465 : nsresult
1466 0 : RDFServiceImpl::RegisterDate(nsIRDFDate* aDate)
1467 : {
1468 : PRTime value;
1469 0 : aDate->GetValue(&value);
1470 :
1471 0 : NS_ASSERTION(!mDates.Search(&value), "date already registered");
1472 :
1473 0 : PLDHashEntryHdr *hdr = mDates.Add(&value, fallible);
1474 0 : if (! hdr)
1475 0 : return NS_ERROR_OUT_OF_MEMORY;
1476 :
1477 0 : DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
1478 :
1479 : // N.B., we only hold a weak reference to the literal: that
1480 : // way, the literal can be destroyed when the last refcount
1481 : // goes away. The single addref that the CreateDate() call
1482 : // made will be owned by the callee.
1483 0 : entry->mDate = aDate;
1484 0 : entry->mKey = value;
1485 :
1486 0 : MOZ_LOG(gLog, LogLevel::Debug,
1487 : ("rdfserv register-date [%p] %" PRId64,
1488 : aDate, value));
1489 :
1490 0 : return NS_OK;
1491 : }
1492 :
1493 :
1494 : nsresult
1495 0 : RDFServiceImpl::UnregisterDate(nsIRDFDate* aDate)
1496 : {
1497 : PRTime value;
1498 0 : aDate->GetValue(&value);
1499 :
1500 0 : NS_ASSERTION(mDates.Search(&value), "date was never registered");
1501 :
1502 0 : mDates.Remove(&value);
1503 :
1504 : // N.B. that we _don't_ release the literal: we only held a weak
1505 : // reference to it in the hashtable.
1506 0 : MOZ_LOG(gLog, LogLevel::Debug,
1507 : ("rdfserv unregister-date [%p] %" PRId64,
1508 : aDate, value));
1509 :
1510 0 : return NS_OK;
1511 : }
1512 :
1513 : nsresult
1514 0 : RDFServiceImpl::RegisterBlob(BlobImpl *aBlob)
1515 : {
1516 0 : NS_ASSERTION(!mBlobs.Search(&aBlob->mData), "blob already registered");
1517 :
1518 0 : PLDHashEntryHdr *hdr = mBlobs.Add(&aBlob->mData, fallible);
1519 0 : if (! hdr)
1520 0 : return NS_ERROR_OUT_OF_MEMORY;
1521 :
1522 0 : BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
1523 :
1524 : // N.B., we only hold a weak reference to the literal: that
1525 : // way, the literal can be destroyed when the last refcount
1526 : // goes away. The single addref that the CreateInt() call
1527 : // made will be owned by the callee.
1528 0 : entry->mBlob = aBlob;
1529 :
1530 0 : MOZ_LOG(gLog, LogLevel::Debug,
1531 : ("rdfserv register-blob [%p] %s",
1532 : aBlob, aBlob->mData.mBytes));
1533 :
1534 0 : return NS_OK;
1535 : }
1536 :
1537 : nsresult
1538 0 : RDFServiceImpl::UnregisterBlob(BlobImpl *aBlob)
1539 : {
1540 0 : NS_ASSERTION(mBlobs.Search(&aBlob->mData), "blob was never registered");
1541 :
1542 0 : mBlobs.Remove(&aBlob->mData);
1543 :
1544 : // N.B. that we _don't_ release the literal: we only held a weak
1545 : // reference to it in the hashtable.
1546 0 : MOZ_LOG(gLog, LogLevel::Debug,
1547 : ("rdfserv unregister-blob [%p] %s",
1548 : aBlob, aBlob->mData.mBytes));
1549 :
1550 0 : return NS_OK;
1551 : }
|