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 "apitools.hxx" 28 #include "core_resource.hrc" 29 #include "core_resource.hxx" 30 #include "databasecontext.hxx" 31 #include "databasedocument.hxx" 32 #include "databaseregistrations.hxx" 33 #include "datasource.hxx" 34 #include "dbastrings.hrc" 35 #include "module_dba.hxx" 36 37 /** === being UNO includes === **/ 38 #include <com/sun/star/beans/NamedValue.hpp> 39 #include <com/sun/star/beans/PropertyAttribute.hpp> 40 #include <com/sun/star/beans/XPropertySet.hpp> 41 #include <com/sun/star/document/MacroExecMode.hpp> 42 #include <com/sun/star/document/XFilter.hpp> 43 #include <com/sun/star/document/XImporter.hpp> 44 #include <com/sun/star/frame/XDesktop.hpp> 45 #include <com/sun/star/frame/XModel.hpp> 46 #include <com/sun/star/frame/XModel2.hpp> 47 #include <com/sun/star/frame/XTerminateListener.hpp> 48 #include <com/sun/star/lang/DisposedException.hpp> 49 #include <com/sun/star/registry/InvalidRegistryException.hpp> 50 #include <com/sun/star/sdbc/XDataSource.hpp> 51 #include <com/sun/star/task/InteractionClassification.hpp> 52 #include <com/sun/star/ucb/InteractiveIOException.hpp> 53 #include <com/sun/star/ucb/IOErrorCode.hpp> 54 #include <com/sun/star/util/XCloseable.hpp> 55 /** === end UNO includes === **/ 56 57 #include <basic/basmgr.hxx> 58 #include <comphelper/enumhelper.hxx> 59 #include <comphelper/evtlistenerhlp.hxx> 60 #include <comphelper/namedvaluecollection.hxx> 61 #include <comphelper/processfactory.hxx> 62 #include <comphelper/sequence.hxx> 63 #include <cppuhelper/implbase1.hxx> 64 #include <cppuhelper/typeprovider.hxx> 65 #include <cppuhelper/exc_hlp.hxx> 66 #include <svl/filenotation.hxx> 67 #include <tools/debug.hxx> 68 #include <tools/diagnose_ex.h> 69 #include <tools/fsys.hxx> 70 #include <tools/urlobj.hxx> 71 #include <ucbhelper/content.hxx> 72 #include <unotools/confignode.hxx> 73 #include <unotools/pathoptions.hxx> 74 #include <unotools/sharedunocomponent.hxx> 75 #include <list> 76 #include <boost/bind.hpp> 77 78 using namespace ::com::sun::star::sdbc; 79 using namespace ::com::sun::star::sdb; 80 using namespace ::com::sun::star::beans; 81 using namespace ::com::sun::star::uno; 82 using namespace ::com::sun::star::document; 83 using namespace ::com::sun::star::frame; 84 using namespace ::com::sun::star::lang; 85 using namespace ::com::sun::star::container; 86 using namespace ::com::sun::star::util; 87 using namespace ::com::sun::star::registry; 88 using namespace ::com::sun::star; 89 using namespace ::cppu; 90 using namespace ::osl; 91 using namespace ::utl; 92 93 using ::com::sun::star::task::InteractionClassification_ERROR; 94 using ::com::sun::star::ucb::IOErrorCode_NO_FILE; 95 using ::com::sun::star::ucb::InteractiveIOException; 96 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING; 97 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH; 98 99 //========================================================================== 100 101 extern "C" void SAL_CALL createRegistryInfo_ODatabaseContext() 102 { 103 static ::dba::OLegacySingletonRegistration< ::dbaccess::ODatabaseContext > aODatabaseContext_AutoRegistration; 104 } 105 106 //........................................................................ 107 namespace dbaccess 108 { 109 //........................................................................ 110 111 // ............................................................................. 112 typedef ::cppu::WeakImplHelper1 < XTerminateListener 113 > DatabaseDocumentLoader_Base; 114 class DatabaseDocumentLoader : public DatabaseDocumentLoader_Base 115 { 116 private: 117 Reference< XDesktop > m_xDesktop; 118 ::std::list< const ODatabaseModelImpl* > m_aDatabaseDocuments; 119 120 public: 121 DatabaseDocumentLoader( const comphelper::ComponentContext& _aContext); 122 123 inline void append(const ODatabaseModelImpl& _rModelImpl ) 124 { 125 m_aDatabaseDocuments.push_back(&_rModelImpl); 126 } 127 inline void remove(const ODatabaseModelImpl& _rModelImpl) { m_aDatabaseDocuments.remove(&_rModelImpl); } 128 129 private: 130 // XTerminateListener 131 virtual void SAL_CALL queryTermination( const lang::EventObject& Event ) throw (TerminationVetoException, RuntimeException); 132 virtual void SAL_CALL notifyTermination( const lang::EventObject& Event ) throw (RuntimeException); 133 // XEventListener 134 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); 135 }; 136 137 // ............................................................................. 138 DatabaseDocumentLoader::DatabaseDocumentLoader( const comphelper::ComponentContext& _aContext ) 139 { 140 acquire(); 141 try 142 { 143 m_xDesktop.set( _aContext.createComponent( (rtl::OUString)SERVICE_FRAME_DESKTOP ), UNO_QUERY_THROW ); 144 m_xDesktop->addTerminateListener( this ); 145 } 146 catch( const Exception& ) 147 { 148 DBG_UNHANDLED_EXCEPTION(); 149 } 150 } 151 152 struct TerminateFunctor : ::std::unary_function<ODatabaseModelImpl* , void> 153 { 154 void operator()( const ODatabaseModelImpl* _pModelImpl ) const 155 { 156 try 157 { 158 const Reference< XModel2> xModel( _pModelImpl ->getModel_noCreate(),UNO_QUERY_THROW ); 159 if ( !xModel->getControllers()->hasMoreElements() ) 160 { 161 Reference<util::XCloseable> xCloseable(xModel,UNO_QUERY_THROW); 162 xCloseable->close(sal_False); 163 } // if ( !xModel->getControllers()->hasMoreElements() ) 164 } 165 catch(const CloseVetoException&) 166 { 167 throw TerminationVetoException(); 168 } 169 } 170 }; 171 // ............................................................................. 172 void SAL_CALL DatabaseDocumentLoader::queryTermination( const lang::EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException) 173 { 174 ::std::list< const ODatabaseModelImpl* > aCopy(m_aDatabaseDocuments); 175 ::std::for_each(aCopy.begin(),aCopy.end(),TerminateFunctor()); 176 } 177 178 // ............................................................................. 179 void SAL_CALL DatabaseDocumentLoader::notifyTermination( const lang::EventObject& /*Event*/ ) throw (RuntimeException) 180 { 181 } 182 // ............................................................................. 183 void SAL_CALL DatabaseDocumentLoader::disposing( const lang::EventObject& /*Source*/ ) throw (RuntimeException) 184 { 185 } 186 187 //= ODatabaseContext 188 //========================================================================== 189 //-------------------------------------------------------------------------- 190 ODatabaseContext::ODatabaseContext( const Reference< XComponentContext >& _rxContext ) 191 :DatabaseAccessContext_Base(m_aMutex) 192 ,m_aContext( _rxContext ) 193 ,m_aContainerListeners(m_aMutex) 194 { 195 m_pDatabaseDocumentLoader = new DatabaseDocumentLoader( m_aContext ); 196 ::basic::BasicManagerRepository::registerCreationListener( *this ); 197 198 osl_incrementInterlockedCount( &m_refCount ); 199 { 200 m_xDBRegistrationAggregate.set( createDataSourceRegistrations( m_aContext ), UNO_SET_THROW ); 201 m_xDatabaseRegistrations.set( m_xDBRegistrationAggregate, UNO_QUERY_THROW ); 202 203 m_xDBRegistrationAggregate->setDelegator( *this ); 204 } 205 osl_decrementInterlockedCount( &m_refCount ); 206 } 207 208 //-------------------------------------------------------------------------- 209 ODatabaseContext::~ODatabaseContext() 210 { 211 ::basic::BasicManagerRepository::revokeCreationListener( *this ); 212 if ( m_pDatabaseDocumentLoader ) 213 m_pDatabaseDocumentLoader->release(); 214 215 m_xDBRegistrationAggregate->setDelegator( NULL ); 216 m_xDBRegistrationAggregate.clear(); 217 m_xDatabaseRegistrations.clear(); 218 } 219 220 // Helper 221 //------------------------------------------------------------------------------ 222 rtl::OUString ODatabaseContext::getImplementationName_static() throw( RuntimeException ) 223 224 { 225 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.ODatabaseContext")); 226 } 227 228 //------------------------------------------------------------------------------ 229 Reference< XInterface > ODatabaseContext::Create(const Reference< XComponentContext >& _rxContext) 230 { 231 return *( new ODatabaseContext( _rxContext ) ); 232 } 233 234 //------------------------------------------------------------------------------ 235 Sequence< rtl::OUString > ODatabaseContext::getSupportedServiceNames_static(void) throw( RuntimeException ) 236 { 237 Sequence< ::rtl::OUString > aSNS( 1 ); 238 aSNS[0] = SERVICE_SDB_DATABASECONTEXT; 239 return aSNS; 240 } 241 242 // XServiceInfo 243 //------------------------------------------------------------------------------ 244 rtl::OUString ODatabaseContext::getImplementationName( ) throw(RuntimeException) 245 { 246 return getImplementationName_static(); 247 } 248 249 //------------------------------------------------------------------------------ 250 sal_Bool ODatabaseContext::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) 251 { 252 return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; 253 } 254 255 //------------------------------------------------------------------------------ 256 Sequence< ::rtl::OUString > ODatabaseContext::getSupportedServiceNames( ) throw (RuntimeException) 257 { 258 return getSupportedServiceNames_static(); 259 } 260 261 //-------------------------------------------------------------------------- 262 Reference< XInterface > ODatabaseContext::impl_createNewDataSource() 263 { 264 ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( m_aContext.getLegacyServiceFactory(), *this ) ); 265 Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() ); 266 267 return xDataSource.get(); 268 } 269 270 //-------------------------------------------------------------------------- 271 Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( ) throw (Exception, RuntimeException) 272 { 273 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew 274 // has been called at the DatabaseDocument). 275 return impl_createNewDataSource(); 276 } 277 278 //-------------------------------------------------------------------------- 279 Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) 280 { 281 ::comphelper::NamedValueCollection aArgs( _rArguments ); 282 ::rtl::OUString sURL = aArgs.getOrDefault( (::rtl::OUString)INFO_POOLURL, ::rtl::OUString() ); 283 284 Reference< XInterface > xDataSource; 285 if ( sURL.getLength() ) 286 xDataSource = getObject( sURL ); 287 288 if ( !xDataSource.is() ) 289 xDataSource = impl_createNewDataSource(); 290 291 return xDataSource; 292 } 293 // DatabaseAccessContext_Base 294 //------------------------------------------------------------------------------ 295 void ODatabaseContext::disposing() 296 { 297 // notify our listener 298 com::sun::star::lang::EventObject aDisposeEvent(static_cast< XContainer* >(this)); 299 m_aContainerListeners.disposeAndClear(aDisposeEvent); 300 301 // dispose the data sources 302 ObjectCache::iterator aEnd = m_aDatabaseObjects.end(); 303 for ( ObjectCache::iterator aIter = m_aDatabaseObjects.begin(); 304 aIter != aEnd; 305 ++aIter 306 ) 307 { 308 aIter->second->dispose(); 309 } 310 m_aDatabaseObjects.clear(); 311 } 312 313 // XNamingService 314 //------------------------------------------------------------------------------ 315 Reference< XInterface > ODatabaseContext::getRegisteredObject(const rtl::OUString& _rName) throw( Exception, RuntimeException ) 316 { 317 MutexGuard aGuard(m_aMutex); 318 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); 319 320 ::rtl::OUString sURL( getDatabaseLocation( _rName ) ); 321 322 if ( !sURL.getLength() ) 323 // there is a registration for this name, but no URL 324 throw IllegalArgumentException(); 325 326 // check if URL is already loaded 327 Reference< XInterface > xExistent = getObject( sURL ); 328 if ( xExistent.is() ) 329 return xExistent; 330 331 return loadObjectFromURL( _rName, sURL ); 332 } 333 // ----------------------------------------------------------------------------- 334 Reference< XInterface > ODatabaseContext::loadObjectFromURL(const ::rtl::OUString& _rName,const ::rtl::OUString& _sURL) 335 { 336 INetURLObject aURL( _sURL ); 337 if ( aURL.GetProtocol() == INET_PROT_NOT_VALID ) 338 throw NoSuchElementException( _rName, *this ); 339 340 try 341 { 342 ::ucbhelper::Content aContent( _sURL, NULL ); 343 if ( !aContent.isDocument() ) 344 throw InteractiveIOException( 345 _sURL, *this, InteractionClassification_ERROR, IOErrorCode_NO_FILE 346 ); 347 } 348 catch ( const InteractiveIOException& e ) 349 { 350 if ( ( e.Code == IOErrorCode_NO_FILE ) 351 || ( e.Code == IOErrorCode_NOT_EXISTING ) 352 || ( e.Code == IOErrorCode_NOT_EXISTING_PATH ) 353 ) 354 { 355 // #i40463# #i39187# 356 String sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST ) ); 357 ::svt::OFileNotation aTransformer( _sURL ); 358 sErrorMessage.SearchAndReplaceAscii( "$file$", aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) ); 359 360 SQLException aError; 361 aError.Message = sErrorMessage; 362 363 throw WrappedTargetException( _sURL, *this, makeAny( aError ) ); 364 } 365 throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() ); 366 } 367 catch( const Exception& ) 368 { 369 throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() ); 370 } 371 372 OSL_ENSURE( m_aDatabaseObjects.find( _sURL ) == m_aDatabaseObjects.end(), 373 "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" ); 374 375 ::rtl::Reference< ODatabaseModelImpl > pModelImpl; 376 { 377 pModelImpl.set( new ODatabaseModelImpl( _rName, m_aContext.getLegacyServiceFactory(), *this ) ); 378 379 Reference< XModel > xModel( pModelImpl->createNewModel_deliverOwnership( false ), UNO_SET_THROW ); 380 Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW ); 381 382 ::comphelper::NamedValueCollection aArgs; 383 aArgs.put( "URL", _sURL ); 384 aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG ); 385 aArgs.put( "InteractionHandler", m_aContext.createComponent( "com.sun.star.task.InteractionHandler" ) ); 386 387 Sequence< PropertyValue > aResource( aArgs.getPropertyValues() ); 388 xLoad->load( aResource ); 389 xModel->attachResource( _sURL, aResource ); 390 391 ::utl::CloseableComponent aEnsureClose( xModel ); 392 } 393 394 setTransientProperties( _sURL, *pModelImpl ); 395 396 return pModelImpl->getOrCreateDataSource().get(); 397 } 398 // ----------------------------------------------------------------------------- 399 void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel) 400 { 401 m_pDatabaseDocumentLoader->append(_rDataSourceModel); 402 } 403 // ----------------------------------------------------------------------------- 404 void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel) 405 { 406 m_pDatabaseDocumentLoader->remove(_rDataSourceModel); 407 } 408 // ----------------------------------------------------------------------------- 409 void ODatabaseContext::setTransientProperties(const ::rtl::OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel ) 410 { 411 if ( m_aDatasourceProperties.end() == m_aDatasourceProperties.find(_sURL) ) 412 return; 413 try 414 { 415 ::rtl::OUString sAuthFailedPassword; 416 Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW ); 417 const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL]; 418 const PropertyValue* pProp = rSessionPersistentProps.getConstArray(); 419 const PropertyValue* pPropsEnd = rSessionPersistentProps.getConstArray() + rSessionPersistentProps.getLength(); 420 for ( ; pProp != pPropsEnd; ++pProp ) 421 { 422 if ( pProp->Name.equalsAscii( "AuthFailedPassword" ) ) 423 { 424 OSL_VERIFY( pProp->Value >>= sAuthFailedPassword ); 425 } 426 else 427 { 428 xDSProps->setPropertyValue( pProp->Name, pProp->Value ); 429 } 430 } 431 432 _rDataSourceModel.m_sFailedPassword = sAuthFailedPassword; 433 } 434 catch( const Exception& ) 435 { 436 DBG_UNHANDLED_EXCEPTION(); 437 } 438 } 439 440 //------------------------------------------------------------------------------ 441 void ODatabaseContext::registerObject(const rtl::OUString& _rName, const Reference< XInterface > & _rxObject) throw( Exception, RuntimeException ) 442 { 443 MutexGuard aGuard(m_aMutex); 444 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); 445 446 if ( !_rName.getLength() ) 447 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 448 449 Reference< XDocumentDataSource > xDocDataSource( _rxObject, UNO_QUERY ); 450 Reference< XModel > xModel( xDocDataSource.is() ? xDocDataSource->getDatabaseDocument() : Reference< XOfficeDatabaseDocument >(), UNO_QUERY ); 451 if ( !xModel.is() ) 452 throw IllegalArgumentException( ::rtl::OUString(), *this, 2 ); 453 454 ::rtl::OUString sURL = xModel->getURL(); 455 if ( !sURL.getLength() ) 456 throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED ), *this, 2 ); 457 458 registerDatabaseLocation( _rName, sURL ); 459 460 ODatabaseSource::setName( xDocDataSource, _rName, ODatabaseSource::DBContextAccess() ); 461 462 // notify our container listeners 463 ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(_rName), makeAny(_rxObject), Any()); 464 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent ); 465 } 466 467 //------------------------------------------------------------------------------ 468 void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl& _rModelImpl) 469 { 470 Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY ); 471 ::comphelper::NamedValueCollection aRememberProps; 472 473 try 474 { 475 // get the info about the properties, check which ones are transient and not readonly 476 Reference< XPropertySetInfo > xSetInfo; 477 if (xSource.is()) 478 xSetInfo = xSource->getPropertySetInfo(); 479 Sequence< Property > aProperties; 480 if (xSetInfo.is()) 481 aProperties = xSetInfo->getProperties(); 482 483 if (aProperties.getLength()) 484 { 485 const Property* pProperties = aProperties.getConstArray(); 486 for ( sal_Int32 i=0; i<aProperties.getLength(); ++i, ++pProperties ) 487 { 488 if ( ( ( pProperties->Attributes & PropertyAttribute::TRANSIENT) != 0 ) 489 && ( ( pProperties->Attributes & PropertyAttribute::READONLY) == 0 ) 490 ) 491 { 492 // found such a property 493 aRememberProps.put( pProperties->Name, xSource->getPropertyValue( pProperties->Name ) ); 494 } 495 } 496 } 497 } 498 catch ( const Exception& ) 499 { 500 DBG_UNHANDLED_EXCEPTION(); 501 } 502 503 // additionally, remember the "failed password", which is not available as property 504 // #i86178# / 2008-02-19 / frank.schoenheit@sun.com 505 aRememberProps.put( "AuthFailedPassword", _rModelImpl.m_sFailedPassword ); 506 507 ::rtl::OUString sDocumentURL( _rModelImpl.getURL() ); 508 if ( m_aDatabaseObjects.find( sDocumentURL ) != m_aDatabaseObjects.end() ) 509 { 510 m_aDatasourceProperties[ sDocumentURL ] = aRememberProps.getPropertyValues(); 511 } 512 else if ( m_aDatabaseObjects.find( _rModelImpl.m_sName ) != m_aDatabaseObjects.end() ) 513 { 514 OSL_ENSURE( false, "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" ); 515 // all the code should have been changed so that registration is by URL only 516 m_aDatasourceProperties[ _rModelImpl.m_sName ] = aRememberProps.getPropertyValues(); 517 } 518 else 519 { 520 OSL_ENSURE( ( sDocumentURL.getLength() == 0 ) && ( _rModelImpl.m_sName.getLength() == 0 ), 521 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" ); 522 } 523 } 524 525 //------------------------------------------------------------------------------ 526 void SAL_CALL ODatabaseContext::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) 527 { 528 m_aContainerListeners.addInterface(_rxListener); 529 } 530 531 //------------------------------------------------------------------------------ 532 void SAL_CALL ODatabaseContext::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) 533 { 534 m_aContainerListeners.removeInterface(_rxListener); 535 } 536 537 //------------------------------------------------------------------------------ 538 void ODatabaseContext::revokeObject(const rtl::OUString& _rName) throw( Exception, RuntimeException ) 539 { 540 ClearableMutexGuard aGuard(m_aMutex); 541 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); 542 543 ::rtl::OUString sURL = getDatabaseLocation( _rName ); 544 545 revokeDatabaseLocation( _rName ); 546 // will throw if something goes wrong 547 548 if ( m_aDatabaseObjects.find( _rName ) != m_aDatabaseObjects.end() ) 549 { 550 m_aDatasourceProperties[ sURL ] = m_aDatasourceProperties[ _rName ]; 551 } 552 553 // check if URL is already loaded 554 ObjectCacheIterator aExistent = m_aDatabaseObjects.find( sURL ); 555 if ( aExistent != m_aDatabaseObjects.end() ) 556 m_aDatabaseObjects.erase( aExistent ); 557 558 // notify our container listeners 559 ContainerEvent aEvent( *this, makeAny( _rName ), Any(), Any() ); 560 aGuard.clear(); 561 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent ); 562 } 563 564 //------------------------------------------------------------------------------ 565 ::sal_Bool SAL_CALL ODatabaseContext::hasRegisteredDatabase( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, RuntimeException) 566 { 567 return m_xDatabaseRegistrations->hasRegisteredDatabase( _Name ); 568 } 569 570 //------------------------------------------------------------------------------ 571 Sequence< ::rtl::OUString > SAL_CALL ODatabaseContext::getRegistrationNames() throw (RuntimeException) 572 { 573 return m_xDatabaseRegistrations->getRegistrationNames(); 574 } 575 576 //------------------------------------------------------------------------------ 577 ::rtl::OUString SAL_CALL ODatabaseContext::getDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException) 578 { 579 return m_xDatabaseRegistrations->getDatabaseLocation( _Name ); 580 } 581 582 //------------------------------------------------------------------------------ 583 void SAL_CALL ODatabaseContext::registerDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException) 584 { 585 m_xDatabaseRegistrations->registerDatabaseLocation( _Name, _Location ); 586 } 587 588 //------------------------------------------------------------------------------ 589 void SAL_CALL ODatabaseContext::revokeDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException) 590 { 591 m_xDatabaseRegistrations->revokeDatabaseLocation( _Name ); 592 } 593 594 //------------------------------------------------------------------------------ 595 void SAL_CALL ODatabaseContext::changeDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException) 596 { 597 m_xDatabaseRegistrations->changeDatabaseLocation( _Name, _NewLocation ); 598 } 599 600 //------------------------------------------------------------------------------ 601 ::sal_Bool SAL_CALL ODatabaseContext::isDatabaseRegistrationReadOnly( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException) 602 { 603 return m_xDatabaseRegistrations->isDatabaseRegistrationReadOnly( _Name ); 604 } 605 606 //------------------------------------------------------------------------------ 607 void SAL_CALL ODatabaseContext::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException) 608 { 609 m_xDatabaseRegistrations->addDatabaseRegistrationsListener( _Listener ); 610 } 611 612 //------------------------------------------------------------------------------ 613 void SAL_CALL ODatabaseContext::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException) 614 { 615 m_xDatabaseRegistrations->removeDatabaseRegistrationsListener( _Listener ); 616 } 617 618 // ::com::sun::star::container::XElementAccess 619 //------------------------------------------------------------------------------ 620 Type ODatabaseContext::getElementType( ) throw(RuntimeException) 621 { 622 return::getCppuType(static_cast<Reference<XDataSource>*>(NULL)); 623 } 624 625 //------------------------------------------------------------------------------ 626 sal_Bool ODatabaseContext::hasElements(void) throw( RuntimeException ) 627 { 628 MutexGuard aGuard(m_aMutex); 629 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); 630 631 return 0 != getElementNames().getLength(); 632 } 633 634 // ::com::sun::star::container::XEnumerationAccess 635 //------------------------------------------------------------------------------ 636 Reference< ::com::sun::star::container::XEnumeration > ODatabaseContext::createEnumeration(void) throw( RuntimeException ) 637 { 638 MutexGuard aGuard(m_aMutex); 639 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess*>(this)); 640 } 641 642 // ::com::sun::star::container::XNameAccess 643 //------------------------------------------------------------------------------ 644 Any ODatabaseContext::getByName(const rtl::OUString& _rName) throw( NoSuchElementException, 645 WrappedTargetException, RuntimeException ) 646 { 647 MutexGuard aGuard(m_aMutex); 648 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); 649 if ( !_rName.getLength() ) 650 throw NoSuchElementException(_rName, *this); 651 652 try 653 { 654 Reference< XInterface > xExistent = getObject( _rName ); 655 if ( xExistent.is() ) 656 return makeAny( xExistent ); 657 658 // see whether this is an registered name 659 ::rtl::OUString sURL; 660 if ( hasRegisteredDatabase( _rName ) ) 661 { 662 sURL = getDatabaseLocation( _rName ); 663 // is the object cached under its URL? 664 xExistent = getObject( sURL ); 665 } 666 else 667 // interpret the name as URL 668 sURL = _rName; 669 670 if ( !xExistent.is() ) 671 // try to load this as URL 672 xExistent = loadObjectFromURL( _rName, sURL ); 673 return makeAny( xExistent ); 674 } 675 catch (NoSuchElementException&) 676 { // let these exceptions through 677 throw; 678 } 679 catch (WrappedTargetException&) 680 { // let these exceptions through 681 throw; 682 } 683 catch (RuntimeException&) 684 { // let these exceptions through 685 throw; 686 } 687 catch (Exception& e) 688 { // exceptions other than the speciafied ones -> wrap 689 Any aError = ::cppu::getCaughtException(); 690 throw WrappedTargetException(_rName, *this, aError ); 691 } 692 } 693 694 //------------------------------------------------------------------------------ 695 Sequence< rtl::OUString > ODatabaseContext::getElementNames(void) throw( RuntimeException ) 696 { 697 MutexGuard aGuard(m_aMutex); 698 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); 699 700 return getRegistrationNames(); 701 } 702 703 //------------------------------------------------------------------------------ 704 sal_Bool ODatabaseContext::hasByName(const rtl::OUString& _rName) throw( RuntimeException ) 705 { 706 MutexGuard aGuard(m_aMutex); 707 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); 708 709 return hasRegisteredDatabase( _rName ); 710 } 711 712 // ----------------------------------------------------------------------------- 713 Reference< XInterface > ODatabaseContext::getObject( const ::rtl::OUString& _rURL ) 714 { 715 ObjectCacheIterator aFind = m_aDatabaseObjects.find( _rURL ); 716 Reference< XInterface > xExistent; 717 if ( aFind != m_aDatabaseObjects.end() ) 718 xExistent = aFind->second->getOrCreateDataSource(); 719 return xExistent; 720 } 721 // ----------------------------------------------------------------------------- 722 void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl ) 723 { 724 ::rtl::OUString sURL( _rModelImpl.getURL() ); 725 #if OSL_DEBUG_LEVEL > 1 726 OSL_TRACE( "DatabaseContext: registering %s", ::rtl::OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() ); 727 #endif 728 if ( m_aDatabaseObjects.find( sURL ) == m_aDatabaseObjects.end() ) 729 { 730 m_aDatabaseObjects[ sURL ] = &_rModelImpl; 731 setTransientProperties( sURL, _rModelImpl ); 732 } 733 else 734 OSL_ENSURE( false, "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" ); 735 } 736 // ----------------------------------------------------------------------------- 737 void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl ) 738 { 739 ::rtl::OUString sURL( _rModelImpl.getURL() ); 740 #if OSL_DEBUG_LEVEL > 1 741 OSL_TRACE( "DatabaseContext: deregistering %s", ::rtl::OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() ); 742 #endif 743 m_aDatabaseObjects.erase( sURL ); 744 } 745 // ----------------------------------------------------------------------------- 746 void ODatabaseContext::databaseDocumentURLChange( const ::rtl::OUString& _rOldURL, const ::rtl::OUString& _rNewURL ) 747 { 748 #if OSL_DEBUG_LEVEL > 1 749 OSL_TRACE( "DatabaseContext: changing registration from %s to %s", 750 ::rtl::OUStringToOString( _rOldURL, RTL_TEXTENCODING_UTF8 ).getStr(), 751 ::rtl::OUStringToOString( _rNewURL, RTL_TEXTENCODING_UTF8 ).getStr() ); 752 #endif 753 ObjectCache::iterator oldPos = m_aDatabaseObjects.find( _rOldURL ); 754 ENSURE_OR_THROW( oldPos != m_aDatabaseObjects.end(), "illegal old database document URL" ); 755 ObjectCache::iterator newPos = m_aDatabaseObjects.find( _rNewURL ); 756 ENSURE_OR_THROW( newPos == m_aDatabaseObjects.end(), "illegal new database document URL" ); 757 758 m_aDatabaseObjects[ _rNewURL ] = oldPos->second; 759 m_aDatabaseObjects.erase( oldPos ); 760 } 761 // ----------------------------------------------------------------------------- 762 sal_Int64 SAL_CALL ODatabaseContext::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) 763 { 764 if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) 765 return reinterpret_cast<sal_Int64>(this); 766 767 return 0; 768 } 769 // ----------------------------------------------------------------------------- 770 Sequence< sal_Int8 > ODatabaseContext::getUnoTunnelImplementationId() 771 { 772 static ::cppu::OImplementationId * pId = 0; 773 if (! pId) 774 { 775 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 776 if (! pId) 777 { 778 static ::cppu::OImplementationId aId; 779 pId = &aId; 780 } 781 } 782 return pId->getImplementationId(); 783 } 784 785 // ----------------------------------------------------------------------------- 786 void ODatabaseContext::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager ) 787 { 788 // if it's a database document ... 789 Reference< XOfficeDatabaseDocument > xDatabaseDocument( _rxForDocument, UNO_QUERY ); 790 // ... or a sub document of a database document ... 791 if ( !xDatabaseDocument.is() ) 792 { 793 Reference< XChild > xDocAsChild( _rxForDocument, UNO_QUERY ); 794 if ( xDocAsChild.is() ) 795 xDatabaseDocument.set( xDocAsChild->getParent(), UNO_QUERY ); 796 } 797 798 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope. 799 if ( xDatabaseDocument.is() ) 800 _rBasicManager.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument ) ); 801 } 802 803 //........................................................................ 804 } // namespace dbaccess 805 //........................................................................ 806