nsRDFService.cpp 40 KB

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