LibreOffice Module dbaccess (master) 1
databasecontext.cxx
Go to the documentation of this file.
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 <strings.hrc>
23#include <strings.hxx>
24#include <core_resource.hxx>
25#include <databasecontext.hxx>
27#include "datasource.hxx"
28
29#include <com/sun/star/beans/PropertyAttribute.hpp>
30#include <com/sun/star/beans/XPropertySet.hpp>
31#include <com/sun/star/document/MacroExecMode.hpp>
32#include <com/sun/star/frame/Desktop.hpp>
33#include <com/sun/star/frame/TerminationVetoException.hpp>
34#include <com/sun/star/frame/XLoadable.hpp>
35#include <com/sun/star/frame/XModel.hpp>
36#include <com/sun/star/frame/XModel2.hpp>
37#include <com/sun/star/frame/XTerminateListener.hpp>
38#include <com/sun/star/lang/DisposedException.hpp>
39#include <com/sun/star/registry/InvalidRegistryException.hpp>
40#include <com/sun/star/sdbc/XDataSource.hpp>
41#include <com/sun/star/task/InteractionClassification.hpp>
42#include <com/sun/star/ucb/InteractiveIOException.hpp>
43#include <com/sun/star/ucb/IOErrorCode.hpp>
44#include <com/sun/star/uri/UriReferenceFactory.hpp>
45#include <com/sun/star/task/InteractionHandler.hpp>
46#include <com/sun/star/util/CloseVetoException.hpp>
47#include <com/sun/star/util/XCloseable.hpp>
48
49#include <basic/basmgr.hxx>
57#include <cppuhelper/weak.hxx>
58#include <rtl/uri.hxx>
59#include <sal/log.hxx>
60#include <svl/filenotation.hxx>
62#include <tools/urlobj.hxx>
63#include <ucbhelper/content.hxx>
64#include <rtl/ref.hxx>
66#include <vector>
67
68using namespace ::com::sun::star::sdbc;
69using namespace ::com::sun::star::sdb;
70using namespace ::com::sun::star::beans;
71using namespace ::com::sun::star::uno;
72using namespace ::com::sun::star::document;
73using namespace ::com::sun::star::frame;
74using namespace ::com::sun::star::lang;
75using namespace ::com::sun::star::container;
76using namespace ::com::sun::star::util;
77using namespace ::com::sun::star::registry;
78using namespace ::com::sun::star;
79using namespace ::cppu;
80using namespace ::osl;
81using namespace ::utl;
82
83using ::com::sun::star::task::InteractionClassification_ERROR;
84using ::com::sun::star::ucb::IOErrorCode_NO_FILE;
85using ::com::sun::star::ucb::InteractiveIOException;
86using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING;
87using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH;
88
89namespace dbaccess
90{
91
92 typedef ::cppu::WeakImplHelper< XTerminateListener
95 {
96 private:
97 Reference< XDesktop2 > m_xDesktop;
98 std::vector< const ODatabaseModelImpl* > m_aDatabaseDocuments;
99
100 public:
101 explicit DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext);
102
103 void append(const ODatabaseModelImpl& _rModelImpl )
104 {
105 m_aDatabaseDocuments.emplace_back(&_rModelImpl);
106 }
107
108 void remove(const ODatabaseModelImpl& _rModelImpl)
109 {
110 m_aDatabaseDocuments.erase(std::find(m_aDatabaseDocuments.begin(), m_aDatabaseDocuments.end(), &_rModelImpl));
111 }
112
113
114 private:
115 // XTerminateListener
116 virtual void SAL_CALL queryTermination( const lang::EventObject& Event ) override;
117 virtual void SAL_CALL notifyTermination( const lang::EventObject& Event ) override;
118 // XEventListener
119 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
120 };
121
122 DatabaseDocumentLoader::DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext )
123 {
124 try
125 {
126 m_xDesktop.set( Desktop::create(rxContext) );
127 m_xDesktop->addTerminateListener( this );
128 }
129 catch( const Exception& )
130 {
131 DBG_UNHANDLED_EXCEPTION("dbaccess");
132 }
133 }
134
135 void SAL_CALL DatabaseDocumentLoader::queryTermination( const lang::EventObject& /*Event*/ )
136 {
137 std::vector< const ODatabaseModelImpl* > aCpy(m_aDatabaseDocuments);
138 for( const auto& pCopy : aCpy )
139 {
140 try
141 {
142 const Reference< XModel2 > xMod( pCopy->getModel_noCreate(),
143 UNO_QUERY_THROW );
144 if( !xMod->getControllers()->hasMoreElements() )
145 {
146 Reference< util::XCloseable > xClose( xMod,
147 UNO_QUERY_THROW );
148 xClose->close( false );
149 }
150 }
151 catch( const CloseVetoException& )
152 {
153 throw TerminationVetoException();
154 }
155 }
156 }
157
158 void SAL_CALL DatabaseDocumentLoader::notifyTermination( const lang::EventObject& /*Event*/ )
159 {
160 }
161
162 void SAL_CALL DatabaseDocumentLoader::disposing( const lang::EventObject& /*Source*/ )
163 {
164 }
165
166// ODatabaseContext
167
168ODatabaseContext::ODatabaseContext( const Reference< XComponentContext >& _rxContext )
170 ,m_aContext( _rxContext )
171 ,m_aContainerListeners(m_aMutex)
172{
174
175#if HAVE_FEATURE_SCRIPTING
177#endif
178
179 osl_atomic_increment( &m_refCount );
180 {
183
184 m_xDBRegistrationAggregate->setDelegator( *this );
185 }
186 osl_atomic_decrement( &m_refCount );
187}
188
190{
191#if HAVE_FEATURE_SCRIPTING
193#endif
194
196 m_xDBRegistrationAggregate->setDelegator( nullptr );
199}
200
201// XServiceInfo
203{
204 return "com.sun.star.comp.dba.ODatabaseContext";
205}
206
207sal_Bool ODatabaseContext::supportsService( const OUString& _rServiceName )
208{
209 return cppu::supportsService(this, _rServiceName);
210}
211
213{
214 return { "com.sun.star.sdb.DatabaseContext" };
215}
216
218{
219 ::rtl::Reference pImpl( new ODatabaseModelImpl( m_aContext, *this ) );
220 Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() );
221
222 return xDataSource;
223}
224
225Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( )
226{
227 // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
228 // has been called at the DatabaseDocument).
230}
231
232Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments )
233{
234 ::comphelper::NamedValueCollection aArgs( _rArguments );
235 OUString sURL = aArgs.getOrDefault( INFO_POOLURL, OUString() );
236
237 Reference< XInterface > xDataSource;
238 if ( !sURL.isEmpty() )
239 xDataSource = getObject( sURL );
240
241 if ( !xDataSource.is() )
242 xDataSource = impl_createNewDataSource();
243
244 return xDataSource;
245}
246
247// DatabaseAccessContext_Base
249{
250 // notify our listener
251 css::lang::EventObject aDisposeEvent(static_cast< XContainer* >(this));
253
254 // dispose the data sources
255 // disposing seems to remove elements, so work on copy for valid iterators
256 ObjectCache objCopy;
257 objCopy.swap(m_aDatabaseObjects);
258 for (auto const& elem : objCopy)
259 {
261 // make sure obj is acquired and does not delete itself from within
262 // dispose()
263 obj->dispose();
264 }
265}
266
267// XNamingService
268Reference< XInterface > ODatabaseContext::getRegisteredObject(const OUString& _rName)
269{
270 MutexGuard aGuard(m_aMutex);
271 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
272
273 OUString sURL( getDatabaseLocation( _rName ) );
274
275 if ( sURL.isEmpty() )
276 // there is a registration for this name, but no URL
277 throw IllegalArgumentException();
278
279 // check if URL is already loaded
280 Reference< XInterface > xExistent = getObject( sURL );
281 if ( xExistent.is() )
282 return xExistent;
283
284 return loadObjectFromURL( _rName, sURL );
285}
286
287Reference< XInterface > ODatabaseContext::loadObjectFromURL(const OUString& _rName,const OUString& _sURL)
288{
289 INetURLObject aURL( _sURL );
290
291 if ( aURL.GetProtocol() == INetProtocol::NotValid )
292 throw NoSuchElementException( _rName, *this );
293
294 bool bEmbeddedDataSource = aURL.isSchemeEqualTo(INetProtocol::VndSunStarPkg);
295 try
296 {
297 if (!bEmbeddedDataSource)
298 {
300 if ( !aContent.isDocument() )
301 throw InteractiveIOException(
302 _sURL, *this, InteractionClassification_ERROR, IOErrorCode_NO_FILE
303 );
304 }
305 }
306 catch ( const InteractiveIOException& e )
307 {
308 if ( ( e.Code == IOErrorCode_NO_FILE )
309 || ( e.Code == IOErrorCode_NOT_EXISTING )
310 || ( e.Code == IOErrorCode_NOT_EXISTING_PATH )
311 )
312 {
313 // #i40463# #i39187#
314 OUString sErrorMessage( DBA_RES( RID_STR_FILE_DOES_NOT_EXIST ) );
315 ::svt::OFileNotation aTransformer( _sURL );
316
317 SQLException aError;
318 aError.Message = sErrorMessage.replaceAll( "$file$", aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) );
319
320 throw WrappedTargetException( _sURL, *this, Any( aError ) );
321 }
322 throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
323 }
324 catch( const Exception& )
325 {
326 throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
327 }
328
329 OSL_ENSURE( m_aDatabaseObjects.find( _sURL ) == m_aDatabaseObjects.end(),
330 "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
331
333 {
334 pModelImpl.set( new ODatabaseModelImpl( _rName, m_aContext, *this ) );
335
336 Reference< XModel > xModel( pModelImpl->createNewModel_deliverOwnership(), UNO_SET_THROW );
337 Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
338
340 aArgs.put( "URL", _sURL );
341 aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
342 aArgs.put( "InteractionHandler", task::InteractionHandler::createWithParent(m_aContext, nullptr) );
343 if (bEmbeddedDataSource)
344 {
345 // In this case the host contains the real path, and the path is the embedded stream name.
346 auto const uri = css::uri::UriReferenceFactory::create(m_aContext)->parse(_sURL);
347 if (uri.is() && uri->isAbsolute()
348 && uri->hasAuthority() && !uri->hasQuery() && !uri->hasFragment())
349 {
350 auto const auth = uri->getAuthority();
351 auto const decAuth = rtl::Uri::decode(
352 auth, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
353 if (auth.isEmpty() == decAuth.isEmpty()) {
354 // Decoding of auth to UTF-8 succeeded:
355 OUString sBaseURI = decAuth + uri->getPath();
356 aArgs.put("BaseURI", sBaseURI);
357 } else {
358 SAL_WARN(
359 "dbaccess.core",
360 "<" << _sURL << "> cannot be parse as vnd.sun.star.pkg URL");
361 }
362 } else {
363 SAL_WARN(
364 "dbaccess.core", "<" << _sURL << "> cannot be parse as vnd.sun.star.pkg URL");
365 }
366 }
367
368 Sequence< PropertyValue > aResource( aArgs.getPropertyValues() );
369 xLoad->load( aResource );
370 xModel->attachResource( _sURL, aResource );
371
372 ::utl::CloseableComponent aEnsureClose( xModel );
373 }
374
375 setTransientProperties( _sURL, *pModelImpl );
376
377 return pModelImpl->getOrCreateDataSource();
378}
379
381{
382 m_xDatabaseDocumentLoader->append(_rDataSourceModel);
383}
384
386{
387 m_xDatabaseDocumentLoader->remove(_rDataSourceModel);
388}
389
390void ODatabaseContext::setTransientProperties(const OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel )
391{
392 if ( m_aDatasourceProperties.end() == m_aDatasourceProperties.find(_sURL) )
393 return;
394 try
395 {
396 OUString sAuthFailedPassword;
397 Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW );
398 const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL];
399 for ( auto const & prop : rSessionPersistentProps )
400 {
401 if ( prop.Name == "AuthFailedPassword" )
402 {
403 OSL_VERIFY( prop.Value >>= sAuthFailedPassword );
404 }
405 else
406 {
407 xDSProps->setPropertyValue( prop.Name, prop.Value );
408 }
409 }
410
411 _rDataSourceModel.m_sFailedPassword = sAuthFailedPassword;
412 }
413 catch( const Exception& )
414 {
415 DBG_UNHANDLED_EXCEPTION("dbaccess");
416 }
417}
418
419void ODatabaseContext::registerObject(const OUString& _rName, const Reference< XInterface > & _rxObject)
420{
421 if ( _rName.isEmpty() )
422 throw IllegalArgumentException( OUString(), *this, 1 );
423
424 Reference< XDocumentDataSource > xDocDataSource( _rxObject, UNO_QUERY );
425 Reference< XModel > xModel( xDocDataSource.is() ? xDocDataSource->getDatabaseDocument() : Reference< XOfficeDatabaseDocument >(), UNO_QUERY );
426 if ( !xModel.is() )
427 throw IllegalArgumentException( OUString(), *this, 2 );
428
429 OUString sURL = xModel->getURL();
430 if ( sURL.isEmpty() )
431 throw IllegalArgumentException( DBA_RES( RID_STR_DATASOURCE_NOT_STORED ), *this, 2 );
432
433 { // avoid deadlocks: lock m_aMutex after checking arguments
434 MutexGuard aGuard(m_aMutex);
435 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
436
437 registerDatabaseLocation( _rName, sURL );
438
440 }
441
442 // notify our container listeners
443 ContainerEvent aEvent(static_cast<XContainer*>(this), Any(_rName), Any(_rxObject), Any());
444 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
445}
446
448{
449 Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY );
451
452 try
453 {
454 // get the info about the properties, check which ones are transient and not readonly
455 Reference< XPropertySetInfo > xSetInfo;
456 if (xSource.is())
457 xSetInfo = xSource->getPropertySetInfo();
458 Sequence< Property > aProperties;
459 if (xSetInfo.is())
460 aProperties = xSetInfo->getProperties();
461
462 for ( const Property& rProperty : std::as_const(aProperties) )
463 {
464 if ( ( ( rProperty.Attributes & PropertyAttribute::TRANSIENT) != 0 )
465 && ( ( rProperty.Attributes & PropertyAttribute::READONLY) == 0 )
466 )
467 {
468 // found such a property
469 aRememberProps.put( rProperty.Name, xSource->getPropertyValue( rProperty.Name ) );
470 }
471 }
472 }
473 catch ( const Exception& )
474 {
475 DBG_UNHANDLED_EXCEPTION("dbaccess");
476 }
477
478 // additionally, remember the "failed password", which is not available as property
479 // #i86178#
480 aRememberProps.put( "AuthFailedPassword", _rModelImpl.m_sFailedPassword );
481
482 OUString sDocumentURL( _rModelImpl.getURL() );
483 if ( m_aDatabaseObjects.find( sDocumentURL ) != m_aDatabaseObjects.end() )
484 {
485 m_aDatasourceProperties[ sDocumentURL ] = aRememberProps.getPropertyValues();
486 }
487 else if ( m_aDatabaseObjects.find( _rModelImpl.m_sName ) != m_aDatabaseObjects.end() )
488 {
489 OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
490 // all the code should have been changed so that registration is by URL only
491 m_aDatasourceProperties[ _rModelImpl.m_sName ] = aRememberProps.getPropertyValues();
492 }
493 else
494 {
495 OSL_ENSURE( sDocumentURL.isEmpty() && _rModelImpl.m_sName.isEmpty() ,
496 "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
497 }
498}
499
500void SAL_CALL ODatabaseContext::addContainerListener( const Reference< XContainerListener >& _rxListener )
501{
503}
504
505void SAL_CALL ODatabaseContext::removeContainerListener( const Reference< XContainerListener >& _rxListener )
506{
508}
509
510void ODatabaseContext::revokeObject(const OUString& _rName)
511{
512 ClearableMutexGuard aGuard(m_aMutex);
513 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
514
515 OUString sURL = getDatabaseLocation( _rName );
516
517 revokeDatabaseLocation( _rName );
518 // will throw if something goes wrong
519
520 if ( m_aDatabaseObjects.find( _rName ) != m_aDatabaseObjects.end() )
521 {
523 }
524
525 // check if URL is already loaded
526 ObjectCache::const_iterator aExistent = m_aDatabaseObjects.find( sURL );
527 if ( aExistent != m_aDatabaseObjects.end() )
528 m_aDatabaseObjects.erase( aExistent );
529
530 // notify our container listeners
531 ContainerEvent aEvent( *this, Any( _rName ), Any(), Any() );
532 aGuard.clear();
533 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
534}
535
536sal_Bool SAL_CALL ODatabaseContext::hasRegisteredDatabase( const OUString& Name )
537{
538 return m_xDatabaseRegistrations->hasRegisteredDatabase( Name );
539}
540
541Sequence< OUString > SAL_CALL ODatabaseContext::getRegistrationNames()
542{
543 return m_xDatabaseRegistrations->getRegistrationNames();
544}
545
546OUString SAL_CALL ODatabaseContext::getDatabaseLocation( const OUString& Name )
547{
548 return m_xDatabaseRegistrations->getDatabaseLocation( Name );
549}
550
551void SAL_CALL ODatabaseContext::registerDatabaseLocation( const OUString& Name, const OUString& Location )
552{
553 m_xDatabaseRegistrations->registerDatabaseLocation( Name, Location );
554}
555
556void SAL_CALL ODatabaseContext::revokeDatabaseLocation( const OUString& Name )
557{
558 m_xDatabaseRegistrations->revokeDatabaseLocation( Name );
559}
560
561void SAL_CALL ODatabaseContext::changeDatabaseLocation( const OUString& Name, const OUString& NewLocation )
562{
563 m_xDatabaseRegistrations->changeDatabaseLocation( Name, NewLocation );
564}
565
567{
568 return m_xDatabaseRegistrations->isDatabaseRegistrationReadOnly( Name );
569}
570
571void SAL_CALL ODatabaseContext::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener )
572{
573 m_xDatabaseRegistrations->addDatabaseRegistrationsListener( Listener );
574}
575
576void SAL_CALL ODatabaseContext::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener )
577{
578 m_xDatabaseRegistrations->removeDatabaseRegistrationsListener( Listener );
579}
580
581// css::container::XElementAccess
583{
585}
586
588{
589 MutexGuard aGuard(m_aMutex);
590 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
591
592 return getElementNames().hasElements();
593}
594
595// css::container::XEnumerationAccess
596Reference< css::container::XEnumeration > ODatabaseContext::createEnumeration()
597{
598 MutexGuard aGuard(m_aMutex);
599 return new ::comphelper::OEnumerationByName(static_cast<XNameAccess*>(this));
600}
601
602// css::container::XNameAccess
603Any ODatabaseContext::getByName(const OUString& _rName)
604{
605 MutexGuard aGuard(m_aMutex);
606 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
607 if ( _rName.isEmpty() )
608 throw NoSuchElementException(_rName, *this);
609
610 try
611 {
612 Reference< XInterface > xExistent = getObject( _rName );
613 if ( xExistent.is() )
614 return Any( xExistent );
615
616 // see whether this is a registered name
617 OUString sURL;
618 if ( hasRegisteredDatabase( _rName ) )
619 {
620 sURL = getDatabaseLocation( _rName );
621 // is the object cached under its URL?
622 xExistent = getObject( sURL );
623 }
624 else
625 // interpret the name as URL
626 sURL = _rName;
627
628 if ( !xExistent.is() )
629 // try to load this as URL
630 xExistent = loadObjectFromURL( _rName, sURL );
631 return Any( xExistent );
632 }
633 catch (const NoSuchElementException&)
634 { // let these exceptions through
635 throw;
636 }
637 catch (const WrappedTargetException&)
638 { // let these exceptions through
639 throw;
640 }
641 catch (const RuntimeException&)
642 { // let these exceptions through
643 throw;
644 }
645 catch (const Exception&)
646 { // exceptions other than the specified ones -> wrap
647 Any aError = ::cppu::getCaughtException();
648 throw WrappedTargetException(_rName, *this, aError );
649 }
650}
651
653{
654 MutexGuard aGuard(m_aMutex);
655 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
656
657 return getRegistrationNames();
658}
659
661{
662 MutexGuard aGuard(m_aMutex);
663 ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
664
665 return hasRegisteredDatabase( _rName );
666}
667
668Reference< XInterface > ODatabaseContext::getObject( const OUString& _rURL )
669{
670 ObjectCache::const_iterator aFind = m_aDatabaseObjects.find( _rURL );
671 Reference< XInterface > xExistent;
672 if ( aFind != m_aDatabaseObjects.end() )
673 xExistent = aFind->second->getOrCreateDataSource();
674 return xExistent;
675}
676
678{
679 OUString sURL( _rModelImpl.getURL() );
680 SAL_INFO("dbaccess.core", "DatabaseContext: registering " << sURL);
681 if ( m_aDatabaseObjects.find( sURL ) == m_aDatabaseObjects.end() )
682 {
683 m_aDatabaseObjects[ sURL ] = &_rModelImpl;
684 setTransientProperties( sURL, _rModelImpl );
685 }
686 else
687 OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
688}
689
691{
692 const OUString& sURL( _rModelImpl.getURL() );
693 SAL_INFO("dbaccess.core", "DatabaseContext: deregistering " << sURL);
694 m_aDatabaseObjects.erase( sURL );
695}
696
697void ODatabaseContext::databaseDocumentURLChange( const OUString& _rOldURL, const OUString& _rNewURL )
698{
699 SAL_INFO("dbaccess.core", "DatabaseContext: changing registrations from " << _rOldURL <<
700 " to " << _rNewURL);
701 ObjectCache::const_iterator oldPos = m_aDatabaseObjects.find( _rOldURL );
702 ENSURE_OR_THROW( oldPos != m_aDatabaseObjects.end(), "illegal old database document URL" );
703 ObjectCache::const_iterator newPos = m_aDatabaseObjects.find( _rNewURL );
704 ENSURE_OR_THROW( newPos == m_aDatabaseObjects.end(), "illegal new database document URL" );
705
706 m_aDatabaseObjects[ _rNewURL ] = oldPos->second;
707 m_aDatabaseObjects.erase( oldPos );
708}
709
710void ODatabaseContext::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager )
711{
712#if !HAVE_FEATURE_SCRIPTING
713 (void) _rxForDocument;
714 (void) _rBasicManager;
715#else
716 // if it's a database document ...
717 Reference< XOfficeDatabaseDocument > xDatabaseDocument( _rxForDocument, UNO_QUERY );
718 // ... or a sub document of a database document ...
719 if ( !xDatabaseDocument.is() )
720 {
721 Reference< XChild > xDocAsChild( _rxForDocument, UNO_QUERY );
722 if ( xDocAsChild.is() )
723 xDatabaseDocument.set( xDocAsChild->getParent(), UNO_QUERY );
724 }
725
726 // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
727 if ( xDatabaseDocument.is() )
728 _rBasicManager.SetGlobalUNOConstant( "ThisDatabaseDocument", Any( xDatabaseDocument ) );
729#endif
730}
731
732} // namespace dbaccess
733
734
735extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
737 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
738{
739 return cppu::acquire(new dbaccess::ODatabaseContext(context));
740}
741
742/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
AnyEventRef aEvent
void SetGlobalUNOConstant(const OUString &rName, const css::uno::Any &_rValue, css::uno::Any *pOldValue=nullptr)
static void registerCreationListener(BasicManagerCreationListener &_rListener)
static void revokeCreationListener(BasicManagerCreationListener &_rListener)
bool put(const OUString &_rValueName, const VALUE_TYPE &_rValue)
css::uno::Sequence< css::beans::PropertyValue > getPropertyValues() const
VALUE_TYPE getOrDefault(const OUString &_rValueName, const VALUE_TYPE &_rDefault) const
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
css::uno::Type const & get()
void remove(const ODatabaseModelImpl &_rModelImpl)
virtual void SAL_CALL queryTermination(const lang::EventObject &Event) override
DatabaseDocumentLoader(const Reference< XComponentContext > &rxContext)
void append(const ODatabaseModelImpl &_rModelImpl)
Reference< XDesktop2 > m_xDesktop
virtual void SAL_CALL notifyTermination(const lang::EventObject &Event) override
std::vector< const ODatabaseModelImpl * > m_aDatabaseDocuments
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual void SAL_CALL changeDatabaseLocation(const OUString &Name, const OUString &NewLocation) override
virtual void SAL_CALL registerObject(const OUString &Name, const css::uno::Reference< css::uno::XInterface > &Object) override
ODatabaseContext(const css::uno::Reference< css::uno::XComponentContext > &)
virtual void SAL_CALL removeDatabaseRegistrationsListener(const css::uno::Reference< css::sdb::XDatabaseRegistrationsListener > &Listener) override
css::uno::Reference< css::uno::XComponentContext > m_aContext
void removeFromTerminateListener(const ODatabaseModelImpl &_rDataSourceModel)
virtual css::uno::Sequence< OUString > SAL_CALL getRegistrationNames() override
css::uno::Reference< css::uno::XAggregation > m_xDBRegistrationAggregate
virtual OUString SAL_CALL getDatabaseLocation(const OUString &Name) override
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getRegisteredObject(const OUString &Name) override
void databaseDocumentURLChange(const OUString &_sOldName, const OUString &_sNewName)
virtual sal_Bool SAL_CALL isDatabaseRegistrationReadOnly(const OUString &Name) override
virtual void onBasicManagerCreated(const css::uno::Reference< css::frame::XModel > &_rxForDocument, BasicManager &_rBasicManager) override
virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
PropertyCache m_aDatasourceProperties
virtual void SAL_CALL addDatabaseRegistrationsListener(const css::uno::Reference< css::sdb::XDatabaseRegistrationsListener > &Listener) override
virtual void SAL_CALL disposing() override
virtual void SAL_CALL addContainerListener(const css::uno::Reference< css::container::XContainerListener > &xListener) override
virtual void SAL_CALL removeContainerListener(const css::uno::Reference< css::container::XContainerListener > &xListener) override
::comphelper::OInterfaceContainerHelper3< css::container::XContainerListener > m_aContainerListeners
std::map< OUString, ODatabaseModelImpl * > ObjectCache
void setTransientProperties(const OUString &_sURL, ODatabaseModelImpl &_rDataSourceModel)
sets all properties which were transient at the data source.
virtual OUString SAL_CALL getImplementationName() override
virtual sal_Bool SAL_CALL hasElements() override
void storeTransientProperties(ODatabaseModelImpl &_rModelImpl)
void registerDatabaseDocument(ODatabaseModelImpl &_rModelImpl)
virtual void SAL_CALL revokeObject(const OUString &Name) override
void revokeDatabaseDocument(const ODatabaseModelImpl &_rModelImpl)
virtual sal_Bool SAL_CALL hasRegisteredDatabase(const OUString &Name) override
css::uno::Reference< css::uno::XInterface > loadObjectFromURL(const OUString &_rName, const OUString &_sURL)
loads the given object from the given URL
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override
virtual ~ODatabaseContext() override
void appendAtTerminateListener(const ODatabaseModelImpl &_rDataSourceModel)
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance() override
virtual void SAL_CALL revokeDatabaseLocation(const OUString &Name) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL registerDatabaseLocation(const OUString &Name, const OUString &Location) override
virtual css::uno::Any SAL_CALL getByName(const OUString &aName) override
virtual css::uno::Type SAL_CALL getElementType() override
css::uno::Reference< css::sdb::XDatabaseRegistrations > m_xDatabaseRegistrations
css::uno::Reference< css::uno::XInterface > getObject(const OUString &_rURL)
rtl::Reference< DatabaseDocumentLoader > m_xDatabaseDocumentLoader
css::uno::Reference< css::uno::XInterface > impl_createNewDataSource()
creates a new data source
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const css::uno::Sequence< css::uno::Any > &_rArguments) override
virtual sal_Bool SAL_CALL hasByName(const OUString &aName) override
const OUString & getURL() const
Definition: ModelImpl.hxx:241
css::uno::Reference< css::sdbc::XDataSource > getOrCreateDataSource()
returns the data source.
Definition: ModelImpl.cxx:952
static void setName(const css::uno::Reference< css::sdb::XDocumentDataSource > &_rxDocument, const OUString &_rNewName, DBContextAccess)
sets a new name for the data source
Definition: datasource.cxx:497
OUString get(NOTATION _eOutputNotation) const
#define DBA_RES(id)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_dba_ODatabaseContext_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Reference< XComponentContext > m_aContext
#define ENSURE_OR_THROW(c, m)
#define DBG_UNHANDLED_EXCEPTION(...)
ULONG m_refCount
std::mutex m_aMutex
URL aURL
Definition: intercept.cxx:87
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
@ Exception
Reference< XComponentContext > getProcessComponentContext()
Type
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
::cppu::WeakComponentImplHelper< css::lang::XServiceInfo, css::sdb::XDatabaseContext > DatabaseAccessContext_Base
Reference< XAggregation > createDataSourceRegistrations(const Reference< XComponentContext > &_rxContext)
::cppu::WeakImplHelper< XTerminateListener > DatabaseDocumentLoader_Base
constexpr OUStringLiteral INFO_POOLURL
Definition: strings.hxx:233
Reference< XModel > xModel
the model of the sub component. Might be <NULL>
OUString Name
unsigned char sal_Bool