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