1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbaccess.hxx"
26
27 #include "apitools.hxx"
28 #include "core_resource.hrc"
29 #include "core_resource.hxx"
30 #include "databasecontext.hxx"
31 #include "databasedocument.hxx"
32 #include "databaseregistrations.hxx"
33 #include "datasource.hxx"
34 #include "dbastrings.hrc"
35 #include "module_dba.hxx"
36
37 /** === being UNO includes === **/
38 #include <com/sun/star/beans/NamedValue.hpp>
39 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/document/MacroExecMode.hpp>
42 #include <com/sun/star/document/XFilter.hpp>
43 #include <com/sun/star/document/XImporter.hpp>
44 #include <com/sun/star/frame/XDesktop.hpp>
45 #include <com/sun/star/frame/XModel.hpp>
46 #include <com/sun/star/frame/XModel2.hpp>
47 #include <com/sun/star/frame/XTerminateListener.hpp>
48 #include <com/sun/star/lang/DisposedException.hpp>
49 #include <com/sun/star/registry/InvalidRegistryException.hpp>
50 #include <com/sun/star/sdbc/XDataSource.hpp>
51 #include <com/sun/star/task/InteractionClassification.hpp>
52 #include <com/sun/star/ucb/InteractiveIOException.hpp>
53 #include <com/sun/star/ucb/IOErrorCode.hpp>
54 #include <com/sun/star/util/XCloseable.hpp>
55 /** === end UNO includes === **/
56
57 #include <basic/basmgr.hxx>
58 #include <comphelper/enumhelper.hxx>
59 #include <comphelper/evtlistenerhlp.hxx>
60 #include <comphelper/namedvaluecollection.hxx>
61 #include <comphelper/processfactory.hxx>
62 #include <comphelper/sequence.hxx>
63 #include <cppuhelper/implbase1.hxx>
64 #include <cppuhelper/typeprovider.hxx>
65 #include <cppuhelper/exc_hlp.hxx>
66 #include <svl/filenotation.hxx>
67 #include <tools/debug.hxx>
68 #include <tools/diagnose_ex.h>
69 #include <tools/fsys.hxx>
70 #include <tools/urlobj.hxx>
71 #include <ucbhelper/content.hxx>
72 #include <unotools/confignode.hxx>
73 #include <unotools/pathoptions.hxx>
74 #include <unotools/sharedunocomponent.hxx>
75 #include <list>
76 #include <boost/bind.hpp>
77
78 using namespace ::com::sun::star::sdbc;
79 using namespace ::com::sun::star::sdb;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::uno;
82 using namespace ::com::sun::star::document;
83 using namespace ::com::sun::star::frame;
84 using namespace ::com::sun::star::lang;
85 using namespace ::com::sun::star::container;
86 using namespace ::com::sun::star::util;
87 using namespace ::com::sun::star::registry;
88 using namespace ::com::sun::star;
89 using namespace ::cppu;
90 using namespace ::osl;
91 using namespace ::utl;
92
93 using ::com::sun::star::task::InteractionClassification_ERROR;
94 using ::com::sun::star::ucb::IOErrorCode_NO_FILE;
95 using ::com::sun::star::ucb::InteractiveIOException;
96 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING;
97 using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH;
98
99 //==========================================================================
100
createRegistryInfo_ODatabaseContext()101 extern "C" void SAL_CALL createRegistryInfo_ODatabaseContext()
102 {
103 static ::dba::OLegacySingletonRegistration< ::dbaccess::ODatabaseContext > aODatabaseContext_AutoRegistration;
104 }
105
106 //........................................................................
107 namespace dbaccess
108 {
109 //........................................................................
110
111 // .............................................................................
112 typedef ::cppu::WeakImplHelper1 < XTerminateListener
113 > DatabaseDocumentLoader_Base;
114 class DatabaseDocumentLoader : public DatabaseDocumentLoader_Base
115 {
116 private:
117 Reference< XDesktop > m_xDesktop;
118 ::std::list< const ODatabaseModelImpl* > m_aDatabaseDocuments;
119
120 public:
121 DatabaseDocumentLoader( const comphelper::ComponentContext& _aContext);
122
append(const ODatabaseModelImpl & _rModelImpl)123 inline void append(const ODatabaseModelImpl& _rModelImpl )
124 {
125 m_aDatabaseDocuments.push_back(&_rModelImpl);
126 }
remove(const ODatabaseModelImpl & _rModelImpl)127 inline void remove(const ODatabaseModelImpl& _rModelImpl) { m_aDatabaseDocuments.remove(&_rModelImpl); }
128
129 private:
130 // XTerminateListener
131 virtual void SAL_CALL queryTermination( const lang::EventObject& Event ) throw (TerminationVetoException, RuntimeException);
132 virtual void SAL_CALL notifyTermination( const lang::EventObject& Event ) throw (RuntimeException);
133 // XEventListener
134 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
135 };
136
137 // .............................................................................
DatabaseDocumentLoader(const comphelper::ComponentContext & _aContext)138 DatabaseDocumentLoader::DatabaseDocumentLoader( const comphelper::ComponentContext& _aContext )
139 {
140 acquire();
141 try
142 {
143 m_xDesktop.set( _aContext.createComponent( (rtl::OUString)SERVICE_FRAME_DESKTOP ), UNO_QUERY_THROW );
144 m_xDesktop->addTerminateListener( this );
145 }
146 catch( const Exception& )
147 {
148 DBG_UNHANDLED_EXCEPTION();
149 }
150 }
151
152 struct TerminateFunctor : ::std::unary_function<ODatabaseModelImpl* , void>
153 {
operator ()dbaccess::TerminateFunctor154 void operator()( const ODatabaseModelImpl* _pModelImpl ) const
155 {
156 try
157 {
158 const Reference< XModel2> xModel( _pModelImpl ->getModel_noCreate(),UNO_QUERY_THROW );
159 if ( !xModel->getControllers()->hasMoreElements() )
160 {
161 Reference<util::XCloseable> xCloseable(xModel,UNO_QUERY_THROW);
162 xCloseable->close(sal_False);
163 } // if ( !xModel->getControllers()->hasMoreElements() )
164 }
165 catch(const CloseVetoException&)
166 {
167 throw TerminationVetoException();
168 }
169 }
170 };
171 // .............................................................................
queryTermination(const lang::EventObject &)172 void SAL_CALL DatabaseDocumentLoader::queryTermination( const lang::EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException)
173 {
174 ::std::list< const ODatabaseModelImpl* > aCopy(m_aDatabaseDocuments);
175 ::std::for_each(aCopy.begin(),aCopy.end(),TerminateFunctor());
176 }
177
178 // .............................................................................
notifyTermination(const lang::EventObject &)179 void SAL_CALL DatabaseDocumentLoader::notifyTermination( const lang::EventObject& /*Event*/ ) throw (RuntimeException)
180 {
181 }
182 // .............................................................................
disposing(const lang::EventObject &)183 void SAL_CALL DatabaseDocumentLoader::disposing( const lang::EventObject& /*Source*/ ) throw (RuntimeException)
184 {
185 }
186
187 //= ODatabaseContext
188 //==========================================================================
189 //--------------------------------------------------------------------------
ODatabaseContext(const Reference<XComponentContext> & _rxContext)190 ODatabaseContext::ODatabaseContext( const Reference< XComponentContext >& _rxContext )
191 :DatabaseAccessContext_Base(m_aMutex)
192 ,m_aContext( _rxContext )
193 ,m_aContainerListeners(m_aMutex)
194 {
195 m_pDatabaseDocumentLoader = new DatabaseDocumentLoader( m_aContext );
196 ::basic::BasicManagerRepository::registerCreationListener( *this );
197
198 osl_incrementInterlockedCount( &m_refCount );
199 {
200 m_xDBRegistrationAggregate.set( createDataSourceRegistrations( m_aContext ), UNO_SET_THROW );
201 m_xDatabaseRegistrations.set( m_xDBRegistrationAggregate, UNO_QUERY_THROW );
202
203 m_xDBRegistrationAggregate->setDelegator( *this );
204 }
205 osl_decrementInterlockedCount( &m_refCount );
206 }
207
208 //--------------------------------------------------------------------------
~ODatabaseContext()209 ODatabaseContext::~ODatabaseContext()
210 {
211 ::basic::BasicManagerRepository::revokeCreationListener( *this );
212 if ( m_pDatabaseDocumentLoader )
213 m_pDatabaseDocumentLoader->release();
214
215 m_xDBRegistrationAggregate->setDelegator( NULL );
216 m_xDBRegistrationAggregate.clear();
217 m_xDatabaseRegistrations.clear();
218 }
219
220 // Helper
221 //------------------------------------------------------------------------------
getImplementationName_static()222 rtl::OUString ODatabaseContext::getImplementationName_static() throw( RuntimeException )
223
224 {
225 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.ODatabaseContext"));
226 }
227
228 //------------------------------------------------------------------------------
Create(const Reference<XComponentContext> & _rxContext)229 Reference< XInterface > ODatabaseContext::Create(const Reference< XComponentContext >& _rxContext)
230 {
231 return *( new ODatabaseContext( _rxContext ) );
232 }
233
234 //------------------------------------------------------------------------------
getSupportedServiceNames_static(void)235 Sequence< rtl::OUString > ODatabaseContext::getSupportedServiceNames_static(void) throw( RuntimeException )
236 {
237 Sequence< ::rtl::OUString > aSNS( 1 );
238 aSNS[0] = SERVICE_SDB_DATABASECONTEXT;
239 return aSNS;
240 }
241
242 // XServiceInfo
243 //------------------------------------------------------------------------------
getImplementationName()244 rtl::OUString ODatabaseContext::getImplementationName( ) throw(RuntimeException)
245 {
246 return getImplementationName_static();
247 }
248
249 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)250 sal_Bool ODatabaseContext::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
251 {
252 return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
253 }
254
255 //------------------------------------------------------------------------------
getSupportedServiceNames()256 Sequence< ::rtl::OUString > ODatabaseContext::getSupportedServiceNames( ) throw (RuntimeException)
257 {
258 return getSupportedServiceNames_static();
259 }
260
261 //--------------------------------------------------------------------------
impl_createNewDataSource()262 Reference< XInterface > ODatabaseContext::impl_createNewDataSource()
263 {
264 ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( m_aContext.getLegacyServiceFactory(), *this ) );
265 Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() );
266
267 return xDataSource.get();
268 }
269
270 //--------------------------------------------------------------------------
createInstance()271 Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( ) throw (Exception, RuntimeException)
272 {
273 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
274 // has been called at the DatabaseDocument).
275 return impl_createNewDataSource();
276 }
277
278 //--------------------------------------------------------------------------
createInstanceWithArguments(const Sequence<Any> & _rArguments)279 Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
280 {
281 ::comphelper::NamedValueCollection aArgs( _rArguments );
282 ::rtl::OUString sURL = aArgs.getOrDefault( (::rtl::OUString)INFO_POOLURL, ::rtl::OUString() );
283
284 Reference< XInterface > xDataSource;
285 if ( sURL.getLength() )
286 xDataSource = getObject( sURL );
287
288 if ( !xDataSource.is() )
289 xDataSource = impl_createNewDataSource();
290
291 return xDataSource;
292 }
293 // DatabaseAccessContext_Base
294 //------------------------------------------------------------------------------
disposing()295 void ODatabaseContext::disposing()
296 {
297 // notify our listener
298 com::sun::star::lang::EventObject aDisposeEvent(static_cast< XContainer* >(this));
299 m_aContainerListeners.disposeAndClear(aDisposeEvent);
300
301 // dispose the data sources
302 ObjectCache::iterator aEnd = m_aDatabaseObjects.end();
303 for ( ObjectCache::iterator aIter = m_aDatabaseObjects.begin();
304 aIter != aEnd;
305 ++aIter
306 )
307 {
308 aIter->second->dispose();
309 }
310 m_aDatabaseObjects.clear();
311 }
312
313 // XNamingService
314 //------------------------------------------------------------------------------
getRegisteredObject(const rtl::OUString & _rName)315 Reference< XInterface > ODatabaseContext::getRegisteredObject(const rtl::OUString& _rName) throw( Exception, RuntimeException )
316 {
317 MutexGuard aGuard(m_aMutex);
318 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
319
320 ::rtl::OUString sURL( getDatabaseLocation( _rName ) );
321
322 if ( !sURL.getLength() )
323 // there is a registration for this name, but no URL
324 throw IllegalArgumentException();
325
326 // check if URL is already loaded
327 Reference< XInterface > xExistent = getObject( sURL );
328 if ( xExistent.is() )
329 return xExistent;
330
331 return loadObjectFromURL( _rName, sURL );
332 }
333 // -----------------------------------------------------------------------------
loadObjectFromURL(const::rtl::OUString & _rName,const::rtl::OUString & _sURL)334 Reference< XInterface > ODatabaseContext::loadObjectFromURL(const ::rtl::OUString& _rName,const ::rtl::OUString& _sURL)
335 {
336 INetURLObject aURL( _sURL );
337 if ( aURL.GetProtocol() == INET_PROT_NOT_VALID )
338 throw NoSuchElementException( _rName, *this );
339
340 try
341 {
342 ::ucbhelper::Content aContent( _sURL, NULL );
343 if ( !aContent.isDocument() )
344 throw InteractiveIOException(
345 _sURL, *this, InteractionClassification_ERROR, IOErrorCode_NO_FILE
346 );
347 }
348 catch ( const InteractiveIOException& e )
349 {
350 if ( ( e.Code == IOErrorCode_NO_FILE )
351 || ( e.Code == IOErrorCode_NOT_EXISTING )
352 || ( e.Code == IOErrorCode_NOT_EXISTING_PATH )
353 )
354 {
355 // #i40463# #i39187#
356 String sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST ) );
357 ::svt::OFileNotation aTransformer( _sURL );
358 sErrorMessage.SearchAndReplaceAscii( "$file$", aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) );
359
360 SQLException aError;
361 aError.Message = sErrorMessage;
362
363 throw WrappedTargetException( _sURL, *this, makeAny( aError ) );
364 }
365 throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
366 }
367 catch( const Exception& )
368 {
369 throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
370 }
371
372 OSL_ENSURE( m_aDatabaseObjects.find( _sURL ) == m_aDatabaseObjects.end(),
373 "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
374
375 ::rtl::Reference< ODatabaseModelImpl > pModelImpl;
376 {
377 pModelImpl.set( new ODatabaseModelImpl( _rName, m_aContext.getLegacyServiceFactory(), *this ) );
378
379 Reference< XModel > xModel( pModelImpl->createNewModel_deliverOwnership( false ), UNO_SET_THROW );
380 Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
381
382 ::comphelper::NamedValueCollection aArgs;
383 aArgs.put( "URL", _sURL );
384 aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
385 aArgs.put( "InteractionHandler", m_aContext.createComponent( "com.sun.star.task.InteractionHandler" ) );
386
387 Sequence< PropertyValue > aResource( aArgs.getPropertyValues() );
388 xLoad->load( aResource );
389 xModel->attachResource( _sURL, aResource );
390
391 ::utl::CloseableComponent aEnsureClose( xModel );
392 }
393
394 setTransientProperties( _sURL, *pModelImpl );
395
396 return pModelImpl->getOrCreateDataSource().get();
397 }
398 // -----------------------------------------------------------------------------
appendAtTerminateListener(const ODatabaseModelImpl & _rDataSourceModel)399 void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
400 {
401 m_pDatabaseDocumentLoader->append(_rDataSourceModel);
402 }
403 // -----------------------------------------------------------------------------
removeFromTerminateListener(const ODatabaseModelImpl & _rDataSourceModel)404 void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
405 {
406 m_pDatabaseDocumentLoader->remove(_rDataSourceModel);
407 }
408 // -----------------------------------------------------------------------------
setTransientProperties(const::rtl::OUString & _sURL,ODatabaseModelImpl & _rDataSourceModel)409 void ODatabaseContext::setTransientProperties(const ::rtl::OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel )
410 {
411 if ( m_aDatasourceProperties.end() == m_aDatasourceProperties.find(_sURL) )
412 return;
413 try
414 {
415 ::rtl::OUString sAuthFailedPassword;
416 Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW );
417 const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL];
418 const PropertyValue* pProp = rSessionPersistentProps.getConstArray();
419 const PropertyValue* pPropsEnd = rSessionPersistentProps.getConstArray() + rSessionPersistentProps.getLength();
420 for ( ; pProp != pPropsEnd; ++pProp )
421 {
422 if ( pProp->Name.equalsAscii( "AuthFailedPassword" ) )
423 {
424 OSL_VERIFY( pProp->Value >>= sAuthFailedPassword );
425 }
426 else
427 {
428 xDSProps->setPropertyValue( pProp->Name, pProp->Value );
429 }
430 }
431
432 _rDataSourceModel.m_sFailedPassword = sAuthFailedPassword;
433 }
434 catch( const Exception& )
435 {
436 DBG_UNHANDLED_EXCEPTION();
437 }
438 }
439
440 //------------------------------------------------------------------------------
registerObject(const rtl::OUString & _rName,const Reference<XInterface> & _rxObject)441 void ODatabaseContext::registerObject(const rtl::OUString& _rName, const Reference< XInterface > & _rxObject) throw( Exception, RuntimeException )
442 {
443 MutexGuard aGuard(m_aMutex);
444 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
445
446 if ( !_rName.getLength() )
447 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
448
449 Reference< XDocumentDataSource > xDocDataSource( _rxObject, UNO_QUERY );
450 Reference< XModel > xModel( xDocDataSource.is() ? xDocDataSource->getDatabaseDocument() : Reference< XOfficeDatabaseDocument >(), UNO_QUERY );
451 if ( !xModel.is() )
452 throw IllegalArgumentException( ::rtl::OUString(), *this, 2 );
453
454 ::rtl::OUString sURL = xModel->getURL();
455 if ( !sURL.getLength() )
456 throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED ), *this, 2 );
457
458 registerDatabaseLocation( _rName, sURL );
459
460 ODatabaseSource::setName( xDocDataSource, _rName, ODatabaseSource::DBContextAccess() );
461
462 // notify our container listeners
463 ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(_rName), makeAny(_rxObject), Any());
464 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
465 }
466
467 //------------------------------------------------------------------------------
storeTransientProperties(ODatabaseModelImpl & _rModelImpl)468 void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl& _rModelImpl)
469 {
470 Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY );
471 ::comphelper::NamedValueCollection aRememberProps;
472
473 try
474 {
475 // get the info about the properties, check which ones are transient and not readonly
476 Reference< XPropertySetInfo > xSetInfo;
477 if (xSource.is())
478 xSetInfo = xSource->getPropertySetInfo();
479 Sequence< Property > aProperties;
480 if (xSetInfo.is())
481 aProperties = xSetInfo->getProperties();
482
483 if (aProperties.getLength())
484 {
485 const Property* pProperties = aProperties.getConstArray();
486 for ( sal_Int32 i=0; i<aProperties.getLength(); ++i, ++pProperties )
487 {
488 if ( ( ( pProperties->Attributes & PropertyAttribute::TRANSIENT) != 0 )
489 && ( ( pProperties->Attributes & PropertyAttribute::READONLY) == 0 )
490 )
491 {
492 // found such a property
493 aRememberProps.put( pProperties->Name, xSource->getPropertyValue( pProperties->Name ) );
494 }
495 }
496 }
497 }
498 catch ( const Exception& )
499 {
500 DBG_UNHANDLED_EXCEPTION();
501 }
502
503 // additionally, remember the "failed password", which is not available as property
504 // #i86178# / 2008-02-19 / frank.schoenheit@sun.com
505 aRememberProps.put( "AuthFailedPassword", _rModelImpl.m_sFailedPassword );
506
507 ::rtl::OUString sDocumentURL( _rModelImpl.getURL() );
508 if ( m_aDatabaseObjects.find( sDocumentURL ) != m_aDatabaseObjects.end() )
509 {
510 m_aDatasourceProperties[ sDocumentURL ] = aRememberProps.getPropertyValues();
511 }
512 else if ( m_aDatabaseObjects.find( _rModelImpl.m_sName ) != m_aDatabaseObjects.end() )
513 {
514 OSL_ENSURE( false, "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
515 // all the code should have been changed so that registration is by URL only
516 m_aDatasourceProperties[ _rModelImpl.m_sName ] = aRememberProps.getPropertyValues();
517 }
518 else
519 {
520 OSL_ENSURE( ( sDocumentURL.getLength() == 0 ) && ( _rModelImpl.m_sName.getLength() == 0 ),
521 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
522 }
523 }
524
525 //------------------------------------------------------------------------------
addContainerListener(const Reference<XContainerListener> & _rxListener)526 void SAL_CALL ODatabaseContext::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException)
527 {
528 m_aContainerListeners.addInterface(_rxListener);
529 }
530
531 //------------------------------------------------------------------------------
removeContainerListener(const Reference<XContainerListener> & _rxListener)532 void SAL_CALL ODatabaseContext::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException)
533 {
534 m_aContainerListeners.removeInterface(_rxListener);
535 }
536
537 //------------------------------------------------------------------------------
revokeObject(const rtl::OUString & _rName)538 void ODatabaseContext::revokeObject(const rtl::OUString& _rName) throw( Exception, RuntimeException )
539 {
540 ClearableMutexGuard aGuard(m_aMutex);
541 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
542
543 ::rtl::OUString sURL = getDatabaseLocation( _rName );
544
545 revokeDatabaseLocation( _rName );
546 // will throw if something goes wrong
547
548 if ( m_aDatabaseObjects.find( _rName ) != m_aDatabaseObjects.end() )
549 {
550 m_aDatasourceProperties[ sURL ] = m_aDatasourceProperties[ _rName ];
551 }
552
553 // check if URL is already loaded
554 ObjectCacheIterator aExistent = m_aDatabaseObjects.find( sURL );
555 if ( aExistent != m_aDatabaseObjects.end() )
556 m_aDatabaseObjects.erase( aExistent );
557
558 // notify our container listeners
559 ContainerEvent aEvent( *this, makeAny( _rName ), Any(), Any() );
560 aGuard.clear();
561 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
562 }
563
564 //------------------------------------------------------------------------------
hasRegisteredDatabase(const::rtl::OUString & _Name)565 ::sal_Bool SAL_CALL ODatabaseContext::hasRegisteredDatabase( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, RuntimeException)
566 {
567 return m_xDatabaseRegistrations->hasRegisteredDatabase( _Name );
568 }
569
570 //------------------------------------------------------------------------------
getRegistrationNames()571 Sequence< ::rtl::OUString > SAL_CALL ODatabaseContext::getRegistrationNames() throw (RuntimeException)
572 {
573 return m_xDatabaseRegistrations->getRegistrationNames();
574 }
575
576 //------------------------------------------------------------------------------
getDatabaseLocation(const::rtl::OUString & _Name)577 ::rtl::OUString SAL_CALL ODatabaseContext::getDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
578 {
579 return m_xDatabaseRegistrations->getDatabaseLocation( _Name );
580 }
581
582 //------------------------------------------------------------------------------
registerDatabaseLocation(const::rtl::OUString & _Name,const::rtl::OUString & _Location)583 void SAL_CALL ODatabaseContext::registerDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException)
584 {
585 m_xDatabaseRegistrations->registerDatabaseLocation( _Name, _Location );
586 }
587
588 //------------------------------------------------------------------------------
revokeDatabaseLocation(const::rtl::OUString & _Name)589 void SAL_CALL ODatabaseContext::revokeDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException)
590 {
591 m_xDatabaseRegistrations->revokeDatabaseLocation( _Name );
592 }
593
594 //------------------------------------------------------------------------------
changeDatabaseLocation(const::rtl::OUString & _Name,const::rtl::OUString & _NewLocation)595 void SAL_CALL ODatabaseContext::changeDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException)
596 {
597 m_xDatabaseRegistrations->changeDatabaseLocation( _Name, _NewLocation );
598 }
599
600 //------------------------------------------------------------------------------
isDatabaseRegistrationReadOnly(const::rtl::OUString & _Name)601 ::sal_Bool SAL_CALL ODatabaseContext::isDatabaseRegistrationReadOnly( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
602 {
603 return m_xDatabaseRegistrations->isDatabaseRegistrationReadOnly( _Name );
604 }
605
606 //------------------------------------------------------------------------------
addDatabaseRegistrationsListener(const Reference<XDatabaseRegistrationsListener> & _Listener)607 void SAL_CALL ODatabaseContext::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException)
608 {
609 m_xDatabaseRegistrations->addDatabaseRegistrationsListener( _Listener );
610 }
611
612 //------------------------------------------------------------------------------
removeDatabaseRegistrationsListener(const Reference<XDatabaseRegistrationsListener> & _Listener)613 void SAL_CALL ODatabaseContext::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException)
614 {
615 m_xDatabaseRegistrations->removeDatabaseRegistrationsListener( _Listener );
616 }
617
618 // ::com::sun::star::container::XElementAccess
619 //------------------------------------------------------------------------------
getElementType()620 Type ODatabaseContext::getElementType( ) throw(RuntimeException)
621 {
622 return::getCppuType(static_cast<Reference<XDataSource>*>(NULL));
623 }
624
625 //------------------------------------------------------------------------------
hasElements(void)626 sal_Bool ODatabaseContext::hasElements(void) throw( RuntimeException )
627 {
628 MutexGuard aGuard(m_aMutex);
629 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
630
631 return 0 != getElementNames().getLength();
632 }
633
634 // ::com::sun::star::container::XEnumerationAccess
635 //------------------------------------------------------------------------------
createEnumeration(void)636 Reference< ::com::sun::star::container::XEnumeration > ODatabaseContext::createEnumeration(void) throw( RuntimeException )
637 {
638 MutexGuard aGuard(m_aMutex);
639 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess*>(this));
640 }
641
642 // ::com::sun::star::container::XNameAccess
643 //------------------------------------------------------------------------------
getByName(const rtl::OUString & _rName)644 Any ODatabaseContext::getByName(const rtl::OUString& _rName) throw( NoSuchElementException,
645 WrappedTargetException, RuntimeException )
646 {
647 MutexGuard aGuard(m_aMutex);
648 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
649 if ( !_rName.getLength() )
650 throw NoSuchElementException(_rName, *this);
651
652 try
653 {
654 Reference< XInterface > xExistent = getObject( _rName );
655 if ( xExistent.is() )
656 return makeAny( xExistent );
657
658 // see whether this is an registered name
659 ::rtl::OUString sURL;
660 if ( hasRegisteredDatabase( _rName ) )
661 {
662 sURL = getDatabaseLocation( _rName );
663 // is the object cached under its URL?
664 xExistent = getObject( sURL );
665 }
666 else
667 // interpret the name as URL
668 sURL = _rName;
669
670 if ( !xExistent.is() )
671 // try to load this as URL
672 xExistent = loadObjectFromURL( _rName, sURL );
673 return makeAny( xExistent );
674 }
675 catch (NoSuchElementException&)
676 { // let these exceptions through
677 throw;
678 }
679 catch (WrappedTargetException&)
680 { // let these exceptions through
681 throw;
682 }
683 catch (RuntimeException&)
684 { // let these exceptions through
685 throw;
686 }
687 catch (Exception& e)
688 { // exceptions other than the speciafied ones -> wrap
689 Any aError = ::cppu::getCaughtException();
690 throw WrappedTargetException(_rName, *this, aError );
691 }
692 }
693
694 //------------------------------------------------------------------------------
getElementNames(void)695 Sequence< rtl::OUString > ODatabaseContext::getElementNames(void) throw( RuntimeException )
696 {
697 MutexGuard aGuard(m_aMutex);
698 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
699
700 return getRegistrationNames();
701 }
702
703 //------------------------------------------------------------------------------
hasByName(const rtl::OUString & _rName)704 sal_Bool ODatabaseContext::hasByName(const rtl::OUString& _rName) throw( RuntimeException )
705 {
706 MutexGuard aGuard(m_aMutex);
707 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
708
709 return hasRegisteredDatabase( _rName );
710 }
711
712 // -----------------------------------------------------------------------------
getObject(const::rtl::OUString & _rURL)713 Reference< XInterface > ODatabaseContext::getObject( const ::rtl::OUString& _rURL )
714 {
715 ObjectCacheIterator aFind = m_aDatabaseObjects.find( _rURL );
716 Reference< XInterface > xExistent;
717 if ( aFind != m_aDatabaseObjects.end() )
718 xExistent = aFind->second->getOrCreateDataSource();
719 return xExistent;
720 }
721 // -----------------------------------------------------------------------------
registerDatabaseDocument(ODatabaseModelImpl & _rModelImpl)722 void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl )
723 {
724 ::rtl::OUString sURL( _rModelImpl.getURL() );
725 #if OSL_DEBUG_LEVEL > 1
726 OSL_TRACE( "DatabaseContext: registering %s", ::rtl::OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() );
727 #endif
728 if ( m_aDatabaseObjects.find( sURL ) == m_aDatabaseObjects.end() )
729 {
730 m_aDatabaseObjects[ sURL ] = &_rModelImpl;
731 setTransientProperties( sURL, _rModelImpl );
732 }
733 else
734 OSL_ENSURE( false, "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
735 }
736 // -----------------------------------------------------------------------------
revokeDatabaseDocument(const ODatabaseModelImpl & _rModelImpl)737 void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl )
738 {
739 ::rtl::OUString sURL( _rModelImpl.getURL() );
740 #if OSL_DEBUG_LEVEL > 1
741 OSL_TRACE( "DatabaseContext: deregistering %s", ::rtl::OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() );
742 #endif
743 m_aDatabaseObjects.erase( sURL );
744 }
745 // -----------------------------------------------------------------------------
databaseDocumentURLChange(const::rtl::OUString & _rOldURL,const::rtl::OUString & _rNewURL)746 void ODatabaseContext::databaseDocumentURLChange( const ::rtl::OUString& _rOldURL, const ::rtl::OUString& _rNewURL )
747 {
748 #if OSL_DEBUG_LEVEL > 1
749 OSL_TRACE( "DatabaseContext: changing registration from %s to %s",
750 ::rtl::OUStringToOString( _rOldURL, RTL_TEXTENCODING_UTF8 ).getStr(),
751 ::rtl::OUStringToOString( _rNewURL, RTL_TEXTENCODING_UTF8 ).getStr() );
752 #endif
753 ObjectCache::iterator oldPos = m_aDatabaseObjects.find( _rOldURL );
754 ENSURE_OR_THROW( oldPos != m_aDatabaseObjects.end(), "illegal old database document URL" );
755 ObjectCache::iterator newPos = m_aDatabaseObjects.find( _rNewURL );
756 ENSURE_OR_THROW( newPos == m_aDatabaseObjects.end(), "illegal new database document URL" );
757
758 m_aDatabaseObjects[ _rNewURL ] = oldPos->second;
759 m_aDatabaseObjects.erase( oldPos );
760 }
761 // -----------------------------------------------------------------------------
getSomething(const Sequence<sal_Int8> & rId)762 sal_Int64 SAL_CALL ODatabaseContext::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
763 {
764 if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
765 return reinterpret_cast<sal_Int64>(this);
766
767 return 0;
768 }
769 // -----------------------------------------------------------------------------
getUnoTunnelImplementationId()770 Sequence< sal_Int8 > ODatabaseContext::getUnoTunnelImplementationId()
771 {
772 static ::cppu::OImplementationId * pId = 0;
773 if (! pId)
774 {
775 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
776 if (! pId)
777 {
778 static ::cppu::OImplementationId aId;
779 pId = &aId;
780 }
781 }
782 return pId->getImplementationId();
783 }
784
785 // -----------------------------------------------------------------------------
onBasicManagerCreated(const Reference<XModel> & _rxForDocument,BasicManager & _rBasicManager)786 void ODatabaseContext::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager )
787 {
788 // if it's a database document ...
789 Reference< XOfficeDatabaseDocument > xDatabaseDocument( _rxForDocument, UNO_QUERY );
790 // ... or a sub document of a database document ...
791 if ( !xDatabaseDocument.is() )
792 {
793 Reference< XChild > xDocAsChild( _rxForDocument, UNO_QUERY );
794 if ( xDocAsChild.is() )
795 xDatabaseDocument.set( xDocAsChild->getParent(), UNO_QUERY );
796 }
797
798 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
799 if ( xDatabaseDocument.is() )
800 _rBasicManager.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument ) );
801 }
802
803 //........................................................................
804 } // namespace dbaccess
805 //........................................................................
806