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