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 <strings.hxx>
24 #include <core_resource.hxx>
25 #include <databasecontext.hxx>
26 #include "databaseregistrations.hxx"
27 #include "datasource.hxx"
28 #include "databasedocument.hxx"
30 #include <com/sun/star/beans/PropertyAttribute.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/document/MacroExecMode.hpp>
33 #include <com/sun/star/frame/Desktop.hpp>
34 #include <com/sun/star/frame/TerminationVetoException.hpp>
35 #include <com/sun/star/frame/XLoadable.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/frame/XModel2.hpp>
38 #include <com/sun/star/frame/XTerminateListener.hpp>
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include <com/sun/star/registry/InvalidRegistryException.hpp>
41 #include <com/sun/star/sdbc/XDataSource.hpp>
42 #include <com/sun/star/task/InteractionClassification.hpp>
43 #include <com/sun/star/ucb/InteractiveIOException.hpp>
44 #include <com/sun/star/ucb/IOErrorCode.hpp>
45 #include <com/sun/star/uri/UriReferenceFactory.hpp>
46 #include <com/sun/star/task/InteractionHandler.hpp>
47 #include <com/sun/star/util/CloseVetoException.hpp>
48 #include <com/sun/star/util/XCloseable.hpp>
50 #include <basic/basmgr.hxx>
51 #include <comphelper/enumhelper.hxx>
52 #include <comphelper/namedvaluecollection.hxx>
53 #include <comphelper/processfactory.hxx>
54 #include <comphelper/servicehelper.hxx>
55 #include <cppuhelper/implbase.hxx>
56 #include <cppuhelper/supportsservice.hxx>
57 #include <cppuhelper/exc_hlp.hxx>
58 #include <cppuhelper/weak.hxx>
59 #include <rtl/uri.hxx>
60 #include <sal/log.hxx>
61 #include <svl/filenotation.hxx>
62 #include <comphelper/diagnose_ex.hxx>
63 #include <tools/urlobj.hxx>
64 #include <ucbhelper/content.hxx>
65 #include <rtl/ref.hxx>
66 #include <unotools/sharedunocomponent.hxx>
69 using namespace ::com::sun::star::sdbc
;
70 using namespace ::com::sun::star::sdb
;
71 using namespace ::com::sun::star::beans
;
72 using namespace ::com::sun::star::uno
;
73 using namespace ::com::sun::star::document
;
74 using namespace ::com::sun::star::frame
;
75 using namespace ::com::sun::star::lang
;
76 using namespace ::com::sun::star::container
;
77 using namespace ::com::sun::star::util
;
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 rtl::Reference
< ODatabaseDocument
> xMod( pCopy
->getModel_noCreate() );
144 throw uno::RuntimeException();
145 if( !xMod
->getControllers()->hasMoreElements() )
146 xMod
->close( false );
148 catch( const CloseVetoException
& )
150 throw TerminationVetoException();
155 void SAL_CALL
DatabaseDocumentLoader::notifyTermination( const lang::EventObject
& /*Event*/ )
159 void SAL_CALL
DatabaseDocumentLoader::disposing( const lang::EventObject
& /*Source*/ )
165 ODatabaseContext::ODatabaseContext( const Reference
< XComponentContext
>& _rxContext
)
166 :DatabaseAccessContext_Base(m_aMutex
)
167 ,m_aContext( _rxContext
)
168 ,m_aContainerListeners(m_aMutex
)
170 m_xDatabaseDocumentLoader
= new DatabaseDocumentLoader( _rxContext
);
172 #if HAVE_FEATURE_SCRIPTING
173 ::basic::BasicManagerRepository::registerCreationListener( *this );
176 osl_atomic_increment( &m_refCount
);
177 m_xDatabaseRegistrations
= createDataSourceRegistrations( m_aContext
);
178 osl_atomic_decrement( &m_refCount
);
181 ODatabaseContext::~ODatabaseContext()
183 #if HAVE_FEATURE_SCRIPTING
184 ::basic::BasicManagerRepository::revokeCreationListener( *this );
187 m_xDatabaseDocumentLoader
.clear();
188 m_xDatabaseRegistrations
.clear();
192 OUString
ODatabaseContext::getImplementationName( )
194 return u
"com.sun.star.comp.dba.ODatabaseContext"_ustr
;
197 sal_Bool
ODatabaseContext::supportsService( const OUString
& _rServiceName
)
199 return cppu::supportsService(this, _rServiceName
);
202 Sequence
< OUString
> ODatabaseContext::getSupportedServiceNames( )
204 return { u
"com.sun.star.sdb.DatabaseContext"_ustr
};
207 Reference
< XInterface
> ODatabaseContext::impl_createNewDataSource()
209 ::rtl::Reference
pImpl( new ODatabaseModelImpl( m_aContext
, *this ) );
210 Reference
< XDataSource
> xDataSource( pImpl
->getOrCreateDataSource() );
215 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstance( )
217 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
218 // has been called at the DatabaseDocument).
219 return impl_createNewDataSource();
222 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstanceWithArguments( const Sequence
< Any
>& _rArguments
)
224 ::comphelper::NamedValueCollection
aArgs( _rArguments
);
225 OUString sURL
= aArgs
.getOrDefault( INFO_POOLURL
, OUString() );
227 Reference
< XInterface
> xDataSource
;
228 if ( !sURL
.isEmpty() )
229 xDataSource
= getObject( sURL
);
231 if ( !xDataSource
.is() )
232 xDataSource
= impl_createNewDataSource();
237 // DatabaseAccessContext_Base
238 void ODatabaseContext::disposing()
240 // notify our listener
241 css::lang::EventObject
aDisposeEvent(static_cast< XContainer
* >(this));
242 m_aContainerListeners
.disposeAndClear(aDisposeEvent
);
244 // dispose the data sources
245 // disposing seems to remove elements, so work on copy for valid iterators
247 objCopy
.swap(m_aDatabaseObjects
);
248 for (auto const& elem
: objCopy
)
250 rtl::Reference
< ODatabaseModelImpl
> obj(elem
.second
);
251 // make sure obj is acquired and does not delete itself from within
258 Reference
< XInterface
> ODatabaseContext::getRegisteredObject(const OUString
& _rName
)
260 MutexGuard
aGuard(m_aMutex
);
261 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
263 OUString
sURL( getDatabaseLocation( _rName
) );
265 if ( sURL
.isEmpty() )
266 // there is a registration for this name, but no URL
267 throw IllegalArgumentException();
269 // check if URL is already loaded
270 Reference
< XInterface
> xExistent
= getObject( sURL
);
271 if ( xExistent
.is() )
274 return loadObjectFromURL( _rName
, sURL
);
277 Reference
< XInterface
> ODatabaseContext::loadObjectFromURL(const OUString
& _rName
,const OUString
& _sURL
)
279 INetURLObject
aURL( _sURL
);
281 if ( aURL
.GetProtocol() == INetProtocol::NotValid
)
282 throw NoSuchElementException( _rName
, *this );
284 bool bEmbeddedDataSource
= aURL
.isSchemeEqualTo(INetProtocol::VndSunStarPkg
);
287 if (!bEmbeddedDataSource
)
289 ::ucbhelper::Content
aContent( _sURL
, nullptr, comphelper::getProcessComponentContext() );
290 if ( !aContent
.isDocument() )
291 throw InteractiveIOException(
292 _sURL
, *this, InteractionClassification_ERROR
, IOErrorCode_NO_FILE
296 catch ( const InteractiveIOException
& e
)
298 if ( ( e
.Code
== IOErrorCode_NO_FILE
)
299 || ( e
.Code
== IOErrorCode_NOT_EXISTING
)
300 || ( e
.Code
== IOErrorCode_NOT_EXISTING_PATH
)
304 OUString
sErrorMessage( DBA_RES( RID_STR_FILE_DOES_NOT_EXIST
) );
305 ::svt::OFileNotation
aTransformer( _sURL
);
307 SQLException
aError(sErrorMessage
.replaceAll(
308 "$file$", aTransformer
.get(::svt::OFileNotation::N_SYSTEM
)),
311 throw WrappedTargetException( _sURL
, *this, Any( aError
) );
313 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
315 catch( const Exception
& )
317 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
320 OSL_ENSURE( m_aDatabaseObjects
.find( _sURL
) == m_aDatabaseObjects
.end(),
321 "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
323 ::rtl::Reference
< ODatabaseModelImpl
> pModelImpl
;
325 pModelImpl
.set( new ODatabaseModelImpl( _rName
, m_aContext
, *this ) );
327 Reference
< XModel
> xModel( pModelImpl
->createNewModel_deliverOwnership(), UNO_SET_THROW
);
328 Reference
< XLoadable
> xLoad( xModel
, UNO_QUERY_THROW
);
330 ::comphelper::NamedValueCollection aArgs
;
331 aArgs
.put( u
"URL"_ustr
, _sURL
);
332 aArgs
.put( u
"MacroExecutionMode"_ustr
, MacroExecMode::USE_CONFIG
);
333 aArgs
.put( u
"InteractionHandler"_ustr
, task::InteractionHandler::createWithParent(m_aContext
, nullptr) );
334 if (bEmbeddedDataSource
)
336 // In this case the host contains the real path, and the path is the embedded stream name.
337 auto const uri
= css::uri::UriReferenceFactory::create(m_aContext
)->parse(_sURL
);
338 if (uri
.is() && uri
->isAbsolute()
339 && uri
->hasAuthority() && !uri
->hasQuery() && !uri
->hasFragment())
341 auto const auth
= uri
->getAuthority();
342 auto const decAuth
= rtl::Uri::decode(
343 auth
, rtl_UriDecodeStrict
, RTL_TEXTENCODING_UTF8
);
344 if (auth
.isEmpty() == decAuth
.isEmpty()) {
345 // Decoding of auth to UTF-8 succeeded:
346 OUString sBaseURI
= decAuth
+ uri
->getPath();
347 aArgs
.put(u
"BaseURI"_ustr
, sBaseURI
);
351 "<" << _sURL
<< "> cannot be parse as vnd.sun.star.pkg URL");
355 "dbaccess.core", "<" << _sURL
<< "> cannot be parse as vnd.sun.star.pkg URL");
359 Sequence
< PropertyValue
> aResource( aArgs
.getPropertyValues() );
360 xLoad
->load( aResource
);
361 xModel
->attachResource( _sURL
, aResource
);
363 ::utl::CloseableComponent
aEnsureClose( xModel
);
366 setTransientProperties( _sURL
, *pModelImpl
);
368 return pModelImpl
->getOrCreateDataSource();
371 void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
373 m_xDatabaseDocumentLoader
->append(_rDataSourceModel
);
376 void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
378 m_xDatabaseDocumentLoader
->remove(_rDataSourceModel
);
381 void ODatabaseContext::setTransientProperties(const OUString
& _sURL
, ODatabaseModelImpl
& _rDataSourceModel
)
383 if ( m_aDatasourceProperties
.end() == m_aDatasourceProperties
.find(_sURL
) )
387 OUString sAuthFailedPassword
;
388 Reference
< XPropertySet
> xDSProps( _rDataSourceModel
.getOrCreateDataSource(), UNO_QUERY_THROW
);
389 const Sequence
< PropertyValue
>& rSessionPersistentProps
= m_aDatasourceProperties
[_sURL
];
390 for ( auto const & prop
: rSessionPersistentProps
)
392 if ( prop
.Name
== "AuthFailedPassword" )
394 OSL_VERIFY( prop
.Value
>>= sAuthFailedPassword
);
398 xDSProps
->setPropertyValue( prop
.Name
, prop
.Value
);
402 _rDataSourceModel
.m_sFailedPassword
= sAuthFailedPassword
;
404 catch( const Exception
& )
406 DBG_UNHANDLED_EXCEPTION("dbaccess");
410 void ODatabaseContext::registerObject(const OUString
& _rName
, const Reference
< XInterface
> & _rxObject
)
412 if ( _rName
.isEmpty() )
413 throw IllegalArgumentException( OUString(), *this, 1 );
415 Reference
< XDocumentDataSource
> xDocDataSource( _rxObject
, UNO_QUERY
);
416 Reference
< XModel
> xModel( xDocDataSource
.is() ? xDocDataSource
->getDatabaseDocument() : Reference
< XOfficeDatabaseDocument
>(), UNO_QUERY
);
418 throw IllegalArgumentException( OUString(), *this, 2 );
420 OUString sURL
= xModel
->getURL();
421 if ( sURL
.isEmpty() )
422 throw IllegalArgumentException( DBA_RES( RID_STR_DATASOURCE_NOT_STORED
), *this, 2 );
424 { // avoid deadlocks: lock m_aMutex after checking arguments
425 MutexGuard
aGuard(m_aMutex
);
426 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
428 registerDatabaseLocation( _rName
, sURL
);
430 ODatabaseSource::setName( xDocDataSource
, _rName
, ODatabaseSource::DBContextAccess() );
433 // notify our container listeners
434 ContainerEvent
aEvent(static_cast<XContainer
*>(this), Any(_rName
), Any(_rxObject
), Any());
435 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
438 void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl
& _rModelImpl
)
440 Reference
< XPropertySet
> xSource( _rModelImpl
.getOrCreateDataSource(), UNO_QUERY
);
441 ::comphelper::NamedValueCollection aRememberProps
;
445 // get the info about the properties, check which ones are transient and not readonly
446 Reference
< XPropertySetInfo
> xSetInfo
;
448 xSetInfo
= xSource
->getPropertySetInfo();
449 Sequence
< Property
> aProperties
;
451 aProperties
= xSetInfo
->getProperties();
453 for (const Property
& rProperty
: aProperties
)
455 if ( ( ( rProperty
.Attributes
& PropertyAttribute::TRANSIENT
) != 0 )
456 && ( ( rProperty
.Attributes
& PropertyAttribute::READONLY
) == 0 )
459 // found such a property
460 aRememberProps
.put( rProperty
.Name
, xSource
->getPropertyValue( rProperty
.Name
) );
464 catch ( const Exception
& )
466 DBG_UNHANDLED_EXCEPTION("dbaccess");
469 // additionally, remember the "failed password", which is not available as property
471 aRememberProps
.put( u
"AuthFailedPassword"_ustr
, _rModelImpl
.m_sFailedPassword
);
473 OUString
sDocumentURL( _rModelImpl
.getURL() );
474 if ( m_aDatabaseObjects
.find( sDocumentURL
) != m_aDatabaseObjects
.end() )
476 m_aDatasourceProperties
[ sDocumentURL
] = aRememberProps
.getPropertyValues();
478 else if ( m_aDatabaseObjects
.find( _rModelImpl
.m_sName
) != m_aDatabaseObjects
.end() )
480 OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
481 // all the code should have been changed so that registration is by URL only
482 m_aDatasourceProperties
[ _rModelImpl
.m_sName
] = aRememberProps
.getPropertyValues();
486 OSL_ENSURE( sDocumentURL
.isEmpty() && _rModelImpl
.m_sName
.isEmpty() ,
487 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
491 void SAL_CALL
ODatabaseContext::addContainerListener( const Reference
< XContainerListener
>& _rxListener
)
493 m_aContainerListeners
.addInterface(_rxListener
);
496 void SAL_CALL
ODatabaseContext::removeContainerListener( const Reference
< XContainerListener
>& _rxListener
)
498 m_aContainerListeners
.removeInterface(_rxListener
);
501 void ODatabaseContext::revokeObject(const OUString
& _rName
)
503 ClearableMutexGuard
aGuard(m_aMutex
);
504 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
506 OUString sURL
= getDatabaseLocation( _rName
);
508 revokeDatabaseLocation( _rName
);
509 // will throw if something goes wrong
511 if ( m_aDatabaseObjects
.find( _rName
) != m_aDatabaseObjects
.end() )
513 m_aDatasourceProperties
[ sURL
] = m_aDatasourceProperties
[ _rName
];
516 // check if URL is already loaded
517 ObjectCache::const_iterator aExistent
= m_aDatabaseObjects
.find( sURL
);
518 if ( aExistent
!= m_aDatabaseObjects
.end() )
519 m_aDatabaseObjects
.erase( aExistent
);
521 // notify our container listeners
522 ContainerEvent
aEvent( *this, Any( _rName
), Any(), Any() );
524 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, aEvent
);
527 sal_Bool SAL_CALL
ODatabaseContext::hasRegisteredDatabase( const OUString
& Name
)
529 return m_xDatabaseRegistrations
->hasRegisteredDatabase( Name
);
532 Sequence
< OUString
> SAL_CALL
ODatabaseContext::getRegistrationNames()
534 return m_xDatabaseRegistrations
->getRegistrationNames();
537 OUString SAL_CALL
ODatabaseContext::getDatabaseLocation( const OUString
& Name
)
539 return m_xDatabaseRegistrations
->getDatabaseLocation( Name
);
542 void SAL_CALL
ODatabaseContext::registerDatabaseLocation( const OUString
& Name
, const OUString
& Location
)
544 m_xDatabaseRegistrations
->registerDatabaseLocation( Name
, Location
);
547 void SAL_CALL
ODatabaseContext::revokeDatabaseLocation( const OUString
& Name
)
549 m_xDatabaseRegistrations
->revokeDatabaseLocation( Name
);
552 void SAL_CALL
ODatabaseContext::changeDatabaseLocation( const OUString
& Name
, const OUString
& NewLocation
)
554 m_xDatabaseRegistrations
->changeDatabaseLocation( Name
, NewLocation
);
557 sal_Bool SAL_CALL
ODatabaseContext::isDatabaseRegistrationReadOnly( const OUString
& Name
)
559 return m_xDatabaseRegistrations
->isDatabaseRegistrationReadOnly( Name
);
562 void SAL_CALL
ODatabaseContext::addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
)
564 m_xDatabaseRegistrations
->addDatabaseRegistrationsListener( Listener
);
567 void SAL_CALL
ODatabaseContext::removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
)
569 m_xDatabaseRegistrations
->removeDatabaseRegistrationsListener( Listener
);
572 // css::container::XElementAccess
573 Type
ODatabaseContext::getElementType( )
575 return cppu::UnoType
<XDataSource
>::get();
578 sal_Bool
ODatabaseContext::hasElements()
580 MutexGuard
aGuard(m_aMutex
);
581 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
583 return getElementNames().hasElements();
586 // css::container::XEnumerationAccess
587 Reference
< css::container::XEnumeration
> ODatabaseContext::createEnumeration()
589 MutexGuard
aGuard(m_aMutex
);
590 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess
*>(this));
593 // css::container::XNameAccess
594 Any
ODatabaseContext::getByName(const OUString
& _rName
)
596 MutexGuard
aGuard(m_aMutex
);
597 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
598 if ( _rName
.isEmpty() )
599 throw NoSuchElementException(_rName
, *this);
603 Reference
< XInterface
> xExistent
= getObject( _rName
);
604 if ( xExistent
.is() )
605 return Any( xExistent
);
607 // see whether this is a registered name
609 if ( hasRegisteredDatabase( _rName
) )
611 sURL
= getDatabaseLocation( _rName
);
612 // is the object cached under its URL?
613 xExistent
= getObject( sURL
);
616 // interpret the name as URL
619 if ( !xExistent
.is() )
620 // try to load this as URL
621 xExistent
= loadObjectFromURL( _rName
, sURL
);
622 return Any( xExistent
);
624 catch (const NoSuchElementException
&)
625 { // let these exceptions through
628 catch (const WrappedTargetException
&)
629 { // let these exceptions through
632 catch (const RuntimeException
&)
633 { // let these exceptions through
636 catch (const Exception
&)
637 { // exceptions other than the specified ones -> wrap
638 Any aError
= ::cppu::getCaughtException();
639 throw WrappedTargetException(_rName
, *this, aError
);
643 Sequence
< OUString
> ODatabaseContext::getElementNames()
645 MutexGuard
aGuard(m_aMutex
);
646 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
648 return getRegistrationNames();
651 sal_Bool
ODatabaseContext::hasByName(const OUString
& _rName
)
653 MutexGuard
aGuard(m_aMutex
);
654 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
656 return hasRegisteredDatabase( _rName
);
659 Reference
< XInterface
> ODatabaseContext::getObject( const OUString
& _rURL
)
661 ObjectCache::const_iterator aFind
= m_aDatabaseObjects
.find( _rURL
);
662 Reference
< XInterface
> xExistent
;
663 if ( aFind
!= m_aDatabaseObjects
.end() )
664 xExistent
= aFind
->second
->getOrCreateDataSource();
668 void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl
& _rModelImpl
)
670 OUString
sURL( _rModelImpl
.getURL() );
671 SAL_INFO("dbaccess.core", "DatabaseContext: registering " << sURL
);
672 if ( m_aDatabaseObjects
.find( sURL
) == m_aDatabaseObjects
.end() )
674 m_aDatabaseObjects
[ sURL
] = &_rModelImpl
;
675 setTransientProperties( sURL
, _rModelImpl
);
678 OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
681 void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl
& _rModelImpl
)
683 const OUString
& sURL( _rModelImpl
.getURL() );
684 SAL_INFO("dbaccess.core", "DatabaseContext: deregistering " << sURL
);
685 m_aDatabaseObjects
.erase( sURL
);
688 void ODatabaseContext::databaseDocumentURLChange( const OUString
& _rOldURL
, const OUString
& _rNewURL
)
690 SAL_INFO("dbaccess.core", "DatabaseContext: changing registrations from " << _rOldURL
<<
692 ObjectCache::const_iterator oldPos
= m_aDatabaseObjects
.find( _rOldURL
);
693 ENSURE_OR_THROW( oldPos
!= m_aDatabaseObjects
.end(), "illegal old database document URL" );
694 ObjectCache::const_iterator newPos
= m_aDatabaseObjects
.find( _rNewURL
);
695 ENSURE_OR_THROW( newPos
== m_aDatabaseObjects
.end(), "illegal new database document URL" );
697 m_aDatabaseObjects
[ _rNewURL
] = oldPos
->second
;
698 m_aDatabaseObjects
.erase( oldPos
);
701 void ODatabaseContext::onBasicManagerCreated( const Reference
< XModel
>& _rxForDocument
, BasicManager
& _rBasicManager
)
703 #if !HAVE_FEATURE_SCRIPTING
704 (void) _rxForDocument
;
705 (void) _rBasicManager
;
707 // if it's a database document ...
708 Reference
< XOfficeDatabaseDocument
> xDatabaseDocument( _rxForDocument
, UNO_QUERY
);
709 // ... or a sub document of a database document ...
710 if ( !xDatabaseDocument
.is() )
712 Reference
< XChild
> xDocAsChild( _rxForDocument
, UNO_QUERY
);
713 if ( xDocAsChild
.is() )
714 xDatabaseDocument
.set( xDocAsChild
->getParent(), UNO_QUERY
);
717 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
718 if ( xDatabaseDocument
.is() )
719 _rBasicManager
.SetGlobalUNOConstant( u
"ThisDatabaseDocument"_ustr
, Any( xDatabaseDocument
) );
723 } // namespace dbaccess
726 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
727 com_sun_star_comp_dba_ODatabaseContext_get_implementation(
728 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
730 return cppu::acquire(new dbaccess::ODatabaseContext(context
));
733 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */