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

Generated by: LCOV version 1.10