michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsRDFResource.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIRDFDelegateFactory.h" michael@0: #include "nsIRDFService.h" michael@0: #include "nsRDFCID.h" michael@0: #include "prlog.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: michael@0: static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); michael@0: michael@0: nsIRDFService* nsRDFResource::gRDFService = nullptr; michael@0: nsrefcnt nsRDFResource::gRDFServiceRefCnt = 0; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: nsRDFResource::nsRDFResource(void) michael@0: : mDelegates(nullptr) michael@0: { michael@0: } michael@0: michael@0: nsRDFResource::~nsRDFResource(void) michael@0: { michael@0: // Release all of the delegate objects michael@0: while (mDelegates) { michael@0: DelegateEntry* doomed = mDelegates; michael@0: mDelegates = mDelegates->mNext; michael@0: delete doomed; michael@0: } michael@0: michael@0: if (!gRDFService) michael@0: return; michael@0: michael@0: gRDFService->UnregisterResource(this); michael@0: michael@0: if (--gRDFServiceRefCnt == 0) michael@0: NS_RELEASE(gRDFService); michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsRDFResource, nsIRDFResource, nsIRDFNode) michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // nsIRDFNode methods: michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::EqualsNode(nsIRDFNode* aNode, bool* aResult) michael@0: { michael@0: NS_PRECONDITION(aNode != nullptr, "null ptr"); michael@0: if (! aNode) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: nsresult rv; michael@0: nsIRDFResource* resource; michael@0: rv = aNode->QueryInterface(NS_GET_IID(nsIRDFResource), (void**)&resource); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: *aResult = (static_cast(this) == resource); michael@0: NS_RELEASE(resource); michael@0: return NS_OK; michael@0: } michael@0: else if (rv == NS_NOINTERFACE) { michael@0: *aResult = false; michael@0: return NS_OK; michael@0: } michael@0: else { michael@0: return rv; michael@0: } michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // nsIRDFResource methods: michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::Init(const char* aURI) michael@0: { michael@0: NS_PRECONDITION(aURI != nullptr, "null ptr"); michael@0: if (! aURI) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: mURI = aURI; michael@0: michael@0: if (gRDFServiceRefCnt++ == 0) { michael@0: nsresult rv = CallGetService(kRDFServiceCID, &gRDFService); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: // don't replace an existing resource with the same URI automatically michael@0: return gRDFService->RegisterResource(this, true); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::GetValue(char* *aURI) michael@0: { michael@0: NS_ASSERTION(aURI, "Null out param."); michael@0: michael@0: *aURI = ToNewCString(mURI); michael@0: michael@0: if (!*aURI) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::GetValueUTF8(nsACString& aResult) michael@0: { michael@0: aResult = mURI; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::GetValueConst(const char** aURI) michael@0: { michael@0: *aURI = mURI.get(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::EqualsString(const char* aURI, bool* aResult) michael@0: { michael@0: NS_PRECONDITION(aURI != nullptr, "null ptr"); michael@0: if (! aURI) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: NS_PRECONDITION(aResult, "null ptr"); michael@0: michael@0: *aResult = mURI.Equals(aURI); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::GetDelegate(const char* aKey, REFNSIID aIID, void** aResult) michael@0: { michael@0: NS_PRECONDITION(aKey != nullptr, "null ptr"); michael@0: if (! aKey) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: nsresult rv; michael@0: *aResult = nullptr; michael@0: michael@0: DelegateEntry* entry = mDelegates; michael@0: while (entry) { michael@0: if (entry->mKey.Equals(aKey)) { michael@0: rv = entry->mDelegate->QueryInterface(aIID, aResult); michael@0: return rv; michael@0: } michael@0: michael@0: entry = entry->mNext; michael@0: } michael@0: michael@0: // Construct a ContractID of the form "@mozilla.org/rdf/delegate/[key]/[scheme];1 michael@0: nsAutoCString contractID(NS_RDF_DELEGATEFACTORY_CONTRACTID_PREFIX); michael@0: contractID.Append(aKey); michael@0: contractID.Append("&scheme="); michael@0: michael@0: int32_t i = mURI.FindChar(':'); michael@0: contractID += StringHead(mURI, i); michael@0: michael@0: nsCOMPtr delegateFactory = michael@0: do_CreateInstance(contractID.get(), &rv); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = delegateFactory->CreateDelegate(this, aKey, aIID, aResult); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: // Okay, we've successfully created a delegate. Let's remember it. michael@0: entry = new DelegateEntry; michael@0: if (! entry) { michael@0: NS_RELEASE(*reinterpret_cast(aResult)); michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: entry->mKey = aKey; michael@0: entry->mDelegate = do_QueryInterface(*reinterpret_cast(aResult), &rv); michael@0: if (NS_FAILED(rv)) { michael@0: NS_ERROR("nsRDFResource::GetDelegate(): can't QI to nsISupports!"); michael@0: michael@0: delete entry; michael@0: NS_RELEASE(*reinterpret_cast(aResult)); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: entry->mNext = mDelegates; michael@0: michael@0: mDelegates = entry; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRDFResource::ReleaseDelegate(const char* aKey) michael@0: { michael@0: NS_PRECONDITION(aKey != nullptr, "null ptr"); michael@0: if (! aKey) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: DelegateEntry* entry = mDelegates; michael@0: DelegateEntry** link = &mDelegates; michael@0: michael@0: while (entry) { michael@0: if (entry->mKey.Equals(aKey)) { michael@0: *link = entry->mNext; michael@0: delete entry; michael@0: return NS_OK; michael@0: } michael@0: michael@0: link = &(entry->mNext); michael@0: entry = entry->mNext; michael@0: } michael@0: michael@0: NS_WARNING("nsRDFResource::ReleaseDelegate() no delegate found"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////////