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