summaryrefslogtreecommitdiff
path: root/connectivity/source/drivers/mozab/mozillasrc/MQueryHelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'connectivity/source/drivers/mozab/mozillasrc/MQueryHelper.cxx')
-rw-r--r--connectivity/source/drivers/mozab/mozillasrc/MQueryHelper.cxx637
1 files changed, 637 insertions, 0 deletions
diff --git a/connectivity/source/drivers/mozab/mozillasrc/MQueryHelper.cxx b/connectivity/source/drivers/mozab/mozillasrc/MQueryHelper.cxx
new file mode 100644
index 000000000000..1ce71c85b9da
--- /dev/null
+++ b/connectivity/source/drivers/mozab/mozillasrc/MQueryHelper.cxx
@@ -0,0 +1,637 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_connectivity.hxx"
+
+#include "MQueryHelper.hxx"
+#include "MTypeConverter.hxx"
+#include "MConnection.hxx"
+#include "MNSDeclares.hxx"
+#include "MLdapAttributeMap.hxx"
+
+#include <connectivity/dbexception.hxx>
+
+#include "resource/mozab_res.hrc"
+
+using namespace connectivity::mozab;
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(connectivity::mozab::MQueryHelper,nsIAbDirectoryQueryResultListener)
+
+//
+// class MQueryHelperResultEntry
+//
+
+
+MQueryHelperResultEntry::MQueryHelperResultEntry()
+{
+ m_Card = NULL;
+ m_RowStates = 0;
+}
+
+MQueryHelperResultEntry::~MQueryHelperResultEntry()
+{
+ OSL_TRACE("IN MQueryHelperResultEntry::~MQueryHelperResultEntry()\n");
+ OSL_TRACE("OUT MQueryHelperResultEntry::~MQueryHelperResultEntry()\n");
+
+}
+void
+MQueryHelperResultEntry::setCard(nsIAbCard *card)
+{
+ m_Card = card;
+}
+nsIAbCard *
+MQueryHelperResultEntry::getCard()
+{
+ return m_Card;
+}
+void MQueryHelperResultEntry::insert( const rtl::OString &key, rtl::OUString &value )
+{
+ m_Fields[ key ] = value;
+}
+
+rtl::OUString MQueryHelperResultEntry::getValue( const rtl::OString &key ) const
+{
+ FieldMap::const_iterator iter = m_Fields.find( key );
+ if ( iter == m_Fields.end() )
+ {
+ return rtl::OUString();
+ }
+ else
+ {
+ return iter->second;
+ }
+}
+
+void MQueryHelperResultEntry::setValue( const rtl::OString &key, const rtl::OUString & rValue)
+{
+ m_Fields[ key ] = rValue;
+}
+//
+// class MQueryHelper
+//
+MQueryHelper::MQueryHelper()
+ :m_nIndex( 0 )
+ ,m_bHasMore( sal_True )
+ ,m_bAtEnd( sal_False )
+ ,m_bErrorCondition( sal_False )
+ ,m_bQueryComplete( sal_False )
+ ,mRefCnt( 0 ) // NSISUPPORTS - Initialize RefCnt to 0
+{
+ m_aResults.clear();
+#if OSL_DEBUG_LEVEL > 0
+ m_oThreadID = osl_getThreadIdentifier(NULL);
+#endif
+}
+
+MQueryHelper::~MQueryHelper()
+{
+ OSL_TRACE("IN MQueryHelper::~MQueryHelper()\n");
+ clear_results();
+ OSL_TRACE("OUT MQueryHelper::~MQueryHelper()\n");
+}
+
+void
+MQueryHelper::append(MQueryHelperResultEntry* resEnt )
+{
+ if ( resEnt != NULL ) {
+ m_aResults.push_back( resEnt );
+ m_bAtEnd = sal_False;
+ }
+}
+
+void
+MQueryHelper::clear_results()
+{
+ resultsArray::iterator iter = m_aResults.begin();
+ while ( iter != m_aResults.end() ) {
+ delete (*iter);
+ ++iter;
+ }
+ m_aResults.clear();
+}
+
+void
+MQueryHelper::rewind()
+{
+ m_nIndex = 0;
+}
+
+void
+MQueryHelper::reset()
+{
+ m_nIndex = 0;
+ m_bHasMore = sal_True;
+ m_bQueryComplete = sal_False;
+ m_bAtEnd = sal_False;
+ m_bErrorCondition = sal_False;
+ clear_results();
+}
+
+void
+MQueryHelper::clearResultOrComplete()
+{
+ // Don't use a Mutex, it should be called by a method already holding it.
+ OSL_TRACE("In/Out : clearResultOrComplete()");
+ m_aCondition.reset();
+}
+
+void
+MQueryHelper::notifyResultOrComplete()
+{
+ OSL_TRACE("In/Out : notifyResultOrComplete()");
+ m_aCondition.set();
+}
+
+sal_Bool
+MQueryHelper::waitForResultOrComplete( )
+{
+ TimeValue timeValue = { 1, 0 }; // 20 Seconds 0 NanoSecond timeout
+ sal_Int32 times=0;
+ osl::Condition::Result rv = ::osl::Condition::result_ok;
+
+ OSL_TRACE("In : waitForResultOrComplete()");
+ // Can't hold mutex or condition would never get set...
+ while( (m_aCondition.check() == sal_False || rv == ::osl::Condition::result_error) && times < 20) {
+ rv = m_aCondition.wait( &timeValue );
+ times ++;
+ }
+ if (times >= 20 && rv == ::osl::Condition::result_timeout ) {
+ OSL_TRACE("waitForResultOrComplete() : Timeout!");
+ m_aError.setResId( STR_TIMEOUT_WAITING );
+ return sal_False;
+ }
+
+ if ( isError() ) {
+ OSL_TRACE("waitForResultOrComplete() : Error returned!");
+ m_aError.setResId( STR_ERR_EXECUTING_QUERY );
+ return sal_False;
+ }
+ m_aError.reset();
+ OSL_TRACE(" Out : waitForResultOrComplete()");
+ return sal_True;
+}
+
+
+MQueryHelperResultEntry*
+MQueryHelper::next( )
+{
+ MQueryHelperResultEntry* result;
+ sal_Int32 index;
+
+ m_aMutex.acquire();
+ index = m_nIndex;
+ m_aMutex.release();
+
+ result = getByIndex( index + 1) ; // Add 1 as Row is numbered from 1 to N
+
+ if ( result ) {
+ m_aMutex.acquire();
+ m_nIndex++;
+ m_aMutex.release();
+ }
+
+ return( result );
+}
+
+MQueryHelperResultEntry*
+MQueryHelper::getByIndex( sal_uInt32 nRow )
+{
+ // Row numbers are from 1 to N, need to ensure this, and then
+ // substract 1
+ if ( nRow < 1 ) {
+ return( NULL );
+ }
+
+ do {
+ // Obtain the Mutex - don't use a guard as we want to be able to release
+ // and acquire again...
+ m_aMutex.acquire();
+ if ( nRow > m_aResults.size() )
+ {
+ if ( m_bQueryComplete )
+ {
+ m_bAtEnd = sal_True;
+ m_aMutex.release();
+ return( NULL );
+ }
+ else
+ {
+ clearResultOrComplete();
+ m_aMutex.release();
+ if ( !waitForResultOrComplete( ) )
+ return( NULL );
+ }
+ }
+ else
+ {
+ m_aMutex.release();
+ return( m_aResults[ nRow -1 ] );
+ }
+ } while ( sal_True );
+}
+
+sal_Bool
+MQueryHelper::hasMore() const
+{
+ return m_bHasMore;
+}
+
+sal_Bool
+MQueryHelper::atEnd() const
+{
+ return m_bAtEnd;
+}
+
+sal_Bool
+MQueryHelper::isError() const
+{
+ return m_bErrorCondition;
+}
+
+sal_Bool
+MQueryHelper::queryComplete() const
+{
+ return m_bQueryComplete;
+}
+
+sal_Bool
+MQueryHelper::waitForQueryComplete( )
+{
+ m_aMutex.acquire();
+
+ OSL_TRACE("In : waitForQueryComplete()");
+ if ( ! m_bQueryComplete ) {
+ do
+ {
+ m_aMutex.release();
+ clearResultOrComplete();
+ if ( !waitForResultOrComplete( ) )
+ return( sal_False );
+ m_aMutex.acquire();
+ }
+ while ( !m_bQueryComplete );
+ }
+
+ m_aMutex.release();
+ OSL_TRACE("Out : waitForQueryComplete()");
+ return( sal_True );
+}
+
+sal_Bool
+MQueryHelper::waitForRow( sal_Int32 rowNum )
+{
+ m_aMutex.acquire();
+ do
+ {
+ m_aMutex.release();
+ clearResultOrComplete();
+ if ( !waitForResultOrComplete() )
+ return( sal_False );
+ m_aMutex.acquire();
+ }
+ while ( !m_bQueryComplete && m_aResults.size() < (size_t)rowNum );
+
+ m_aMutex.release();
+ return( sal_True );
+}
+
+// -------------------------------------------------------------------------
+
+sal_Int32
+MQueryHelper::getResultCount() const
+{
+ OSL_TRACE( "IN MQueryHelper::getResultCount()" );
+ if ( !m_bQueryComplete )
+ {
+ OSL_TRACE( "\tOUT MQueryHelper::getResultCount() = -1\n");
+ return -1;
+ }
+ else
+ {
+ OSL_TRACE( "\tOUT MQueryHelper::getResultCount() = %d\n", m_aResults.size() );
+ return static_cast<sal_Int32>(m_aResults.size());
+ }
+}
+
+// -------------------------------------------------------------------------
+
+sal_uInt32
+MQueryHelper::getRealCount() const
+{
+ OSL_TRACE( "IN/OUT MQueryHelper::getRealCount() = %d\n", m_aResults.size() );
+ return static_cast<sal_Int32>(m_aResults.size());
+}
+
+// -------------------------------------------------------------------------
+NS_IMETHODIMP MQueryHelper::OnQueryItem(nsIAbDirectoryQueryResult *result)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+#if OSL_DEBUG_LEVEL > 0
+ OSL_TRACE( "IN MQueryHelper::OnQueryItem() Caller thread: %4d \n",m_oThreadID );
+#endif
+ nsresult rv;
+ PRInt32 resultType;
+
+ if ( result == NULL ) {
+ OSL_TRACE("\tresult ptr is NULL\n");
+ return NS_OK;
+ }
+
+ // Get return status of executeQuery() call.
+ rv = result -> GetType(&resultType);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Check for errors of the executeQuery() call.
+ switch ( resultType ) {
+ case nsIAbDirectoryQueryResult::queryResultError:
+ OSL_TRACE("\tresultType == nsIAbDirectoryQueryResult::queryResultError\n");
+ m_bQueryComplete = sal_True;
+ m_bErrorCondition = sal_True;
+ notifyResultOrComplete();
+ return NS_OK;
+ case nsIAbDirectoryQueryResult::queryResultStopped:
+ OSL_TRACE("\tresultType == nsIAbDirectoryQueryResult::queryResultStopped\n");
+ m_bQueryComplete = sal_True;
+ notifyResultOrComplete();
+ return NS_OK;
+ case nsIAbDirectoryQueryResult::queryResultComplete:
+ OSL_TRACE("\tresultType == nsIAbDirectoryQueryResult::queryResultComplete\n");
+ m_bQueryComplete = sal_True;
+ notifyResultOrComplete();
+ return NS_OK;
+ case nsIAbDirectoryQueryResult::queryResultMatch:
+ OSL_TRACE("IN MQueryHelper::OnQueryItem --> queryResultMatch\n");
+ // Don't return, continues onto rest of method.
+ break;
+ default:
+ OSL_TRACE("\t******** Unexpected : resultType\n");
+ m_bQueryComplete = sal_True;
+ return NS_OK;
+ }
+
+ // Initialise an array that holds the resultset of the query.
+ nsCOMPtr<nsISupportsArray> properties;
+ rv = result -> GetResult(getter_AddRefs (properties));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+
+ nsCOMPtr<nsISupports> item;
+ rv = properties -> GetElementAt(0, getter_AddRefs(item));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbDirectoryQueryPropertyValue> property(do_QueryInterface(item, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ char *name;
+ rv = property -> GetName(&name);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if ( !strcmp(name,"card:nsIAbCard") )
+ {
+ nsCOMPtr<nsISupports> cardSupports;
+ property->GetValueISupports (getter_AddRefs (cardSupports));
+ nsCOMPtr<nsIAbCard> card(do_QueryInterface(cardSupports, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ getCardValues(card);
+ }
+ nsMemory::Free(name);
+
+ OSL_TRACE( "\tOUT MQueryHelper::OnQueryItem()\n" );
+
+ notifyResultOrComplete();
+
+ return(NS_OK);
+}
+
+// -----------------------------------------------------------------------------
+void MQueryHelper::notifyQueryError()
+{
+ m_bQueryComplete = sal_True ;
+ notifyResultOrComplete() ;
+}
+
+const char * getAddrURI(const nsIAbDirectory* directory)
+{
+ nsresult retCode;
+ nsCOMPtr<nsIRDFResource> rdfResource = do_QueryInterface((nsISupports *)directory, &retCode) ;
+ if (NS_FAILED(retCode)) { return NULL; }
+ const char * uri;
+ retCode=rdfResource->GetValueConst(&uri);
+ if (NS_FAILED(retCode)) { return NULL; }
+ return uri;
+ }
+
+#define ENSURE_GETUPDATECARD(x) \
+ if (NS_FAILED(retCode)) \
+ { \
+ OSL_TRACE( x ); \
+ return card; \
+ }
+static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
+
+//Some address book does not support query uri on card
+//In this case, we can't resync the cards, we just return the old cards
+nsIAbCard * getUpdatedCard( nsIAbCard* card)
+{
+ OSL_ENSURE(card != NULL, "getUpdatedCard for NULL");
+ nsresult retCode;
+ nsCOMPtr<nsIRDFResource> rdfResource = do_QueryInterface((nsISupports *)card, &retCode) ;
+ ENSURE_GETUPDATECARD( "IN getUpdatedCard: Card does not support nsIRDFResource\n" );
+
+ const char * uri;
+ retCode=rdfResource->GetValueConst(&uri);
+ ENSURE_GETUPDATECARD( "IN getUpdatedCard: Card does not has a uri\n" );
+
+ nsCOMPtr<nsIRDFService> rdfService (do_GetService(kRDFServiceCID, &retCode)) ;
+ ENSURE_GETUPDATECARD( "IN getUpdatedCard: Card does not has a uri\n" );
+
+ nsCOMPtr<nsIRDFResource> rdfCard;
+
+ retCode = rdfService->GetResource(nsDependentCString(uri), getter_AddRefs(rdfCard)) ;
+ ENSURE_GETUPDATECARD( "IN getUpdatedCard: Can not get the updated card\n" );
+
+ nsCOMPtr<nsIAbCard> aNewCard=do_QueryInterface((nsISupports *)rdfCard, &retCode);
+ ENSURE_GETUPDATECARD( "IN getUpdatedCard: Error in get new card\n" );
+
+ return aNewCard;
+ }
+
+#define ENSURE_MOZAB_PROFILE_NOT_LOOKED(directory) \
+ if (getDirectoryType(directory) == SDBCAddress::Mozilla && isProfileLocked(NULL)) \
+ { \
+ m_aError.setResId( STR_MOZILLA_IS_RUNNIG_NO_CHANGES ); \
+ return sal_False; \
+ }
+
+sal_Int32 MQueryHelper::commitCard(const sal_Int32 rowIndex,nsIAbDirectory * directory)
+{
+ ENSURE_MOZAB_PROFILE_NOT_LOOKED(directory);
+
+ MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
+ if (!resEntry)
+ {
+ return sal_False;
+ }
+ nsIAbCard *card=resEntry->getCard();
+ if (!card)
+ {
+ return sal_False;
+ }
+ nsresult rv;
+ PRBool hasCard;
+ rv = directory->HasCard(card,&hasCard);
+ if (setCardValues(rowIndex) != sal_True)
+ return sal_False;
+
+ if (!NS_FAILED(rv) && hasCard)
+ {
+ rv = card->EditCardToDatabase(getAddrURI(directory));
+ }
+ else
+ {
+ nsIAbCard *addedCard=NULL;
+ rv = directory->AddCard(card,&addedCard);
+ if (!NS_FAILED(rv))
+ resEntry->setCard(addedCard);
+ }
+ //We return NS_ERROR_FILE_ACCESS_DENIED in the case the mozillaAB has been changed out side of our process
+ if (rv == NS_ERROR_FILE_ACCESS_DENIED )
+ m_aError.setResId( STR_FOREIGN_PROCESS_CHANGED_AB );
+
+ return !(NS_FAILED(rv));
+}
+
+sal_Int32 MQueryHelper::deleteCard(const sal_Int32 rowIndex,nsIAbDirectory * directory)
+{
+ ENSURE_MOZAB_PROFILE_NOT_LOOKED(directory);
+ MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
+ if (!resEntry)
+ {
+ return sal_False;
+ }
+ nsIAbCard *card=resEntry->getCard();
+ if (!card)
+ {
+ return sal_False;
+ }
+ nsresult rv;
+ PRBool hasCard;
+ if (resEntry->getRowStates() == RowStates_Inserted)
+ {
+ rv = 0;
+ hasCard = sal_True;
+ }
+ else
+ rv = directory->HasCard(card,&hasCard);
+
+ if (!NS_FAILED(rv) && hasCard)
+ {
+ nsCOMPtr <nsISupportsArray> cardsToDelete;
+ rv = NS_NewISupportsArray(getter_AddRefs(cardsToDelete));
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(card, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = cardsToDelete->AppendElement(supports);
+ if (NS_SUCCEEDED(rv))
+ rv = directory->DeleteCards(cardsToDelete);
+ }
+ }
+ }
+
+ if (NS_SUCCEEDED(rv))
+ resEntry->setRowStates(RowStates_Deleted);
+ //We return NS_ERROR_FILE_ACCESS_DENIED in the case the mozillaAB has been changed out side of our process
+ if (rv == NS_ERROR_FILE_ACCESS_DENIED )
+ m_aError.setResId( STR_FOREIGN_PROCESS_CHANGED_AB );
+ return !(NS_FAILED(rv));
+}
+
+sal_Bool MQueryHelper::setCardValues(const sal_Int32 rowIndex)
+{
+ MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
+ if (!resEntry)
+ {
+ m_aError.setResId( STR_CANT_FIND_ROW );
+ return sal_False;
+ }
+ nsIAbCard *card=resEntry->getCard();
+ if (!card)
+ {
+ m_aError.setResId( STR_CANT_FIND_CARD_FOR_ROW );
+ return sal_False;
+ }
+
+ MLdapAttributeMap::fillCardFromResult( *card, *resEntry );
+ return sal_True;
+}
+
+void MQueryHelper::getCardValues(nsIAbCard *card,sal_Int32 rowIndex)
+{
+ MQueryHelperResultEntry *resEntry;
+ if (rowIndex>0)
+ {
+ resEntry = getByIndex(rowIndex);
+ }
+ else
+ resEntry = new MQueryHelperResultEntry();
+
+ MLdapAttributeMap::fillResultFromCard( *resEntry, *card );
+ resEntry->setCard(card);
+ if (!rowIndex)
+ append( resEntry );
+}
+sal_Bool MQueryHelper::resyncRow(sal_Int32 rowIndex)
+{
+
+ MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
+ if (!resEntry)
+ {
+ m_aError.setResId( STR_CANT_FIND_ROW );
+ return sal_False;
+ }
+ nsIAbCard *card=resEntry->getCard();
+ card = getUpdatedCard(card);
+ getCardValues(card,rowIndex);
+ return sal_True;
+}
+// -------------------------------------------------------------------------
+sal_Int32 MQueryHelper::createNewCard()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ nsresult rv;
+ nsCOMPtr <nsIAbCard> card = do_CreateInstance(NS_ABCARDPROPERTY_CONTRACTID, &rv);
+ //set default values
+ getCardValues(card);
+ return static_cast<sal_Int32>(m_aResults.size());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */