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