/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Jan Varga * Portions created by the Initial Developer are Copyright (C) 2003 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsReadableUtils.h" #include "nsXPIDLString.h" #include "nsCRT.h" #include "nsIAtom.h" #include "nsISupportsUtils.h" #include "nsIServiceManager.h" #include "rdf.h" #include "nsRDFCID.h" #include "nsAppDirectoryServiceDefs.h" #include "nsNetUtil.h" #include "nsIRDFXMLSink.h" #include "nsIWindowWatcher.h" #include "nsIPrompt.h" #include "mozSqlService.h" #include "mozSqlConnection.h" #define SQL_NAMESPACE_URI "http://www.mozilla.org/SQL-rdf#" static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID); nsIRDFService* mozSqlService::gRDFService; nsIRDFContainerUtils* mozSqlService::gRDFContainerUtils; nsIRDFResource* mozSqlService::kSQL_AliasesRoot; nsIRDFResource* mozSqlService::kSQL_Name; nsIRDFResource* mozSqlService::kSQL_Type; nsIRDFResource* mozSqlService::kSQL_Hostname; nsIRDFResource* mozSqlService::kSQL_Port; nsIRDFResource* mozSqlService::kSQL_Database; nsIRDFResource* mozSqlService::kSQL_Priority; mozSqlService::mozSqlService() : mConnectionCache(nsnull) { } mozSqlService::~mozSqlService() { gRDFService->UnregisterDataSource(this); delete mConnectionCache; NS_IF_RELEASE(kSQL_AliasesRoot); NS_IF_RELEASE(kSQL_Name); NS_IF_RELEASE(kSQL_Type); NS_IF_RELEASE(kSQL_Hostname); NS_IF_RELEASE(kSQL_Port); NS_IF_RELEASE(kSQL_Database); NS_IF_RELEASE(kSQL_Priority); NS_IF_RELEASE(gRDFContainerUtils); NS_IF_RELEASE(gRDFService); } NS_IMPL_ISUPPORTS3(mozSqlService, mozISqlService, nsIRDFDataSource, nsIRDFRemoteDataSource) NS_IMETHODIMP mozSqlService::GetErrorMessage(nsAString& aErrorMessage) { aErrorMessage = mErrorMessage; return NS_OK; } nsresult mozSqlService::Init() { nsresult rv; rv = CallGetService(kRDFServiceCID, &gRDFService); if (NS_FAILED(rv)) return rv; rv = CallGetService(kRDFContainerUtilsCID, &gRDFContainerUtils); if (NS_FAILED(rv)) return rv; gRDFService->GetResource(NS_LITERAL_CSTRING("SQL:AliasesRoot"), &kSQL_AliasesRoot); gRDFService->GetResource(NS_LITERAL_CSTRING(SQL_NAMESPACE_URI "name"), &kSQL_Name); gRDFService->GetResource(NS_LITERAL_CSTRING(SQL_NAMESPACE_URI "type"), &kSQL_Type); gRDFService->GetResource(NS_LITERAL_CSTRING(SQL_NAMESPACE_URI "hostname"), &kSQL_Hostname); gRDFService->GetResource(NS_LITERAL_CSTRING(SQL_NAMESPACE_URI "port"), &kSQL_Port); gRDFService->GetResource(NS_LITERAL_CSTRING(SQL_NAMESPACE_URI "database"), &kSQL_Database); gRDFService->GetResource(NS_LITERAL_CSTRING(SQL_NAMESPACE_URI "priority"), &kSQL_Priority); nsCOMPtr file; rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file)); if (NS_FAILED(rv)) return rv; rv = file->AppendNative(NS_LITERAL_CSTRING("sql.rdf")); if (NS_FAILED(rv)) return rv; nsCAutoString sql; NS_GetURLSpecFromFile(file, sql); rv = gRDFService->GetDataSourceBlocking(sql.get(), getter_AddRefs(mInner)); if (NS_FAILED(rv)) return rv; nsCOMPtr sink = do_QueryInterface(mInner); if (sink) { nsCOMPtr prefix = do_GetAtom("SQL"); sink->AddNameSpace(prefix, NS_ConvertASCIItoUTF16(SQL_NAMESPACE_URI)); } return gRDFService->RegisterDataSource(this, PR_FALSE); } NS_IMETHODIMP mozSqlService::AddAlias(const nsAString& aName, const nsAString& aType, const nsAString& aHostname, PRInt32 aPort, const nsAString& aDatabase, PRInt32 aPriority, nsIRDFResource** aResult) { nsCOMPtr alias; gRDFService->GetAnonymousResource(getter_AddRefs(alias)); nsCOMPtr rdfLiteral; nsCOMPtr rdfInt; gRDFService->GetLiteral(PromiseFlatString(aName).get(), getter_AddRefs(rdfLiteral)); mInner->Assert(alias, kSQL_Name, rdfLiteral, PR_TRUE); gRDFService->GetLiteral(PromiseFlatString(aType).get(), getter_AddRefs(rdfLiteral)); mInner->Assert(alias, kSQL_Type, rdfLiteral, PR_TRUE); gRDFService->GetLiteral(PromiseFlatString(aHostname).get(), getter_AddRefs(rdfLiteral)); mInner->Assert(alias, kSQL_Hostname, rdfLiteral, PR_TRUE); gRDFService->GetIntLiteral(aPort, getter_AddRefs(rdfInt)); mInner->Assert(alias, kSQL_Port, rdfInt, PR_TRUE); gRDFService->GetLiteral(PromiseFlatString(aDatabase).get(), getter_AddRefs(rdfLiteral)); mInner->Assert(alias, kSQL_Database, rdfLiteral, PR_TRUE); gRDFService->GetIntLiteral(aPriority, getter_AddRefs(rdfInt)); mInner->Assert(alias, kSQL_Priority, rdfInt, PR_TRUE); nsresult rv = EnsureAliasesContainer(); if (NS_FAILED(rv)) return rv; mAliasesContainer->AppendElement(alias); Flush(); NS_ADDREF(*aResult = alias); return NS_OK; } NS_IMETHODIMP mozSqlService::FetchAlias(nsIRDFResource* aAlias, nsAString& aName, nsAString& aType, nsAString& aHostname, PRInt32* aPort, nsAString& aDatabase, PRInt32* aPriority) { nsCOMPtr rdfNode; nsCOMPtr rdfLiteral; nsCOMPtr rdfInt; const PRUnichar* value; mInner->GetTarget(aAlias, kSQL_Name, PR_TRUE, getter_AddRefs(rdfNode)); if (rdfNode) { rdfLiteral = do_QueryInterface(rdfNode); rdfLiteral->GetValueConst(&value); aName.Assign(value); } mInner->GetTarget(aAlias, kSQL_Type, PR_TRUE, getter_AddRefs(rdfNode)); if (rdfNode) { rdfLiteral = do_QueryInterface(rdfNode); rdfLiteral->GetValueConst(&value); aType.Assign(value); } mInner->GetTarget(aAlias, kSQL_Hostname, PR_TRUE, getter_AddRefs(rdfNode)); if (rdfNode) { rdfLiteral = do_QueryInterface(rdfNode); rdfLiteral->GetValueConst(&value); aHostname.Assign(value); } mInner->GetTarget(aAlias, kSQL_Port, PR_TRUE, getter_AddRefs(rdfNode)); if (rdfNode) { rdfInt = do_QueryInterface(rdfNode); rdfInt->GetValue(aPort); } mInner->GetTarget(aAlias, kSQL_Database, PR_TRUE, getter_AddRefs(rdfNode)); if (rdfNode) { rdfLiteral = do_QueryInterface(rdfNode); rdfLiteral->GetValueConst(&value); aDatabase.Assign(value); } mInner->GetTarget(aAlias, kSQL_Priority, PR_TRUE, getter_AddRefs(rdfNode)); if (rdfNode) { rdfInt = do_QueryInterface(rdfNode); rdfInt->GetValue(aPriority); } return NS_OK; } NS_IMETHODIMP mozSqlService::UpdateAlias(nsIRDFResource* aAlias, const nsAString& aName, const nsAString& aType, const nsAString& aHostname, PRInt32 aPort, const nsAString& aDatabase, PRInt32 aPriority) { nsCOMPtr rdfNode; nsCOMPtr rdfLiteral; nsCOMPtr rdfInt; mInner->GetTarget(aAlias, kSQL_Name, PR_TRUE, getter_AddRefs(rdfNode)); gRDFService->GetLiteral(PromiseFlatString(aName).get(), getter_AddRefs(rdfLiteral)); mInner->Change(aAlias, kSQL_Name, rdfNode, rdfLiteral); mInner->GetTarget(aAlias, kSQL_Type, PR_TRUE, getter_AddRefs(rdfNode)); gRDFService->GetLiteral(PromiseFlatString(aType).get(), getter_AddRefs(rdfLiteral)); mInner->Change(aAlias, kSQL_Type, rdfNode, rdfLiteral); mInner->GetTarget(aAlias, kSQL_Hostname, PR_TRUE, getter_AddRefs(rdfNode)); gRDFService->GetLiteral(PromiseFlatString(aHostname).get(), getter_AddRefs(rdfLiteral)); mInner->Change(aAlias, kSQL_Hostname, rdfNode, rdfLiteral); mInner->GetTarget(aAlias, kSQL_Port, PR_TRUE, getter_AddRefs(rdfNode)); gRDFService->GetIntLiteral(aPort, getter_AddRefs(rdfInt)); mInner->Change(aAlias, kSQL_Port, rdfNode, rdfInt); mInner->GetTarget(aAlias, kSQL_Database, PR_TRUE, getter_AddRefs(rdfNode)); gRDFService->GetLiteral(PromiseFlatString(aDatabase).get(), getter_AddRefs(rdfLiteral)); mInner->Change(aAlias, kSQL_Database, rdfNode, rdfLiteral); mInner->GetTarget(aAlias, kSQL_Priority, PR_TRUE, getter_AddRefs(rdfNode)); gRDFService->GetIntLiteral(aPriority, getter_AddRefs(rdfInt)); if (rdfNode) mInner->Change(aAlias, kSQL_Priority, rdfNode, rdfInt); else mInner->Assert(aAlias, kSQL_Priority, rdfInt, PR_TRUE); Flush(); return NS_OK; } NS_IMETHODIMP mozSqlService::RemoveAlias(nsIRDFResource* aAlias) { nsCOMPtr rdfNode; mInner->GetTarget(aAlias, kSQL_Name, PR_TRUE, getter_AddRefs(rdfNode)); mInner->Unassert(aAlias, kSQL_Name, rdfNode); mInner->GetTarget(aAlias, kSQL_Type, PR_TRUE, getter_AddRefs(rdfNode)); mInner->Unassert(aAlias, kSQL_Type, rdfNode); mInner->GetTarget(aAlias, kSQL_Hostname, PR_TRUE, getter_AddRefs(rdfNode)); mInner->Unassert(aAlias, kSQL_Hostname, rdfNode); mInner->GetTarget(aAlias, kSQL_Port, PR_TRUE, getter_AddRefs(rdfNode)); mInner->Unassert(aAlias, kSQL_Port, rdfNode); mInner->GetTarget(aAlias, kSQL_Database, PR_TRUE, getter_AddRefs(rdfNode)); mInner->Unassert(aAlias, kSQL_Database, rdfNode); mInner->GetTarget(aAlias, kSQL_Priority, PR_TRUE, getter_AddRefs(rdfNode)); mInner->Unassert(aAlias, kSQL_Priority, rdfNode); nsresult rv = EnsureAliasesContainer(); if (NS_FAILED(rv)) return rv; mAliasesContainer->RemoveElement(aAlias, PR_TRUE); Flush(); return NS_OK; } NS_IMETHODIMP mozSqlService::GetAlias(const nsAString& aName, nsIRDFResource** _retval) { nsCOMPtr nameLiteral; nsresult rv = gRDFService->GetLiteral(PromiseFlatString(aName).get(), getter_AddRefs(nameLiteral)); if (NS_FAILED(rv)) return rv; nsCOMPtr alias; rv = mInner->GetSource(kSQL_Name, nameLiteral, PR_TRUE, getter_AddRefs(alias)); if (NS_FAILED(rv)) return rv; NS_IF_ADDREF(*_retval = alias); return NS_OK; } NS_IMETHODIMP mozSqlService::GetAliases(const nsAString& aName, nsISimpleEnumerator** _retval) { nsCOMPtr nameLiteral; nsresult rv = gRDFService->GetLiteral(PromiseFlatString(aName).get(), getter_AddRefs(nameLiteral)); if (NS_FAILED(rv)) return rv; nsCOMPtr aliases; rv = mInner->GetSources(kSQL_Name, nameLiteral, PR_TRUE, getter_AddRefs(aliases)); if (NS_FAILED(rv)) return rv; NS_IF_ADDREF(*_retval = aliases); return NS_OK; } NS_IMETHODIMP mozSqlService::GetConnection(nsIRDFResource* aAlias, mozISqlConnection **_retval) { nsISupportsKey key(aAlias); nsCOMPtr weakRef; nsCOMPtr conn; if (mConnectionCache) { weakRef = getter_AddRefs(static_cast(mConnectionCache->Get(&key))); if (weakRef) { conn = do_QueryReferent(weakRef); if (conn) NS_ADDREF(*_retval = conn); } } if (! *_retval) { nsresult rv = GetNewConnection(aAlias, getter_AddRefs(conn)); if (NS_FAILED(rv)) return rv; weakRef = do_GetWeakReference(conn); if (! mConnectionCache) { mConnectionCache = new nsSupportsHashtable(16); if (! mConnectionCache) return NS_ERROR_OUT_OF_MEMORY; } mConnectionCache->Put(&key, weakRef); NS_ADDREF(*_retval = conn); } return NS_OK; } NS_IMETHODIMP mozSqlService::GetNewConnection(nsIRDFResource* aAlias, mozISqlConnection **_retval) { nsAutoString name; nsAutoString type; nsAutoString hostname; PRInt32 port; nsAutoString database; PRInt32 priority; nsresult rv = FetchAlias(aAlias, name, type, hostname, &port, database, &priority); if (NS_FAILED(rv)) return rv; nsCAutoString contractID("@mozilla.org/sql/connection;1?type="); AppendUTF16toUTF8(type, contractID); nsCOMPtr conn = do_CreateInstance(contractID.get()); if (! conn) return NS_ERROR_FAILURE; nsCOMPtr watcher(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); nsCOMPtr prompter; watcher->GetNewPrompter(0, getter_AddRefs(prompter)); PRBool retval; do { nsXPIDLString username; nsXPIDLString password; prompter->PromptUsernameAndPassword( nsnull, // in wstring dialogTitle nsnull, // in wstring text getter_Copies(username), getter_Copies(password), nsnull, // in wstring checkMsg nsnull, // inout boolean checkValue &retval ); if (retval) { rv = conn->Init(hostname, port, database, username, password); if (NS_FAILED(rv)) { conn->GetErrorMessage(mErrorMessage); prompter->Alert(nsnull, mErrorMessage.get()); } } } while(retval && NS_FAILED(rv)); NS_IF_ADDREF(*_retval = conn); return rv; } NS_IMETHODIMP mozSqlService::GetURI(char** aURI) { if (!aURI) return NS_ERROR_NULL_POINTER; *aURI = nsCRT::strdup("rdf:sql"); if (!(*aURI)) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; } NS_IMETHODIMP mozSqlService::GetSource(nsIRDFResource* aProperty, nsIRDFNode* aTarget, PRBool aTruthValue, nsIRDFResource** aSource) { return mInner->GetSource(aProperty, aTarget, aTruthValue, aSource); } NS_IMETHODIMP mozSqlService::GetSources(nsIRDFResource* aProperty, nsIRDFNode* aTarget, PRBool aTruthValue, nsISimpleEnumerator** aSources) { return mInner->GetSources(aProperty, aTarget, aTruthValue, aSources); } NS_IMETHODIMP mozSqlService::GetTarget(nsIRDFResource* aSource, nsIRDFResource* aProperty, PRBool aTruthValue, nsIRDFNode** aTarget) { return mInner->GetTarget(aSource, aProperty, aTruthValue, aTarget); } NS_IMETHODIMP mozSqlService::GetTargets(nsIRDFResource* aSource, nsIRDFResource* aProperty, PRBool aTruthValue, nsISimpleEnumerator** aTargets) { return mInner->GetTargets(aSource, aProperty, aTruthValue, aTargets); } NS_IMETHODIMP mozSqlService::Assert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget, PRBool aTruthValue) { return mInner->Assert(aSource, aProperty, aTarget, aTruthValue); } NS_IMETHODIMP mozSqlService::Unassert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget) { return mInner->Unassert(aSource, aProperty, aTarget); } NS_IMETHODIMP mozSqlService::Change(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aOldTarget, nsIRDFNode* aNewTarget) { return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget); } NS_IMETHODIMP mozSqlService::Move(nsIRDFResource* aOldSource, nsIRDFResource* aNewSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget) { return mInner->Move(aOldSource, aNewSource, aProperty, aTarget); } NS_IMETHODIMP mozSqlService::HasAssertion(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aTarget, PRBool aTruthValue, PRBool* hasAssertion) { return mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, hasAssertion); } NS_IMETHODIMP mozSqlService::AddObserver(nsIRDFObserver* aObserver) { return mInner->AddObserver(aObserver); } NS_IMETHODIMP mozSqlService::RemoveObserver(nsIRDFObserver* aObserver) { return mInner->RemoveObserver(aObserver); } NS_IMETHODIMP mozSqlService::HasArcIn(nsIRDFNode* aNode, nsIRDFResource* aArc, PRBool* _retval) { return mInner->HasArcIn(aNode, aArc, _retval); } NS_IMETHODIMP mozSqlService::HasArcOut(nsIRDFResource* aSource, nsIRDFResource* aArc, PRBool* _retval) { return mInner->HasArcOut(aSource, aArc, _retval); } NS_IMETHODIMP mozSqlService::ArcLabelsIn(nsIRDFNode* aNode, nsISimpleEnumerator** aLabels) { return mInner->ArcLabelsIn(aNode, aLabels); } NS_IMETHODIMP mozSqlService::ArcLabelsOut(nsIRDFResource* aSource, nsISimpleEnumerator** aLabels) { return mInner->ArcLabelsIn(aSource, aLabels); } NS_IMETHODIMP mozSqlService::GetAllResources(nsISimpleEnumerator** aResult) { return mInner->GetAllResources(aResult); } NS_IMETHODIMP mozSqlService::GetAllCmds(nsIRDFResource* aSource, nsISimpleEnumerator** aCommands) { return mInner->GetAllCmds(aSource, aCommands); } NS_IMETHODIMP mozSqlService::IsCommandEnabled(nsISupportsArray* aSources, nsIRDFResource* aCommand, nsISupportsArray* aArguments, PRBool* aResult) { return mInner->IsCommandEnabled(aSources, aCommand, aArguments, aResult); } NS_IMETHODIMP mozSqlService::DoCommand(nsISupportsArray* aSources, nsIRDFResource* aCommand, nsISupportsArray* aArguments) { return mInner->DoCommand(aSources, aCommand, aArguments); } NS_IMETHODIMP mozSqlService::BeginUpdateBatch() { return mInner->BeginUpdateBatch(); } NS_IMETHODIMP mozSqlService::EndUpdateBatch() { return mInner->EndUpdateBatch(); } // nsIRDFRemoteDataSource NS_IMETHODIMP mozSqlService::GetLoaded(PRBool* aResult) { nsCOMPtr remote(do_QueryInterface(mInner)); return remote->GetLoaded(aResult); } NS_IMETHODIMP mozSqlService::Init(const char* aURI) { return NS_OK; } NS_IMETHODIMP mozSqlService::Refresh(PRBool aBlocking) { nsCOMPtr remote(do_QueryInterface(mInner)); return remote->Refresh(aBlocking); } NS_IMETHODIMP mozSqlService::Flush() { nsCOMPtr remote(do_QueryInterface(mInner)); return remote->Flush(); } NS_IMETHODIMP mozSqlService::FlushTo(const char *aURI) { nsCOMPtr remote(do_QueryInterface(mInner)); return remote->FlushTo(aURI); } nsresult mozSqlService::EnsureAliasesContainer() { if (! mAliasesContainer) { PRBool isContainer; nsresult rv = gRDFContainerUtils->IsContainer(mInner, kSQL_AliasesRoot, &isContainer); if (NS_FAILED(rv)) return rv; if (!isContainer) { rv = gRDFContainerUtils->MakeSeq(mInner, kSQL_AliasesRoot, getter_AddRefs(mAliasesContainer)); if (NS_FAILED(rv)) return rv; } else { mAliasesContainer = do_CreateInstance(NS_RDF_CONTRACTID "/container;1", &rv); if (NS_FAILED(rv)) return rv; rv = mAliasesContainer->Init(mInner, kSQL_AliasesRoot); if (NS_FAILED(rv)) return rv; } } return NS_OK; }