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"
30 #include "module_dba.hxx"
32 #include <com/sun/star/beans/NamedValue.hpp>
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/document/MacroExecMode.hpp>
36 #include <com/sun/star/document/XFilter.hpp>
37 #include <com/sun/star/document/XImporter.hpp>
38 #include <com/sun/star/frame/Desktop.hpp>
39 #include <com/sun/star/frame/XModel.hpp>
40 #include <com/sun/star/frame/XModel2.hpp>
41 #include <com/sun/star/frame/XTerminateListener.hpp>
42 #include <com/sun/star/lang/DisposedException.hpp>
43 #include <com/sun/star/registry/InvalidRegistryException.hpp>
44 #include <com/sun/star/sdbc/XDataSource.hpp>
45 #include <com/sun/star/task/InteractionClassification.hpp>
46 #include <com/sun/star/ucb/InteractiveIOException.hpp>
47 #include <com/sun/star/ucb/IOErrorCode.hpp>
48 #include <com/sun/star/task/InteractionHandler.hpp>
49 #include <com/sun/star/util/XCloseable.hpp>
51 #include <basic/basmgr.hxx>
52 #include <comphelper/enumhelper.hxx>
53 #include <comphelper/evtlistenerhlp.hxx>
54 #include <comphelper/namedvaluecollection.hxx>
55 #include <comphelper/processfactory.hxx>
56 #include <comphelper/sequence.hxx>
57 #include <cppuhelper/implbase1.hxx>
58 #include <cppuhelper/supportsservice.hxx>
59 #include <cppuhelper/typeprovider.hxx>
60 #include <cppuhelper/exc_hlp.hxx>
61 #include <svl/filenotation.hxx>
62 #include <tools/debug.hxx>
63 #include <tools/diagnose_ex.h>
64 #include <tools/urlobj.hxx>
65 #include <ucbhelper/content.hxx>
66 #include <unotools/confignode.hxx>
67 #include <unotools/pathoptions.hxx>
68 #include <unotools/sharedunocomponent.hxx>
71 using namespace ::com::sun::star::sdbc
;
72 using namespace ::com::sun::star::sdb
;
73 using namespace ::com::sun::star::beans
;
74 using namespace ::com::sun::star::uno
;
75 using namespace ::com::sun::star::document
;
76 using namespace ::com::sun::star::frame
;
77 using namespace ::com::sun::star::lang
;
78 using namespace ::com::sun::star::container
;
79 using namespace ::com::sun::star::util
;
80 using namespace ::com::sun::star::registry
;
81 using namespace ::com::sun::star
;
82 using namespace ::cppu
;
83 using namespace ::osl
;
84 using namespace ::utl
;
86 using ::com::sun::star::task::InteractionClassification_ERROR
;
87 using ::com::sun::star::ucb::IOErrorCode_NO_FILE
;
88 using ::com::sun::star::ucb::InteractiveIOException
;
89 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING
;
90 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH
;
95 typedef ::cppu::WeakImplHelper1
< XTerminateListener
96 > DatabaseDocumentLoader_Base
;
97 class DatabaseDocumentLoader
: public DatabaseDocumentLoader_Base
100 Reference
< XDesktop2
> m_xDesktop
;
101 ::std::list
< const ODatabaseModelImpl
* > m_aDatabaseDocuments
;
104 DatabaseDocumentLoader( const Reference
<XComponentContext
> & rxContext
);
106 inline void append(const ODatabaseModelImpl
& _rModelImpl
)
108 m_aDatabaseDocuments
.push_back(&_rModelImpl
);
110 inline void remove(const ODatabaseModelImpl
& _rModelImpl
) { m_aDatabaseDocuments
.remove(&_rModelImpl
); }
113 // XTerminateListener
114 virtual void SAL_CALL
queryTermination( const lang::EventObject
& Event
) throw (TerminationVetoException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
115 virtual void SAL_CALL
notifyTermination( const lang::EventObject
& Event
) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
117 virtual void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& Source
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
120 DatabaseDocumentLoader::DatabaseDocumentLoader( const Reference
<XComponentContext
> & rxContext
)
125 m_xDesktop
.set( Desktop::create(rxContext
) );
126 m_xDesktop
->addTerminateListener( this );
128 catch( const Exception
& )
130 DBG_UNHANDLED_EXCEPTION();
134 struct TerminateFunctor
: ::std::unary_function
<ODatabaseModelImpl
* , void>
136 void operator()( const ODatabaseModelImpl
* _pModelImpl
) const
140 const Reference
< XModel2
> xModel( _pModelImpl
->getModel_noCreate(),UNO_QUERY_THROW
);
141 if ( !xModel
->getControllers()->hasMoreElements() )
143 Reference
<util::XCloseable
> xCloseable(xModel
,UNO_QUERY_THROW
);
144 xCloseable
->close(sal_False
);
147 catch(const CloseVetoException
&)
149 throw TerminationVetoException();
154 void SAL_CALL
DatabaseDocumentLoader::queryTermination( const lang::EventObject
& /*Event*/ ) throw (TerminationVetoException
, RuntimeException
, std::exception
)
156 ::std::list
< const ODatabaseModelImpl
* > aCopy(m_aDatabaseDocuments
);
157 ::std::for_each(aCopy
.begin(),aCopy
.end(),TerminateFunctor());
160 void SAL_CALL
DatabaseDocumentLoader::notifyTermination( const lang::EventObject
& /*Event*/ ) throw (RuntimeException
, std::exception
)
164 void SAL_CALL
DatabaseDocumentLoader::disposing( const lang::EventObject
& /*Source*/ ) throw (RuntimeException
, std::exception
)
170 ODatabaseContext::ODatabaseContext( const Reference
< XComponentContext
>& _rxContext
)
171 :DatabaseAccessContext_Base(m_aMutex
)
172 ,m_aContext( _rxContext
)
173 ,m_aContainerListeners(m_aMutex
)
175 m_pDatabaseDocumentLoader
= new DatabaseDocumentLoader( _rxContext
);
177 #if HAVE_FEATURE_SCRIPTING
178 ::basic::BasicManagerRepository::registerCreationListener( *this );
181 osl_atomic_increment( &m_refCount
);
183 m_xDBRegistrationAggregate
.set( createDataSourceRegistrations( m_aContext
), UNO_SET_THROW
);
184 m_xDatabaseRegistrations
.set( m_xDBRegistrationAggregate
, UNO_QUERY_THROW
);
186 m_xDBRegistrationAggregate
->setDelegator( *this );
188 osl_atomic_decrement( &m_refCount
);
191 ODatabaseContext::~ODatabaseContext()
193 #if HAVE_FEATURE_SCRIPTING
194 ::basic::BasicManagerRepository::revokeCreationListener( *this );
197 if ( m_pDatabaseDocumentLoader
)
198 m_pDatabaseDocumentLoader
->release();
200 m_xDBRegistrationAggregate
->setDelegator( NULL
);
201 m_xDBRegistrationAggregate
.clear();
202 m_xDatabaseRegistrations
.clear();
206 OUString
ODatabaseContext::getImplementationName_static() throw( RuntimeException
)
208 return OUString("com.sun.star.comp.dba.ODatabaseContext");
211 Reference
< XInterface
> ODatabaseContext::Create(const Reference
< XComponentContext
>& _rxContext
)
213 return *( new ODatabaseContext( _rxContext
) );
216 Sequence
< OUString
> ODatabaseContext::getSupportedServiceNames_static() throw( RuntimeException
)
218 Sequence
< OUString
> aSNS( 1 );
219 aSNS
[0] = "com.sun.star.sdb.DatabaseContext";
224 OUString
ODatabaseContext::getImplementationName( ) throw(RuntimeException
, std::exception
)
226 return getImplementationName_static();
229 sal_Bool
ODatabaseContext::supportsService( const OUString
& _rServiceName
) throw (RuntimeException
, std::exception
)
231 return cppu::supportsService(this, _rServiceName
);
234 Sequence
< OUString
> ODatabaseContext::getSupportedServiceNames( ) throw (RuntimeException
, std::exception
)
236 return getSupportedServiceNames_static();
239 Reference
< XInterface
> ODatabaseContext::impl_createNewDataSource()
241 ::rtl::Reference
<ODatabaseModelImpl
> pImpl( new ODatabaseModelImpl( m_aContext
, *this ) );
242 Reference
< XDataSource
> xDataSource( pImpl
->getOrCreateDataSource() );
244 return xDataSource
.get();
247 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstance( ) throw (Exception
, RuntimeException
, std::exception
)
249 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
250 // has been called at the DatabaseDocument).
251 return impl_createNewDataSource();
254 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstanceWithArguments( const Sequence
< Any
>& _rArguments
) throw (Exception
, RuntimeException
, std::exception
)
256 ::comphelper::NamedValueCollection
aArgs( _rArguments
);
257 OUString sURL
= aArgs
.getOrDefault( OUString(INFO_POOLURL
), OUString() );
259 Reference
< XInterface
> xDataSource
;
260 if ( !sURL
.isEmpty() )
261 xDataSource
= getObject( sURL
);
263 if ( !xDataSource
.is() )
264 xDataSource
= impl_createNewDataSource();
269 // DatabaseAccessContext_Base
270 void ODatabaseContext::disposing()
272 // notify our listener
273 com::sun::star::lang::EventObject
aDisposeEvent(static_cast< XContainer
* >(this));
274 m_aContainerListeners
.disposeAndClear(aDisposeEvent
);
276 // dispose the data sources
277 // disposing seems to remove elements, so work on copy for valid iterators
278 ObjectCache
objCopy(m_aDatabaseObjects
);
279 ObjectCache::iterator
const aEnd
= objCopy
.end();
280 for ( ObjectCache::iterator aIter
= objCopy
.begin();
285 rtl::Reference
< ODatabaseModelImpl
> obj(aIter
->second
);
286 // make sure obj is acquired and does not delete itself from within
290 m_aDatabaseObjects
.clear();
294 Reference
< XInterface
> ODatabaseContext::getRegisteredObject(const OUString
& _rName
) throw( Exception
, RuntimeException
, std::exception
)
296 MutexGuard
aGuard(m_aMutex
);
297 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
299 OUString
sURL( getDatabaseLocation( _rName
) );
301 if ( sURL
.isEmpty() )
302 // there is a registration for this name, but no URL
303 throw IllegalArgumentException();
305 // check if URL is already loaded
306 Reference
< XInterface
> xExistent
= getObject( sURL
);
307 if ( xExistent
.is() )
310 return loadObjectFromURL( _rName
, sURL
);
313 Reference
< XInterface
> ODatabaseContext::loadObjectFromURL(const OUString
& _rName
,const OUString
& _sURL
)
315 INetURLObject
aURL( _sURL
);
317 if ( aURL
.GetProtocol() == INetProtocol::NotValid
)
318 throw NoSuchElementException( _rName
, *this );
322 ::ucbhelper::Content
aContent( _sURL
, NULL
, comphelper::getProcessComponentContext() );
323 bool bEmbeddedDataSource
= _sURL
.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:");
324 if ( !aContent
.isDocument() && !bEmbeddedDataSource
)
325 throw InteractiveIOException(
326 _sURL
, *this, InteractionClassification_ERROR
, IOErrorCode_NO_FILE
329 catch ( const InteractiveIOException
& e
)
331 if ( ( e
.Code
== IOErrorCode_NO_FILE
)
332 || ( e
.Code
== IOErrorCode_NOT_EXISTING
)
333 || ( e
.Code
== IOErrorCode_NOT_EXISTING_PATH
)
337 OUString
sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST
) );
338 ::svt::OFileNotation
aTransformer( _sURL
);
341 aError
.Message
= sErrorMessage
.replaceAll( "$file$", aTransformer
.get( ::svt::OFileNotation::N_SYSTEM
) );
343 throw WrappedTargetException( _sURL
, *this, makeAny( aError
) );
345 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
347 catch( const Exception
& )
349 throw WrappedTargetException( _sURL
, *this, ::cppu::getCaughtException() );
352 OSL_ENSURE( m_aDatabaseObjects
.find( _sURL
) == m_aDatabaseObjects
.end(),
353 "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
355 ::rtl::Reference
< ODatabaseModelImpl
> pModelImpl
;
357 pModelImpl
.set( new ODatabaseModelImpl( _rName
, m_aContext
, *this ) );
359 Reference
< XModel
> xModel( pModelImpl
->createNewModel_deliverOwnership( false ), UNO_SET_THROW
);
360 Reference
< XLoadable
> xLoad( xModel
, UNO_QUERY_THROW
);
362 ::comphelper::NamedValueCollection aArgs
;
363 aArgs
.put( "URL", _sURL
);
364 aArgs
.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG
);
365 aArgs
.put( "InteractionHandler", task::InteractionHandler::createWithParent(m_aContext
, 0) );
367 Sequence
< PropertyValue
> aResource( aArgs
.getPropertyValues() );
368 xLoad
->load( aResource
);
369 xModel
->attachResource( _sURL
, aResource
);
371 ::utl::CloseableComponent
aEnsureClose( xModel
);
374 setTransientProperties( _sURL
, *pModelImpl
);
376 return pModelImpl
->getOrCreateDataSource().get();
379 void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
381 m_pDatabaseDocumentLoader
->append(_rDataSourceModel
);
384 void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
386 m_pDatabaseDocumentLoader
->remove(_rDataSourceModel
);
389 void ODatabaseContext::setTransientProperties(const OUString
& _sURL
, ODatabaseModelImpl
& _rDataSourceModel
)
391 if ( m_aDatasourceProperties
.end() == m_aDatasourceProperties
.find(_sURL
) )
395 OUString sAuthFailedPassword
;
396 Reference
< XPropertySet
> xDSProps( _rDataSourceModel
.getOrCreateDataSource(), UNO_QUERY_THROW
);
397 const Sequence
< PropertyValue
>& rSessionPersistentProps
= m_aDatasourceProperties
[_sURL
];
398 const PropertyValue
* pProp
= rSessionPersistentProps
.getConstArray();
399 const PropertyValue
* pPropsEnd
= rSessionPersistentProps
.getConstArray() + rSessionPersistentProps
.getLength();
400 for ( ; pProp
!= pPropsEnd
; ++pProp
)
402 if ( pProp
->Name
== "AuthFailedPassword" )
404 OSL_VERIFY( pProp
->Value
>>= sAuthFailedPassword
);
408 xDSProps
->setPropertyValue( pProp
->Name
, pProp
->Value
);
412 _rDataSourceModel
.m_sFailedPassword
= sAuthFailedPassword
;
414 catch( const Exception
& )
416 DBG_UNHANDLED_EXCEPTION();
420 void ODatabaseContext::registerObject(const OUString
& _rName
, const Reference
< XInterface
> & _rxObject
) throw( Exception
, RuntimeException
, std::exception
)
422 MutexGuard
aGuard(m_aMutex
);
423 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
425 if ( _rName
.isEmpty() )
426 throw IllegalArgumentException( OUString(), *this, 1 );
428 Reference
< XDocumentDataSource
> xDocDataSource( _rxObject
, UNO_QUERY
);
429 Reference
< XModel
> xModel( xDocDataSource
.is() ? xDocDataSource
->getDatabaseDocument() : Reference
< XOfficeDatabaseDocument
>(), UNO_QUERY
);
431 throw IllegalArgumentException( OUString(), *this, 2 );
433 OUString sURL
= xModel
->getURL();
434 if ( sURL
.isEmpty() )
435 throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED
), *this, 2 );
437 registerDatabaseLocation( _rName
, sURL
);
439 ODatabaseSource::setName( xDocDataSource
, _rName
, ODatabaseSource::DBContextAccess() );
441 // notify our container listeners
442 ContainerEvent
aEvent(static_cast<XContainer
*>(this), makeAny(_rName
), makeAny(_rxObject
), Any());
443 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
446 void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl
& _rModelImpl
)
448 Reference
< XPropertySet
> xSource( _rModelImpl
.getOrCreateDataSource(), UNO_QUERY
);
449 ::comphelper::NamedValueCollection aRememberProps
;
453 // get the info about the properties, check which ones are transient and not readonly
454 Reference
< XPropertySetInfo
> xSetInfo
;
456 xSetInfo
= xSource
->getPropertySetInfo();
457 Sequence
< Property
> aProperties
;
459 aProperties
= xSetInfo
->getProperties();
461 if (aProperties
.getLength())
463 const Property
* pProperties
= aProperties
.getConstArray();
464 for ( sal_Int32 i
=0; i
<aProperties
.getLength(); ++i
, ++pProperties
)
466 if ( ( ( pProperties
->Attributes
& PropertyAttribute::TRANSIENT
) != 0 )
467 && ( ( pProperties
->Attributes
& PropertyAttribute::READONLY
) == 0 )
470 // found such a property
471 aRememberProps
.put( pProperties
->Name
, xSource
->getPropertyValue( pProperties
->Name
) );
476 catch ( const Exception
& )
478 DBG_UNHANDLED_EXCEPTION();
481 // additionally, remember the "failed password", which is not available as property
483 aRememberProps
.put( "AuthFailedPassword", _rModelImpl
.m_sFailedPassword
);
485 OUString
sDocumentURL( _rModelImpl
.getURL() );
486 if ( m_aDatabaseObjects
.find( sDocumentURL
) != m_aDatabaseObjects
.end() )
488 m_aDatasourceProperties
[ sDocumentURL
] = aRememberProps
.getPropertyValues();
490 else if ( m_aDatabaseObjects
.find( _rModelImpl
.m_sName
) != m_aDatabaseObjects
.end() )
492 OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
493 // all the code should have been changed so that registration is by URL only
494 m_aDatasourceProperties
[ _rModelImpl
.m_sName
] = aRememberProps
.getPropertyValues();
498 OSL_ENSURE( sDocumentURL
.isEmpty() && _rModelImpl
.m_sName
.isEmpty() ,
499 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
503 void SAL_CALL
ODatabaseContext::addContainerListener( const Reference
< XContainerListener
>& _rxListener
) throw(RuntimeException
, std::exception
)
505 m_aContainerListeners
.addInterface(_rxListener
);
508 void SAL_CALL
ODatabaseContext::removeContainerListener( const Reference
< XContainerListener
>& _rxListener
) throw(RuntimeException
, std::exception
)
510 m_aContainerListeners
.removeInterface(_rxListener
);
513 void ODatabaseContext::revokeObject(const OUString
& _rName
) throw( Exception
, RuntimeException
, std::exception
)
515 ClearableMutexGuard
aGuard(m_aMutex
);
516 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
518 OUString sURL
= getDatabaseLocation( _rName
);
520 revokeDatabaseLocation( _rName
);
521 // will throw if something goes wrong
523 if ( m_aDatabaseObjects
.find( _rName
) != m_aDatabaseObjects
.end() )
525 m_aDatasourceProperties
[ sURL
] = m_aDatasourceProperties
[ _rName
];
528 // check if URL is already loaded
529 ObjectCache::iterator aExistent
= m_aDatabaseObjects
.find( sURL
);
530 if ( aExistent
!= m_aDatabaseObjects
.end() )
531 m_aDatabaseObjects
.erase( aExistent
);
533 // notify our container listeners
534 ContainerEvent
aEvent( *this, makeAny( _rName
), Any(), Any() );
536 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, aEvent
);
539 sal_Bool SAL_CALL
ODatabaseContext::hasRegisteredDatabase( const OUString
& _Name
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
541 return m_xDatabaseRegistrations
->hasRegisteredDatabase( _Name
);
544 Sequence
< OUString
> SAL_CALL
ODatabaseContext::getRegistrationNames() throw (RuntimeException
, std::exception
)
546 return m_xDatabaseRegistrations
->getRegistrationNames();
549 OUString SAL_CALL
ODatabaseContext::getDatabaseLocation( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
551 return m_xDatabaseRegistrations
->getDatabaseLocation( _Name
);
554 void SAL_CALL
ODatabaseContext::registerDatabaseLocation( const OUString
& _Name
, const OUString
& _Location
) throw (IllegalArgumentException
, ElementExistException
, RuntimeException
, std::exception
)
556 m_xDatabaseRegistrations
->registerDatabaseLocation( _Name
, _Location
);
559 void SAL_CALL
ODatabaseContext::revokeDatabaseLocation( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
561 m_xDatabaseRegistrations
->revokeDatabaseLocation( _Name
);
564 void SAL_CALL
ODatabaseContext::changeDatabaseLocation( const OUString
& _Name
, const OUString
& _NewLocation
) throw (IllegalArgumentException
, NoSuchElementException
, IllegalAccessException
, RuntimeException
, std::exception
)
566 m_xDatabaseRegistrations
->changeDatabaseLocation( _Name
, _NewLocation
);
569 sal_Bool SAL_CALL
ODatabaseContext::isDatabaseRegistrationReadOnly( const OUString
& _Name
) throw (IllegalArgumentException
, NoSuchElementException
, RuntimeException
, std::exception
)
571 return m_xDatabaseRegistrations
->isDatabaseRegistrationReadOnly( _Name
);
574 void SAL_CALL
ODatabaseContext::addDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& _Listener
) throw (RuntimeException
, std::exception
)
576 m_xDatabaseRegistrations
->addDatabaseRegistrationsListener( _Listener
);
579 void SAL_CALL
ODatabaseContext::removeDatabaseRegistrationsListener( const Reference
< XDatabaseRegistrationsListener
>& _Listener
) throw (RuntimeException
, std::exception
)
581 m_xDatabaseRegistrations
->removeDatabaseRegistrationsListener( _Listener
);
584 // ::com::sun::star::container::XElementAccess
585 Type
ODatabaseContext::getElementType( ) throw(RuntimeException
, std::exception
)
587 return cppu::UnoType
<XDataSource
>::get();
590 sal_Bool
ODatabaseContext::hasElements() throw( RuntimeException
, std::exception
)
592 MutexGuard
aGuard(m_aMutex
);
593 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
595 return 0 != getElementNames().getLength();
598 // ::com::sun::star::container::XEnumerationAccess
599 Reference
< ::com::sun::star::container::XEnumeration
> ODatabaseContext::createEnumeration() throw( RuntimeException
, std::exception
)
601 MutexGuard
aGuard(m_aMutex
);
602 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess
*>(this));
605 // ::com::sun::star::container::XNameAccess
606 Any
ODatabaseContext::getByName(const OUString
& _rName
) throw( NoSuchElementException
,
607 WrappedTargetException
, RuntimeException
, std::exception
)
609 MutexGuard
aGuard(m_aMutex
);
610 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
611 if ( _rName
.isEmpty() )
612 throw NoSuchElementException(_rName
, *this);
616 Reference
< XInterface
> xExistent
= getObject( _rName
);
617 if ( xExistent
.is() )
618 return makeAny( xExistent
);
620 // see whether this is an registered name
622 if ( hasRegisteredDatabase( _rName
) )
624 sURL
= getDatabaseLocation( _rName
);
625 // is the object cached under its URL?
626 xExistent
= getObject( sURL
);
629 // interpret the name as URL
632 if ( !xExistent
.is() )
633 // try to load this as URL
634 xExistent
= loadObjectFromURL( _rName
, sURL
);
635 return makeAny( xExistent
);
637 catch (const NoSuchElementException
&)
638 { // let these exceptions through
641 catch (const WrappedTargetException
&)
642 { // let these exceptions through
645 catch (const RuntimeException
&)
646 { // let these exceptions through
649 catch (const Exception
&)
650 { // exceptions other than the speciafied ones -> wrap
651 Any aError
= ::cppu::getCaughtException();
652 throw WrappedTargetException(_rName
, *this, aError
);
656 Sequence
< OUString
> ODatabaseContext::getElementNames() throw( RuntimeException
, std::exception
)
658 MutexGuard
aGuard(m_aMutex
);
659 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
661 return getRegistrationNames();
664 sal_Bool
ODatabaseContext::hasByName(const OUString
& _rName
) throw( RuntimeException
, std::exception
)
666 MutexGuard
aGuard(m_aMutex
);
667 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
669 return hasRegisteredDatabase( _rName
);
672 Reference
< XInterface
> ODatabaseContext::getObject( const OUString
& _rURL
)
674 ObjectCache::iterator aFind
= m_aDatabaseObjects
.find( _rURL
);
675 Reference
< XInterface
> xExistent
;
676 if ( aFind
!= m_aDatabaseObjects
.end() )
677 xExistent
= aFind
->second
->getOrCreateDataSource();
681 void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl
& _rModelImpl
)
683 OUString
sURL( _rModelImpl
.getURL() );
684 #if OSL_DEBUG_LEVEL > 1
685 OSL_TRACE( "DatabaseContext: registering %s", OUStringToOString( sURL
, RTL_TEXTENCODING_UTF8
).getStr() );
687 if ( m_aDatabaseObjects
.find( sURL
) == m_aDatabaseObjects
.end() )
689 m_aDatabaseObjects
[ sURL
] = &_rModelImpl
;
690 setTransientProperties( sURL
, _rModelImpl
);
693 OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
696 void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl
& _rModelImpl
)
698 OUString
sURL( _rModelImpl
.getURL() );
699 #if OSL_DEBUG_LEVEL > 1
700 OSL_TRACE( "DatabaseContext: deregistering %s", OUStringToOString( sURL
, RTL_TEXTENCODING_UTF8
).getStr() );
702 m_aDatabaseObjects
.erase( sURL
);
705 void ODatabaseContext::databaseDocumentURLChange( const OUString
& _rOldURL
, const OUString
& _rNewURL
)
707 #if OSL_DEBUG_LEVEL > 1
708 OSL_TRACE( "DatabaseContext: changing registration from %s to %s",
709 OUStringToOString( _rOldURL
, RTL_TEXTENCODING_UTF8
).getStr(),
710 OUStringToOString( _rNewURL
, RTL_TEXTENCODING_UTF8
).getStr() );
712 ObjectCache::iterator oldPos
= m_aDatabaseObjects
.find( _rOldURL
);
713 ENSURE_OR_THROW( oldPos
!= m_aDatabaseObjects
.end(), "illegal old database document URL" );
714 ObjectCache::iterator newPos
= m_aDatabaseObjects
.find( _rNewURL
);
715 ENSURE_OR_THROW( newPos
== m_aDatabaseObjects
.end(), "illegal new database document URL" );
717 m_aDatabaseObjects
[ _rNewURL
] = oldPos
->second
;
718 m_aDatabaseObjects
.erase( oldPos
);
721 sal_Int64 SAL_CALL
ODatabaseContext::getSomething( const Sequence
< sal_Int8
>& rId
) throw(RuntimeException
, std::exception
)
723 if (rId
.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
724 return reinterpret_cast<sal_Int64
>(this);
729 Sequence
< sal_Int8
> ODatabaseContext::getUnoTunnelImplementationId()
731 static ::cppu::OImplementationId
* pId
= 0;
734 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
737 static ::cppu::OImplementationId aId
;
741 return pId
->getImplementationId();
744 void ODatabaseContext::onBasicManagerCreated( const Reference
< XModel
>& _rxForDocument
, BasicManager
& _rBasicManager
)
746 #if !HAVE_FEATURE_SCRIPTING
747 (void) _rxForDocument
;
748 (void) _rBasicManager
;
750 // if it's a database document ...
751 Reference
< XOfficeDatabaseDocument
> xDatabaseDocument( _rxForDocument
, UNO_QUERY
);
752 // ... or a sub document of a database document ...
753 if ( !xDatabaseDocument
.is() )
755 Reference
< XChild
> xDocAsChild( _rxForDocument
, UNO_QUERY
);
756 if ( xDocAsChild
.is() )
757 xDatabaseDocument
.set( xDocAsChild
->getParent(), UNO_QUERY
);
760 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
761 if ( xDatabaseDocument
.is() )
762 _rBasicManager
.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument
) );
766 } // namespace dbaccess
768 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */