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 "apitools.hxx"
23 #include "core_resource.hrc"
24 #include "core_resource.hxx"
25 #include "databasecontext.hxx"
26 #include "databasedocument.hxx"
27 #include "databaseregistrations.hxx"
28 #include "datasource.hxx"
29 #include "dbastrings.hrc"
31 #include <com/sun/star/beans/NamedValue.hpp>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/document/MacroExecMode.hpp>
35 #include <com/sun/star/document/XFilter.hpp>
36 #include <com/sun/star/document/XImporter.hpp>
37 #include <com/sun/star/frame/Desktop.hpp>
38 #include <com/sun/star/frame/XModel.hpp>
39 #include <com/sun/star/frame/XModel2.hpp>
40 #include <com/sun/star/frame/XTerminateListener.hpp>
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include <com/sun/star/registry/InvalidRegistryException.hpp>
43 #include <com/sun/star/sdbc/XDataSource.hpp>
44 #include <com/sun/star/task/InteractionClassification.hpp>
45 #include <com/sun/star/ucb/InteractiveIOException.hpp>
46 #include <com/sun/star/ucb/IOErrorCode.hpp>
47 #include <com/sun/star/task/InteractionHandler.hpp>
48 #include <com/sun/star/util/XCloseable.hpp>
50 #include <basic/basmgr.hxx>
51 #include <comphelper/enumhelper.hxx>
52 #include <comphelper/evtlistenerhlp.hxx>
53 #include <comphelper/namedvaluecollection.hxx>
54 #include <comphelper/processfactory.hxx>
55 #include <comphelper/sequence.hxx>
56 #include <cppuhelper/implbase.hxx>
57 #include <cppuhelper/supportsservice.hxx>
58 #include <cppuhelper/typeprovider.hxx>
59 #include <cppuhelper/exc_hlp.hxx>
60 #include <svl/filenotation.hxx>
61 #include <tools/debug.hxx>
62 #include <tools/diagnose_ex.h>
63 #include <tools/urlobj.hxx>
64 #include <ucbhelper/content.hxx>
65 #include <unotools/confignode.hxx>
66 #include <unotools/pathoptions.hxx>
67 #include <unotools/sharedunocomponent.hxx>
70 using namespace ::com::sun::star::sdbc
;
71 using namespace ::com::sun::star::sdb
;
72 using namespace ::com::sun::star::beans
;
73 using namespace ::com::sun::star::uno
;
74 using namespace ::com::sun::star::document
;
75 using namespace ::com::sun::star::frame
;
76 using namespace ::com::sun::star::lang
;
77 using namespace ::com::sun::star::container
;
78 using namespace ::com::sun::star::util
;
79 using namespace ::com::sun::star::registry
;
80 using namespace ::com::sun::star
;
81 using namespace ::cppu
;
82 using namespace ::osl
;
83 using namespace ::utl
;
85 using ::com::sun::star::task::InteractionClassification_ERROR
;
86 using ::com::sun::star::ucb::IOErrorCode_NO_FILE
;
87 using ::com::sun::star::ucb::InteractiveIOException
;
88 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING
;
89 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH
;
94 typedef ::cppu::WeakImplHelper
< XTerminateListener
95 > DatabaseDocumentLoader_Base
;
96 class DatabaseDocumentLoader
: public DatabaseDocumentLoader_Base
99 Reference
< XDesktop2
> m_xDesktop
;
100 ::std::list
< const ODatabaseModelImpl
* > m_aDatabaseDocuments
;
103 explicit DatabaseDocumentLoader( const Reference
<XComponentContext
> & rxContext
);
105 inline void append(const ODatabaseModelImpl
& _rModelImpl
)
107 m_aDatabaseDocuments
.push_back(&_rModelImpl
);
109 inline void remove(const ODatabaseModelImpl
& _rModelImpl
) { m_aDatabaseDocuments
.remove(&_rModelImpl
); }
112 // XTerminateListener
113 virtual void SAL_CALL
queryTermination( const lang::EventObject
& Event
) throw (TerminationVetoException
, RuntimeException
, std::exception
) override
;
114 virtual void SAL_CALL
notifyTermination( const lang::EventObject
& Event
) throw (RuntimeException
, std::exception
) override
;
116 virtual void SAL_CALL
disposing( const css::lang::EventObject
& Source
) throw (css::uno::RuntimeException
, std::exception
) override
;
119 DatabaseDocumentLoader::DatabaseDocumentLoader( const Reference
<XComponentContext
> & rxContext
)
124 m_xDesktop
.set( Desktop::create(rxContext
) );
125 m_xDesktop
->addTerminateListener( this );
127 catch( const Exception
& )
129 DBG_UNHANDLED_EXCEPTION();
133 void SAL_CALL
DatabaseDocumentLoader::queryTermination( const lang::EventObject
& /*Event*/ ) throw (TerminationVetoException
, RuntimeException
, std::exception
)
135 ::std::list
< const ODatabaseModelImpl
* > aCpy(m_aDatabaseDocuments
);
136 for( const auto& pCopy
: aCpy
)
140 const Reference
< XModel2
> xMod( pCopy
->getModel_noCreate(),
142 if( !xMod
->getControllers()->hasMoreElements() )
144 Reference
< util::XCloseable
> xClose( xMod
,
146 xClose
->close( false );
149 catch( const CloseVetoException
& )
151 throw TerminationVetoException();
156 void SAL_CALL
DatabaseDocumentLoader::notifyTermination( const lang::EventObject
& /*Event*/ ) throw (RuntimeException
, std::exception
)
160 void SAL_CALL
DatabaseDocumentLoader::disposing( const lang::EventObject
& /*Source*/ ) throw (RuntimeException
, std::exception
)
166 ODatabaseContext::ODatabaseContext( const Reference
< XComponentContext
>& _rxContext
)
167 :DatabaseAccessContext_Base(m_aMutex
)
168 ,m_aContext( _rxContext
)
169 ,m_aContainerListeners(m_aMutex
)
171 m_pDatabaseDocumentLoader
= new DatabaseDocumentLoader( _rxContext
);
173 #if HAVE_FEATURE_SCRIPTING
174 ::basic::BasicManagerRepository::registerCreationListener( *this );
177 osl_atomic_increment( &m_refCount
);
179 m_xDBRegistrationAggregate
.set( createDataSourceRegistrations( m_aContext
), UNO_SET_THROW
);
180 m_xDatabaseRegistrations
.set( m_xDBRegistrationAggregate
, UNO_QUERY_THROW
);
182 m_xDBRegistrationAggregate
->setDelegator( *this );
184 osl_atomic_decrement( &m_refCount
);
187 ODatabaseContext::~ODatabaseContext()
189 #if HAVE_FEATURE_SCRIPTING
190 ::basic::BasicManagerRepository::revokeCreationListener( *this );
193 if ( m_pDatabaseDocumentLoader
)
194 m_pDatabaseDocumentLoader
->release();
196 m_xDBRegistrationAggregate
->setDelegator( nullptr );
197 m_xDBRegistrationAggregate
.clear();
198 m_xDatabaseRegistrations
.clear();
202 OUString
ODatabaseContext::getImplementationName_static() throw( RuntimeException
)
204 return OUString("com.sun.star.comp.dba.ODatabaseContext");
207 Reference
< XInterface
> ODatabaseContext::Create(const Reference
< XComponentContext
>& _rxContext
)
209 return *( new ODatabaseContext( _rxContext
) );
212 Sequence
< OUString
> ODatabaseContext::getSupportedServiceNames_static() throw( RuntimeException
)
214 Sequence
<OUString
> aSNS
{ "com.sun.star.sdb.DatabaseContext" };
219 OUString
ODatabaseContext::getImplementationName( ) throw(RuntimeException
, std::exception
)
221 return getImplementationName_static();
224 sal_Bool
ODatabaseContext::supportsService( const OUString
& _rServiceName
) throw (RuntimeException
, std::exception
)
226 return cppu::supportsService(this, _rServiceName
);
229 Sequence
< OUString
> ODatabaseContext::getSupportedServiceNames( ) throw (RuntimeException
, std::exception
)
231 return getSupportedServiceNames_static();
234 Reference
< XInterface
> ODatabaseContext::impl_createNewDataSource()
236 ::rtl::Reference
<ODatabaseModelImpl
> pImpl( new ODatabaseModelImpl( m_aContext
, *this ) );
237 Reference
< XDataSource
> xDataSource( pImpl
->getOrCreateDataSource() );
239 return xDataSource
.get();
242 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstance( ) throw (Exception
, RuntimeException
, std::exception
)
244 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
245 // has been called at the DatabaseDocument).
246 return impl_createNewDataSource();
249 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstanceWithArguments( const Sequence
< Any
>& _rArguments
) throw (Exception
, RuntimeException
, std::exception
)
251 ::comphelper::NamedValueCollection
aArgs( _rArguments
);
252 OUString sURL
= aArgs
.getOrDefault( INFO_POOLURL
, OUString() );
254 Reference
< XInterface
> xDataSource
;
255 if ( !sURL
.isEmpty() )
256 xDataSource
= getObject( sURL
);
258 if ( !xDataSource
.is() )
259 xDataSource
= impl_createNewDataSource();
264 // DatabaseAccessContext_Base
265 void ODatabaseContext::disposing()
267 // notify our listener
268 css::lang::EventObject
aDisposeEvent(static_cast< XContainer
* >(this));
269 m_aContainerListeners
.disposeAndClear(aDisposeEvent
);
271 // dispose the data sources
272 // disposing seems to remove elements, so work on copy for valid iterators
273 ObjectCache
objCopy(m_aDatabaseObjects
);
274 ObjectCache::const_iterator
const aEnd
= objCopy
.end();
275 for ( ObjectCache::const_iterator aIter
= objCopy
.begin();
280 rtl::Reference
< ODatabaseModelImpl
> obj(aIter
->second
);
281 // make sure obj is acquired and does not delete itself from within
285 m_aDatabaseObjects
.clear();
289 Reference
< XInterface
> ODatabaseContext::getRegisteredObject(const OUString
& _rName
) throw( Exception
, RuntimeException
, std::exception
)
291 MutexGuard
aGuard(m_aMutex
);
292 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
294 OUString
sURL( getDatabaseLocation( _rName
) );
296 if ( sURL
.isEmpty() )
297 // there is a registration for this name, but no URL
298 throw IllegalArgumentException();
300 // check if URL is already loaded
301 Reference
< XInterface
> xExistent
= getObject( sURL
);
302 if ( xExistent
.is() )
305 return loadObjectFromURL( _rName
, sURL
);
308 Reference
< XInterface
> ODatabaseContext::loadObjectFromURL(const OUString
& _rName
,const OUString
& _sURL
)
310 INetURLObject
aURL( _sURL
);
312 if ( aURL
.GetProtocol() == INetProtocol::NotValid
)
313 throw NoSuchElementException( _rName
, *this );
315 bool bEmbeddedDataSource
= _sURL
.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:");
318 if (!bEmbeddedDataSource
)
320 ::ucbhelper::Content
aContent( _sURL
, nullptr, comphelper::getProcessComponentContext() );
321 if ( !aContent
.isDocument() )
322 throw InteractiveIOException(
323 _sURL
, *this, InteractionClassification_ERROR
, IOErrorCode_NO_FILE
327 catch ( const InteractiveIOException
& e
)
329 if ( ( e
.Code
== IOErrorCode_NO_FILE
)
330 || ( e
.Code
== IOErrorCode_NOT_EXISTING
)
331 || ( e
.Code
== IOErrorCode_NOT_EXISTING_PATH
)
335 OUString
sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST
) );
336 ::svt::OFileNotation
aTransformer( _sURL
);
339 aError
.Message
= sErrorMessage
.replaceAll( "$file$", aTransformer
.get( ::svt::OFileNotation::N_SYSTEM
) );
341 throw WrappedTargetException( _sURL
, *this, makeAny( aError
) );
343 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
345 catch( const Exception
& )
347 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
350 OSL_ENSURE( m_aDatabaseObjects
.find( _sURL
) == m_aDatabaseObjects
.end(),
351 "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
353 ::rtl::Reference
< ODatabaseModelImpl
> pModelImpl
;
355 pModelImpl
.set( new ODatabaseModelImpl( _rName
, m_aContext
, *this ) );
357 Reference
< XModel
> xModel( pModelImpl
->createNewModel_deliverOwnership(), UNO_SET_THROW
);
358 Reference
< XLoadable
> xLoad( xModel
, UNO_QUERY_THROW
);
360 ::comphelper::NamedValueCollection aArgs
;
361 aArgs
.put( "URL", _sURL
);
362 aArgs
.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG
);
363 aArgs
.put( "InteractionHandler", task::InteractionHandler::createWithParent(m_aContext
, nullptr) );
364 if (bEmbeddedDataSource
)
366 // In this case the host contains the real path, and the path is the embedded stream name.
367 OUString sBaseURI
= aURL
.GetHost(INetURLObject::DecodeMechanism::WithCharset
) + aURL
.GetURLPath(INetURLObject::DecodeMechanism::WithCharset
);
368 aArgs
.put("BaseURI", sBaseURI
);
371 Sequence
< PropertyValue
> aResource( aArgs
.getPropertyValues() );
372 xLoad
->load( aResource
);
373 xModel
->attachResource( _sURL
, aResource
);
375 ::utl::CloseableComponent
aEnsureClose( xModel
);
378 setTransientProperties( _sURL
, *pModelImpl
);
380 return pModelImpl
->getOrCreateDataSource().get();
383 void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
385 m_pDatabaseDocumentLoader
->append(_rDataSourceModel
);
388 void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
390 m_pDatabaseDocumentLoader
->remove(_rDataSourceModel
);
393 void ODatabaseContext::setTransientProperties(const OUString
& _sURL
, ODatabaseModelImpl
& _rDataSourceModel
)
395 if ( m_aDatasourceProperties
.end() == m_aDatasourceProperties
.find(_sURL
) )
399 OUString sAuthFailedPassword
;
400 Reference
< XPropertySet
> xDSProps( _rDataSourceModel
.getOrCreateDataSource(), UNO_QUERY_THROW
);
401 const Sequence
< PropertyValue
>& rSessionPersistentProps
= m_aDatasourceProperties
[_sURL
];
402 const PropertyValue
* pProp
= rSessionPersistentProps
.getConstArray();
403 const PropertyValue
* pPropsEnd
= rSessionPersistentProps
.getConstArray() + rSessionPersistentProps
.getLength();
404 for ( ; pProp
!= pPropsEnd
; ++pProp
)
406 if ( pProp
->Name
== "AuthFailedPassword" )
408 OSL_VERIFY( pProp
->Value
>>= sAuthFailedPassword
);
412 xDSProps
->setPropertyValue( pProp
->Name
, pProp
->Value
);
416 _rDataSourceModel
.m_sFailedPassword
= sAuthFailedPassword
;
418 catch( const Exception
& )
420 DBG_UNHANDLED_EXCEPTION();
424 void ODatabaseContext::registerObject(const OUString
& _rName
, const Reference
< XInterface
> & _rxObject
) throw( Exception
, RuntimeException
, std::exception
)
426 MutexGuard
aGuard(m_aMutex
);
427 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
429 if ( _rName
.isEmpty() )
430 throw IllegalArgumentException( OUString(), *this, 1 );
432 Reference
< XDocumentDataSource
> xDocDataSource( _rxObject
, UNO_QUERY
);
433 Reference
< XModel
> xModel( xDocDataSource
.is() ? xDocDataSource
->getDatabaseDocument() : Reference
< XOfficeDatabaseDocument
>(), UNO_QUERY
);
435 throw IllegalArgumentException( OUString(), *this, 2 );
437 OUString sURL
= xModel
->getURL();
438 if ( sURL
.isEmpty() )
439 throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED
), *this, 2 );
441 registerDatabaseLocation( _rName
, sURL
);
443 ODatabaseSource::setName( xDocDataSource
, _rName
, ODatabaseSource::DBContextAccess() );
445 // notify our container listeners
446 ContainerEvent
aEvent(static_cast<XContainer
*>(this), makeAny(_rName
), makeAny(_rxObject
), Any());
447 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
450 void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl
& _rModelImpl
)
452 Reference
< XPropertySet
> xSource( _rModelImpl
.getOrCreateDataSource(), UNO_QUERY
);
453 ::comphelper::NamedValueCollection aRememberProps
;
457 // get the info about the properties, check which ones are transient and not readonly
458 Reference
< XPropertySetInfo
> xSetInfo
;
460 xSetInfo
= xSource
->getPropertySetInfo();
461 Sequence
< Property
> aProperties
;
463 aProperties
= xSetInfo
->getProperties();
465 if (aProperties
.getLength())
467 const Property
* pProperties
= aProperties
.getConstArray();
468 for ( sal_Int32 i
=0; i
<aProperties
.getLength(); ++i
, ++pProperties
)
470 if ( ( ( pProperties
->Attributes
& PropertyAttribute::TRANSIENT
) != 0 )
471 && ( ( pProperties
->Attributes
& PropertyAttribute::READONLY
) == 0 )
474 // found such a property
475 aRememberProps
.put( pProperties
->Name
, xSource
->getPropertyValue( pProperties
->Name
) );
480 catch ( const Exception
& )
482 DBG_UNHANDLED_EXCEPTION();
485 // additionally, remember the "failed password", which is not available as property
487 aRememberProps
.put( "AuthFailedPassword", _rModelImpl
.m_sFailedPassword
);
489 OUString
sDocumentURL( _rModelImpl
.getURL() );
490 if ( m_aDatabaseObjects
.find( sDocumentURL
) != m_aDatabaseObjects
.end() )
492 m_aDatasourceProperties
[ sDocumentURL
] = aRememberProps
.getPropertyValues();
494 else if ( m_aDatabaseObjects
.find( _rModelImpl
.m_sName
) != m_aDatabaseObjects
.end() )
496 OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
497 // all the code should have been changed so that registration is by URL only
498 m_aDatasourceProperties
[ _rModelImpl
.m_sName
] = aRememberProps
.getPropertyValues();
502 OSL_ENSURE( sDocumentURL
.isEmpty() && _rModelImpl
.m_sName
.isEmpty() ,
503 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
507 void SAL_CALL
ODatabaseContext::addContainerListener( const Reference
< XContainerListener
>& _rxListener
) throw(RuntimeException
, std::exception
)
509 m_aContainerListeners
.addInterface(_rxListener
);
512 void SAL_CALL
ODatabaseContext::removeContainerListener( const Reference
< XContainerListener
>& _rxListener
) throw(RuntimeException
, std::exception
)
514 m_aContainerListeners
.removeInterface(_rxListener
);
517 void ODatabaseContext::revokeObject(const OUString
& _rName
) throw( Exception
, RuntimeException
, std::exception
)
519 ClearableMutexGuard
aGuard(m_aMutex
);
520 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
522 OUString sURL
= getDatabaseLocation( _rName
);
524 revokeDatabaseLocation( _rName
);
525 // will throw if something goes wrong
527 if ( m_aDatabaseObjects
.find( _rName
) != m_aDatabaseObjects
.end() )
529 m_aDatasourceProperties
[ sURL
] = m_aDatasourceProperties
[ _rName
];
532 // check if URL is already loaded
533 ObjectCache::const_iterator aExistent
= m_aDatabaseObjects
.find( sURL
);
534 if ( aExistent
!= m_aDatabaseObjects
.end() )
535 m_aDatabaseObjects
.erase( aExistent
);
537 // notify our container listeners
538 ContainerEvent
aEvent( *this, makeAny( _rName
), Any(), Any() );
540 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, aEvent
);
543 sal_Bool SAL_CALL
ODatabaseContext::hasRegisteredDatabase( const OUString
& Name
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
545 return m_xDatabaseRegistrations
->hasRegisteredDatabase( Name
);
548 Sequence
< OUString
> SAL_CALL
ODatabaseContext::getRegistrationNames() throw (RuntimeException
, std::exception
)
550 return m_xDatabaseRegistrations
->getRegistrationNames();
553 OUString SAL_CALL
ODatabaseContext::getDatabaseLocation( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
555 return m_xDatabaseRegistrations
->getDatabaseLocation( Name
);
558 void SAL_CALL
ODatabaseContext::registerDatabaseLocation( const OUString
& Name
, const OUString
& Location
) throw (IllegalArgumentException
, ElementExistException
, RuntimeException
, std::exception
)
560 m_xDatabaseRegistrations
->registerDatabaseLocation( Name
, Location
);
563 void SAL_CALL
ODatabaseContext::revokeDatabaseLocation( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
565 m_xDatabaseRegistrations
->revokeDatabaseLocation( Name
);
568 void SAL_CALL
ODatabaseContext::changeDatabaseLocation( const OUString
& Name
, const OUString
& NewLocation
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
570 m_xDatabaseRegistrations
->changeDatabaseLocation( Name
, NewLocation
);
573 sal_Bool SAL_CALL
ODatabaseContext::isDatabaseRegistrationReadOnly( const OUString
& Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
575 return m_xDatabaseRegistrations
->isDatabaseRegistrationReadOnly( Name
);
578 void SAL_CALL
ODatabaseContext::addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
)
580 m_xDatabaseRegistrations
->addDatabaseRegistrationsListener( Listener
);
583 void SAL_CALL
ODatabaseContext::removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& Listener
) throw (RuntimeException
, std::exception
)
585 m_xDatabaseRegistrations
->removeDatabaseRegistrationsListener( Listener
);
588 // css::container::XElementAccess
589 Type
ODatabaseContext::getElementType( ) throw(RuntimeException
, std::exception
)
591 return cppu::UnoType
<XDataSource
>::get();
594 sal_Bool
ODatabaseContext::hasElements() throw( RuntimeException
, std::exception
)
596 MutexGuard
aGuard(m_aMutex
);
597 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
599 return 0 != getElementNames().getLength();
602 // css::container::XEnumerationAccess
603 Reference
< css::container::XEnumeration
> ODatabaseContext::createEnumeration() throw( RuntimeException
, std::exception
)
605 MutexGuard
aGuard(m_aMutex
);
606 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess
*>(this));
609 // css::container::XNameAccess
610 Any
ODatabaseContext::getByName(const OUString
& _rName
) throw( NoSuchElementException
,
611 WrappedTargetException
, RuntimeException
, std::exception
)
613 MutexGuard
aGuard(m_aMutex
);
614 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
615 if ( _rName
.isEmpty() )
616 throw NoSuchElementException(_rName
, *this);
620 Reference
< XInterface
> xExistent
= getObject( _rName
);
621 if ( xExistent
.is() )
622 return makeAny( xExistent
);
624 // see whether this is an registered name
626 if ( hasRegisteredDatabase( _rName
) )
628 sURL
= getDatabaseLocation( _rName
);
629 // is the object cached under its URL?
630 xExistent
= getObject( sURL
);
633 // interpret the name as URL
636 if ( !xExistent
.is() )
637 // try to load this as URL
638 xExistent
= loadObjectFromURL( _rName
, sURL
);
639 return makeAny( xExistent
);
641 catch (const NoSuchElementException
&)
642 { // let these exceptions through
645 catch (const WrappedTargetException
&)
646 { // let these exceptions through
649 catch (const RuntimeException
&)
650 { // let these exceptions through
653 catch (const Exception
&)
654 { // exceptions other than the speciafied ones -> wrap
655 Any aError
= ::cppu::getCaughtException();
656 throw WrappedTargetException(_rName
, *this, aError
);
660 Sequence
< OUString
> ODatabaseContext::getElementNames() throw( RuntimeException
, std::exception
)
662 MutexGuard
aGuard(m_aMutex
);
663 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
665 return getRegistrationNames();
668 sal_Bool
ODatabaseContext::hasByName(const OUString
& _rName
) throw( RuntimeException
, std::exception
)
670 MutexGuard
aGuard(m_aMutex
);
671 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
673 return hasRegisteredDatabase( _rName
);
676 Reference
< XInterface
> ODatabaseContext::getObject( const OUString
& _rURL
)
678 ObjectCache::const_iterator aFind
= m_aDatabaseObjects
.find( _rURL
);
679 Reference
< XInterface
> xExistent
;
680 if ( aFind
!= m_aDatabaseObjects
.end() )
681 xExistent
= aFind
->second
->getOrCreateDataSource();
685 void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl
& _rModelImpl
)
687 OUString
sURL( _rModelImpl
.getURL() );
688 SAL_INFO("dbaccess.core", "DatabaseContext: registering " << sURL
);
689 if ( m_aDatabaseObjects
.find( sURL
) == m_aDatabaseObjects
.end() )
691 m_aDatabaseObjects
[ sURL
] = &_rModelImpl
;
692 setTransientProperties( sURL
, _rModelImpl
);
695 OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
698 void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl
& _rModelImpl
)
700 const OUString
& sURL( _rModelImpl
.getURL() );
701 SAL_INFO("dbaccess.core", "DatabaseContext: deregistering " << sURL
);
702 m_aDatabaseObjects
.erase( sURL
);
705 void ODatabaseContext::databaseDocumentURLChange( const OUString
& _rOldURL
, const OUString
& _rNewURL
)
707 SAL_INFO("dbaccess.core", "DatabaseContext: changing registrations from " << _rOldURL
<<
709 ObjectCache::const_iterator oldPos
= m_aDatabaseObjects
.find( _rOldURL
);
710 ENSURE_OR_THROW( oldPos
!= m_aDatabaseObjects
.end(), "illegal old database document URL" );
711 ObjectCache::const_iterator newPos
= m_aDatabaseObjects
.find( _rNewURL
);
712 ENSURE_OR_THROW( newPos
== m_aDatabaseObjects
.end(), "illegal new database document URL" );
714 m_aDatabaseObjects
[ _rNewURL
] = oldPos
->second
;
715 m_aDatabaseObjects
.erase( oldPos
);
718 sal_Int64 SAL_CALL
ODatabaseContext::getSomething( const Sequence
< sal_Int8
>& rId
) throw(RuntimeException
, std::exception
)
720 if (rId
.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
721 return reinterpret_cast<sal_Int64
>(this);
726 Sequence
< sal_Int8
> ODatabaseContext::getUnoTunnelImplementationId()
728 static ::cppu::OImplementationId
* pId
= nullptr;
731 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
734 static ::cppu::OImplementationId aId
;
738 return pId
->getImplementationId();
741 void ODatabaseContext::onBasicManagerCreated( const Reference
< XModel
>& _rxForDocument
, BasicManager
& _rBasicManager
)
743 #if !HAVE_FEATURE_SCRIPTING
744 (void) _rxForDocument
;
745 (void) _rBasicManager
;
747 // if it's a database document ...
748 Reference
< XOfficeDatabaseDocument
> xDatabaseDocument( _rxForDocument
, UNO_QUERY
);
749 // ... or a sub document of a database document ...
750 if ( !xDatabaseDocument
.is() )
752 Reference
< XChild
> xDocAsChild( _rxForDocument
, UNO_QUERY
);
753 if ( xDocAsChild
.is() )
754 xDatabaseDocument
.set( xDocAsChild
->getParent(), UNO_QUERY
);
757 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
758 if ( xDatabaseDocument
.is() )
759 _rBasicManager
.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument
) );
763 } // namespace dbaccess
765 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */