Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <config_features.h>
21 :
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"
31 :
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>
50 :
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>
69 : #include <list>
70 :
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;
85 :
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;
91 :
92 : namespace dbaccess
93 : {
94 :
95 : typedef ::cppu::WeakImplHelper1 < XTerminateListener
96 : > DatabaseDocumentLoader_Base;
97 44 : class DatabaseDocumentLoader : public DatabaseDocumentLoader_Base
98 : {
99 : private:
100 : Reference< XDesktop2 > m_xDesktop;
101 : ::std::list< const ODatabaseModelImpl* > m_aDatabaseDocuments;
102 :
103 : public:
104 : DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext);
105 :
106 214 : inline void append(const ODatabaseModelImpl& _rModelImpl )
107 : {
108 214 : m_aDatabaseDocuments.push_back(&_rModelImpl);
109 214 : }
110 212 : inline void remove(const ODatabaseModelImpl& _rModelImpl) { m_aDatabaseDocuments.remove(&_rModelImpl); }
111 :
112 : private:
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;
116 : // XEventListener
117 : virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
118 : };
119 :
120 28 : DatabaseDocumentLoader::DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext )
121 : {
122 28 : acquire();
123 : try
124 : {
125 28 : m_xDesktop.set( Desktop::create(rxContext) );
126 28 : m_xDesktop->addTerminateListener( this );
127 : }
128 0 : catch( const Exception& )
129 : {
130 : DBG_UNHANDLED_EXCEPTION();
131 : }
132 28 : }
133 :
134 : struct TerminateFunctor : ::std::unary_function<ODatabaseModelImpl* , void>
135 : {
136 4 : void operator()( const ODatabaseModelImpl* _pModelImpl ) const
137 : {
138 : try
139 : {
140 6 : const Reference< XModel2> xModel( _pModelImpl ->getModel_noCreate(),UNO_QUERY_THROW );
141 2 : if ( !xModel->getControllers()->hasMoreElements() )
142 : {
143 2 : Reference<util::XCloseable> xCloseable(xModel,UNO_QUERY_THROW);
144 2 : xCloseable->close(sal_False);
145 2 : }
146 : }
147 0 : catch(const CloseVetoException&)
148 : {
149 0 : throw TerminationVetoException();
150 : }
151 2 : }
152 : };
153 :
154 10 : void SAL_CALL DatabaseDocumentLoader::queryTermination( const lang::EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException, std::exception)
155 : {
156 10 : ::std::list< const ODatabaseModelImpl* > aCopy(m_aDatabaseDocuments);
157 12 : ::std::for_each(aCopy.begin(),aCopy.end(),TerminateFunctor());
158 8 : }
159 :
160 8 : void SAL_CALL DatabaseDocumentLoader::notifyTermination( const lang::EventObject& /*Event*/ ) throw (RuntimeException, std::exception)
161 : {
162 8 : }
163 :
164 24 : void SAL_CALL DatabaseDocumentLoader::disposing( const lang::EventObject& /*Source*/ ) throw (RuntimeException, std::exception)
165 : {
166 24 : }
167 :
168 : // ODatabaseContext
169 :
170 28 : ODatabaseContext::ODatabaseContext( const Reference< XComponentContext >& _rxContext )
171 : :DatabaseAccessContext_Base(m_aMutex)
172 : ,m_aContext( _rxContext )
173 28 : ,m_aContainerListeners(m_aMutex)
174 : {
175 28 : m_pDatabaseDocumentLoader = new DatabaseDocumentLoader( _rxContext );
176 :
177 : #if HAVE_FEATURE_SCRIPTING
178 28 : ::basic::BasicManagerRepository::registerCreationListener( *this );
179 : #endif
180 :
181 28 : osl_atomic_increment( &m_refCount );
182 : {
183 28 : m_xDBRegistrationAggregate.set( createDataSourceRegistrations( m_aContext ), UNO_SET_THROW );
184 28 : m_xDatabaseRegistrations.set( m_xDBRegistrationAggregate, UNO_QUERY_THROW );
185 :
186 28 : m_xDBRegistrationAggregate->setDelegator( *this );
187 : }
188 28 : osl_atomic_decrement( &m_refCount );
189 28 : }
190 :
191 66 : ODatabaseContext::~ODatabaseContext()
192 : {
193 : #if HAVE_FEATURE_SCRIPTING
194 22 : ::basic::BasicManagerRepository::revokeCreationListener( *this );
195 : #endif
196 :
197 22 : if ( m_pDatabaseDocumentLoader )
198 22 : m_pDatabaseDocumentLoader->release();
199 :
200 22 : m_xDBRegistrationAggregate->setDelegator( NULL );
201 22 : m_xDBRegistrationAggregate.clear();
202 22 : m_xDatabaseRegistrations.clear();
203 44 : }
204 :
205 : // Helper
206 28 : OUString ODatabaseContext::getImplementationName_static() throw( RuntimeException )
207 : {
208 28 : return OUString("com.sun.star.comp.dba.ODatabaseContext");
209 : }
210 :
211 28 : Reference< XInterface > ODatabaseContext::Create(const Reference< XComponentContext >& _rxContext)
212 : {
213 28 : return *( new ODatabaseContext( _rxContext ) );
214 : }
215 :
216 28 : Sequence< OUString > ODatabaseContext::getSupportedServiceNames_static(void) throw( RuntimeException )
217 : {
218 28 : Sequence< OUString > aSNS( 1 );
219 28 : aSNS[0] = "com.sun.star.sdb.DatabaseContext";
220 28 : return aSNS;
221 : }
222 :
223 : // XServiceInfo
224 0 : OUString ODatabaseContext::getImplementationName( ) throw(RuntimeException, std::exception)
225 : {
226 0 : return getImplementationName_static();
227 : }
228 :
229 0 : sal_Bool ODatabaseContext::supportsService( const OUString& _rServiceName ) throw (RuntimeException, std::exception)
230 : {
231 0 : return cppu::supportsService(this, _rServiceName);
232 : }
233 :
234 0 : Sequence< OUString > ODatabaseContext::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
235 : {
236 0 : return getSupportedServiceNames_static();
237 : }
238 :
239 194 : Reference< XInterface > ODatabaseContext::impl_createNewDataSource()
240 : {
241 194 : ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( m_aContext, *this ) );
242 388 : Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() );
243 :
244 388 : return xDataSource.get();
245 : }
246 :
247 176 : Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( ) throw (Exception, RuntimeException, std::exception)
248 : {
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 176 : return impl_createNewDataSource();
252 : }
253 :
254 18 : Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException, std::exception)
255 : {
256 18 : ::comphelper::NamedValueCollection aArgs( _rArguments );
257 36 : OUString sURL = aArgs.getOrDefault( OUString(INFO_POOLURL), OUString() );
258 :
259 18 : Reference< XInterface > xDataSource;
260 18 : if ( !sURL.isEmpty() )
261 16 : xDataSource = getObject( sURL );
262 :
263 18 : if ( !xDataSource.is() )
264 18 : xDataSource = impl_createNewDataSource();
265 :
266 36 : return xDataSource;
267 : }
268 :
269 : // DatabaseAccessContext_Base
270 26 : void ODatabaseContext::disposing()
271 : {
272 : // notify our listener
273 26 : com::sun::star::lang::EventObject aDisposeEvent(static_cast< XContainer* >(this));
274 26 : m_aContainerListeners.disposeAndClear(aDisposeEvent);
275 :
276 : // dispose the data sources
277 : // disposing seems to remove elements, so work on copy for valid iterators
278 52 : ObjectCache objCopy(m_aDatabaseObjects);
279 26 : ObjectCache::iterator const aEnd = objCopy.end();
280 42 : for ( ObjectCache::iterator aIter = objCopy.begin();
281 : aIter != aEnd;
282 : ++aIter
283 : )
284 : {
285 16 : rtl::Reference< ODatabaseModelImpl > obj(aIter->second);
286 : // make sure obj is acquired and does not delete itself from within
287 : // dispose()
288 16 : obj->dispose();
289 16 : }
290 52 : m_aDatabaseObjects.clear();
291 26 : }
292 :
293 : // XNamingService
294 12 : Reference< XInterface > ODatabaseContext::getRegisteredObject(const OUString& _rName) throw( Exception, RuntimeException, std::exception )
295 : {
296 12 : MutexGuard aGuard(m_aMutex);
297 12 : ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
298 :
299 16 : OUString sURL( getDatabaseLocation( _rName ) );
300 :
301 4 : if ( sURL.isEmpty() )
302 : // there is a registration for this name, but no URL
303 0 : throw IllegalArgumentException();
304 :
305 : // check if URL is already loaded
306 8 : Reference< XInterface > xExistent = getObject( sURL );
307 4 : if ( xExistent.is() )
308 2 : return xExistent;
309 :
310 14 : return loadObjectFromURL( _rName, sURL );
311 : }
312 :
313 20 : Reference< XInterface > ODatabaseContext::loadObjectFromURL(const OUString& _rName,const OUString& _sURL)
314 : {
315 20 : INetURLObject aURL( _sURL );
316 20 : if ( aURL.GetProtocol() == INET_PROT_NOT_VALID )
317 2 : throw NoSuchElementException( _rName, *this );
318 :
319 : try
320 : {
321 18 : ::ucbhelper::Content aContent( _sURL, NULL, comphelper::getProcessComponentContext() );
322 18 : if ( !aContent.isDocument() )
323 : throw InteractiveIOException(
324 : _sURL, *this, InteractionClassification_ERROR, IOErrorCode_NO_FILE
325 0 : );
326 : }
327 0 : catch ( const InteractiveIOException& e )
328 : {
329 0 : if ( ( e.Code == IOErrorCode_NO_FILE )
330 0 : || ( e.Code == IOErrorCode_NOT_EXISTING )
331 0 : || ( e.Code == IOErrorCode_NOT_EXISTING_PATH )
332 : )
333 : {
334 : // #i40463# #i39187#
335 0 : OUString sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST ) );
336 0 : ::svt::OFileNotation aTransformer( _sURL );
337 :
338 0 : SQLException aError;
339 0 : aError.Message = sErrorMessage.replaceAll( "$file$", aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) );
340 :
341 0 : throw WrappedTargetException( _sURL, *this, makeAny( aError ) );
342 : }
343 0 : throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
344 : }
345 0 : catch( const Exception& )
346 : {
347 0 : throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
348 : }
349 :
350 : OSL_ENSURE( m_aDatabaseObjects.find( _sURL ) == m_aDatabaseObjects.end(),
351 : "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
352 :
353 36 : ::rtl::Reference< ODatabaseModelImpl > pModelImpl;
354 : {
355 18 : pModelImpl.set( new ODatabaseModelImpl( _rName, m_aContext, *this ) );
356 :
357 18 : Reference< XModel > xModel( pModelImpl->createNewModel_deliverOwnership( false ), UNO_SET_THROW );
358 36 : Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
359 :
360 36 : ::comphelper::NamedValueCollection aArgs;
361 18 : aArgs.put( "URL", _sURL );
362 18 : aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
363 18 : aArgs.put( "InteractionHandler", task::InteractionHandler::createWithParent(m_aContext, 0) );
364 :
365 36 : Sequence< PropertyValue > aResource( aArgs.getPropertyValues() );
366 18 : xLoad->load( aResource );
367 18 : xModel->attachResource( _sURL, aResource );
368 :
369 36 : ::utl::CloseableComponent aEnsureClose( xModel );
370 : }
371 :
372 18 : setTransientProperties( _sURL, *pModelImpl );
373 :
374 38 : return pModelImpl->getOrCreateDataSource().get();
375 : }
376 :
377 214 : void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
378 : {
379 214 : m_pDatabaseDocumentLoader->append(_rDataSourceModel);
380 214 : }
381 :
382 212 : void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
383 : {
384 212 : m_pDatabaseDocumentLoader->remove(_rDataSourceModel);
385 212 : }
386 :
387 228 : void ODatabaseContext::setTransientProperties(const OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel )
388 : {
389 228 : if ( m_aDatasourceProperties.end() == m_aDatasourceProperties.find(_sURL) )
390 290 : return;
391 : try
392 : {
393 166 : OUString sAuthFailedPassword;
394 332 : Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW );
395 166 : const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL];
396 166 : const PropertyValue* pProp = rSessionPersistentProps.getConstArray();
397 166 : const PropertyValue* pPropsEnd = rSessionPersistentProps.getConstArray() + rSessionPersistentProps.getLength();
398 498 : for ( ; pProp != pPropsEnd; ++pProp )
399 : {
400 332 : if ( pProp->Name == "AuthFailedPassword" )
401 : {
402 166 : OSL_VERIFY( pProp->Value >>= sAuthFailedPassword );
403 : }
404 : else
405 : {
406 166 : xDSProps->setPropertyValue( pProp->Name, pProp->Value );
407 : }
408 : }
409 :
410 332 : _rDataSourceModel.m_sFailedPassword = sAuthFailedPassword;
411 : }
412 0 : catch( const Exception& )
413 : {
414 : DBG_UNHANDLED_EXCEPTION();
415 : }
416 : }
417 :
418 178 : void ODatabaseContext::registerObject(const OUString& _rName, const Reference< XInterface > & _rxObject) throw( Exception, RuntimeException, std::exception )
419 : {
420 178 : MutexGuard aGuard(m_aMutex);
421 178 : ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
422 :
423 178 : if ( _rName.isEmpty() )
424 0 : throw IllegalArgumentException( OUString(), *this, 1 );
425 :
426 356 : Reference< XDocumentDataSource > xDocDataSource( _rxObject, UNO_QUERY );
427 356 : Reference< XModel > xModel( xDocDataSource.is() ? xDocDataSource->getDatabaseDocument() : Reference< XOfficeDatabaseDocument >(), UNO_QUERY );
428 178 : if ( !xModel.is() )
429 0 : throw IllegalArgumentException( OUString(), *this, 2 );
430 :
431 356 : OUString sURL = xModel->getURL();
432 178 : if ( sURL.isEmpty() )
433 0 : throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED ), *this, 2 );
434 :
435 178 : registerDatabaseLocation( _rName, sURL );
436 :
437 178 : ODatabaseSource::setName( xDocDataSource, _rName, ODatabaseSource::DBContextAccess() );
438 :
439 : // notify our container listeners
440 356 : ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(_rName), makeAny(_rxObject), Any());
441 356 : m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
442 178 : }
443 :
444 212 : void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl& _rModelImpl)
445 : {
446 212 : Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY );
447 424 : ::comphelper::NamedValueCollection aRememberProps;
448 :
449 : try
450 : {
451 : // get the info about the properties, check which ones are transient and not readonly
452 212 : Reference< XPropertySetInfo > xSetInfo;
453 212 : if (xSource.is())
454 212 : xSetInfo = xSource->getPropertySetInfo();
455 424 : Sequence< Property > aProperties;
456 212 : if (xSetInfo.is())
457 212 : aProperties = xSetInfo->getProperties();
458 :
459 212 : if (aProperties.getLength())
460 : {
461 212 : const Property* pProperties = aProperties.getConstArray();
462 2968 : for ( sal_Int32 i=0; i<aProperties.getLength(); ++i, ++pProperties )
463 : {
464 2756 : if ( ( ( pProperties->Attributes & PropertyAttribute::TRANSIENT) != 0 )
465 424 : && ( ( pProperties->Attributes & PropertyAttribute::READONLY) == 0 )
466 : )
467 : {
468 : // found such a property
469 212 : aRememberProps.put( pProperties->Name, xSource->getPropertyValue( pProperties->Name ) );
470 : }
471 : }
472 212 : }
473 : }
474 0 : catch ( const Exception& )
475 : {
476 : DBG_UNHANDLED_EXCEPTION();
477 : }
478 :
479 : // additionally, remember the "failed password", which is not available as property
480 : // #i86178#
481 212 : aRememberProps.put( "AuthFailedPassword", _rModelImpl.m_sFailedPassword );
482 :
483 424 : OUString sDocumentURL( _rModelImpl.getURL() );
484 212 : if ( m_aDatabaseObjects.find( sDocumentURL ) != m_aDatabaseObjects.end() )
485 : {
486 188 : m_aDatasourceProperties[ sDocumentURL ] = aRememberProps.getPropertyValues();
487 : }
488 24 : else if ( m_aDatabaseObjects.find( _rModelImpl.m_sName ) != m_aDatabaseObjects.end() )
489 : {
490 : OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
491 : // all the code should have been changed so that registration is by URL only
492 0 : m_aDatasourceProperties[ _rModelImpl.m_sName ] = aRememberProps.getPropertyValues();
493 : }
494 : else
495 : {
496 : OSL_ENSURE( sDocumentURL.isEmpty() && _rModelImpl.m_sName.isEmpty() ,
497 : "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
498 212 : }
499 212 : }
500 :
501 2 : void SAL_CALL ODatabaseContext::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException, std::exception)
502 : {
503 2 : m_aContainerListeners.addInterface(_rxListener);
504 2 : }
505 :
506 2 : void SAL_CALL ODatabaseContext::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException, std::exception)
507 : {
508 2 : m_aContainerListeners.removeInterface(_rxListener);
509 2 : }
510 :
511 344 : void ODatabaseContext::revokeObject(const OUString& _rName) throw( Exception, RuntimeException, std::exception )
512 : {
513 344 : ClearableMutexGuard aGuard(m_aMutex);
514 344 : ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
515 :
516 516 : OUString sURL = getDatabaseLocation( _rName );
517 :
518 172 : revokeDatabaseLocation( _rName );
519 : // will throw if something goes wrong
520 :
521 172 : if ( m_aDatabaseObjects.find( _rName ) != m_aDatabaseObjects.end() )
522 : {
523 0 : m_aDatasourceProperties[ sURL ] = m_aDatasourceProperties[ _rName ];
524 : }
525 :
526 : // check if URL is already loaded
527 172 : ObjectCache::iterator aExistent = m_aDatabaseObjects.find( sURL );
528 172 : if ( aExistent != m_aDatabaseObjects.end() )
529 20 : m_aDatabaseObjects.erase( aExistent );
530 :
531 : // notify our container listeners
532 344 : ContainerEvent aEvent( *this, makeAny( _rName ), Any(), Any() );
533 172 : aGuard.clear();
534 516 : m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
535 172 : }
536 :
537 124 : sal_Bool SAL_CALL ODatabaseContext::hasRegisteredDatabase( const OUString& _Name ) throw (IllegalArgumentException, RuntimeException, std::exception)
538 : {
539 124 : return m_xDatabaseRegistrations->hasRegisteredDatabase( _Name );
540 : }
541 :
542 8 : Sequence< OUString > SAL_CALL ODatabaseContext::getRegistrationNames() throw (RuntimeException, std::exception)
543 : {
544 8 : return m_xDatabaseRegistrations->getRegistrationNames();
545 : }
546 :
547 470 : OUString SAL_CALL ODatabaseContext::getDatabaseLocation( const OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
548 : {
549 470 : return m_xDatabaseRegistrations->getDatabaseLocation( _Name );
550 : }
551 :
552 178 : void SAL_CALL ODatabaseContext::registerDatabaseLocation( const OUString& _Name, const OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException, std::exception)
553 : {
554 178 : m_xDatabaseRegistrations->registerDatabaseLocation( _Name, _Location );
555 178 : }
556 :
557 172 : void SAL_CALL ODatabaseContext::revokeDatabaseLocation( const OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException, std::exception)
558 : {
559 172 : m_xDatabaseRegistrations->revokeDatabaseLocation( _Name );
560 172 : }
561 :
562 0 : void SAL_CALL ODatabaseContext::changeDatabaseLocation( const OUString& _Name, const OUString& _NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException, std::exception)
563 : {
564 0 : m_xDatabaseRegistrations->changeDatabaseLocation( _Name, _NewLocation );
565 0 : }
566 :
567 0 : sal_Bool SAL_CALL ODatabaseContext::isDatabaseRegistrationReadOnly( const OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
568 : {
569 0 : return m_xDatabaseRegistrations->isDatabaseRegistrationReadOnly( _Name );
570 : }
571 :
572 2 : void SAL_CALL ODatabaseContext::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException, std::exception)
573 : {
574 2 : m_xDatabaseRegistrations->addDatabaseRegistrationsListener( _Listener );
575 2 : }
576 :
577 2 : void SAL_CALL ODatabaseContext::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException, std::exception)
578 : {
579 2 : m_xDatabaseRegistrations->removeDatabaseRegistrationsListener( _Listener );
580 2 : }
581 :
582 : // ::com::sun::star::container::XElementAccess
583 2 : Type ODatabaseContext::getElementType( ) throw(RuntimeException, std::exception)
584 : {
585 2 : return cppu::UnoType<XDataSource>::get();
586 : }
587 :
588 2 : sal_Bool ODatabaseContext::hasElements(void) throw( RuntimeException, std::exception )
589 : {
590 2 : MutexGuard aGuard(m_aMutex);
591 2 : ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
592 :
593 2 : return 0 != getElementNames().getLength();
594 : }
595 :
596 : // ::com::sun::star::container::XEnumerationAccess
597 2 : Reference< ::com::sun::star::container::XEnumeration > ODatabaseContext::createEnumeration(void) throw( RuntimeException, std::exception )
598 : {
599 2 : MutexGuard aGuard(m_aMutex);
600 2 : return new ::comphelper::OEnumerationByName(static_cast<XNameAccess*>(this));
601 : }
602 :
603 : // ::com::sun::star::container::XNameAccess
604 116 : Any ODatabaseContext::getByName(const OUString& _rName) throw( NoSuchElementException,
605 : WrappedTargetException, RuntimeException, std::exception )
606 : {
607 116 : MutexGuard aGuard(m_aMutex);
608 116 : ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
609 116 : if ( _rName.isEmpty() )
610 0 : throw NoSuchElementException(_rName, *this);
611 :
612 : try
613 : {
614 116 : Reference< XInterface > xExistent = getObject( _rName );
615 116 : if ( xExistent.is() )
616 0 : return makeAny( xExistent );
617 :
618 : // see whether this is an registered name
619 232 : OUString sURL;
620 116 : if ( hasRegisteredDatabase( _rName ) )
621 : {
622 114 : sURL = getDatabaseLocation( _rName );
623 : // is the object cached under its URL?
624 114 : xExistent = getObject( sURL );
625 : }
626 : else
627 : // interpret the name as URL
628 2 : sURL = _rName;
629 :
630 116 : if ( !xExistent.is() )
631 : // try to load this as URL
632 18 : xExistent = loadObjectFromURL( _rName, sURL );
633 230 : return makeAny( xExistent );
634 : }
635 4 : catch (const NoSuchElementException&)
636 : { // let these exceptions through
637 2 : throw;
638 : }
639 0 : catch (const WrappedTargetException&)
640 : { // let these exceptions through
641 0 : throw;
642 : }
643 0 : catch (const RuntimeException&)
644 : { // let these exceptions through
645 0 : throw;
646 : }
647 0 : catch (const Exception&)
648 : { // exceptions other than the speciafied ones -> wrap
649 0 : Any aError = ::cppu::getCaughtException();
650 0 : throw WrappedTargetException(_rName, *this, aError );
651 116 : }
652 : }
653 :
654 8 : Sequence< OUString > ODatabaseContext::getElementNames(void) throw( RuntimeException, std::exception )
655 : {
656 8 : MutexGuard aGuard(m_aMutex);
657 8 : ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
658 :
659 8 : return getRegistrationNames();
660 : }
661 :
662 8 : sal_Bool ODatabaseContext::hasByName(const OUString& _rName) throw( RuntimeException, std::exception )
663 : {
664 8 : MutexGuard aGuard(m_aMutex);
665 8 : ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
666 :
667 8 : return hasRegisteredDatabase( _rName );
668 : }
669 :
670 250 : Reference< XInterface > ODatabaseContext::getObject( const OUString& _rURL )
671 : {
672 250 : ObjectCache::iterator aFind = m_aDatabaseObjects.find( _rURL );
673 250 : Reference< XInterface > xExistent;
674 250 : if ( aFind != m_aDatabaseObjects.end() )
675 100 : xExistent = aFind->second->getOrCreateDataSource();
676 250 : return xExistent;
677 : }
678 :
679 210 : void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl )
680 : {
681 210 : OUString sURL( _rModelImpl.getURL() );
682 : #if OSL_DEBUG_LEVEL > 1
683 : OSL_TRACE( "DatabaseContext: registering %s", OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() );
684 : #endif
685 210 : if ( m_aDatabaseObjects.find( sURL ) == m_aDatabaseObjects.end() )
686 : {
687 210 : m_aDatabaseObjects[ sURL ] = &_rModelImpl;
688 210 : setTransientProperties( sURL, _rModelImpl );
689 : }
690 : else
691 210 : OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
692 210 : }
693 :
694 208 : void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl )
695 : {
696 208 : OUString sURL( _rModelImpl.getURL() );
697 : #if OSL_DEBUG_LEVEL > 1
698 : OSL_TRACE( "DatabaseContext: deregistering %s", OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() );
699 : #endif
700 208 : m_aDatabaseObjects.erase( sURL );
701 208 : }
702 :
703 0 : void ODatabaseContext::databaseDocumentURLChange( const OUString& _rOldURL, const OUString& _rNewURL )
704 : {
705 : #if OSL_DEBUG_LEVEL > 1
706 : OSL_TRACE( "DatabaseContext: changing registration from %s to %s",
707 : OUStringToOString( _rOldURL, RTL_TEXTENCODING_UTF8 ).getStr(),
708 : OUStringToOString( _rNewURL, RTL_TEXTENCODING_UTF8 ).getStr() );
709 : #endif
710 0 : ObjectCache::iterator oldPos = m_aDatabaseObjects.find( _rOldURL );
711 0 : ENSURE_OR_THROW( oldPos != m_aDatabaseObjects.end(), "illegal old database document URL" );
712 0 : ObjectCache::iterator newPos = m_aDatabaseObjects.find( _rNewURL );
713 0 : ENSURE_OR_THROW( newPos == m_aDatabaseObjects.end(), "illegal new database document URL" );
714 :
715 0 : m_aDatabaseObjects[ _rNewURL ] = oldPos->second;
716 0 : m_aDatabaseObjects.erase( oldPos );
717 0 : }
718 :
719 2 : sal_Int64 SAL_CALL ODatabaseContext::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException, std::exception)
720 : {
721 2 : if (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
722 2 : return reinterpret_cast<sal_Int64>(this);
723 :
724 0 : return 0;
725 : }
726 :
727 4 : Sequence< sal_Int8 > ODatabaseContext::getUnoTunnelImplementationId()
728 : {
729 : static ::cppu::OImplementationId * pId = 0;
730 4 : if (! pId)
731 : {
732 2 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
733 2 : if (! pId)
734 : {
735 2 : static ::cppu::OImplementationId aId;
736 2 : pId = &aId;
737 2 : }
738 : }
739 4 : return pId->getImplementationId();
740 : }
741 :
742 18 : void ODatabaseContext::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager )
743 : {
744 : #if !HAVE_FEATURE_SCRIPTING
745 : (void) _rxForDocument;
746 : (void) _rBasicManager;
747 : #else
748 : // if it's a database document ...
749 18 : Reference< XOfficeDatabaseDocument > xDatabaseDocument( _rxForDocument, UNO_QUERY );
750 : // ... or a sub document of a database document ...
751 18 : if ( !xDatabaseDocument.is() )
752 : {
753 18 : Reference< XChild > xDocAsChild( _rxForDocument, UNO_QUERY );
754 18 : if ( xDocAsChild.is() )
755 6 : xDatabaseDocument.set( xDocAsChild->getParent(), UNO_QUERY );
756 : }
757 :
758 : // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
759 18 : if ( xDatabaseDocument.is() )
760 0 : _rBasicManager.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument ) );
761 : #endif
762 18 : }
763 :
764 : } // namespace dbaccess
765 :
766 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|