LCOV - code coverage report
Current view: top level - libreoffice/dbaccess/source/core/dataaccess - datasource.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 10 601 1.7 %
Date: 2012-12-27 Functions: 3 82 3.7 %
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 file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "datasource.hxx"
      22             : #include "module_dba.hxx"
      23             : #include "userinformation.hxx"
      24             : #include "commandcontainer.hxx"
      25             : #include "dbastrings.hrc"
      26             : #include "core_resource.hxx"
      27             : #include "core_resource.hrc"
      28             : #include "connection.hxx"
      29             : #include "SharedConnection.hxx"
      30             : #include "databasedocument.hxx"
      31             : #include "OAuthenticationContinuation.hxx"
      32             : 
      33             : 
      34             : #include <com/sun/star/beans/NamedValue.hpp>
      35             : #include <com/sun/star/beans/PropertyAttribute.hpp>
      36             : #include <com/sun/star/beans/PropertyState.hpp>
      37             : #include <com/sun/star/beans/XPropertyContainer.hpp>
      38             : #include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
      39             : #include <com/sun/star/document/XEventBroadcaster.hpp>
      40             : #include <com/sun/star/embed/XTransactedObject.hpp>
      41             : #include <com/sun/star/lang/DisposedException.hpp>
      42             : #include <com/sun/star/reflection/ProxyFactory.hpp>
      43             : #include <com/sun/star/sdb/DatabaseContext.hpp>
      44             : #include <com/sun/star/sdbc/ConnectionPool.hpp>
      45             : #include <com/sun/star/sdbc/XDriverAccess.hpp>
      46             : #include <com/sun/star/sdbc/XDriverManager.hpp>
      47             : #include <com/sun/star/sdbc/DriverManager.hpp>
      48             : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
      49             : #include <com/sun/star/ucb/AuthenticationRequest.hpp>
      50             : #include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
      51             : #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
      52             : #include <com/sun/star/view/XPrintable.hpp>
      53             : 
      54             : #include <comphelper/extract.hxx>
      55             : #include <comphelper/guarding.hxx>
      56             : #include <comphelper/interaction.hxx>
      57             : #include <comphelper/namedvaluecollection.hxx>
      58             : #include <comphelper/property.hxx>
      59             : #include <comphelper/seqstream.hxx>
      60             : #include <comphelper/sequence.hxx>
      61             : #include <connectivity/dbexception.hxx>
      62             : #include <connectivity/dbtools.hxx>
      63             : #include <cppuhelper/typeprovider.hxx>
      64             : #include <tools/debug.hxx>
      65             : #include <tools/diagnose_ex.h>
      66             : #include <osl/diagnose.h>
      67             : #include <tools/urlobj.hxx>
      68             : #include <typelib/typedescription.hxx>
      69             : #include <unotools/confignode.hxx>
      70             : #include <unotools/sharedunocomponent.hxx>
      71             : #include <rtl/logfile.hxx>
      72             : #include <rtl/digest.h>
      73             : #include <algorithm>
      74             : #include <iterator>
      75             : 
      76             : using namespace ::com::sun::star::sdbc;
      77             : using namespace ::com::sun::star::sdbcx;
      78             : using namespace ::com::sun::star::sdb;
      79             : using namespace ::com::sun::star::beans;
      80             : using namespace ::com::sun::star::uno;
      81             : using namespace ::com::sun::star::lang;
      82             : using namespace ::com::sun::star::embed;
      83             : using namespace ::com::sun::star::container;
      84             : using namespace ::com::sun::star::util;
      85             : using namespace ::com::sun::star::io;
      86             : using namespace ::com::sun::star::task;
      87             : using namespace ::com::sun::star::ucb;
      88             : using namespace ::com::sun::star::frame;
      89             : using namespace ::com::sun::star::reflection;
      90             : using namespace ::cppu;
      91             : using namespace ::osl;
      92             : using namespace ::dbtools;
      93             : using namespace ::comphelper;
      94             : 
      95             : namespace dbaccess
      96             : {
      97             : 
      98             : //============================================================
      99             : //= FlushNotificationAdapter
     100             : //============================================================
     101             : typedef ::cppu::WeakImplHelper1< XFlushListener > FlushNotificationAdapter_Base;
     102             : /** helper class which implements a XFlushListener, and forwards all
     103             :     notification events to another XFlushListener
     104             : 
     105             :     The speciality is that the foreign XFlushListener instance, to which
     106             :     the notifications are forwarded, is held weak.
     107             : 
     108             :     Thus, the class can be used with XFlushable instance which hold
     109             :     their listeners with a hard reference, if you simply do not *want*
     110             :     to be held hard-ref-wise.
     111             : */
     112             : class FlushNotificationAdapter : public FlushNotificationAdapter_Base
     113             : {
     114             : private:
     115             :     WeakReference< XFlushable >     m_aBroadcaster;
     116             :     WeakReference< XFlushListener > m_aListener;
     117             : 
     118             : public:
     119           0 :     static void installAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
     120             :     {
     121           0 :         Reference< XFlushListener > xAdapter( new FlushNotificationAdapter( _rxBroadcaster, _rxListener ) );
     122           0 :     }
     123             : 
     124             : protected:
     125             :     FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener );
     126             :     ~FlushNotificationAdapter();
     127             : 
     128             :     void SAL_CALL impl_dispose( bool _bRevokeListener );
     129             : 
     130             : protected:
     131             :     // XFlushListener
     132             :     virtual void SAL_CALL flushed( const ::com::sun::star::lang::EventObject& rEvent ) throw (::com::sun::star::uno::RuntimeException);
     133             :     // XEventListener
     134             :     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
     135             : };
     136             : 
     137             : //------------------------------------------------------------
     138             : DBG_NAME( FlushNotificationAdapter )
     139             : //------------------------------------------------------------
     140           0 : FlushNotificationAdapter::FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
     141             :     :m_aBroadcaster( _rxBroadcaster )
     142           0 :     ,m_aListener( _rxListener )
     143             : {
     144             :     DBG_CTOR( FlushNotificationAdapter, NULL );
     145             :     OSL_ENSURE( _rxBroadcaster.is(), "FlushNotificationAdapter::FlushNotificationAdapter: invalid flushable!" );
     146             : 
     147           0 :     osl_atomic_increment( &m_refCount );
     148             :     {
     149           0 :         if ( _rxBroadcaster.is() )
     150           0 :             _rxBroadcaster->addFlushListener( this );
     151             :     }
     152           0 :     osl_atomic_decrement( &m_refCount );
     153             :     OSL_ENSURE( m_refCount == 1, "FlushNotificationAdapter::FlushNotificationAdapter: broadcaster isn't holding by hard ref!?" );
     154           0 : }
     155             : 
     156             : //------------------------------------------------------------
     157           0 : FlushNotificationAdapter::~FlushNotificationAdapter()
     158             : {
     159             :     DBG_DTOR( FlushNotificationAdapter, NULL );
     160           0 : }
     161             : 
     162           0 : void SAL_CALL FlushNotificationAdapter::impl_dispose( bool _bRevokeListener )
     163             : {
     164           0 :     Reference< XFlushListener > xKeepAlive( this );
     165             : 
     166           0 :     if ( _bRevokeListener )
     167             :     {
     168           0 :         Reference< XFlushable > xFlushable( m_aBroadcaster );
     169           0 :         if ( xFlushable.is() )
     170           0 :             xFlushable->removeFlushListener( this );
     171             :     }
     172             : 
     173           0 :     m_aListener = Reference< XFlushListener >();
     174           0 :     m_aBroadcaster = Reference< XFlushable >();
     175           0 : }
     176             : 
     177           0 : void SAL_CALL FlushNotificationAdapter::flushed( const EventObject& rEvent ) throw (RuntimeException)
     178             : {
     179           0 :     Reference< XFlushListener > xListener( m_aListener );
     180           0 :     if ( xListener.is() )
     181           0 :         xListener->flushed( rEvent );
     182             :     else
     183           0 :         impl_dispose( true );
     184           0 : }
     185             : 
     186           0 : void SAL_CALL FlushNotificationAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
     187             : {
     188           0 :     Reference< XFlushListener > xListener( m_aListener );
     189           0 :     if ( xListener.is() )
     190           0 :         xListener->disposing( Source );
     191             : 
     192           0 :     impl_dispose( true );
     193           0 : }
     194             : 
     195           0 : OAuthenticationContinuation::OAuthenticationContinuation()
     196             :     :m_bRemberPassword(sal_True),   // TODO: a meaningful default
     197           0 :     m_bCanSetUserName(sal_True)
     198             : {
     199           0 : }
     200             : 
     201           0 : sal_Bool SAL_CALL OAuthenticationContinuation::canSetRealm(  ) throw(RuntimeException)
     202             : {
     203           0 :     return sal_False;
     204             : }
     205             : 
     206           0 : void SAL_CALL OAuthenticationContinuation::setRealm( const ::rtl::OUString& /*Realm*/ ) throw(RuntimeException)
     207             : {
     208             :     OSL_FAIL("OAuthenticationContinuation::setRealm: not supported!");
     209           0 : }
     210             : 
     211           0 : sal_Bool SAL_CALL OAuthenticationContinuation::canSetUserName(  ) throw(RuntimeException)
     212             : {
     213             :     // we always allow this, even if the database document is read-only. In this case,
     214             :     // it's simply that the user cannot store the new user name.
     215           0 :     return m_bCanSetUserName;
     216             : }
     217             : 
     218           0 : void SAL_CALL OAuthenticationContinuation::setUserName( const ::rtl::OUString& _rUser ) throw(RuntimeException)
     219             : {
     220           0 :     m_sUser = _rUser;
     221           0 : }
     222             : 
     223           0 : sal_Bool SAL_CALL OAuthenticationContinuation::canSetPassword(  ) throw(RuntimeException)
     224             : {
     225           0 :     return sal_True;
     226             : }
     227             : 
     228           0 : void SAL_CALL OAuthenticationContinuation::setPassword( const ::rtl::OUString& _rPassword ) throw(RuntimeException)
     229             : {
     230           0 :     m_sPassword = _rPassword;
     231           0 : }
     232             : 
     233           0 : Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberPasswordModes( RememberAuthentication& _reDefault ) throw(RuntimeException)
     234             : {
     235           0 :     Sequence< RememberAuthentication > aReturn(1);
     236           0 :     _reDefault = aReturn[0] = RememberAuthentication_SESSION;
     237           0 :     return aReturn;
     238             : }
     239             : 
     240           0 : void SAL_CALL OAuthenticationContinuation::setRememberPassword( RememberAuthentication _eRemember ) throw(RuntimeException)
     241             : {
     242           0 :     m_bRemberPassword = (RememberAuthentication_NO != _eRemember);
     243           0 : }
     244             : 
     245           0 : sal_Bool SAL_CALL OAuthenticationContinuation::canSetAccount(  ) throw(RuntimeException)
     246             : {
     247           0 :     return sal_False;
     248             : }
     249             : 
     250           0 : void SAL_CALL OAuthenticationContinuation::setAccount( const ::rtl::OUString& ) throw(RuntimeException)
     251             : {
     252             :     OSL_FAIL("OAuthenticationContinuation::setAccount: not supported!");
     253           0 : }
     254             : 
     255           0 : Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberAccountModes( RememberAuthentication& _reDefault ) throw(RuntimeException)
     256             : {
     257           0 :     Sequence < RememberAuthentication > aReturn(1);
     258           0 :     aReturn[0] = RememberAuthentication_NO;
     259           0 :     _reDefault = RememberAuthentication_NO;
     260           0 :     return aReturn;
     261             : }
     262             : 
     263           0 : void SAL_CALL OAuthenticationContinuation::setRememberAccount( RememberAuthentication /*Remember*/ ) throw(RuntimeException)
     264             : {
     265             :     OSL_FAIL("OAuthenticationContinuation::setRememberAccount: not supported!");
     266           0 : }
     267             : 
     268             : /** The class OSharedConnectionManager implements a structure to share connections.
     269             :     It owns the master connections which will be disposed when the last connection proxy is gone.
     270             : */
     271             : typedef ::cppu::WeakImplHelper1< XEventListener > OConnectionHelper_BASE;
     272             : // need to hold the digest
     273             : struct TDigestHolder
     274             : {
     275             :     sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1];
     276           0 :     TDigestHolder()
     277             :     {
     278           0 :         m_pBuffer[0] = 0;
     279           0 :     }
     280             : 
     281             : };
     282             : 
     283             : class OSharedConnectionManager : public OConnectionHelper_BASE
     284             : {
     285             : 
     286             :      // contains the currently used master connections
     287             :     typedef struct
     288           0 :     {
     289             :         Reference< XConnection >    xMasterConnection;
     290             :         oslInterlockedCount         nALiveCount;
     291           0 :     } TConnectionHolder;
     292             : 
     293             :     // the less-compare functor, used for the stl::map
     294             :     struct TDigestLess : public ::std::binary_function< TDigestHolder, TDigestHolder, bool>
     295             :     {
     296           0 :         bool operator() (const TDigestHolder& x, const TDigestHolder& y) const
     297             :         {
     298             :             sal_uInt32 i;
     299           0 :             for(i=0;i < RTL_DIGEST_LENGTH_SHA1 && (x.m_pBuffer[i] >= y.m_pBuffer[i]); ++i)
     300             :                 ;
     301           0 :             return i < RTL_DIGEST_LENGTH_SHA1;
     302             :         }
     303             :     };
     304             : 
     305             :     typedef ::std::map< TDigestHolder,TConnectionHolder,TDigestLess>        TConnectionMap;      // holds the master connections
     306             :     typedef ::std::map< Reference< XConnection >,TConnectionMap::iterator>  TSharedConnectionMap;// holds the shared connections
     307             : 
     308             :     ::osl::Mutex                m_aMutex;
     309             :     TConnectionMap              m_aConnections;         // remember the master connection in conjunction with the digest
     310             :     TSharedConnectionMap        m_aSharedConnection;    // the shared connections with conjunction with an iterator into the connections map
     311             :     Reference< XProxyFactory >  m_xProxyFactory;
     312             : 
     313             : protected:
     314             :     ~OSharedConnectionManager();
     315             : 
     316             : public:
     317             :     OSharedConnectionManager(const Reference< XComponentContext >& _rxContext);
     318             : 
     319             :     void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException);
     320             :     Reference<XConnection> getConnection(   const rtl::OUString& url,
     321             :                                             const rtl::OUString& user,
     322             :                                             const rtl::OUString& password,
     323             :                                             const Sequence< PropertyValue >& _aInfo,
     324             :                                             ODatabaseSource* _pDataSource);
     325             :     void addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter);
     326             : };
     327             : 
     328             : DBG_NAME(OSharedConnectionManager)
     329           0 : OSharedConnectionManager::OSharedConnectionManager(const Reference< XComponentContext >& _rxContext)
     330             : {
     331             :     DBG_CTOR(OSharedConnectionManager,NULL);
     332           0 :     m_xProxyFactory.set( ProxyFactory::create( _rxContext ) );
     333           0 : }
     334             : 
     335           0 : OSharedConnectionManager::~OSharedConnectionManager()
     336             : {
     337             :     DBG_DTOR(OSharedConnectionManager,NULL);
     338           0 : }
     339             : 
     340           0 : void SAL_CALL OSharedConnectionManager::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException)
     341             : {
     342           0 :     MutexGuard aGuard(m_aMutex);
     343           0 :     Reference<XConnection> xConnection(Source.Source,UNO_QUERY);
     344           0 :     TSharedConnectionMap::iterator aFind = m_aSharedConnection.find(xConnection);
     345           0 :     if ( m_aSharedConnection.end() != aFind )
     346             :     {
     347           0 :         osl_atomic_decrement(&aFind->second->second.nALiveCount);
     348           0 :         if ( !aFind->second->second.nALiveCount )
     349             :         {
     350           0 :             ::comphelper::disposeComponent(aFind->second->second.xMasterConnection);
     351           0 :             m_aConnections.erase(aFind->second);
     352             :         }
     353           0 :         m_aSharedConnection.erase(aFind);
     354           0 :     }
     355           0 : }
     356             : 
     357           0 : Reference<XConnection> OSharedConnectionManager::getConnection( const rtl::OUString& url,
     358             :                                         const rtl::OUString& user,
     359             :                                         const rtl::OUString& password,
     360             :                                         const Sequence< PropertyValue >& _aInfo,
     361             :                                         ODatabaseSource* _pDataSource)
     362             : {
     363           0 :     MutexGuard aGuard(m_aMutex);
     364           0 :     TConnectionMap::key_type nId;
     365           0 :     Sequence< PropertyValue > aInfoCopy(_aInfo);
     366           0 :     sal_Int32 nPos = aInfoCopy.getLength();
     367           0 :     aInfoCopy.realloc( nPos + 2 );
     368           0 :     aInfoCopy[nPos].Name      = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableFilter"));
     369           0 :     aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableFilter;
     370           0 :     aInfoCopy[nPos].Name      = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableTypeFilter"));
     371           0 :     aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableTypeFilter;
     372             : 
     373           0 :     ::rtl::OUString sUser = user;
     374           0 :     ::rtl::OUString sPassword = password;
     375           0 :     if ((sUser.isEmpty()) && (sPassword.isEmpty()) && (!_pDataSource->m_pImpl->m_sUser.isEmpty()))
     376             :     {   // ease the usage of this method. data source which are intended to have a user automatically
     377             :         // fill in the user/password combination if the caller of this method does not specify otherwise
     378           0 :         sUser = _pDataSource->m_pImpl->m_sUser;
     379           0 :         if (!_pDataSource->m_pImpl->m_aPassword.isEmpty())
     380           0 :             sPassword = _pDataSource->m_pImpl->m_aPassword;
     381             :     }
     382             : 
     383           0 :     ::connectivity::OConnectionWrapper::createUniqueId(url,aInfoCopy,nId.m_pBuffer,sUser,sPassword);
     384           0 :     TConnectionMap::iterator aIter = m_aConnections.find(nId);
     385             : 
     386           0 :     if ( m_aConnections.end() == aIter )
     387             :     {
     388           0 :         TConnectionHolder aHolder;
     389           0 :         aHolder.nALiveCount = 0; // will be incremented by addListener
     390           0 :         aHolder.xMasterConnection = _pDataSource->buildIsolatedConnection(user,password);
     391           0 :         aIter = m_aConnections.insert(TConnectionMap::value_type(nId,aHolder)).first;
     392             :     }
     393             : 
     394           0 :     Reference<XConnection> xRet;
     395           0 :     if ( aIter->second.xMasterConnection.is() )
     396             :     {
     397           0 :         Reference< XAggregation > xConProxy = m_xProxyFactory->createProxy(aIter->second.xMasterConnection.get());
     398           0 :         xRet = new OSharedConnection(xConProxy);
     399           0 :         m_aSharedConnection.insert(TSharedConnectionMap::value_type(xRet,aIter));
     400           0 :         addEventListener(xRet,aIter);
     401             :     }
     402             : 
     403           0 :     return xRet;
     404             : }
     405           0 : void OSharedConnectionManager::addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter)
     406             : {
     407           0 :     Reference<XComponent> xComp(_rxConnection,UNO_QUERY);
     408           0 :     xComp->addEventListener(this);
     409             :     OSL_ENSURE( m_aConnections.end() != _rIter , "Iterator is end!");
     410           0 :     osl_atomic_increment(&_rIter->second.nALiveCount);
     411           0 : }
     412             : 
     413             : namespace
     414             : {
     415           0 :     Sequence< PropertyValue > lcl_filterDriverProperties( const Reference< XDriver >& _xDriver, const ::rtl::OUString& _sUrl,
     416             :         const Sequence< PropertyValue >& _rDataSourceSettings, const AsciiPropertyValue* _pKnownSettings )
     417             :     {
     418           0 :         if ( _xDriver.is() )
     419             :         {
     420           0 :             Sequence< DriverPropertyInfo > aDriverInfo(_xDriver->getPropertyInfo(_sUrl,_rDataSourceSettings));
     421             : 
     422           0 :             const PropertyValue* pDataSourceSetting = _rDataSourceSettings.getConstArray();
     423           0 :             const PropertyValue* pEnd = pDataSourceSetting + _rDataSourceSettings.getLength();
     424             : 
     425           0 :             ::std::vector< PropertyValue > aRet;
     426             : 
     427           0 :             for ( ; pDataSourceSetting != pEnd ; ++pDataSourceSetting )
     428             :             {
     429           0 :                 sal_Bool bAllowSetting = sal_False;
     430           0 :                 const AsciiPropertyValue* pSetting = _pKnownSettings;
     431           0 :                 for ( ; pSetting->AsciiName; ++pSetting )
     432             :                 {
     433           0 :                     if ( !pDataSourceSetting->Name.compareToAscii( pSetting->AsciiName ) )
     434             :                     {   // the particular data source setting is known
     435             : 
     436           0 :                         const DriverPropertyInfo* pAllowedDriverSetting = aDriverInfo.getConstArray();
     437           0 :                         const DriverPropertyInfo* pDriverSettingsEnd = pAllowedDriverSetting + aDriverInfo.getLength();
     438           0 :                         for ( ; pAllowedDriverSetting != pDriverSettingsEnd; ++pAllowedDriverSetting )
     439             :                         {
     440           0 :                             if ( !pAllowedDriverSetting->Name.compareToAscii( pSetting->AsciiName ) )
     441             :                             {   // the driver also allows this setting
     442           0 :                                 bAllowSetting = sal_True;
     443           0 :                                 break;
     444             :                             }
     445             :                         }
     446           0 :                         break;
     447             :                     }
     448             :                 }
     449           0 :                 if ( bAllowSetting || !pSetting->AsciiName )
     450             :                 {   // if the driver allows this particular setting, or if the setting is completely unknown,
     451             :                     // we pass it to the driver
     452           0 :                     aRet.push_back( *pDataSourceSetting );
     453             :                 }
     454             :             }
     455           0 :             if ( !aRet.empty() )
     456           0 :                 return Sequence< PropertyValue >(&(*aRet.begin()),aRet.size());
     457             :         }
     458           0 :         return Sequence< PropertyValue >();
     459             :     }
     460             : 
     461             :     typedef ::std::map< ::rtl::OUString, sal_Int32 > PropertyAttributeCache;
     462             : 
     463             :     struct IsDefaultAndNotRemoveable : public ::std::unary_function< PropertyValue, bool >
     464             :     {
     465             :     private:
     466             :         const PropertyAttributeCache& m_rAttribs;
     467             : 
     468             :     public:
     469           0 :         IsDefaultAndNotRemoveable( const PropertyAttributeCache& _rAttribs ) : m_rAttribs( _rAttribs ) { }
     470             : 
     471           0 :         bool operator()( const PropertyValue& _rProp )
     472             :         {
     473           0 :             if ( _rProp.State != PropertyState_DEFAULT_VALUE )
     474           0 :                 return false;
     475             : 
     476           0 :             bool bRemoveable = true;
     477             : 
     478           0 :             PropertyAttributeCache::const_iterator pos = m_rAttribs.find( _rProp.Name );
     479             :             OSL_ENSURE( pos != m_rAttribs.end(), "IsDefaultAndNotRemoveable: illegal property name!" );
     480           0 :             if ( pos != m_rAttribs.end() )
     481           0 :                 bRemoveable = ( ( pos->second & PropertyAttribute::REMOVEABLE ) != 0 );
     482             : 
     483           0 :             return !bRemoveable;
     484             :         }
     485             :     };
     486             : }
     487             : //============================================================
     488             : //= ODatabaseContext
     489             : //============================================================
     490             : DBG_NAME(ODatabaseSource)
     491             : 
     492           3 : extern "C" void SAL_CALL createRegistryInfo_ODatabaseSource()
     493             : {
     494           3 :     static ::dba::OAutoRegistration< ODatabaseSource > aAutoRegistration;
     495           3 : }
     496             : 
     497           0 : ODatabaseSource::ODatabaseSource(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl)
     498             :             :ModelDependentComponent( _pImpl )
     499           0 :             ,ODatabaseSource_Base( getMutex() )
     500             :             ,OPropertySetHelper( ODatabaseSource_Base::rBHelper )
     501           0 :             ,m_aBookmarks( *this, getMutex() )
     502           0 :             ,m_aFlushListeners( getMutex() )
     503             : {
     504             :     // some kind of default
     505             :     DBG_CTOR(ODatabaseSource,NULL);
     506             :     OSL_TRACE( "DS: ctor: %p: %p", this, m_pImpl.get() );
     507           0 : }
     508             : 
     509           0 : ODatabaseSource::~ODatabaseSource()
     510             : {
     511             :     OSL_TRACE( "DS: dtor: %p: %p", this, m_pImpl.get() );
     512             :     DBG_DTOR(ODatabaseSource,NULL);
     513           0 :     if ( !ODatabaseSource_Base::rBHelper.bInDispose && !ODatabaseSource_Base::rBHelper.bDisposed )
     514             :     {
     515           0 :         acquire();
     516           0 :         dispose();
     517             :     }
     518           0 : }
     519             : 
     520           0 : void ODatabaseSource::setName( const Reference< XDocumentDataSource >& _rxDocument, const ::rtl::OUString& _rNewName, DBContextAccess )
     521             : {
     522             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setName" );
     523           0 :     ODatabaseSource& rModelImpl = dynamic_cast< ODatabaseSource& >( *_rxDocument.get() );
     524             : 
     525           0 :     ::osl::MutexGuard aGuard( rModelImpl.m_aMutex );
     526           0 :     if ( rModelImpl.m_pImpl.is() )
     527           0 :         rModelImpl.m_pImpl->m_sName = _rNewName;
     528           0 : }
     529             : 
     530             : // com::sun::star::lang::XTypeProvider
     531           0 : Sequence< Type > ODatabaseSource::getTypes() throw (RuntimeException)
     532             : {
     533             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTypes" );
     534           0 :     OTypeCollection aPropertyHelperTypes(   ::getCppuType( (const Reference< XFastPropertySet > *)0 ),
     535           0 :                                             ::getCppuType( (const Reference< XPropertySet > *)0 ),
     536           0 :                                             ::getCppuType( (const Reference< XMultiPropertySet > *)0 ));
     537             : 
     538             :     return ::comphelper::concatSequences(
     539             :         ODatabaseSource_Base::getTypes(),
     540             :         aPropertyHelperTypes.getTypes()
     541           0 :     );
     542             : }
     543             : 
     544           0 : Sequence< sal_Int8 > ODatabaseSource::getImplementationId() throw (RuntimeException)
     545             : {
     546             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationId" );
     547             :     static OImplementationId * pId = 0;
     548           0 :     if (! pId)
     549             :     {
     550           0 :         MutexGuard aGuard( Mutex::getGlobalMutex() );
     551           0 :         if (! pId)
     552             :         {
     553           0 :             static OImplementationId aId;
     554           0 :             pId = &aId;
     555           0 :         }
     556             :     }
     557           0 :     return pId->getImplementationId();
     558             : }
     559             : 
     560             : // com::sun::star::uno::XInterface
     561           0 : Any ODatabaseSource::queryInterface( const Type & rType ) throw (RuntimeException)
     562             : {
     563           0 :     Any aIface = ODatabaseSource_Base::queryInterface( rType );
     564           0 :     if ( !aIface.hasValue() )
     565           0 :         aIface = ::cppu::OPropertySetHelper::queryInterface( rType );
     566           0 :     return aIface;
     567             : }
     568             : 
     569           0 : void ODatabaseSource::acquire() throw ()
     570             : {
     571           0 :     ODatabaseSource_Base::acquire();
     572           0 : }
     573             : 
     574           0 : void ODatabaseSource::release() throw ()
     575             : {
     576           0 :     ODatabaseSource_Base::release();
     577           0 : }
     578             : 
     579           0 : void SAL_CALL ODatabaseSource::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException)
     580             : {
     581           0 :     if ( m_pImpl.is() )
     582           0 :         m_pImpl->disposing(Source);
     583           0 : }
     584             : // XServiceInfo
     585           0 : rtl::OUString ODatabaseSource::getImplementationName(  ) throw(RuntimeException)
     586             : {
     587             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName" );
     588           0 :     return getImplementationName_static();
     589             : }
     590             : 
     591           3 : rtl::OUString ODatabaseSource::getImplementationName_static(  ) throw(RuntimeException)
     592             : {
     593             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName_static" );
     594           3 :     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.ODatabaseSource"));
     595             : }
     596             : 
     597           0 : Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames(  ) throw (RuntimeException)
     598             : {
     599             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames" );
     600           0 :     return getSupportedServiceNames_static();
     601             : }
     602             : 
     603           0 : Reference< XInterface > ODatabaseSource::Create( const Reference< XComponentContext >& _rxContext )
     604             : {
     605             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::Create" );
     606           0 :     Reference< XDatabaseContext > xDBContext( DatabaseContext::create(_rxContext) );
     607           0 :     return xDBContext->createInstance();
     608             : }
     609             : 
     610           3 : Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames_static(  ) throw (RuntimeException)
     611             : {
     612             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames_static" );
     613           3 :     Sequence< ::rtl::OUString > aSNS( 2 );
     614           3 :     aSNS[0] = SERVICE_SDB_DATASOURCE;
     615           3 :     aSNS[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.DocumentDataSource"));
     616           3 :     return aSNS;
     617             : }
     618             : 
     619           0 : sal_Bool ODatabaseSource::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
     620             : {
     621             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::supportsService" );
     622           0 :     return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
     623             : }
     624             : 
     625             : // OComponentHelper
     626           0 : void ODatabaseSource::disposing()
     627             : {
     628             :     OSL_TRACE( "DS: disp: %p, %p", this, m_pImpl.get() );
     629           0 :     ODatabaseSource_Base::WeakComponentImplHelperBase::disposing();
     630           0 :     OPropertySetHelper::disposing();
     631             : 
     632           0 :     EventObject aDisposeEvent(static_cast<XWeak*>(this));
     633           0 :     m_aFlushListeners.disposeAndClear( aDisposeEvent );
     634             : 
     635           0 :     ODatabaseDocument::clearObjectContainer(m_pImpl->m_xCommandDefinitions);
     636           0 :     ODatabaseDocument::clearObjectContainer(m_pImpl->m_xTableDefinitions);
     637           0 :     m_pImpl.clear();
     638           0 : }
     639             : 
     640           0 : Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const ::rtl::OUString& _rUid, const ::rtl::OUString& _rPwd)
     641             : {
     642             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildLowLevelConnection" );
     643           0 :     Reference< XConnection > xReturn;
     644             : 
     645           0 :     Reference< XDriverManager > xManager;
     646             :     try {
     647           0 :         xManager.set( ConnectionPool::create( m_pImpl->m_aContext.getUNOContext() ), UNO_QUERY_THROW );
     648           0 :     } catch( const Exception& ) {  }
     649           0 :     if ( !xManager.is() )
     650             :         // no connection pool installed, fall back to driver manager
     651           0 :         xManager.set( DriverManager::create(m_pImpl->m_aContext.getUNOContext() ), UNO_QUERY_THROW );
     652             : 
     653           0 :     ::rtl::OUString sUser(_rUid);
     654           0 :     ::rtl::OUString sPwd(_rPwd);
     655           0 :     if ((sUser.isEmpty()) && (sPwd.isEmpty()) && (!m_pImpl->m_sUser.isEmpty()))
     656             :     {   // ease the usage of this method. data source which are intended to have a user automatically
     657             :         // fill in the user/password combination if the caller of this method does not specify otherwise
     658           0 :         sUser = m_pImpl->m_sUser;
     659           0 :         if (!m_pImpl->m_aPassword.isEmpty())
     660           0 :             sPwd = m_pImpl->m_aPassword;
     661             :     }
     662             : 
     663           0 :     sal_uInt16 nExceptionMessageId = RID_STR_COULDNOTCONNECT_UNSPECIFIED;
     664           0 :     if (xManager.is())
     665             :     {
     666           0 :         sal_Int32 nAdditionalArgs(0);
     667           0 :         if (!sUser.isEmpty()) ++nAdditionalArgs;
     668           0 :         if (!sPwd.isEmpty()) ++nAdditionalArgs;
     669             : 
     670           0 :         Sequence< PropertyValue > aUserPwd(nAdditionalArgs);
     671           0 :         sal_Int32 nArgPos = 0;
     672           0 :         if (sUser.getLength())
     673             :         {
     674           0 :             aUserPwd[ nArgPos ].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user"));
     675           0 :             aUserPwd[ nArgPos ].Value <<= sUser;
     676           0 :             ++nArgPos;
     677             :         }
     678           0 :         if (!sPwd.isEmpty())
     679             :         {
     680           0 :             aUserPwd[ nArgPos ].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("password"));
     681           0 :             aUserPwd[ nArgPos ].Value <<= sPwd;
     682             :         }
     683           0 :         Reference< XDriver > xDriver;
     684             :         try
     685             :         {
     686           0 :             Reference< XDriverAccess > xAccessDrivers( xManager, UNO_QUERY );
     687           0 :             if ( xAccessDrivers.is() )
     688           0 :                 xDriver = xAccessDrivers->getDriverByURL( m_pImpl->m_sConnectURL );
     689             :         }
     690           0 :         catch( const Exception& )
     691             :         {
     692             :             OSL_FAIL( "ODatabaseSource::buildLowLevelConnection: got a strange exception while analyzing the error!" );
     693             :         }
     694           0 :         if ( !xDriver.is() || !xDriver->acceptsURL( m_pImpl->m_sConnectURL ) )
     695             :         {
     696             :             // Nowadays, it's allowed for a driver to be registered for a given URL, but actually not to accept it.
     697             :             // This is because registration nowadays happens at compile time (by adding respective configuration data),
     698             :             // but acceptance is decided at runtime.
     699           0 :             nExceptionMessageId = RID_STR_COULDNOTCONNECT_NODRIVER;
     700             :         }
     701             :         else
     702             :         {
     703             :             Sequence< PropertyValue > aDriverInfo = lcl_filterDriverProperties(
     704             :                 xDriver,
     705           0 :                 m_pImpl->m_sConnectURL,
     706           0 :                 m_pImpl->m_xSettings->getPropertyValues(),
     707           0 :                 m_pImpl->getDefaultDataSourceSettings()
     708           0 :             );
     709             : 
     710           0 :             if ( m_pImpl->isEmbeddedDatabase() )
     711             :             {
     712           0 :                 sal_Int32 nCount = aDriverInfo.getLength();
     713           0 :                 aDriverInfo.realloc(nCount + 2 );
     714           0 :                 aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
     715           0 :                 aDriverInfo[nCount++].Value <<= m_pImpl->getURL();
     716           0 :                 aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Storage"));
     717           0 :                 Reference< css::document::XDocumentSubStorageSupplier> xDocSup( m_pImpl->getDocumentSubStorageSupplier() );
     718           0 :                 aDriverInfo[nCount++].Value <<= xDocSup->getDocumentSubStorage(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("database")),ElementModes::READWRITE);
     719             :             }
     720           0 :             if (nAdditionalArgs)
     721           0 :                 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL, ::comphelper::concatSequences(aUserPwd,aDriverInfo));
     722             :             else
     723           0 :                 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL,aDriverInfo);
     724             : 
     725           0 :             if ( m_pImpl->isEmbeddedDatabase() )
     726             :             {
     727             :                 // see ODatabaseSource::flushed for comment on why we register as FlushListener
     728             :                 // at the connection
     729           0 :                 Reference< XFlushable > xFlushable( xReturn, UNO_QUERY );
     730           0 :                 if ( xFlushable.is() )
     731           0 :                     FlushNotificationAdapter::installAdapter( xFlushable, this );
     732           0 :             }
     733           0 :         }
     734             :     }
     735             :     else
     736           0 :         nExceptionMessageId = RID_STR_COULDNOTLOAD_MANAGER;
     737             : 
     738           0 :     if ( !xReturn.is() )
     739             :     {
     740           0 :         ::rtl::OUString sMessage = DBACORE_RESSTRING( nExceptionMessageId );
     741             : 
     742           0 :         SQLContext aContext;
     743             :         aContext.Message = DBACORE_RESSTRING(RID_STR_CONNECTION_REQUEST).
     744           0 :             replaceFirst("$name$", m_pImpl->m_sConnectURL);
     745             : 
     746           0 :         throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), makeAny( aContext ) );
     747             :     }
     748             : 
     749           0 :     return xReturn;
     750             : }
     751             : 
     752             : // OPropertySetHelper
     753           0 : Reference< XPropertySetInfo >  ODatabaseSource::getPropertySetInfo() throw (RuntimeException)
     754             : {
     755             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getPropertySetInfo" );
     756           0 :     return createPropertySetInfo( getInfoHelper() ) ;
     757             : }
     758             : 
     759             : // comphelper::OPropertyArrayUsageHelper
     760           0 : ::cppu::IPropertyArrayHelper* ODatabaseSource::createArrayHelper( ) const
     761             : {
     762             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::createArrayHelper" );
     763           0 :     BEGIN_PROPERTY_HELPER(13)
     764           0 :         DECL_PROP1(INFO,                        Sequence< PropertyValue >,  BOUND);
     765           0 :         DECL_PROP1_BOOL(ISPASSWORDREQUIRED,                                 BOUND);
     766           0 :         DECL_PROP1_BOOL(ISREADONLY,                                         READONLY);
     767           0 :         DECL_PROP1(LAYOUTINFORMATION,           Sequence< PropertyValue >,  BOUND);
     768           0 :         DECL_PROP1(NAME,                        ::rtl::OUString,            READONLY);
     769           0 :         DECL_PROP2_IFACE(NUMBERFORMATSSUPPLIER, XNumberFormatsSupplier,     READONLY, TRANSIENT);
     770           0 :         DECL_PROP1(PASSWORD,                    ::rtl::OUString,            TRANSIENT);
     771           0 :         DECL_PROP2_IFACE(SETTINGS,              XPropertySet,               BOUND, READONLY);
     772           0 :         DECL_PROP1_BOOL(SUPPRESSVERSIONCL,                                  BOUND);
     773           0 :         DECL_PROP1(TABLEFILTER,                 Sequence< ::rtl::OUString >,BOUND);
     774           0 :         DECL_PROP1(TABLETYPEFILTER,             Sequence< ::rtl::OUString >,BOUND);
     775           0 :         DECL_PROP1(URL,                         ::rtl::OUString,            BOUND);
     776           0 :         DECL_PROP1(USER,                        ::rtl::OUString,            BOUND);
     777           0 :     END_PROPERTY_HELPER();
     778             : }
     779             : 
     780             : // cppu::OPropertySetHelper
     781           0 : ::cppu::IPropertyArrayHelper& ODatabaseSource::getInfoHelper()
     782             : {
     783           0 :     return *getArrayHelper();
     784             : }
     785             : 
     786           0 : sal_Bool ODatabaseSource::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException  )
     787             : {
     788           0 :     sal_Bool bModified(sal_False);
     789           0 :     if ( m_pImpl.is() )
     790             :     {
     791           0 :         switch (nHandle)
     792             :         {
     793             :             case PROPERTY_ID_TABLEFILTER:
     794           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableFilter);
     795           0 :                 break;
     796             :             case PROPERTY_ID_TABLETYPEFILTER:
     797           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableTypeFilter);
     798           0 :                 break;
     799             :             case PROPERTY_ID_USER:
     800           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sUser);
     801           0 :                 break;
     802             :             case PROPERTY_ID_PASSWORD:
     803           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aPassword);
     804           0 :                 break;
     805             :             case PROPERTY_ID_ISPASSWORDREQUIRED:
     806           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bPasswordRequired);
     807           0 :                 break;
     808             :             case PROPERTY_ID_SUPPRESSVERSIONCL:
     809           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bSuppressVersionColumns);
     810           0 :                 break;
     811             :             case PROPERTY_ID_LAYOUTINFORMATION:
     812           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aLayoutInformation);
     813           0 :                 break;
     814             :             case PROPERTY_ID_URL:
     815             :             {
     816           0 :                 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sConnectURL);
     817           0 :             }   break;
     818             :             case PROPERTY_ID_INFO:
     819             :             {
     820           0 :                 Sequence<PropertyValue> aValues;
     821           0 :                 if (!(rValue >>= aValues))
     822           0 :                     throw IllegalArgumentException();
     823             : 
     824           0 :                 const PropertyValue* valueEnd = aValues.getConstArray() + aValues.getLength();
     825           0 :                 const PropertyValue* checkName = aValues.getConstArray();
     826           0 :                 for ( ;checkName != valueEnd; ++checkName )
     827             :                 {
     828           0 :                     if ( checkName->Name.isEmpty() )
     829           0 :                         throw IllegalArgumentException();
     830             :                 }
     831             : 
     832           0 :                 Sequence< PropertyValue > aSettings = m_pImpl->m_xSettings->getPropertyValues();
     833           0 :                 bModified = aSettings.getLength() != aValues.getLength();
     834           0 :                 if ( !bModified )
     835             :                 {
     836           0 :                     const PropertyValue* pInfoIter = aSettings.getConstArray();
     837           0 :                     const PropertyValue* checkValue = aValues.getConstArray();
     838           0 :                     for ( ;!bModified && checkValue != valueEnd ; ++checkValue,++pInfoIter)
     839             :                     {
     840           0 :                         bModified = checkValue->Name != pInfoIter->Name;
     841           0 :                         if ( !bModified )
     842             :                         {
     843           0 :                             bModified = !::comphelper::compare(checkValue->Value,pInfoIter->Value);
     844             :                         }
     845             :                     }
     846             :                 }
     847             : 
     848           0 :                 rConvertedValue = rValue;
     849           0 :                 rOldValue <<= aSettings;
     850             :             }
     851           0 :             break;
     852             :             default:
     853             :                 OSL_FAIL( "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" );
     854             :         }
     855             :     }
     856           0 :     return bModified;
     857             : }
     858             : 
     859             : namespace
     860             : {
     861             :     struct SelectPropertyName : public ::std::unary_function< PropertyValue, ::rtl::OUString >
     862             :     {
     863             :     public:
     864           0 :         const ::rtl::OUString& operator()( const PropertyValue& _lhs )
     865             :         {
     866           0 :             return _lhs.Name;
     867             :         }
     868             :     };
     869             : 
     870             :     /** sets a new set of property values for a given property bag instance
     871             : 
     872             :         The method takes a property bag, and a sequence of property values to set for this bag.
     873             :         Upon return, every property which is not part of the given sequence is
     874             :         <ul><li>removed from the bag, if it's a removeable property</li>
     875             :             <li><em>or</em>reset to its default value, if it's not a removeable property</li>
     876             :         </ul>.
     877             : 
     878             :         @param  _rxPropertyBag
     879             :             the property bag to operate on
     880             :         @param  _rAllNewPropertyValues
     881             :             the new property values to set for the bag
     882             :     */
     883           0 :     void lcl_setPropertyValues_resetOrRemoveOther( const Reference< XPropertyAccess >& _rxPropertyBag, const Sequence< PropertyValue >& _rAllNewPropertyValues )
     884             :     {
     885             :         // sequences are ugly to operate on
     886             :         typedef ::std::set< ::rtl::OUString >   StringSet;
     887           0 :         StringSet aToBeSetPropertyNames;
     888             :         ::std::transform(
     889             :             _rAllNewPropertyValues.getConstArray(),
     890           0 :             _rAllNewPropertyValues.getConstArray() + _rAllNewPropertyValues.getLength(),
     891             :             ::std::insert_iterator< StringSet >( aToBeSetPropertyNames, aToBeSetPropertyNames.end() ),
     892             :             SelectPropertyName()
     893           0 :         );
     894             : 
     895             :         try
     896             :         {
     897             :             // obtain all properties currently known at the bag
     898           0 :             Reference< XPropertySet > xPropertySet( _rxPropertyBag, UNO_QUERY_THROW );
     899           0 :             Reference< XPropertySetInfo > xPSI( xPropertySet->getPropertySetInfo(), UNO_QUERY_THROW );
     900           0 :             Sequence< Property > aAllExistentProperties( xPSI->getProperties() );
     901             : 
     902           0 :             Reference< XPropertyState > xPropertyState( _rxPropertyBag, UNO_QUERY_THROW );
     903           0 :             Reference< XPropertyContainer > xPropertyContainer( _rxPropertyBag, UNO_QUERY_THROW );
     904             : 
     905             :             // loop through them, and reset resp. default properties which are not to be set
     906           0 :             const Property* pExistentProperty( aAllExistentProperties.getConstArray() );
     907           0 :             const Property* pExistentPropertyEnd( aAllExistentProperties.getConstArray() + aAllExistentProperties.getLength() );
     908           0 :             for ( ; pExistentProperty != pExistentPropertyEnd; ++pExistentProperty )
     909             :             {
     910           0 :                 if ( aToBeSetPropertyNames.find( pExistentProperty->Name ) != aToBeSetPropertyNames.end() )
     911           0 :                     continue;
     912             : 
     913             :                 // this property is not to be set, but currently exists in the bag.
     914             :                 // -> Remove it, or reset it to the default.
     915           0 :                 if ( ( pExistentProperty->Attributes & PropertyAttribute::REMOVEABLE ) != 0 )
     916           0 :                     xPropertyContainer->removeProperty( pExistentProperty->Name );
     917             :                 else
     918           0 :                     xPropertyState->setPropertyToDefault( pExistentProperty->Name );
     919             :             }
     920             : 
     921             :             // finally, set the new property values
     922           0 :             _rxPropertyBag->setPropertyValues( _rAllNewPropertyValues );
     923             :         }
     924           0 :         catch( const Exception& )
     925             :         {
     926             :             DBG_UNHANDLED_EXCEPTION();
     927           0 :         }
     928           0 :     }
     929             : }
     930             : 
     931           0 : void ODatabaseSource::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
     932             : {
     933             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setFastPropertyValue_NoBroadcast" );
     934           0 :     if ( m_pImpl.is() )
     935             :     {
     936           0 :         switch(nHandle)
     937             :         {
     938             :             case PROPERTY_ID_TABLEFILTER:
     939           0 :                 rValue >>= m_pImpl->m_aTableFilter;
     940           0 :                 break;
     941             :             case PROPERTY_ID_TABLETYPEFILTER:
     942           0 :                 rValue >>= m_pImpl->m_aTableTypeFilter;
     943           0 :                 break;
     944             :             case PROPERTY_ID_USER:
     945           0 :                 rValue >>= m_pImpl->m_sUser;
     946             :                 // if the user name has changed, reset the password
     947           0 :                 m_pImpl->m_aPassword = ::rtl::OUString();
     948           0 :                 break;
     949             :             case PROPERTY_ID_PASSWORD:
     950           0 :                 rValue >>= m_pImpl->m_aPassword;
     951           0 :                 break;
     952             :             case PROPERTY_ID_ISPASSWORDREQUIRED:
     953           0 :                 m_pImpl->m_bPasswordRequired = any2bool(rValue);
     954           0 :                 break;
     955             :             case PROPERTY_ID_SUPPRESSVERSIONCL:
     956           0 :                 m_pImpl->m_bSuppressVersionColumns = any2bool(rValue);
     957           0 :                 break;
     958             :             case PROPERTY_ID_URL:
     959           0 :                 rValue >>= m_pImpl->m_sConnectURL;
     960           0 :                 break;
     961             :             case PROPERTY_ID_INFO:
     962             :             {
     963           0 :                 Sequence< PropertyValue > aInfo;
     964           0 :                 OSL_VERIFY( rValue >>= aInfo );
     965           0 :                 lcl_setPropertyValues_resetOrRemoveOther( m_pImpl->m_xSettings, aInfo );
     966             :             }
     967           0 :             break;
     968             :             case PROPERTY_ID_LAYOUTINFORMATION:
     969           0 :                 rValue >>= m_pImpl->m_aLayoutInformation;
     970           0 :                 break;
     971             :         }
     972           0 :         m_pImpl->setModified(sal_True);
     973             :     }
     974           0 : }
     975             : 
     976           0 : void ODatabaseSource::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
     977             : {
     978             :     //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getFastPropertyValue" );
     979           0 :     if ( m_pImpl.is() )
     980             :     {
     981           0 :         switch (nHandle)
     982             :         {
     983             :             case PROPERTY_ID_TABLEFILTER:
     984           0 :                 rValue <<= m_pImpl->m_aTableFilter;
     985           0 :                 break;
     986             :             case PROPERTY_ID_TABLETYPEFILTER:
     987           0 :                 rValue <<= m_pImpl->m_aTableTypeFilter;
     988           0 :                 break;
     989             :             case PROPERTY_ID_USER:
     990           0 :                 rValue <<= m_pImpl->m_sUser;
     991           0 :                 break;
     992             :             case PROPERTY_ID_PASSWORD:
     993           0 :                 rValue <<= m_pImpl->m_aPassword;
     994           0 :                 break;
     995             :             case PROPERTY_ID_ISPASSWORDREQUIRED:
     996           0 :                 rValue = bool2any(m_pImpl->m_bPasswordRequired);
     997           0 :                 break;
     998             :             case PROPERTY_ID_SUPPRESSVERSIONCL:
     999           0 :                 rValue = bool2any(m_pImpl->m_bSuppressVersionColumns);
    1000           0 :                 break;
    1001             :             case PROPERTY_ID_ISREADONLY:
    1002           0 :                 rValue = bool2any(m_pImpl->m_bReadOnly);
    1003           0 :                 break;
    1004             :             case PROPERTY_ID_INFO:
    1005             :             {
    1006             :                 try
    1007             :                 {
    1008             :                     // collect the property attributes of all current settings
    1009           0 :                     Reference< XPropertySet > xSettingsAsProps( m_pImpl->m_xSettings, UNO_QUERY_THROW );
    1010           0 :                     Reference< XPropertySetInfo > xPST( xSettingsAsProps->getPropertySetInfo(), UNO_QUERY_THROW );
    1011           0 :                     Sequence< Property > aSettings( xPST->getProperties() );
    1012           0 :                     ::std::map< ::rtl::OUString, sal_Int32 > aPropertyAttributes;
    1013           0 :                     for (   const Property* pSettings = aSettings.getConstArray();
    1014           0 :                             pSettings != aSettings.getConstArray() + aSettings.getLength();
    1015             :                             ++pSettings
    1016             :                         )
    1017             :                     {
    1018           0 :                         aPropertyAttributes[ pSettings->Name ] = pSettings->Attributes;
    1019             :                     }
    1020             : 
    1021             :                     // get all current settings with their values
    1022           0 :                     Sequence< PropertyValue > aValues( m_pImpl->m_xSettings->getPropertyValues() );
    1023             : 
    1024             :                     // transform them so that only property values which fulfill certain
    1025             :                     // criteria survive
    1026           0 :                     Sequence< PropertyValue > aNonDefaultOrUserDefined( aValues.getLength() );
    1027             :                     const PropertyValue* pCopyEnd = ::std::remove_copy_if(
    1028             :                         aValues.getConstArray(),
    1029           0 :                         aValues.getConstArray() + aValues.getLength(),
    1030             :                         aNonDefaultOrUserDefined.getArray(),
    1031             :                         IsDefaultAndNotRemoveable( aPropertyAttributes )
    1032           0 :                     );
    1033           0 :                     aNonDefaultOrUserDefined.realloc( pCopyEnd - aNonDefaultOrUserDefined.getArray() );
    1034           0 :                     rValue <<= aNonDefaultOrUserDefined;
    1035             :                 }
    1036           0 :                 catch( const Exception& )
    1037             :                 {
    1038             :                     DBG_UNHANDLED_EXCEPTION();
    1039             :                 }
    1040             :             }
    1041           0 :             break;
    1042             :             case PROPERTY_ID_SETTINGS:
    1043           0 :                 rValue <<= m_pImpl->m_xSettings;
    1044           0 :                 break;
    1045             :             case PROPERTY_ID_URL:
    1046           0 :                 rValue <<= m_pImpl->m_sConnectURL;
    1047           0 :                 break;
    1048             :             case PROPERTY_ID_NUMBERFORMATSSUPPLIER:
    1049           0 :                 rValue <<= m_pImpl->getNumberFormatsSupplier();
    1050           0 :                 break;
    1051             :             case PROPERTY_ID_NAME:
    1052           0 :                 rValue <<= m_pImpl->m_sName;
    1053           0 :                 break;
    1054             :             case PROPERTY_ID_LAYOUTINFORMATION:
    1055           0 :                 rValue <<= m_pImpl->m_aLayoutInformation;
    1056           0 :                 break;
    1057             :             default:
    1058             :                 OSL_FAIL("unknown Property");
    1059             :         }
    1060             :     }
    1061           0 : }
    1062             : 
    1063             : // XDataSource
    1064           0 : void ODatabaseSource::setLoginTimeout(sal_Int32 seconds) throw( SQLException, RuntimeException )
    1065             : {
    1066             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setLoginTimeout" );
    1067           0 :     ModelMethodGuard aGuard( *this );
    1068           0 :     m_pImpl->m_nLoginTimeout = seconds;
    1069           0 : }
    1070             : 
    1071           0 : sal_Int32 ODatabaseSource::getLoginTimeout(void) throw( SQLException, RuntimeException )
    1072             : {
    1073             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getLoginTimeout" );
    1074           0 :     ModelMethodGuard aGuard( *this );
    1075           0 :     return m_pImpl->m_nLoginTimeout;
    1076             : }
    1077             : 
    1078             : // XCompletedConnection
    1079           0 : Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
    1080             : {
    1081             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
    1082           0 :     return connectWithCompletion(_rxHandler,sal_False);
    1083             : }
    1084             : 
    1085           0 : Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password) throw( SQLException, RuntimeException )
    1086             : {
    1087             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
    1088           0 :     return getConnection(user,password,sal_False);
    1089             : }
    1090             : 
    1091           0 : Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnection( const ::rtl::OUString& user, const ::rtl::OUString& password ) throw(SQLException, RuntimeException)
    1092             : {
    1093             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnection" );
    1094           0 :     return getConnection(user,password,sal_True);
    1095             : }
    1096             : 
    1097           0 : Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnectionWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
    1098             : {
    1099             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnectionWithCompletion" );
    1100           0 :     return connectWithCompletion(_rxHandler,sal_True);
    1101             : }
    1102             : 
    1103           0 : Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler,sal_Bool _bIsolated ) throw(SQLException, RuntimeException)
    1104             : {
    1105             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
    1106           0 :     ModelMethodGuard aGuard( *this );
    1107             : 
    1108           0 :     if (!_rxHandler.is())
    1109             :     {
    1110             :         OSL_FAIL("ODatabaseSource::connectWithCompletion: invalid interaction handler!");
    1111           0 :         return getConnection(m_pImpl->m_sUser, m_pImpl->m_aPassword,_bIsolated);
    1112             :     }
    1113             : 
    1114           0 :     ::rtl::OUString sUser(m_pImpl->m_sUser), sPassword(m_pImpl->m_aPassword);
    1115           0 :     sal_Bool bNewPasswordGiven = sal_False;
    1116             : 
    1117           0 :     if (m_pImpl->m_bPasswordRequired && sPassword.isEmpty())
    1118             :     {   // we need a password, but don't have one yet.
    1119             :         // -> ask the user
    1120             : 
    1121             :         // build an interaction request
    1122             :         // two continuations (Ok and Cancel)
    1123           0 :         OInteractionAbort* pAbort = new OInteractionAbort;
    1124           0 :         OAuthenticationContinuation* pAuthenticate = new OAuthenticationContinuation;
    1125             : 
    1126             :         // the name which should be referred in the login dialog
    1127           0 :         ::rtl::OUString sServerName( m_pImpl->m_sName );
    1128           0 :         INetURLObject aURLCheck( sServerName );
    1129           0 :         if ( aURLCheck.GetProtocol() != INET_PROT_NOT_VALID )
    1130           0 :             sServerName = aURLCheck.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_UNAMBIGUOUS );
    1131             : 
    1132             :         // the request
    1133           0 :         AuthenticationRequest aRequest;
    1134           0 :         aRequest.ServerName = sServerName;
    1135           0 :         aRequest.HasRealm = aRequest.HasAccount = sal_False;
    1136           0 :         aRequest.HasUserName = aRequest.HasPassword = sal_True;
    1137           0 :         aRequest.UserName = m_pImpl->m_sUser;
    1138           0 :         aRequest.Password = m_pImpl->m_sFailedPassword.isEmpty() ?  m_pImpl->m_aPassword : m_pImpl->m_sFailedPassword;
    1139           0 :         OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
    1140           0 :         Reference< XInteractionRequest > xRequest(pRequest);
    1141             :         // some knittings
    1142           0 :         pRequest->addContinuation(pAbort);
    1143           0 :         pRequest->addContinuation(pAuthenticate);
    1144             : 
    1145             :         // handle the request
    1146             :         try
    1147             :         {
    1148           0 :             MutexRelease aRelease( getMutex() );
    1149             :                 // release the mutex when calling the handler, it may need to lock the SolarMutex
    1150           0 :             _rxHandler->handle(xRequest);
    1151             :         }
    1152           0 :         catch(Exception&)
    1153             :         {
    1154             :             DBG_UNHANDLED_EXCEPTION();
    1155             :         }
    1156             : 
    1157           0 :         if (!pAuthenticate->wasSelected())
    1158           0 :             return Reference< XConnection >();
    1159             : 
    1160             :         // get the result
    1161           0 :         sUser = m_pImpl->m_sUser = pAuthenticate->getUser();
    1162           0 :         sPassword = pAuthenticate->getPassword();
    1163             : 
    1164           0 :         if (pAuthenticate->getRememberPassword())
    1165             :         {
    1166           0 :             m_pImpl->m_aPassword = pAuthenticate->getPassword();
    1167           0 :             bNewPasswordGiven = sal_True;
    1168             :         }
    1169           0 :         m_pImpl->m_sFailedPassword = ::rtl::OUString();
    1170             :     }
    1171             : 
    1172             :     try
    1173             :     {
    1174           0 :         return getConnection(sUser, sPassword,_bIsolated);
    1175             :     }
    1176           0 :     catch(Exception&)
    1177             :     {
    1178           0 :         if (bNewPasswordGiven)
    1179             :         {
    1180           0 :             m_pImpl->m_sFailedPassword = m_pImpl->m_aPassword;
    1181             :             // assume that we had an authentication problem. Without this we may, after an unsucessful connect, while
    1182             :             // the user gave us a password an the order to remember it, never allow an password input again (at least
    1183             :             // not without restarting the session)
    1184           0 :             m_pImpl->m_aPassword = ::rtl::OUString();
    1185             :         }
    1186           0 :         throw;
    1187           0 :     }
    1188             : }
    1189             : 
    1190           0 : Reference< XConnection > ODatabaseSource::buildIsolatedConnection(const rtl::OUString& user, const rtl::OUString& password)
    1191             : {
    1192             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildIsolatedConnection" );
    1193           0 :     Reference< XConnection > xConn;
    1194           0 :     Reference< XConnection > xSdbcConn = buildLowLevelConnection(user, password);
    1195             :     OSL_ENSURE( xSdbcConn.is(), "ODatabaseSource::buildIsolatedConnection: invalid return value of buildLowLevelConnection!" );
    1196             :     // buildLowLevelConnection is expected to always succeed
    1197           0 :     if ( xSdbcConn.is() )
    1198             :     {
    1199             :         // build a connection server and return it (no stubs)
    1200           0 :         xConn = new OConnection(*this, xSdbcConn, m_pImpl->m_aContext.getLegacyServiceFactory());
    1201             :     }
    1202           0 :     return xConn;
    1203             : }
    1204             : 
    1205           0 : Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password,sal_Bool _bIsolated) throw( SQLException, RuntimeException )
    1206             : {
    1207             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
    1208           0 :     ModelMethodGuard aGuard( *this );
    1209             : 
    1210           0 :     Reference< XConnection > xConn;
    1211           0 :     if ( _bIsolated )
    1212             :     {
    1213           0 :         xConn = buildIsolatedConnection(user,password);
    1214             :     }
    1215             :     else
    1216             :     { // create a new proxy for the connection
    1217           0 :         if ( !m_pImpl->m_xSharedConnectionManager.is() )
    1218             :         {
    1219           0 :             m_pImpl->m_pSharedConnectionManager = new OSharedConnectionManager( m_pImpl->m_aContext.getUNOContext() );
    1220           0 :             m_pImpl->m_xSharedConnectionManager = m_pImpl->m_pSharedConnectionManager;
    1221             :         }
    1222           0 :         xConn = m_pImpl->m_pSharedConnectionManager->getConnection(
    1223           0 :             m_pImpl->m_sConnectURL, user, password, m_pImpl->m_xSettings->getPropertyValues(), this );
    1224             :     }
    1225             : 
    1226           0 :     if ( xConn.is() )
    1227             :     {
    1228           0 :         Reference< XComponent> xComp(xConn,UNO_QUERY);
    1229           0 :         if ( xComp.is() )
    1230           0 :             xComp->addEventListener( static_cast< XContainerListener* >( this ) );
    1231           0 :         m_pImpl->m_aConnections.push_back(OWeakConnection(xConn));
    1232             :     }
    1233             : 
    1234           0 :     return xConn;
    1235             : }
    1236             : 
    1237           0 : Reference< XNameAccess > SAL_CALL ODatabaseSource::getBookmarks(  ) throw (RuntimeException)
    1238             : {
    1239             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getBookmarks" );
    1240           0 :     ModelMethodGuard aGuard( *this );
    1241           0 :     return static_cast< XNameContainer* >(&m_aBookmarks);
    1242             : }
    1243             : 
    1244           0 : Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( ) throw(RuntimeException)
    1245             : {
    1246             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getQueryDefinitions" );
    1247           0 :     ModelMethodGuard aGuard( *this );
    1248             : 
    1249           0 :     Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions;
    1250           0 :     if ( !xContainer.is() )
    1251             :     {
    1252           0 :         Any aValue;
    1253           0 :         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xMy(*this);
    1254           0 :         if ( dbtools::getDataSourceSetting(xMy,"CommandDefinitions",aValue) )
    1255             :         {
    1256           0 :             ::rtl::OUString sSupportService;
    1257           0 :             aValue >>= sSupportService;
    1258           0 :             if ( !sSupportService.isEmpty() )
    1259             :             {
    1260           0 :                 Sequence<Any> aArgs(1);
    1261           0 :                 aArgs[0] <<= NamedValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSource")),makeAny(xMy));
    1262           0 :                 xContainer.set(m_pImpl->m_aContext.createComponentWithArguments(sSupportService,aArgs),UNO_QUERY);
    1263           0 :             }
    1264             :         }
    1265           0 :         if ( !xContainer.is() )
    1266             :         {
    1267           0 :             TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_QUERY ) );
    1268           0 :             xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_False );
    1269             :         }
    1270           0 :         m_pImpl->m_xCommandDefinitions = xContainer;
    1271             :     }
    1272           0 :     return xContainer;
    1273             : }
    1274             : 
    1275             : // XTablesSupplier
    1276           0 : Reference< XNameAccess >  ODatabaseSource::getTables() throw( RuntimeException )
    1277             : {
    1278             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTables" );
    1279           0 :     ModelMethodGuard aGuard( *this );
    1280             : 
    1281           0 :     Reference< XNameAccess > xContainer = m_pImpl->m_xTableDefinitions;
    1282           0 :     if ( !xContainer.is() )
    1283             :     {
    1284           0 :         TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_TABLE ) );
    1285           0 :         xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_True );
    1286           0 :         m_pImpl->m_xTableDefinitions = xContainer;
    1287             :     }
    1288           0 :     return xContainer;
    1289             : }
    1290             : 
    1291           0 : void SAL_CALL ODatabaseSource::flush(  ) throw (RuntimeException)
    1292             : {
    1293             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flush" );
    1294             :     try
    1295             :     {
    1296             :         // SYNCHRONIZED ->
    1297             :         {
    1298           0 :             ModelMethodGuard aGuard( *this );
    1299             : 
    1300             :             typedef ::utl::SharedUNOComponent< XModel, ::utl::CloseableComponent > SharedModel;
    1301           0 :             SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership );
    1302             : 
    1303           0 :             if ( !xModel.is() )
    1304           0 :                 xModel.reset( m_pImpl->createNewModel_deliverOwnership( false ), SharedModel::TakeOwnership );
    1305             : 
    1306           0 :             Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW );
    1307           0 :             xStorable->store();
    1308             :         }
    1309             :         // <- SYNCHRONIZED
    1310             : 
    1311           0 :         css::lang::EventObject aFlushedEvent(*this);
    1312           0 :         m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent );
    1313             :     }
    1314           0 :     catch( const Exception& )
    1315             :     {
    1316             :         DBG_UNHANDLED_EXCEPTION();
    1317             :     }
    1318           0 : }
    1319             : 
    1320           0 : void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ ) throw (RuntimeException)
    1321             : {
    1322             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flushed" );
    1323           0 :     ModelMethodGuard aGuard( *this );
    1324             : 
    1325             :     // Okay, this is some hack.
    1326             :     //
    1327             :     // In general, we have the problem that embedded databases write into their underlying storage, which
    1328             :     // logically is one of our sub storage, and practically is a temporary file maintained by the
    1329             :     // package implementation. As long as we did not commit this storage and our main storage,
    1330             :     // the changes made by the embedded database engine are not really reflected in the database document
    1331             :     // file. This is Bad (TM) for a "real" database application - imagine somebody entering some
    1332             :     // data, and then crashing: For a database application, you would expect that the data still is present
    1333             :     // when you connect to the database next time.
    1334             :     //
    1335             :     // Since this is a conceptual problem as long as we do use those ZIP packages (in fact, we *cannot*
    1336             :     // provide the desired functionality as long as we do not have a package format which allows O(1) writes),
    1337             :     // we cannot completely fix this. However, we can relax the problem by commiting more often - often
    1338             :     // enough so that data loss is more seldom, and seldom enough so that there's no noticable performance
    1339             :     // decrease.
    1340             :     //
    1341             :     // For this, we introduced a few places which XFlushable::flush their connections, and register as
    1342             :     // XFlushListener at the embedded connection (which needs to provide the XFlushable functionality).
    1343             :     // Then, when the connection is flushed, we commit both the database storage and our main storage.
    1344             :     //
    1345             :     // #i55274#
    1346             : 
    1347             :     OSL_ENSURE( m_pImpl->isEmbeddedDatabase(), "ODatabaseSource::flushed: no embedded database?!" );
    1348           0 :     sal_Bool bWasModified = m_pImpl->m_bModified;
    1349           0 :     m_pImpl->commitEmbeddedStorage();
    1350           0 :     m_pImpl->setModified( bWasModified );
    1351           0 : }
    1352             : 
    1353           0 : void SAL_CALL ODatabaseSource::addFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
    1354             : {
    1355             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::addFlushListener" );
    1356           0 :     m_aFlushListeners.addInterface(_xListener);
    1357           0 : }
    1358             : 
    1359           0 : void SAL_CALL ODatabaseSource::removeFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
    1360             : {
    1361             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::removeFlushListener" );
    1362           0 :     m_aFlushListeners.removeInterface(_xListener);
    1363           0 : }
    1364             : 
    1365           0 : void SAL_CALL ODatabaseSource::elementInserted( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
    1366             : {
    1367             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementInserted" );
    1368           0 :     ModelMethodGuard aGuard( *this );
    1369           0 :     if ( m_pImpl.is() )
    1370           0 :         m_pImpl->setModified(sal_True);
    1371           0 : }
    1372             : 
    1373           0 : void SAL_CALL ODatabaseSource::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
    1374             : {
    1375             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementRemoved" );
    1376           0 :     ModelMethodGuard aGuard( *this );
    1377           0 :     if ( m_pImpl.is() )
    1378           0 :         m_pImpl->setModified(sal_True);
    1379           0 : }
    1380             : 
    1381           0 : void SAL_CALL ODatabaseSource::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
    1382             : {
    1383             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementReplaced" );
    1384           0 :     ModelMethodGuard aGuard( *this );
    1385           0 :     if ( m_pImpl.is() )
    1386           0 :         m_pImpl->setModified(sal_True);
    1387           0 : }
    1388             : 
    1389             : // XDocumentDataSource
    1390           0 : Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocument() throw (RuntimeException)
    1391             : {
    1392             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getDatabaseDocument" );
    1393           0 :     ModelMethodGuard aGuard( *this );
    1394             : 
    1395           0 :     Reference< XModel > xModel( m_pImpl->getModel_noCreate() );
    1396           0 :     if ( !xModel.is() )
    1397           0 :         xModel = m_pImpl->createNewModel_deliverOwnership( false );
    1398             : 
    1399           0 :     return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW );
    1400             : }
    1401             : 
    1402           0 : Reference< XInterface > ODatabaseSource::getThis() const
    1403             : {
    1404             :     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getThis" );
    1405           0 :     return *const_cast< ODatabaseSource* >( this );
    1406             : }
    1407             : 
    1408             : }   // namespace dbaccess
    1409             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10