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

Generated by: LCOV version 1.11