LCOV - code coverage report
Current view: top level - rdf/base - nsRDFService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 139 567 24.5 %
Date: 2017-07-14 16:53:18 Functions: 22 84 26.2 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.13