1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: databasecontext.cxx,v $
10 * $Revision: 1.43.4.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #include "apitools.hxx"
35 #include "core_resource.hrc"
36 #include "core_resource.hxx"
37 #include "databasecontext.hxx"
38 #include "databasedocument.hxx"
39 #include "datasource.hxx"
40 #include "dbastrings.hrc"
41 #include "module_dba.hxx"
43 /** === being UNO includes === **/
44 #include <com/sun/star/beans/NamedValue.hpp>
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/document/MacroExecMode.hpp>
48 #include <com/sun/star/document/XFilter.hpp>
49 #include <com/sun/star/document/XImporter.hpp>
50 #include <com/sun/star/frame/XDesktop.hpp>
51 #include <com/sun/star/frame/XModel.hpp>
52 #include <com/sun/star/frame/XModel2.hpp>
53 #include <com/sun/star/frame/XTerminateListener.hpp>
54 #include <com/sun/star/lang/DisposedException.hpp>
55 #include <com/sun/star/registry/InvalidRegistryException.hpp>
56 #include <com/sun/star/sdbc/XDataSource.hpp>
57 #include <com/sun/star/task/InteractionClassification.hpp>
58 #include <com/sun/star/ucb/InteractiveIOException.hpp>
59 #include <com/sun/star/ucb/IOErrorCode.hpp>
60 #include <com/sun/star/util/XCloseable.hpp>
61 /** === end UNO includes === **/
63 #include <basic/basmgr.hxx>
64 #include <comphelper/enumhelper.hxx>
65 #include <comphelper/evtlistenerhlp.hxx>
66 #include <comphelper/namedvaluecollection.hxx>
67 #include <comphelper/processfactory.hxx>
68 #include <comphelper/sequence.hxx>
69 #include <cppuhelper/implbase1.hxx>
70 #include <cppuhelper/typeprovider.hxx>
71 #include <cppuhelper/exc_hlp.hxx>
72 #include <svtools/filenotation.hxx>
73 #include <svtools/pathoptions.hxx>
74 #include <tools/debug.hxx>
75 #include <tools/diagnose_ex.h>
76 #include <tools/fsys.hxx>
77 #include <tools/urlobj.hxx>
78 #include <ucbhelper/content.hxx>
79 #include <unotools/confignode.hxx>
80 #include <unotools/sharedunocomponent.hxx>
82 #include <boost/bind.hpp>
84 using namespace ::com::sun::star::sdbc
;
85 using namespace ::com::sun::star::sdb
;
86 using namespace ::com::sun::star::beans
;
87 using namespace ::com::sun::star::uno
;
88 using namespace ::com::sun::star::document
;
89 using namespace ::com::sun::star::frame
;
90 using namespace ::com::sun::star::lang
;
91 using namespace ::com::sun::star::container
;
92 using namespace ::com::sun::star::util
;
93 using namespace ::com::sun::star::registry
;
94 using namespace ::com::sun::star
;
95 using namespace ::cppu
;
96 using namespace ::osl
;
97 using namespace ::utl
;
99 using ::com::sun::star::task::InteractionClassification_ERROR
;
100 using ::com::sun::star::ucb::IOErrorCode_NO_FILE
;
101 using ::com::sun::star::ucb::InteractiveIOException
;
102 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING
;
103 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH
;
105 //==========================================================================
107 extern "C" void SAL_CALL
createRegistryInfo_ODatabaseContext()
109 static ::dba::OLegacySingletonRegistration
< ::dbaccess::ODatabaseContext
> aODatabaseContext_AutoRegistration
;
112 //........................................................................
115 //........................................................................
119 //--------------------------------------------------------------------
120 const ::rtl::OUString
& getDbRegisteredNamesNodeName()
122 static ::rtl::OUString s_sNodeName
= ::rtl::OUString::createFromAscii("org.openoffice.Office.DataAccess/RegisteredNames");
126 //--------------------------------------------------------------------
127 const ::rtl::OUString
& getDbNameNodeName()
129 static ::rtl::OUString s_sNodeName
= ::rtl::OUString::createFromAscii("Name");
133 //--------------------------------------------------------------------
134 const ::rtl::OUString
& getDbLocationNodeName()
136 static ::rtl::OUString s_sNodeName
= ::rtl::OUString::createFromAscii("Location");
139 // -----------------------------------------------------------------------------
141 // .............................................................................
142 typedef ::cppu::WeakImplHelper1
< XTerminateListener
143 > DatabaseDocumentLoader_Base
;
144 class DatabaseDocumentLoader
: public DatabaseDocumentLoader_Base
147 Reference
< XDesktop
> m_xDesktop
;
148 ::std::list
< const ODatabaseModelImpl
* > m_aDatabaseDocuments
;
151 DatabaseDocumentLoader( const comphelper::ComponentContext
& _aContext
);
153 inline void append(const ODatabaseModelImpl
& _rModelImpl
)
155 m_aDatabaseDocuments
.push_back(&_rModelImpl
);
157 inline void remove(const ODatabaseModelImpl
& _rModelImpl
) { m_aDatabaseDocuments
.remove(&_rModelImpl
); }
160 // XTerminateListener
161 virtual void SAL_CALL
queryTermination( const lang::EventObject
& Event
) throw (TerminationVetoException
, RuntimeException
);
162 virtual void SAL_CALL
notifyTermination( const lang::EventObject
& Event
) throw (RuntimeException
);
164 virtual void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& Source
) throw (::com::sun::star::uno::RuntimeException
);
167 // .............................................................................
168 DatabaseDocumentLoader::DatabaseDocumentLoader( const comphelper::ComponentContext
& _aContext
)
173 m_xDesktop
.set( _aContext
.createComponent( (rtl::OUString
)SERVICE_FRAME_DESKTOP
), UNO_QUERY_THROW
);
174 m_xDesktop
->addTerminateListener( this );
176 catch( const Exception
& )
178 DBG_UNHANDLED_EXCEPTION();
182 struct TerminateFunctor
: ::std::unary_function
<ODatabaseModelImpl
* , void>
184 void operator()( const ODatabaseModelImpl
* _pModelImpl
) const
188 const Reference
< XModel2
> xModel( _pModelImpl
->getModel_noCreate(),UNO_QUERY_THROW
);
189 if ( !xModel
->getControllers()->hasMoreElements() )
191 Reference
<util::XCloseable
> xCloseable(xModel
,UNO_QUERY_THROW
);
192 xCloseable
->close(sal_False
);
193 } // if ( !xModel->getControllers()->hasMoreElements() )
195 catch(const CloseVetoException
&)
197 throw TerminationVetoException();
201 // .............................................................................
202 void SAL_CALL
DatabaseDocumentLoader::queryTermination( const lang::EventObject
& /*Event*/ ) throw (TerminationVetoException
, RuntimeException
)
204 ::std::list
< const ODatabaseModelImpl
* > aCopy(m_aDatabaseDocuments
);
205 ::std::for_each(aCopy
.begin(),aCopy
.end(),TerminateFunctor());
208 // .............................................................................
209 void SAL_CALL
DatabaseDocumentLoader::notifyTermination( const lang::EventObject
& /*Event*/ ) throw (RuntimeException
)
212 // .............................................................................
213 void SAL_CALL
DatabaseDocumentLoader::disposing( const lang::EventObject
& /*Source*/ ) throw (RuntimeException
)
218 //==========================================================================
219 //--------------------------------------------------------------------------
220 ODatabaseContext::ODatabaseContext( const Reference
< XComponentContext
>& _rxContext
)
221 :DatabaseAccessContext_Base(m_aMutex
)
222 ,m_aContext( _rxContext
)
223 ,m_aContainerListeners(m_aMutex
)
225 m_pDatabaseDocumentLoader
= new DatabaseDocumentLoader( m_aContext
);
226 ::basic::BasicManagerRepository::registerCreationListener( *this );
229 //--------------------------------------------------------------------------
230 ODatabaseContext::~ODatabaseContext()
232 ::basic::BasicManagerRepository::revokeCreationListener( *this );
233 if ( m_pDatabaseDocumentLoader
)
234 m_pDatabaseDocumentLoader
->release();
238 //------------------------------------------------------------------------------
239 rtl::OUString
ODatabaseContext::getImplementationName_static() throw( RuntimeException
)
242 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.ODatabaseContext"));
245 //------------------------------------------------------------------------------
246 Reference
< XInterface
> ODatabaseContext::Create(const Reference
< XComponentContext
>& _rxContext
)
248 return *( new ODatabaseContext( _rxContext
) );
251 //------------------------------------------------------------------------------
252 Sequence
< rtl::OUString
> ODatabaseContext::getSupportedServiceNames_static(void) throw( RuntimeException
)
254 Sequence
< ::rtl::OUString
> aSNS( 1 );
255 aSNS
[0] = SERVICE_SDB_DATABASECONTEXT
;
260 //------------------------------------------------------------------------------
261 rtl::OUString
ODatabaseContext::getImplementationName( ) throw(RuntimeException
)
263 return getImplementationName_static();
266 //------------------------------------------------------------------------------
267 sal_Bool
ODatabaseContext::supportsService( const ::rtl::OUString
& _rServiceName
) throw (RuntimeException
)
269 return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName
, sal_True
).getLength() != 0;
272 //------------------------------------------------------------------------------
273 Sequence
< ::rtl::OUString
> ODatabaseContext::getSupportedServiceNames( ) throw (RuntimeException
)
275 return getSupportedServiceNames_static();
278 //--------------------------------------------------------------------------
279 Reference
< XInterface
> ODatabaseContext::impl_createNewDataSource()
281 ::rtl::Reference
<ODatabaseModelImpl
> pImpl( new ODatabaseModelImpl( m_aContext
.getLegacyServiceFactory(), *this ) );
282 Reference
< XDataSource
> xDataSource( pImpl
->getOrCreateDataSource() );
284 return xDataSource
.get();
287 //--------------------------------------------------------------------------
288 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstance( ) throw (Exception
, RuntimeException
)
290 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
291 // has been called at the DatabaseDocument).
292 return impl_createNewDataSource();
295 //--------------------------------------------------------------------------
296 Reference
< XInterface
> SAL_CALL
ODatabaseContext::createInstanceWithArguments( const Sequence
< Any
>& _rArguments
) throw (Exception
, RuntimeException
)
298 ::comphelper::NamedValueCollection
aArgs( _rArguments
);
299 ::rtl::OUString sURL
= aArgs
.getOrDefault( (::rtl::OUString
)INFO_POOLURL
, ::rtl::OUString() );
301 Reference
< XInterface
> xDataSource
;
302 if ( sURL
.getLength() )
303 xDataSource
= getObject( sURL
);
305 if ( !xDataSource
.is() )
306 xDataSource
= impl_createNewDataSource();
310 // DatabaseAccessContext_Base
311 //------------------------------------------------------------------------------
312 void ODatabaseContext::disposing()
314 // notify our listener
315 com::sun::star::lang::EventObject
aDisposeEvent(static_cast< XContainer
* >(this));
316 m_aContainerListeners
.disposeAndClear(aDisposeEvent
);
318 // dispose the data sources
319 ObjectCache::iterator aEnd
= m_aDatabaseObjects
.end();
320 for ( ObjectCache::iterator aIter
= m_aDatabaseObjects
.begin();
325 aIter
->second
->dispose();
327 m_aDatabaseObjects
.clear();
330 //------------------------------------------------------------------------------
331 bool ODatabaseContext::getURLForRegisteredObject( const ::rtl::OUString
& _rRegisteredName
, ::rtl::OUString
& _rURL
)
333 if ( !_rRegisteredName
.getLength() )
334 throw IllegalArgumentException();
336 // the config node where all pooling relevant info are stored under
337 OConfigurationTreeRoot aDbRegisteredNamesRoot
= OConfigurationTreeRoot::createWithServiceFactory(
338 m_aContext
.getLegacyServiceFactory(), getDbRegisteredNamesNodeName(), -1, OConfigurationTreeRoot::CM_READONLY
);
339 if ( aDbRegisteredNamesRoot
.isValid() && aDbRegisteredNamesRoot
.hasByName( _rRegisteredName
) )
341 OConfigurationNode aRegisterObj
= aDbRegisteredNamesRoot
.openNode( _rRegisteredName
);
342 aRegisterObj
.getNodeValue(getDbLocationNodeName()) >>= _rURL
;
343 _rURL
= SvtPathOptions().SubstituteVariable( _rURL
);
350 //------------------------------------------------------------------------------
351 Reference
< XInterface
> ODatabaseContext::getRegisteredObject(const rtl::OUString
& _rName
) throw( Exception
, RuntimeException
)
353 MutexGuard
aGuard(m_aMutex
);
354 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
356 ::rtl::OUString sURL
;
357 if ( !getURLForRegisteredObject( _rName
, sURL
) )
358 throw NoSuchElementException(_rName
, *this);
360 if ( !sURL
.getLength() )
361 // there is a registration for this name, but no URL
362 throw IllegalArgumentException();
364 // check if URL is already loaded
365 Reference
< XInterface
> xExistent
= getObject( sURL
);
366 if ( xExistent
.is() )
369 return loadObjectFromURL( _rName
, sURL
);
371 // -----------------------------------------------------------------------------
372 Reference
< XInterface
> ODatabaseContext::loadObjectFromURL(const ::rtl::OUString
& _rName
,const ::rtl::OUString
& _sURL
)
374 INetURLObject
aURL( _sURL
);
375 if( aURL
.GetProtocol() == INET_PROT_NOT_VALID
)
376 throw NoSuchElementException(_rName
, *this);
380 ::ucbhelper::Content
aContent(_sURL
,Reference
< ::com::sun::star::ucb::XCommandEnvironment
>());
381 if ( !aContent
.isDocument() )
382 throw InteractiveIOException(
383 _sURL
, *this, InteractionClassification_ERROR
, IOErrorCode_NO_FILE
386 catch ( const InteractiveIOException
& e
)
388 if ( ( e
.Code
== IOErrorCode_NO_FILE
)
389 || ( e
.Code
== IOErrorCode_NOT_EXISTING
)
390 || ( e
.Code
== IOErrorCode_NOT_EXISTING_PATH
)
394 String
sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST
) );
395 ::svt::OFileNotation
aTransformer( _sURL
);
396 sErrorMessage
.SearchAndReplaceAscii( "$file$", aTransformer
.get( ::svt::OFileNotation::N_SYSTEM
) );
399 aError
.Message
= sErrorMessage
;
401 throw WrappedTargetException( _sURL
, Reference
< XNamingService
>( this ), makeAny( aError
) );
403 throw WrappedTargetException( _sURL
, Reference
< XNamingService
>( this ), ::cppu::getCaughtException() );
405 catch( const Exception
& )
407 throw WrappedTargetException( _sURL
, Reference
<XNamingService
>(this), ::cppu::getCaughtException() );
410 ::rtl::Reference
< ODatabaseModelImpl
> pExistent
;
411 ObjectCache::iterator aFind
= m_aDatabaseObjects
.find(_sURL
);
413 if ( aFind
!= m_aDatabaseObjects
.end() ) // we found a object registered under the URL
414 { // register it under the new name
415 pExistent
= aFind
->second
;
416 m_aDatabaseObjects
.insert( ObjectCache::value_type( _rName
, pExistent
.get() ) );
417 m_aDatabaseObjects
.erase( aFind
);
420 if ( !pExistent
.get() )
422 pExistent
.set( new ODatabaseModelImpl( _rName
, m_aContext
.getLegacyServiceFactory(), *this ) );
424 Reference
< XModel
> xModel( pExistent
->createNewModel_deliverOwnership( false ), UNO_SET_THROW
);
425 Reference
< XLoadable
> xLoad( xModel
, UNO_QUERY_THROW
);
427 ::comphelper::NamedValueCollection aArgs
;
428 aArgs
.put( "URL", _sURL
);
429 aArgs
.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG
);
430 aArgs
.put( "InteractionHandler", m_aContext
.createComponent( "com.sun.star.sdb.InteractionHandler" ) );
432 Sequence
< PropertyValue
> aResource( aArgs
.getPropertyValues() );
433 xLoad
->load( aResource
);
434 xModel
->attachResource( _sURL
, aResource
);
436 ::utl::CloseableComponent
aEnsureClose( xModel
);
437 } // if ( !pExistent.get() )
439 setTransientProperties( _sURL
, *pExistent
);
441 return pExistent
->getOrCreateDataSource().get();
443 // -----------------------------------------------------------------------------
444 void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
446 m_pDatabaseDocumentLoader
->append(_rDataSourceModel
);
448 // -----------------------------------------------------------------------------
449 void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl
& _rDataSourceModel
)
451 m_pDatabaseDocumentLoader
->remove(_rDataSourceModel
);
453 // -----------------------------------------------------------------------------
454 void ODatabaseContext::setTransientProperties(const ::rtl::OUString
& _sURL
, ODatabaseModelImpl
& _rDataSourceModel
)
456 if ( m_aDatasourceProperties
.end() == m_aDatasourceProperties
.find(_sURL
) )
460 ::rtl::OUString sAuthFailedPassword
;
461 Reference
< XPropertySet
> xDSProps( _rDataSourceModel
.getOrCreateDataSource(), UNO_QUERY_THROW
);
462 const Sequence
< PropertyValue
>& rSessionPersistentProps
= m_aDatasourceProperties
[_sURL
];
463 const PropertyValue
* pProp
= rSessionPersistentProps
.getConstArray();
464 const PropertyValue
* pPropsEnd
= rSessionPersistentProps
.getConstArray() + rSessionPersistentProps
.getLength();
465 for ( ; pProp
!= pPropsEnd
; ++pProp
)
467 if ( pProp
->Name
.equalsAscii( "AuthFailedPassword" ) )
469 OSL_VERIFY( pProp
->Value
>>= sAuthFailedPassword
);
473 xDSProps
->setPropertyValue( pProp
->Name
, pProp
->Value
);
477 _rDataSourceModel
.m_sFailedPassword
= sAuthFailedPassword
;
479 catch( const Exception
& )
481 DBG_UNHANDLED_EXCEPTION();
485 //------------------------------------------------------------------------------
486 void ODatabaseContext::registerObject(const rtl::OUString
& _rName
, const Reference
< XInterface
> & _rxObject
) throw( Exception
, RuntimeException
)
488 MutexGuard
aGuard(m_aMutex
);
489 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
491 if ( !_rName
.getLength() )
492 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
494 Reference
< XDocumentDataSource
> xDocDataSource( _rxObject
, UNO_QUERY
);
495 Reference
< XModel
> xModel( xDocDataSource
.is() ? xDocDataSource
->getDatabaseDocument() : Reference
< XOfficeDatabaseDocument
>(), UNO_QUERY
);
497 throw IllegalArgumentException( ::rtl::OUString(), *this, 2 );
499 ::rtl::OUString sURL
= xModel
->getURL();
500 if ( !sURL
.getLength() )
501 throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED
), *this, 2 );
503 OConfigurationTreeRoot aDbRegisteredNamesRoot
= OConfigurationTreeRoot::createWithServiceFactory(
504 ::comphelper::getProcessServiceFactory(), getDbRegisteredNamesNodeName(), -1, OConfigurationTreeRoot::CM_UPDATABLE
);
506 if ( aDbRegisteredNamesRoot
.isValid() )
508 OConfigurationNode oDataSourceRegistration
;
509 // the sub-node for the concrete registration
510 if (aDbRegisteredNamesRoot
.hasByName(_rName
))
511 oDataSourceRegistration
= aDbRegisteredNamesRoot
.openNode(_rName
);
513 oDataSourceRegistration
= aDbRegisteredNamesRoot
.createNode(_rName
);
516 oDataSourceRegistration
.setNodeValue(getDbNameNodeName(), makeAny(_rName
));
517 oDataSourceRegistration
.setNodeValue(getDbLocationNodeName(), makeAny(sURL
));
518 aDbRegisteredNamesRoot
.commit();
521 ODatabaseSource::setName( xDocDataSource
, _rName
, ODatabaseSource::DBContextAccess() );
523 // notify our container listeners
524 ContainerEvent
aEvent(static_cast<XContainer
*>(this), makeAny(_rName
), makeAny(_rxObject
), Any());
525 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
528 //------------------------------------------------------------------------------
529 void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl
& _rModelImpl
)
531 Reference
< XPropertySet
> xSource( _rModelImpl
.getOrCreateDataSource(), UNO_QUERY
);
532 ::comphelper::NamedValueCollection aRememberProps
;
536 // get the info about the properties, check which ones are transient and not readonly
537 Reference
< XPropertySetInfo
> xSetInfo
;
539 xSetInfo
= xSource
->getPropertySetInfo();
540 Sequence
< Property
> aProperties
;
542 aProperties
= xSetInfo
->getProperties();
544 if (aProperties
.getLength())
546 const Property
* pProperties
= aProperties
.getConstArray();
547 for ( sal_Int32 i
=0; i
<aProperties
.getLength(); ++i
, ++pProperties
)
549 if ( ( ( pProperties
->Attributes
& PropertyAttribute::TRANSIENT
) != 0 )
550 && ( ( pProperties
->Attributes
& PropertyAttribute::READONLY
) == 0 )
553 // found such a property
554 aRememberProps
.put( pProperties
->Name
, xSource
->getPropertyValue( pProperties
->Name
) );
559 catch ( const Exception
& )
561 DBG_UNHANDLED_EXCEPTION();
564 // additionally, remember the "failed password", which is not available as property
565 // #i86178# / 2008-02-19 / frank.schoenheit@sun.com
566 aRememberProps
.put( "AuthFailedPassword", _rModelImpl
.m_sFailedPassword
);
568 ::rtl::OUString
sDocumentURL( _rModelImpl
.getURL() );
569 if ( m_aDatabaseObjects
.find( sDocumentURL
) != m_aDatabaseObjects
.end() )
571 m_aDatasourceProperties
[ sDocumentURL
] = aRememberProps
.getPropertyValues();
573 else if ( m_aDatabaseObjects
.find( _rModelImpl
.m_sName
) != m_aDatabaseObjects
.end() )
575 m_aDatasourceProperties
[ _rModelImpl
.m_sName
] = aRememberProps
.getPropertyValues();
579 OSL_ENSURE( ( sDocumentURL
.getLength() == 0 ) && ( _rModelImpl
.m_sName
.getLength() == 0 ),
580 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
584 //------------------------------------------------------------------------------
585 void SAL_CALL
ODatabaseContext::addContainerListener( const Reference
< XContainerListener
>& _rxListener
) throw(RuntimeException
)
587 m_aContainerListeners
.addInterface(_rxListener
);
590 //------------------------------------------------------------------------------
591 void SAL_CALL
ODatabaseContext::removeContainerListener( const Reference
< XContainerListener
>& _rxListener
) throw(RuntimeException
)
593 m_aContainerListeners
.removeInterface(_rxListener
);
596 //------------------------------------------------------------------------------
597 void ODatabaseContext::revokeObject(const rtl::OUString
& _rName
) throw( Exception
, RuntimeException
)
599 MutexGuard
aGuard(m_aMutex
);
600 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
602 Reference
< XInterface
> xExistent
;
604 OConfigurationTreeRoot aDbRegisteredNamesRoot
= OConfigurationTreeRoot::createWithServiceFactory(
605 m_aContext
.getLegacyServiceFactory(), getDbRegisteredNamesNodeName(), -1, OConfigurationTreeRoot::CM_UPDATABLE
);
606 if ( aDbRegisteredNamesRoot
.isValid() && aDbRegisteredNamesRoot
.hasByName(_rName
) )
608 OConfigurationNode aThisDriverSettings
= aDbRegisteredNamesRoot
.openNode(_rName
);
609 ::rtl::OUString sURL
;
610 aThisDriverSettings
.getNodeValue(getDbLocationNodeName()) >>= sURL
;
611 sURL
= SvtPathOptions().SubstituteVariable(sURL
);
613 if ( m_aDatabaseObjects
.find( _rName
) != m_aDatabaseObjects
.end() )
615 m_aDatasourceProperties
[ sURL
] = m_aDatasourceProperties
[ _rName
];
618 // check if URL is already loaded
619 ObjectCacheIterator aExistent
= m_aDatabaseObjects
.find(sURL
);
620 if ( aExistent
!= m_aDatabaseObjects
.end() )
621 m_aDatabaseObjects
.erase(aExistent
);
622 if (!aDbRegisteredNamesRoot
.removeNode(_rName
))
623 throw Exception(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("An unexpected und unknown error occured.")), static_cast<XNamingService
*>(this));
624 aDbRegisteredNamesRoot
.commit();
627 throw NoSuchElementException(_rName
,*this);
629 // notify our container listeners
630 ContainerEvent
aEvent(static_cast<XContainer
*>(this), makeAny(_rName
), Any(), makeAny(xExistent
));
631 // note that xExistent may be empty, in case somebody removed the data source while it is not alive at this moment
632 OInterfaceIteratorHelper
aListenerLoop(m_aContainerListeners
);
633 while (aListenerLoop
.hasMoreElements())
634 static_cast<XContainerListener
*>(aListenerLoop
.next())->elementRemoved(aEvent
);
637 // ::com::sun::star::container::XElementAccess
638 //------------------------------------------------------------------------------
639 Type
ODatabaseContext::getElementType( ) throw(RuntimeException
)
641 return::getCppuType(static_cast<Reference
<XDataSource
>*>(NULL
));
644 //------------------------------------------------------------------------------
645 sal_Bool
ODatabaseContext::hasElements(void) throw( RuntimeException
)
647 MutexGuard
aGuard(m_aMutex
);
648 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
650 return 0 != getElementNames().getLength();
653 // ::com::sun::star::container::XEnumerationAccess
654 //------------------------------------------------------------------------------
655 Reference
< ::com::sun::star::container::XEnumeration
> ODatabaseContext::createEnumeration(void) throw( RuntimeException
)
657 MutexGuard
aGuard(m_aMutex
);
658 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess
*>(this));
661 // ::com::sun::star::container::XNameAccess
662 //------------------------------------------------------------------------------
663 Any
ODatabaseContext::getByName(const rtl::OUString
& _rName
) throw( NoSuchElementException
,
664 WrappedTargetException
, RuntimeException
)
666 MutexGuard
aGuard(m_aMutex
);
667 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
668 if ( !_rName
.getLength() )
669 throw NoSuchElementException(_rName
, *this);
673 Reference
< XInterface
> xExistent
= getObject(_rName
);
674 if ( xExistent
.is() )
675 return makeAny(xExistent
);
677 // see whether this is an registered name
678 ::rtl::OUString sURL
;
679 if ( getURLForRegisteredObject( _rName
, sURL
) )
681 // is the object cached under its URL?
682 xExistent
= getObject( sURL
);
685 // interpret the name as URL
688 if ( !xExistent
.is() )
689 // try to load this as URL
690 xExistent
= loadObjectFromURL( _rName
, sURL
);
691 return makeAny( xExistent
);
693 catch (NoSuchElementException
&)
694 { // let these exceptions through
697 catch (WrappedTargetException
&)
698 { // let these exceptions through
701 catch (RuntimeException
&)
702 { // let these exceptions through
706 { // exceptions other than the speciafied ones -> wrap
707 throw WrappedTargetException(_rName
, *this, makeAny( e
) );
711 //------------------------------------------------------------------------------
712 Sequence
< rtl::OUString
> ODatabaseContext::getElementNames(void) throw( RuntimeException
)
714 MutexGuard
aGuard(m_aMutex
);
715 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
717 DECLARE_STL_USTRINGACCESS_MAP( bool , TNameMap
);
720 OConfigurationTreeRoot aDbRegisteredNamesRoot
= OConfigurationTreeRoot::createWithServiceFactory(
721 m_aContext
.getLegacyServiceFactory(), getDbRegisteredNamesNodeName(), -1, OConfigurationTreeRoot::CM_READONLY
);
723 Sequence
< ::rtl::OUString
> aSeq
;
724 if ( aDbRegisteredNamesRoot
.isValid() )
726 aSeq
= aDbRegisteredNamesRoot
.getNodeNames();
727 } // if ( aDbRegisteredNamesRoot.isValid() )
732 //------------------------------------------------------------------------------
733 sal_Bool
ODatabaseContext::hasByName(const rtl::OUString
& _rName
) throw( RuntimeException
)
735 MutexGuard
aGuard(m_aMutex
);
736 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper
.bDisposed
);
738 OConfigurationTreeRoot aDbRegisteredNamesRoot
= OConfigurationTreeRoot::createWithServiceFactory(
739 m_aContext
.getLegacyServiceFactory(), getDbRegisteredNamesNodeName(), -1, OConfigurationTreeRoot::CM_READONLY
);
741 return aDbRegisteredNamesRoot
.isValid() && aDbRegisteredNamesRoot
.hasByName(_rName
);
743 // -----------------------------------------------------------------------------
744 Reference
< XInterface
> ODatabaseContext::getObject(const ::rtl::OUString
& _rName
)
746 ObjectCacheIterator aFind
= m_aDatabaseObjects
.find(_rName
);
747 Reference
< XInterface
> xExistent
;
748 if ( aFind
!= m_aDatabaseObjects
.end() )
749 xExistent
= aFind
->second
->getOrCreateDataSource();
752 // -----------------------------------------------------------------------------
753 void ODatabaseContext::registerPrivate(const ::rtl::OUString
& _sName
754 ,const ::rtl::Reference
<ODatabaseModelImpl
>& _pModelImpl
)
756 // OSL_ENSURE(m_aDatabaseObjects.find(_sName) == m_aDatabaseObjects.end(),"Name already exists!");
757 if ( m_aDatabaseObjects
.find(_sName
) == m_aDatabaseObjects
.end() )
759 m_aDatabaseObjects
.insert(ObjectCache::value_type(_sName
,_pModelImpl
.get()));
760 setTransientProperties( _sName
, *_pModelImpl
);
763 // -----------------------------------------------------------------------------
764 void ODatabaseContext::deregisterPrivate(const ::rtl::OUString
& _sName
)
766 m_aDatabaseObjects
.erase(_sName
);
768 // -----------------------------------------------------------------------------
769 void ODatabaseContext::nameChangePrivate(const ::rtl::OUString
& _sOldName
, const ::rtl::OUString
& _sNewName
)
771 ObjectCache::iterator aFind
= m_aDatabaseObjects
.find(_sOldName
);
772 registerPrivate(_sNewName
,aFind
->second
);
773 m_aDatabaseObjects
.erase(aFind
);
775 // -----------------------------------------------------------------------------
776 sal_Int64 SAL_CALL
ODatabaseContext::getSomething( const Sequence
< sal_Int8
>& rId
) throw(RuntimeException
)
778 if (rId
.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
779 return reinterpret_cast<sal_Int64
>(this);
783 // -----------------------------------------------------------------------------
784 Sequence
< sal_Int8
> ODatabaseContext::getUnoTunnelImplementationId()
786 static ::cppu::OImplementationId
* pId
= 0;
789 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
792 static ::cppu::OImplementationId aId
;
796 return pId
->getImplementationId();
799 // -----------------------------------------------------------------------------
800 void ODatabaseContext::onBasicManagerCreated( const Reference
< XModel
>& _rxForDocument
, BasicManager
& _rBasicManager
)
802 // if it's a database document ...
803 Reference
< XOfficeDatabaseDocument
> xDatabaseDocument( _rxForDocument
, UNO_QUERY
);
804 // ... or a sub document of a database document ...
805 if ( !xDatabaseDocument
.is() )
807 Reference
< XChild
> xDocAsChild( _rxForDocument
, UNO_QUERY
);
808 if ( xDocAsChild
.is() )
809 xDatabaseDocument
.set( xDocAsChild
->getParent(), UNO_QUERY
);
812 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
813 if ( xDatabaseDocument
.is() )
814 _rBasicManager
.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument
) );
817 //........................................................................
818 } // namespace dbaccess
819 //........................................................................