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