1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <strings.hrc>
23 #include <core_resource.hxx>
24 #include <databasecontext.hxx>
25 #include "databaseregistrations.hxx"
26 #include "datasource.hxx"
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/document/MacroExecMode.hpp>
31 #include <com/sun/star/frame/Desktop.hpp>
32 #include <com/sun/star/frame/TerminationVetoException.hpp>
33 #include <com/sun/star/frame/XLoadable.hpp>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/frame/XModel2.hpp>
36 #include <com/sun/star/frame/XTerminateListener.hpp>
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include <com/sun/star/registry/InvalidRegistryException.hpp>
39 #include <com/sun/star/sdbc/XDataSource.hpp>
40 #include <com/sun/star/task/InteractionClassification.hpp>
41 #include <com/sun/star/ucb/InteractiveIOException.hpp>
42 #include <com/sun/star/ucb/IOErrorCode.hpp>
43 #include <com/sun/star/uri/UriReferenceFactory.hpp>
44 #include <com/sun/star/task/InteractionHandler.hpp>
45 #include <com/sun/star/util/CloseVetoException.hpp>
46 #include <com/sun/star/util/XCloseable.hpp>
48 #include <basic/basmgr.hxx>
49 #include <comphelper/enumhelper.hxx>
50 #include <comphelper/namedvaluecollection.hxx>
51 #include <comphelper/processfactory.hxx>
52 #include <comphelper/servicehelper.hxx>
53 #include <cppuhelper/implbase.hxx>
54 #include <cppuhelper/supportsservice.hxx>
55 #include <cppuhelper/typeprovider.hxx>
56 #include <cppuhelper/exc_hlp.hxx>
57 #include <cppuhelper/weak.hxx>
58 #include <rtl/uri.hxx>
59 #include <sal/log.hxx>
60 #include <svl/filenotation.hxx>
61 #include <tools/diagnose_ex.h>
62 #include <tools/urlobj.hxx>
63 #include <ucbhelper/content.hxx>
64 #include <rtl/ref.hxx>
65 #include <unotools/sharedunocomponent.hxx>
68 using namespace ::com::sun::star::sdbc
;
69 using namespace ::com::sun::star::sdb
;
70 using namespace ::com::sun::star::beans
;
71 using namespace ::com::sun::star::uno
;
72 using namespace ::com::sun::star::document
;
73 using namespace ::com::sun::star::frame
;
74 using namespace ::com::sun::star::lang
;
75 using namespace ::com::sun::star::container
;
76 using namespace ::com::sun::star::util
;
77 using namespace ::com::sun::star::registry
;
78 using namespace ::com::sun::star
;
79 using namespace ::cppu
;
80 using namespace ::osl
;
81 using namespace ::utl
;
83 using ::com::sun::star::task::InteractionClassification_ERROR
;
84 using ::com::sun::star::ucb::IOErrorCode_NO_FILE
;
85 using ::com::sun::star::ucb::InteractiveIOException
;
86 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING
;
87 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH
;
92 typedef ::cppu::WeakImplHelper
< XTerminateListener
93 > DatabaseDocumentLoader_Base
;
94 class DatabaseDocumentLoader
: public DatabaseDocumentLoader_Base
97 Reference
< XDesktop2
> m_xDesktop
;
98 std::vector
< const ODatabaseModelImpl
* > m_aDatabaseDocuments
;
101 explicit DatabaseDocumentLoader( const Reference
<XComponentContext
> & rxContext
);
103 void append(const ODatabaseModelImpl
& _rModelImpl
)
105 m_aDatabaseDocuments
.emplace_back(&_rModelImpl
);
108 void remove(const ODatabaseModelImpl
& _rModelImpl
)
110 m_aDatabaseDocuments
.erase(std::find(m_aDatabaseDocuments
.begin(), m_aDatabaseDocuments
.end(), &_rModelImpl
));
115 // XTerminateListener
116 virtual void SAL_CALL
queryTermination( const lang::EventObject
& Event
) override
;
117 virtual void SAL_CALL
notifyTermination( const lang::EventObject
& Event
) override
;
119 virtual void SAL_CALL
disposing( const css::lang::EventObject
& Source
) override
;
122 DatabaseDocumentLoader::DatabaseDocumentLoader( const Reference
<XComponentContext
> & rxContext
)
126 m_xDesktop
.set( Desktop::create(rxContext
) );
127 m_xDesktop
->addTerminateListener( this );
129 catch( const Exception
& )
131 DBG_UNHANDLED_EXCEPTION("dbaccess");
135 void SAL_CALL
DatabaseDocumentLoader::queryTermination( const lang::EventObject
& /*Event*/ )
137 std::vector
< const ODatabaseModelImpl
* > aCpy(m_aDatabaseDocuments
);
138 for( const auto& pCopy
: aCpy
)
142 const Reference
< XModel2
> xMod( pCopy
->getModel_noCreate(),
144 if( !xMod
->getControllers()->hasMoreElements() )
146 Reference
< util::XCloseable
> xClose( xMod
,
148 xClose
->close( false );
151 catch( const CloseVetoException
& )
153 throw TerminationVetoException();
158 void SAL_CALL
DatabaseDocumentLoader::notifyTermination( const lang::EventObject
& /*Event*/ )
162 void SAL_CALL
DatabaseDocumentLoader::disposing( const lang::EventObject
& /*Source*/ )
168 ODatabaseContext::ODatabaseContext( const Reference
< XComponentContext
>& _rxContext
)
169 :DatabaseAccessContext_Base(m_aMutex
)
170 ,m_aContext( _rxContext
)
171 ,m_aContainerListeners(m_aMutex
)
173 m_xDatabaseDocumentLoader
= new DatabaseDocumentLoader( _rxContext
);
175 #if HAVE_FEATURE_SCRIPTING
176 ::basic::BasicManagerRepository::registerCreationListener( *this );
179 osl_atomic_increment( &m_refCount
);
181 m_xDBRegistrationAggregate
.set( createDataSourceRegistrations( m_aContext
), UNO_SET_THROW
);
182 m_xDatabaseRegistrations
.set( m_xDBRegistrationAggregate
, UNO_QUERY_THROW
);
184 m_xDBRegistrationAggregate
->setDelegator( *this );
186 osl_atomic_decrement( &m_refCount
);
189 ODatabaseContext::~ODatabaseContext()
191 #if HAVE_FEATURE_SCRIPTING
192 ::basic::BasicManagerRepository::revokeCreationListener( *this );
195 m_xDatabaseDocumentLoader
.clear();
196 m_xDBRegistrationAggregate
->setDelegator( nullptr );
197 m_xDBRegistrationAggregate
.clear();
198 m_xDatabaseRegistrations
.clear();
202 OUString
ODatabaseContext::getImplementationName( )
204 return "com.sun.star.comp.dba.ODatabaseContext";
207 sal_Bool
ODatabaseContext::supportsService( const OUString
& _rServiceName
)
209 return cppu::supportsService(this, _rServiceName
);
212 Sequence
< OUString
> ODatabaseContext::getSupportedServiceNames( )
214 return { "com.sun.star.sdb.DatabaseContext" };
217 Reference
< XInterface
> ODatabaseContext::impl_createNewDataSource()
219 ::rtl::Reference
pImpl( new ODatabaseModelImpl( m_aContext
, *this ) );
220 Reference
< XDataSource
> xDataSource( pImpl
->getOrCreateDataSource() );
222 return xDataSource
.get();
225 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstance( )
227 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
228 // has been called at the DatabaseDocument).
229 return impl_createNewDataSource();
232 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstanceWithArguments( const Sequence
< Any
>& _rArguments
)
234 ::comphelper::NamedValueCollection
aArgs( _rArguments
);
235 OUString sURL
= aArgs
.getOrDefault( INFO_POOLURL
, OUString() );
237 Reference
< XInterface
> xDataSource
;
238 if ( !sURL
.isEmpty() )
239 xDataSource
= getObject( sURL
);
241 if ( !xDataSource
.is() )
242 xDataSource
= impl_createNewDataSource();
247 // DatabaseAccessContext_Base
248 void ODatabaseContext::disposing()
250 // notify our listener
251 css::lang::EventObject
aDisposeEvent(static_cast< XContainer
* >(this));
252 m_aContainerListeners
.disposeAndClear(aDisposeEvent
);
254 // dispose the data sources
255 // disposing seems to remove elements, so work on copy for valid iterators
257 objCopy
.swap(m_aDatabaseObjects
);
258 for (auto const& elem
: objCopy
)
260 rtl::Reference
< ODatabaseModelImpl
> obj(elem
.second
);
261 // make sure obj is acquired and does not delete itself from within
268 Reference
< XInterface
> ODatabaseContext::getRegisteredObject(const OUString
& _rName
)
270 MutexGuard
aGuard(m_aMutex
);
271 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
273 OUString
sURL( getDatabaseLocation( _rName
) );
275 if ( sURL
.isEmpty() )
276 // there is a registration for this name, but no URL
277 throw IllegalArgumentException();
279 // check if URL is already loaded
280 Reference
< XInterface
> xExistent
= getObject( sURL
);
281 if ( xExistent
.is() )
284 return loadObjectFromURL( _rName
, sURL
);
287 Reference
< XInterface
> ODatabaseContext::loadObjectFromURL(const OUString
& _rName
,const OUString
& _sURL
)
289 INetURLObject
aURL( _sURL
);
291 if ( aURL
.GetProtocol() == INetProtocol::NotValid
)
292 throw NoSuchElementException( _rName
, *this );
294 bool bEmbeddedDataSource
= aURL
.isSchemeEqualTo(INetProtocol::VndSunStarPkg
);
297 if (!bEmbeddedDataSource
)
299 ::ucbhelper::Content
aContent( _sURL
, nullptr, comphelper::getProcessComponentContext() );
300 if ( !aContent
.isDocument() )
301 throw InteractiveIOException(
302 _sURL
, *this, InteractionClassification_ERROR
, IOErrorCode_NO_FILE
306 catch ( const InteractiveIOException
& e
)
308 if ( ( e
.Code
== IOErrorCode_NO_FILE
)
309 || ( e
.Code
== IOErrorCode_NOT_EXISTING
)
310 || ( e
.Code
== IOErrorCode_NOT_EXISTING_PATH
)
314 OUString
sErrorMessage( DBA_RES( RID_STR_FILE_DOES_NOT_EXIST
) );
315 ::svt::OFileNotation
aTransformer( _sURL
);
318 aError
.Message
= sErrorMessage
.replaceAll( "$file$", aTransformer
.get( ::svt::OFileNotation::N_SYSTEM
) );
320 throw WrappedTargetException( _sURL
, *this, makeAny( aError
) );
322 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
324 catch( const Exception
& )
326 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
329 OSL_ENSURE( m_aDatabaseObjects
.find( _sURL
) == m_aDatabaseObjects
.end(),
330 "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
332 ::rtl::Reference
< ODatabaseModelImpl
> pModelImpl
;
334 pModelImpl
.set( new ODatabaseModelImpl( _rName
, m_aContext
, *this ) );
336 Reference
< XModel
> xModel( pModelImpl
->createNewModel_deliverOwnership(), UNO_SET_THROW
);
337 Reference
< XLoadable
> xLoad( xModel
, UNO_QUERY_THROW
);
339 ::comphelper::NamedValueCollection aArgs
;
340 aArgs
.put( "URL", _sURL
);
341 aArgs
.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG
);
342 aArgs
.put( "InteractionHandler", task::InteractionHandler::createWithParent(m_aContext
, nullptr) );
343 if (bEmbeddedDataSource
)
345 // In this case the host contains the real path, and the path is the embedded stream name.
346 auto const uri
= css::uri::UriReferenceFactory::create(m_aContext
)->parse(_sURL
);
347 if (uri
.is() && uri
->isAbsolute()
348 && uri
->hasAuthority() && !uri
->hasQuery() && !uri
->hasFragment())
350 auto const auth
= uri
->getAuthority();
351 auto const decAuth
= rtl::Uri::decode(
352 auth
, rtl_UriDecodeStrict
, RTL_TEXTENCODING_UTF8
);
353 if (auth
.isEmpty() == decAuth
.isEmpty()) {
354 // Decoding of auth to UTF-8 succeeded:
355 OUString sBaseURI
= decAuth
+ uri
->getPath();
356 aArgs
.put("BaseURI", sBaseURI
);
360 "<" << _sURL
<< "> cannot be parse as vnd.sun.star.pkg URL");
364 "dbaccess.core", "<" << _sURL
<< "> cannot be parse as vnd.sun.star.pkg URL");
368 Sequence
< PropertyValue
> aResource( aArgs
.getPropertyValues() );
369 xLoad
->load( aResource
);
370 xModel
->attachResource( _sURL
, aResource
);
372 ::utl::CloseableComponent
aEnsureClose( xModel
);
375 setTransientProperties( _sURL
, *pModelImpl
);
377 return pModelImpl
->getOrCreateDataSource().get();
380 void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
382 m_xDatabaseDocumentLoader
->append(_rDataSourceModel
);
385 void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
387 m_xDatabaseDocumentLoader
->remove(_rDataSourceModel
);
390 void ODatabaseContext::setTransientProperties(const OUString
& _sURL
, ODatabaseModelImpl
& _rDataSourceModel
)
392 if ( m_aDatasourceProperties
.end() == m_aDatasourceProperties
.find(_sURL
) )
396 OUString sAuthFailedPassword
;
397 Reference
< XPropertySet
> xDSProps( _rDataSourceModel
.getOrCreateDataSource(), UNO_QUERY_THROW
);
398 const Sequence
< PropertyValue
>& rSessionPersistentProps
= m_aDatasourceProperties
[_sURL
];
399 for ( auto const & prop
: rSessionPersistentProps
)
401 if ( prop
.Name
== "AuthFailedPassword" )
403 OSL_VERIFY( prop
.Value
>>= sAuthFailedPassword
);
407 xDSProps
->setPropertyValue( prop
.Name
, prop
.Value
);
411 _rDataSourceModel
.m_sFailedPassword
= sAuthFailedPassword
;
413 catch( const Exception
& )
415 DBG_UNHANDLED_EXCEPTION("dbaccess");
419 void ODatabaseContext::registerObject(const OUString
& _rName
, const Reference
< XInterface
> & _rxObject
)
421 if ( _rName
.isEmpty() )
422 throw IllegalArgumentException( OUString(), *this, 1 );
424 Reference
< XDocumentDataSource
> xDocDataSource( _rxObject
, UNO_QUERY
);
425 Reference
< XModel
> xModel( xDocDataSource
.is() ? xDocDataSource
->getDatabaseDocument() : Reference
< XOfficeDatabaseDocument
>(), UNO_QUERY
);
427 throw IllegalArgumentException( OUString(), *this, 2 );
429 OUString sURL
= xModel
->getURL();
430 if ( sURL
.isEmpty() )
431 throw IllegalArgumentException( DBA_RES( RID_STR_DATASOURCE_NOT_STORED
), *this, 2 );
433 { // avoid deadlocks: lock m_aMutex after checking arguments
434 MutexGuard
aGuard(m_aMutex
);
435 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
437 registerDatabaseLocation( _rName
, sURL
);
439 ODatabaseSource::setName( xDocDataSource
, _rName
, ODatabaseSource::DBContextAccess() );
442 // notify our container listeners
443 ContainerEvent
aEvent(static_cast<XContainer
*>(this), makeAny(_rName
), makeAny(_rxObject
), Any());
444 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
447 void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl
& _rModelImpl
)
449 Reference
< XPropertySet
> xSource( _rModelImpl
.getOrCreateDataSource(), UNO_QUERY
);
450 ::comphelper::NamedValueCollection aRememberProps
;
454 // get the info about the properties, check which ones are transient and not readonly
455 Reference
< XPropertySetInfo
> xSetInfo
;
457 xSetInfo
= xSource
->getPropertySetInfo();
458 Sequence
< Property
> aProperties
;
460 aProperties
= xSetInfo
->getProperties();
462 for ( const Property
& rProperty
: std::as_const(aProperties
) )
464 if ( ( ( rProperty
.Attributes
& PropertyAttribute::TRANSIENT
) != 0 )
465 && ( ( rProperty
.Attributes
& PropertyAttribute::READONLY
) == 0 )
468 // found such a property
469 aRememberProps
.put( rProperty
.Name
, xSource
->getPropertyValue( rProperty
.Name
) );
473 catch ( const Exception
& )
475 DBG_UNHANDLED_EXCEPTION("dbaccess");
478 // additionally, remember the "failed password", which is not available as property
480 aRememberProps
.put( "AuthFailedPassword", _rModelImpl
.m_sFailedPassword
);
482 OUString
sDocumentURL( _rModelImpl
.getURL() );
483 if ( m_aDatabaseObjects
.find( sDocumentURL
) != m_aDatabaseObjects
.end() )
485 m_aDatasourceProperties
[ sDocumentURL
] = aRememberProps
.getPropertyValues();
487 else if ( m_aDatabaseObjects
.find( _rModelImpl
.m_sName
) != m_aDatabaseObjects
.end() )
489 OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
490 // all the code should have been changed so that registration is by URL only
491 m_aDatasourceProperties
[ _rModelImpl
.m_sName
] = aRememberProps
.getPropertyValues();
495 OSL_ENSURE( sDocumentURL
.isEmpty() && _rModelImpl
.m_sName
.isEmpty() ,
496 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
500 void SAL_CALL
ODatabaseContext::addContainerListener( const Reference
< XContainerListener
>& _rxListener
)
502 m_aContainerListeners
.addInterface(_rxListener
);
505 void SAL_CALL
ODatabaseContext::removeContainerListener( const Reference
< XContainerListener
>& _rxListener
)
507 m_aContainerListeners
.removeInterface(_rxListener
);
510 void ODatabaseContext::revokeObject(const OUString
& _rName
)
512 ClearableMutexGuard
aGuard(m_aMutex
);
513 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
515 OUString sURL
= getDatabaseLocation( _rName
);
517 revokeDatabaseLocation( _rName
);
518 // will throw if something goes wrong
520 if ( m_aDatabaseObjects
.find( _rName
) != m_aDatabaseObjects
.end() )
522 m_aDatasourceProperties
[ sURL
] = m_aDatasourceProperties
[ _rName
];
525 // check if URL is already loaded
526 ObjectCache::const_iterator aExistent
= m_aDatabaseObjects
.find( sURL
);
527 if ( aExistent
!= m_aDatabaseObjects
.end() )
528 m_aDatabaseObjects
.erase( aExistent
);
530 // notify our container listeners
531 ContainerEvent
aEvent( *this, makeAny( _rName
), Any(), Any() );
533 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, aEvent
);
536 sal_Bool SAL_CALL
ODatabaseContext::hasRegisteredDatabase( const OUString
& Name
)
538 return m_xDatabaseRegistrations
->hasRegisteredDatabase( Name
);
541 Sequence
< OUString
> SAL_CALL
ODatabaseContext::getRegistrationNames()
543 return m_xDatabaseRegistrations
->getRegistrationNames();
546 OUString SAL_CALL
ODatabaseContext::getDatabaseLocation( const OUString
& Name
)
548 return m_xDatabaseRegistrations
->getDatabaseLocation( Name
);
551 void SAL_CALL
ODatabaseContext::registerDatabaseLocation( const OUString
& Name
, const OUString
& Location
)
553 m_xDatabaseRegistrations
->registerDatabaseLocation( Name
, Location
);
556 void SAL_CALL
ODatabaseContext::revokeDatabaseLocation( const OUString
& Name
)
558 m_xDatabaseRegistrations
->revokeDatabaseLocation( Name
);
561 void SAL_CALL
ODatabaseContext::changeDatabaseLocation( const OUString
& Name
, const OUString
& NewLocation
)
563 m_xDatabaseRegistrations
->changeDatabaseLocation( Name
, NewLocation
);
566 sal_Bool SAL_CALL
ODatabaseContext::isDatabaseRegistrationReadOnly( const OUString
& Name
)
568 return m_xDatabaseRegistrations
->isDatabaseRegistrationReadOnly( Name
);
571 void SAL_CALL
ODatabaseContext::addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
)
573 m_xDatabaseRegistrations
->addDatabaseRegistrationsListener( Listener
);
576 void SAL_CALL
ODatabaseContext::removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
)
578 m_xDatabaseRegistrations
->removeDatabaseRegistrationsListener( Listener
);
581 // css::container::XElementAccess
582 Type
ODatabaseContext::getElementType( )
584 return cppu::UnoType
<XDataSource
>::get();
587 sal_Bool
ODatabaseContext::hasElements()
589 MutexGuard
aGuard(m_aMutex
);
590 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
592 return getElementNames().hasElements();
595 // css::container::XEnumerationAccess
596 Reference
< css::container::XEnumeration
> ODatabaseContext::createEnumeration()
598 MutexGuard
aGuard(m_aMutex
);
599 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess
*>(this));
602 // css::container::XNameAccess
603 Any
ODatabaseContext::getByName(const OUString
& _rName
)
605 MutexGuard
aGuard(m_aMutex
);
606 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
607 if ( _rName
.isEmpty() )
608 throw NoSuchElementException(_rName
, *this);
612 Reference
< XInterface
> xExistent
= getObject( _rName
);
613 if ( xExistent
.is() )
614 return makeAny( xExistent
);
616 // see whether this is a registered name
618 if ( hasRegisteredDatabase( _rName
) )
620 sURL
= getDatabaseLocation( _rName
);
621 // is the object cached under its URL?
622 xExistent
= getObject( sURL
);
625 // interpret the name as URL
628 if ( !xExistent
.is() )
629 // try to load this as URL
630 xExistent
= loadObjectFromURL( _rName
, sURL
);
631 return makeAny( xExistent
);
633 catch (const NoSuchElementException
&)
634 { // let these exceptions through
637 catch (const WrappedTargetException
&)
638 { // let these exceptions through
641 catch (const RuntimeException
&)
642 { // let these exceptions through
645 catch (const Exception
&)
646 { // exceptions other than the specified ones -> wrap
647 Any aError
= ::cppu::getCaughtException();
648 throw WrappedTargetException(_rName
, *this, aError
);
652 Sequence
< OUString
> ODatabaseContext::getElementNames()
654 MutexGuard
aGuard(m_aMutex
);
655 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
657 return getRegistrationNames();
660 sal_Bool
ODatabaseContext::hasByName(const OUString
& _rName
)
662 MutexGuard
aGuard(m_aMutex
);
663 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
665 return hasRegisteredDatabase( _rName
);
668 Reference
< XInterface
> ODatabaseContext::getObject( const OUString
& _rURL
)
670 ObjectCache::const_iterator aFind
= m_aDatabaseObjects
.find( _rURL
);
671 Reference
< XInterface
> xExistent
;
672 if ( aFind
!= m_aDatabaseObjects
.end() )
673 xExistent
= aFind
->second
->getOrCreateDataSource();
677 void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl
& _rModelImpl
)
679 OUString
sURL( _rModelImpl
.getURL() );
680 SAL_INFO("dbaccess.core", "DatabaseContext: registering " << sURL
);
681 if ( m_aDatabaseObjects
.find( sURL
) == m_aDatabaseObjects
.end() )
683 m_aDatabaseObjects
[ sURL
] = &_rModelImpl
;
684 setTransientProperties( sURL
, _rModelImpl
);
687 OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
690 void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl
& _rModelImpl
)
692 const OUString
& sURL( _rModelImpl
.getURL() );
693 SAL_INFO("dbaccess.core", "DatabaseContext: deregistering " << sURL
);
694 m_aDatabaseObjects
.erase( sURL
);
697 void ODatabaseContext::databaseDocumentURLChange( const OUString
& _rOldURL
, const OUString
& _rNewURL
)
699 SAL_INFO("dbaccess.core", "DatabaseContext: changing registrations from " << _rOldURL
<<
701 ObjectCache::const_iterator oldPos
= m_aDatabaseObjects
.find( _rOldURL
);
702 ENSURE_OR_THROW( oldPos
!= m_aDatabaseObjects
.end(), "illegal old database document URL" );
703 ObjectCache::const_iterator newPos
= m_aDatabaseObjects
.find( _rNewURL
);
704 ENSURE_OR_THROW( newPos
== m_aDatabaseObjects
.end(), "illegal new database document URL" );
706 m_aDatabaseObjects
[ _rNewURL
] = oldPos
->second
;
707 m_aDatabaseObjects
.erase( oldPos
);
710 sal_Int64 SAL_CALL
ODatabaseContext::getSomething( const Sequence
< sal_Int8
>& rId
)
712 if (isUnoTunnelId
<ODatabaseContext
>(rId
))
713 return reinterpret_cast<sal_Int64
>(this);
718 Sequence
< sal_Int8
> ODatabaseContext::getUnoTunnelId()
720 static ::cppu::OImplementationId implId
;
722 return implId
.getImplementationId();
725 void ODatabaseContext::onBasicManagerCreated( const Reference
< XModel
>& _rxForDocument
, BasicManager
& _rBasicManager
)
727 #if !HAVE_FEATURE_SCRIPTING
728 (void) _rxForDocument
;
729 (void) _rBasicManager
;
731 // if it's a database document ...
732 Reference
< XOfficeDatabaseDocument
> xDatabaseDocument( _rxForDocument
, UNO_QUERY
);
733 // ... or a sub document of a database document ...
734 if ( !xDatabaseDocument
.is() )
736 Reference
< XChild
> xDocAsChild( _rxForDocument
, UNO_QUERY
);
737 if ( xDocAsChild
.is() )
738 xDatabaseDocument
.set( xDocAsChild
->getParent(), UNO_QUERY
);
741 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
742 if ( xDatabaseDocument
.is() )
743 _rBasicManager
.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument
) );
747 } // namespace dbaccess
750 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
751 com_sun_star_comp_dba_ODatabaseContext_get_implementation(
752 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
754 return cppu::acquire(static_cast<cppu::OWeakObject
*>(new dbaccess::ODatabaseContext(context
)));
757 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */