LibreOffice Module dbaccess (master) 1
datasource.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 "datasource.hxx"
21#include "commandcontainer.hxx"
22#include <stringconstants.hxx>
23#include <core_resource.hxx>
24#include <strings.hrc>
25#include <strings.hxx>
26#include "connection.hxx"
27#include "SharedConnection.hxx"
28#include "databasedocument.hxx"
30
31#include <hsqlimport.hxx>
32#include <migrwarndlg.hxx>
33
34#include <com/sun/star/beans/NamedValue.hpp>
35#include <com/sun/star/beans/PropertyAttribute.hpp>
36#include <com/sun/star/beans/PropertyState.hpp>
37#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
38#include <com/sun/star/lang/DisposedException.hpp>
39#include <com/sun/star/reflection/ProxyFactory.hpp>
40#include <com/sun/star/sdb/DatabaseContext.hpp>
41#include <com/sun/star/sdb/SQLContext.hpp>
42#include <com/sun/star/sdbc/ConnectionPool.hpp>
43#include <com/sun/star/sdbc/XDriverAccess.hpp>
44#include <com/sun/star/sdbc/XDriverManager.hpp>
45#include <com/sun/star/sdbc/DriverManager.hpp>
46#include <com/sun/star/ucb/AuthenticationRequest.hpp>
47#include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
48
53#include <comphelper/types.hxx>
58#include <officecfg/Office/Common.hxx>
60#include <osl/diagnose.h>
61#include <osl/process.h>
62#include <sal/log.hxx>
63#include <tools/urlobj.hxx>
65#include <rtl/digest.h>
66
67#include <algorithm>
68#include <iterator>
69#include <set>
70
71#include <config_firebird.h>
72
73using namespace ::com::sun::star::sdbc;
74using namespace ::com::sun::star::sdbcx;
75using namespace ::com::sun::star::sdb;
76using namespace ::com::sun::star::beans;
77using namespace ::com::sun::star::uno;
78using namespace ::com::sun::star::lang;
79using namespace ::com::sun::star::embed;
80using namespace ::com::sun::star::container;
81using namespace ::com::sun::star::util;
82using namespace ::com::sun::star::io;
83using namespace ::com::sun::star::task;
84using namespace ::com::sun::star::ucb;
85using namespace ::com::sun::star::frame;
86using namespace ::com::sun::star::reflection;
87using namespace ::cppu;
88using namespace ::osl;
89using namespace ::dbtools;
90using namespace ::comphelper;
91
92namespace dbaccess
93{
94
95namespace {
96
107class FlushNotificationAdapter : public ::cppu::WeakImplHelper< XFlushListener >
108{
109private:
110 WeakReference< XFlushable > m_aBroadcaster;
111 WeakReference< XFlushListener > m_aListener;
112
113public:
114 static void installAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
115 {
116 new FlushNotificationAdapter( _rxBroadcaster, _rxListener );
117 }
118
119protected:
120 FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener );
121 virtual ~FlushNotificationAdapter() override;
122
123 void impl_dispose();
124
125protected:
126 // XFlushListener
127 virtual void SAL_CALL flushed( const css::lang::EventObject& rEvent ) override;
128 // XEventListener
129 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
130};
131
132}
133
134FlushNotificationAdapter::FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
135 :m_aBroadcaster( _rxBroadcaster )
136 ,m_aListener( _rxListener )
137{
138 OSL_ENSURE( _rxBroadcaster.is(), "FlushNotificationAdapter::FlushNotificationAdapter: invalid flushable!" );
139
140 osl_atomic_increment( &m_refCount );
141 {
142 if ( _rxBroadcaster.is() )
143 _rxBroadcaster->addFlushListener( this );
144 }
145 osl_atomic_decrement( &m_refCount );
146 OSL_ENSURE( m_refCount == 1, "FlushNotificationAdapter::FlushNotificationAdapter: broadcaster isn't holding by hard ref!?" );
147}
148
149FlushNotificationAdapter::~FlushNotificationAdapter()
150{
151}
152
153void FlushNotificationAdapter::impl_dispose()
154{
155 Reference< XFlushListener > xKeepAlive( this );
156
157 Reference< XFlushable > xFlushable( m_aBroadcaster );
158 if ( xFlushable.is() )
159 xFlushable->removeFlushListener( this );
160
161 m_aListener.clear();
162 m_aBroadcaster.clear();
163}
164
165void SAL_CALL FlushNotificationAdapter::flushed( const EventObject& rEvent )
166{
167 Reference< XFlushListener > xListener( m_aListener );
168 if ( xListener.is() )
169 xListener->flushed( rEvent );
170 else
171 impl_dispose();
172}
173
174void SAL_CALL FlushNotificationAdapter::disposing( const EventObject& Source )
175{
176 Reference< XFlushListener > xListener( m_aListener );
177 if ( xListener.is() )
178 xListener->disposing( Source );
179
180 impl_dispose();
181}
182
183OAuthenticationContinuation::OAuthenticationContinuation()
184 :m_bRememberPassword(true), // TODO: a meaningful default
185 m_bCanSetUserName(true)
186{
187}
188
190{
191 return false;
192}
193
194void SAL_CALL OAuthenticationContinuation::setRealm( const OUString& /*Realm*/ )
195{
196 SAL_WARN("dbaccess","OAuthenticationContinuation::setRealm: not supported!");
197}
198
200{
201 // we always allow this, even if the database document is read-only. In this case,
202 // it's simply that the user cannot store the new user name.
203 return m_bCanSetUserName;
204}
205
206void SAL_CALL OAuthenticationContinuation::setUserName( const OUString& _rUser )
207{
208 m_sUser = _rUser;
209}
210
212{
213 return true;
214}
215
216void SAL_CALL OAuthenticationContinuation::setPassword( const OUString& _rPassword )
217{
218 m_sPassword = _rPassword;
219}
220
221Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberPasswordModes( RememberAuthentication& _reDefault )
222{
223 _reDefault = RememberAuthentication_SESSION;
224 return { _reDefault };
225}
226
227void SAL_CALL OAuthenticationContinuation::setRememberPassword( RememberAuthentication _eRemember )
228{
229 m_bRememberPassword = (RememberAuthentication_NO != _eRemember);
230}
231
233{
234 return false;
235}
236
237void SAL_CALL OAuthenticationContinuation::setAccount( const OUString& )
238{
239 SAL_WARN("dbaccess","OAuthenticationContinuation::setAccount: not supported!");
240}
241
242Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberAccountModes( RememberAuthentication& _reDefault )
243{
244 _reDefault = RememberAuthentication_NO;
245 return { RememberAuthentication_NO };
246}
247
248void SAL_CALL OAuthenticationContinuation::setRememberAccount( RememberAuthentication /*Remember*/ )
249{
250 SAL_WARN("dbaccess","OAuthenticationContinuation::setRememberAccount: not supported!");
251}
252
253namespace {
254
258// need to hold the digest
259struct TDigestHolder
260{
261 sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1];
263 {
264 m_pBuffer[0] = 0;
265 }
266
267};
268
269}
270
271class OSharedConnectionManager : public ::cppu::WeakImplHelper< XEventListener >
272{
273
274 // contains the currently used master connections
276 {
277 Reference< XConnection > xMasterConnection;
278 oslInterlockedCount nALiveCount;
279 };
280
281 // the less-compare functor, used for the stl::map
283 {
284 bool operator() (const TDigestHolder& x, const TDigestHolder& y) const
285 {
286 sal_uInt32 i;
287 for(i=0;i < RTL_DIGEST_LENGTH_SHA1 && (x.m_pBuffer[i] >= y.m_pBuffer[i]); ++i)
288 ;
289 return i < RTL_DIGEST_LENGTH_SHA1;
290 }
291 };
292
293 typedef std::map< TDigestHolder,TConnectionHolder,TDigestLess> TConnectionMap; // holds the master connections
294 typedef std::map< Reference< XConnection >,TConnectionMap::iterator> TSharedConnectionMap;// holds the shared connections
295
296 ::osl::Mutex m_aMutex;
297 TConnectionMap m_aConnections; // remember the master connection in conjunction with the digest
298 TSharedConnectionMap m_aSharedConnection; // the shared connections with conjunction with an iterator into the connections map
299 Reference< XProxyFactory > m_xProxyFactory;
300
301protected:
302 virtual ~OSharedConnectionManager() override;
303
304public:
305 explicit OSharedConnectionManager(const Reference< XComponentContext >& _rxContext);
306
307 void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
308 Reference<XConnection> getConnection( const OUString& url,
309 const OUString& user,
310 const OUString& password,
311 const Sequence< PropertyValue >& _aInfo,
312 ODatabaseSource* _pDataSource);
313 void addEventListener(const Reference<XConnection>& _rxConnection, TConnectionMap::iterator const & _rIter);
314};
315
316OSharedConnectionManager::OSharedConnectionManager(const Reference< XComponentContext >& _rxContext)
317{
318 m_xProxyFactory.set( ProxyFactory::create( _rxContext ) );
319}
320
322{
323}
324
325void SAL_CALL OSharedConnectionManager::disposing( const css::lang::EventObject& Source )
326{
327 MutexGuard aGuard(m_aMutex);
328 Reference<XConnection> xConnection(Source.Source,UNO_QUERY);
329 TSharedConnectionMap::const_iterator aFind = m_aSharedConnection.find(xConnection);
330 if ( m_aSharedConnection.end() != aFind )
331 {
332 osl_atomic_decrement(&aFind->second->second.nALiveCount);
333 if ( !aFind->second->second.nALiveCount )
334 {
335 ::comphelper::disposeComponent(aFind->second->second.xMasterConnection);
336 m_aConnections.erase(aFind->second);
337 }
338 m_aSharedConnection.erase(aFind);
339 }
340}
341
342Reference<XConnection> OSharedConnectionManager::getConnection( const OUString& url,
343 const OUString& user,
344 const OUString& password,
345 const Sequence< PropertyValue >& _aInfo,
346 ODatabaseSource* _pDataSource)
347{
348 MutexGuard aGuard(m_aMutex);
349 TConnectionMap::key_type nId;
350 Sequence< PropertyValue > aInfoCopy(_aInfo);
351 sal_Int32 nPos = aInfoCopy.getLength();
352 aInfoCopy.realloc( nPos + 2 );
353 auto pInfoCopy = aInfoCopy.getArray();
354 pInfoCopy[nPos].Name = "TableFilter";
355 pInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableFilter;
356 pInfoCopy[nPos].Name = "TableTypeFilter";
357 pInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableTypeFilter;
358
359 OUString sUser = user;
360 OUString sPassword = password;
361 if ((sUser.isEmpty()) && (sPassword.isEmpty()) && (!_pDataSource->m_pImpl->m_sUser.isEmpty()))
362 { // ease the usage of this method. data source which are intended to have a user automatically
363 // fill in the user/password combination if the caller of this method does not specify otherwise
364 sUser = _pDataSource->m_pImpl->m_sUser;
365 if (!_pDataSource->m_pImpl->m_aPassword.isEmpty())
366 sPassword = _pDataSource->m_pImpl->m_aPassword;
367 }
368
369 ::connectivity::OConnectionWrapper::createUniqueId(url,aInfoCopy,nId.m_pBuffer,sUser,sPassword);
370 TConnectionMap::iterator aIter = m_aConnections.find(nId);
371
372 if ( m_aConnections.end() == aIter )
373 {
374 TConnectionHolder aHolder;
375 aHolder.nALiveCount = 0; // will be incremented by addListener
376 aHolder.xMasterConnection = _pDataSource->buildIsolatedConnection(user,password);
377 aIter = m_aConnections.emplace(nId,aHolder).first;
378 }
379
380 Reference<XConnection> xRet;
381 if ( aIter->second.xMasterConnection.is() )
382 {
383 Reference< XAggregation > xConProxy = m_xProxyFactory->createProxy(aIter->second.xMasterConnection);
384 xRet = new OSharedConnection(xConProxy);
385 m_aSharedConnection.emplace(xRet,aIter);
386 addEventListener(xRet,aIter);
387 }
388
389 return xRet;
390}
391
392void OSharedConnectionManager::addEventListener(const Reference<XConnection>& _rxConnection, TConnectionMap::iterator const & _rIter)
393{
394 Reference<XComponent> xComp(_rxConnection,UNO_QUERY);
395 xComp->addEventListener(this);
396 OSL_ENSURE( m_aConnections.end() != _rIter , "Iterator is end!");
397 osl_atomic_increment(&_rIter->second.nALiveCount);
398}
399
400namespace
401{
402 Sequence< PropertyValue > lcl_filterDriverProperties( const Reference< XDriver >& _xDriver, const OUString& _sUrl,
403 const Sequence< PropertyValue >& _rDataSourceSettings, const AsciiPropertyValue* _pKnownSettings )
404 {
405 if ( _xDriver.is() )
406 {
407 Sequence< DriverPropertyInfo > aDriverInfo(_xDriver->getPropertyInfo(_sUrl,_rDataSourceSettings));
408
409 const PropertyValue* pDataSourceSetting = _rDataSourceSettings.getConstArray();
410 const PropertyValue* pEnd = pDataSourceSetting + _rDataSourceSettings.getLength();
411
412 std::vector< PropertyValue > aRet;
413
414 for ( ; pDataSourceSetting != pEnd ; ++pDataSourceSetting )
415 {
416 bool bAllowSetting = false;
417 const AsciiPropertyValue* pSetting = _pKnownSettings;
418 for ( ; pSetting->AsciiName; ++pSetting )
419 {
420 if ( pDataSourceSetting->Name.equalsAscii( pSetting->AsciiName ) )
421 { // the particular data source setting is known
422
423 const DriverPropertyInfo* pAllowedDriverSetting = aDriverInfo.getConstArray();
424 const DriverPropertyInfo* pDriverSettingsEnd = pAllowedDriverSetting + aDriverInfo.getLength();
425 for ( ; pAllowedDriverSetting != pDriverSettingsEnd; ++pAllowedDriverSetting )
426 {
427 if ( pAllowedDriverSetting->Name.equalsAscii( pSetting->AsciiName ) )
428 { // the driver also allows this setting
429 bAllowSetting = true;
430 break;
431 }
432 }
433 break;
434 }
435 }
436 if ( bAllowSetting || !pSetting->AsciiName )
437 { // if the driver allows this particular setting, or if the setting is completely unknown,
438 // we pass it to the driver
439 aRet.push_back( *pDataSourceSetting );
440 }
441 }
442 if ( !aRet.empty() )
444 }
445 return Sequence< PropertyValue >();
446 }
447
448 typedef std::map< OUString, sal_Int32 > PropertyAttributeCache;
449
450 struct IsDefaultAndNotRemoveable
451 {
452 private:
453 const PropertyAttributeCache& m_rAttribs;
454
455 public:
456 explicit IsDefaultAndNotRemoveable( const PropertyAttributeCache& _rAttribs ) : m_rAttribs( _rAttribs ) { }
457
458 bool operator()( const PropertyValue& _rProp )
459 {
460 if ( _rProp.State != PropertyState_DEFAULT_VALUE )
461 return false;
462
463 bool bRemoveable = true;
464
465 PropertyAttributeCache::const_iterator pos = m_rAttribs.find( _rProp.Name );
466 OSL_ENSURE( pos != m_rAttribs.end(), "IsDefaultAndNotRemoveable: illegal property name!" );
467 if ( pos != m_rAttribs.end() )
468 bRemoveable = ( ( pos->second & PropertyAttribute::REMOVABLE ) != 0 );
469
470 return !bRemoveable;
471 }
472 };
473}
474
475
476ODatabaseSource::ODatabaseSource(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl)
477 :ModelDependentComponent( _pImpl )
480 , m_Bookmarks(*this, getMutex())
481 ,m_aFlushListeners( getMutex() )
482{
483 // some kind of default
484 SAL_INFO("dbaccess", "DS: ctor: " << std::hex << this << ": " << std::hex << m_pImpl.get() );
485}
486
488{
489 SAL_INFO("dbaccess", "DS: dtor: " << std::hex << this << ": " << std::hex << m_pImpl.get() );
490 if ( !ODatabaseSource_Base::rBHelper.bInDispose && !ODatabaseSource_Base::rBHelper.bDisposed )
491 {
492 acquire();
493 dispose();
494 }
495}
496
497void ODatabaseSource::setName( const Reference< XDocumentDataSource >& _rxDocument, const OUString& _rNewName, DBContextAccess )
498{
499 ODatabaseSource& rModelImpl = dynamic_cast< ODatabaseSource& >( *_rxDocument );
500
502 if ( rModelImpl.m_pImpl.is() )
503 rModelImpl.m_pImpl->m_sName = _rNewName;
504}
505
506// css::lang::XTypeProvider
508{
509 OTypeCollection aPropertyHelperTypes( cppu::UnoType<XFastPropertySet>::get(),
512
513 return ::comphelper::concatSequences(
514 ODatabaseSource_Base::getTypes(),
515 aPropertyHelperTypes.getTypes()
516 );
517}
518
520{
521 return css::uno::Sequence<sal_Int8>();
522}
523
524// css::uno::XInterface
526{
527 Any aIface = ODatabaseSource_Base::queryInterface( rType );
528 if ( !aIface.hasValue() )
530 return aIface;
531}
532
534{
535 ODatabaseSource_Base::acquire();
536}
537
539{
540 ODatabaseSource_Base::release();
541}
542
543void SAL_CALL ODatabaseSource::disposing( const css::lang::EventObject& Source )
544{
545 if ( m_pImpl.is() )
546 m_pImpl->disposing(Source);
547}
548
549// XServiceInfo
551{
552 return "com.sun.star.comp.dba.ODatabaseSource";
553}
554
556{
557 return { SERVICE_SDB_DATASOURCE, "com.sun.star.sdb.DocumentDataSource" };
558}
559
560sal_Bool ODatabaseSource::supportsService( const OUString& _rServiceName )
561{
562 return cppu::supportsService(this, _rServiceName);
563}
564
565// OComponentHelper
567{
568 SAL_INFO("dbaccess", "DS: disp: " << std::hex << this << ", " << std::hex << m_pImpl.get() );
569 ODatabaseSource_Base::WeakComponentImplHelperBase::disposing();
571
572 EventObject aDisposeEvent(static_cast<XWeak*>(this));
573 m_aFlushListeners.disposeAndClear( aDisposeEvent );
574
575 ODatabaseDocument::clearObjectContainer(m_pImpl->m_xCommandDefinitions);
577 m_pImpl.clear();
578}
579
581{
582 if (m_xDialogParent.is())
584
585 Reference<XModel> xModel = getModel_noCreate();
586 if (!xModel.is())
587 return nullptr;
588 Reference<XController> xController(xModel->getCurrentController());
589 if (!xController.is())
590 return nullptr;
591 Reference<XFrame> xFrame(xController->getFrame());
592 if (!xFrame.is())
593 return nullptr;
594 Reference<css::awt::XWindow> xWindow(xFrame->getContainerWindow());
595 return Application::GetFrameWeld(xWindow);
596}
597
598Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const OUString& _rUid, const OUString& _rPwd)
599{
600 Reference< XConnection > xReturn;
601
602 Reference< XDriverManager > xManager;
603
604#if ENABLE_FIREBIRD_SDBC
605 bool bIgnoreMigration = false;
606 bool bNeedMigration = false;
607 Reference< XModel > xModel = m_pImpl->getModel_noCreate();
608 if ( xModel)
609 {
610 //See ODbTypeWizDialogSetup::SaveDatabaseDocument
611 ::comphelper::NamedValueCollection::get(xModel->getArgs(), u"IgnoreFirebirdMigration") >>= bIgnoreMigration;
612 }
613 else
614 {
615 //ignore when we don't have a model. E.g. Mailmerge, data sources, fields...
616 bIgnoreMigration = true;
617 }
618
619 if (!officecfg::Office::Common::Misc::ExperimentalMode::get())
620 bIgnoreMigration = true;
621
622 if(!bIgnoreMigration && m_pImpl->m_sConnectURL == "sdbc:embedded:hsqldb")
623 {
624 Reference<XStorage> const xRootStorage = m_pImpl->getOrCreateRootStorage();
625 OUString sMigrEnvVal;
626 osl_getEnvironment(OUString("DBACCESS_HSQL_MIGRATION").pData,
627 &sMigrEnvVal.pData);
628 if(!sMigrEnvVal.isEmpty())
629 bNeedMigration = true;
630 else
631 {
632 Reference<XPropertySet> const xPropSet(xRootStorage, UNO_QUERY_THROW);
633 sal_Int32 nOpenMode(0);
634 if ((xPropSet->getPropertyValue("OpenMode") >>= nOpenMode)
635 && (nOpenMode & css::embed::ElementModes::WRITE)
637 {
638 MigrationWarnDialog aWarnDlg(m_pImpl->GetFrameWeld());
639 bNeedMigration = aWarnDlg.run() == RET_OK;
640 }
641 }
642 if (bNeedMigration)
643 {
644 // back up content xml file if migration was successful
645 static constexpr OUStringLiteral BACKUP_XML_NAME = u"content_before_migration.xml";
646 try
647 {
648 if(xRootStorage->isStreamElement(BACKUP_XML_NAME))
649 xRootStorage->removeElement(BACKUP_XML_NAME);
650 }
651 catch (NoSuchElementException&)
652 {
653 SAL_INFO("dbaccess", "No file content_before_migration.xml found" );
654 }
655 xRootStorage->copyElementTo("content.xml", xRootStorage,
656 BACKUP_XML_NAME);
657
658 m_pImpl->m_sConnectURL = "sdbc:embedded:firebird";
659 }
660 }
661#endif
662
663 try {
664 xManager.set( ConnectionPool::create( m_pImpl->m_aContext ), UNO_QUERY_THROW );
665 } catch( const Exception& ) { }
666 if ( !xManager.is() )
667 // no connection pool installed, fall back to driver manager
668 xManager.set( DriverManager::create(m_pImpl->m_aContext ), UNO_QUERY_THROW );
669
670 OUString sUser(_rUid);
671 OUString sPwd(_rPwd);
672 if ((sUser.isEmpty()) && (sPwd.isEmpty()) && (!m_pImpl->m_sUser.isEmpty()))
673 { // ease the usage of this method. data source which are intended to have a user automatically
674 // fill in the user/password combination if the caller of this method does not specify otherwise
675 sUser = m_pImpl->m_sUser;
676 if (!m_pImpl->m_aPassword.isEmpty())
677 sPwd = m_pImpl->m_aPassword;
678 }
679
680 TranslateId pExceptionMessageId = RID_STR_COULDNOTCONNECT_UNSPECIFIED;
681 if (xManager.is())
682 {
683 sal_Int32 nAdditionalArgs(0);
684 if (!sUser.isEmpty()) ++nAdditionalArgs;
685 if (!sPwd.isEmpty()) ++nAdditionalArgs;
686
687 Sequence< PropertyValue > aUserPwd(nAdditionalArgs);
688 auto aUserPwdRange = asNonConstRange(aUserPwd);
689 sal_Int32 nArgPos = 0;
690 if (!sUser.isEmpty())
691 {
692 aUserPwdRange[ nArgPos ].Name = "user";
693 aUserPwdRange[ nArgPos ].Value <<= sUser;
694 ++nArgPos;
695 }
696 if (!sPwd.isEmpty())
697 {
698 aUserPwdRange[ nArgPos ].Name = "password";
699 aUserPwdRange[ nArgPos ].Value <<= sPwd;
700 }
701 Reference< XDriver > xDriver;
702 try
703 {
704
705 // choose driver
706 Reference< XDriverAccess > xAccessDrivers( xManager, UNO_QUERY );
707 if ( xAccessDrivers.is() )
708 xDriver = xAccessDrivers->getDriverByURL( m_pImpl->m_sConnectURL );
709 }
710 catch( const Exception& )
711 {
712 TOOLS_WARN_EXCEPTION("dbaccess", "ODatabaseSource::buildLowLevelConnection: got a strange exception while analyzing the error" );
713 }
714 if ( !xDriver.is() || !xDriver->acceptsURL( m_pImpl->m_sConnectURL ) )
715 {
716 // Nowadays, it's allowed for a driver to be registered for a given URL, but actually not to accept it.
717 // This is because registration nowadays happens at compile time (by adding respective configuration data),
718 // but acceptance is decided at runtime.
719 pExceptionMessageId = RID_STR_COULDNOTCONNECT_NODRIVER;
720 }
721 else
722 {
723 Sequence< PropertyValue > aDriverInfo = lcl_filterDriverProperties(
724 xDriver,
725 m_pImpl->m_sConnectURL,
726 m_pImpl->m_xSettings->getPropertyValues(),
728 );
729
730 if ( m_pImpl->isEmbeddedDatabase() )
731 {
732 sal_Int32 nCount = aDriverInfo.getLength();
733 aDriverInfo.realloc(nCount + 3 );
734 auto pDriverInfo = aDriverInfo.getArray();
735
736 pDriverInfo[nCount].Name = "URL";
737 pDriverInfo[nCount++].Value <<= m_pImpl->getURL();
738
739 pDriverInfo[nCount].Name = "Storage";
740 Reference< css::document::XDocumentSubStorageSupplier> xDocSup( m_pImpl->getDocumentSubStorageSupplier() );
741 pDriverInfo[nCount++].Value <<= xDocSup->getDocumentSubStorage("database",ElementModes::READWRITE);
742
743 pDriverInfo[nCount].Name = "Document";
744 pDriverInfo[nCount++].Value <<= getDatabaseDocument();
745 }
746 if (nAdditionalArgs)
747 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL, ::comphelper::concatSequences(aUserPwd,aDriverInfo));
748 else
749 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL,aDriverInfo);
750
751 if ( m_pImpl->isEmbeddedDatabase() )
752 {
753 // see ODatabaseSource::flushed for comment on why we register as FlushListener
754 // at the connection
755 Reference< XFlushable > xFlushable( xReturn, UNO_QUERY );
756 if ( xFlushable.is() )
757 FlushNotificationAdapter::installAdapter( xFlushable, this );
758 }
759 }
760 }
761 else
762 pExceptionMessageId = RID_STR_COULDNOTLOAD_MANAGER;
763
764 if ( !xReturn.is() )
765 {
766 OUString sMessage = DBA_RES(pExceptionMessageId)
767 .replaceAll("$name$", m_pImpl->m_sConnectURL);
768
769 SQLContext aContext;
770 aContext.Message = DBA_RES(RID_STR_CONNECTION_REQUEST).
771 replaceFirst("$name$", m_pImpl->m_sConnectURL);
772
773 throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), Any( aContext ) );
774 }
775
776#if ENABLE_FIREBIRD_SDBC
777 if( bNeedMigration )
778 {
779 Reference< css::document::XDocumentSubStorageSupplier> xDocSup(
780 m_pImpl->getDocumentSubStorageSupplier() );
782 xDocSup->getDocumentSubStorage("database",ElementModes::READWRITE) );
783 importer.importHsqlDatabase(m_pImpl->GetFrameWeld());
784 }
785#endif
786
787 return xReturn;
788}
789
790// OPropertySetHelper
791Reference< XPropertySetInfo > ODatabaseSource::getPropertySetInfo()
792{
794}
795
796// comphelper::OPropertyArrayUsageHelper
798{
799 return new ::cppu::OPropertyArrayHelper
800 {
801 {
802 { PROPERTY_INFO, PROPERTY_ID_INFO, cppu::UnoType<Sequence< PropertyValue >>::get(), css::beans::PropertyAttribute::BOUND },
803 { PROPERTY_ISPASSWORDREQUIRED, PROPERTY_ID_ISPASSWORDREQUIRED, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND },
804 { PROPERTY_ISREADONLY, PROPERTY_ID_ISREADONLY, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::READONLY },
806 { PROPERTY_NAME, PROPERTY_ID_NAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY },
808 css::beans::PropertyAttribute::READONLY | css::beans::PropertyAttribute::TRANSIENT },
809 { PROPERTY_PASSWORD, PROPERTY_ID_PASSWORD, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::TRANSIENT },
810 { PROPERTY_SETTINGS, PROPERTY_ID_SETTINGS, cppu::UnoType<XPropertySet>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY },
811 { PROPERTY_SUPPRESSVERSIONCL, PROPERTY_ID_SUPPRESSVERSIONCL, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND },
812 { PROPERTY_TABLEFILTER, PROPERTY_ID_TABLEFILTER, cppu::UnoType<Sequence< OUString >>::get(), css::beans::PropertyAttribute::BOUND },
813 { PROPERTY_TABLETYPEFILTER, PROPERTY_ID_TABLETYPEFILTER, cppu::UnoType<Sequence< OUString >>::get(), css::beans::PropertyAttribute::BOUND },
814 { PROPERTY_URL, PROPERTY_ID_URL, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND },
815 { PROPERTY_USER, PROPERTY_ID_USER, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND }
816 }
817 };
818}
819
820// cppu::OPropertySetHelper
822{
823 return *getArrayHelper();
824}
825
826sal_Bool ODatabaseSource::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
827{
828 bool bModified(false);
829 if ( m_pImpl.is() )
830 {
831 switch (nHandle)
832 {
834 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableFilter);
835 break;
837 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableTypeFilter);
838 break;
839 case PROPERTY_ID_USER:
840 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sUser);
841 break;
843 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aPassword);
844 break;
846 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bPasswordRequired);
847 break;
849 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bSuppressVersionColumns);
850 break;
852 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aLayoutInformation);
853 break;
854 case PROPERTY_ID_URL:
855 {
856 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sConnectURL);
857 } break;
858 case PROPERTY_ID_INFO:
859 {
860 Sequence<PropertyValue> aValues;
861 if (!(rValue >>= aValues))
862 throw IllegalArgumentException();
863
864 for ( auto const & checkName : std::as_const(aValues) )
865 {
866 if ( checkName.Name.isEmpty() )
867 throw IllegalArgumentException();
868 }
869
870 Sequence< PropertyValue > aSettings = m_pImpl->m_xSettings->getPropertyValues();
871 bModified = aSettings.getLength() != aValues.getLength();
872 if ( !bModified )
873 {
874 const PropertyValue* pInfoIter = aSettings.getConstArray();
875 const PropertyValue* checkValue = aValues.getConstArray();
876 for ( ;!bModified && checkValue != std::cend(aValues) ; ++checkValue,++pInfoIter)
877 {
878 bModified = checkValue->Name != pInfoIter->Name;
879 if ( !bModified )
880 {
881 bModified = checkValue->Value != pInfoIter->Value;
882 }
883 }
884 }
885
886 rConvertedValue = rValue;
887 rOldValue <<= aSettings;
888 }
889 break;
890 default:
891 SAL_WARN("dbaccess", "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" );
892 }
893 }
894 return bModified;
895}
896
897namespace
898{
899 struct SelectPropertyName
900 {
901 public:
902 const OUString& operator()( const PropertyValue& _lhs )
903 {
904 return _lhs.Name;
905 }
906 };
907
921 void lcl_setPropertyValues_resetOrRemoveOther( const Reference< XPropertyBag >& _rxPropertyBag, const Sequence< PropertyValue >& _rAllNewPropertyValues )
922 {
923 // sequences are ugly to operate on
924 std::set<OUString> aToBeSetPropertyNames;
925 std::transform(
926 _rAllNewPropertyValues.begin(),
927 _rAllNewPropertyValues.end(),
928 std::inserter( aToBeSetPropertyNames, aToBeSetPropertyNames.end() ),
929 SelectPropertyName()
930 );
931
932 try
933 {
934 // obtain all properties currently known at the bag
935 Reference< XPropertySetInfo > xPSI( _rxPropertyBag->getPropertySetInfo(), UNO_SET_THROW );
936 const Sequence< Property > aAllExistentProperties( xPSI->getProperties() );
937
938 Reference< XPropertyState > xPropertyState( _rxPropertyBag, UNO_QUERY_THROW );
939
940 // loop through them, and reset resp. default properties which are not to be set
941 for ( auto const & existentProperty : aAllExistentProperties )
942 {
943 if ( aToBeSetPropertyNames.find( existentProperty.Name ) != aToBeSetPropertyNames.end() )
944 continue;
945
946 // this property is not to be set, but currently exists in the bag.
947 // -> Remove it, or reset it to the default.
948 if ( ( existentProperty.Attributes & PropertyAttribute::REMOVABLE ) != 0 )
949 _rxPropertyBag->removeProperty( existentProperty.Name );
950 else
951 xPropertyState->setPropertyToDefault( existentProperty.Name );
952 }
953
954 // finally, set the new property values
955 _rxPropertyBag->setPropertyValues( _rAllNewPropertyValues );
956 }
957 catch( const Exception& )
958 {
959 DBG_UNHANDLED_EXCEPTION("dbaccess");
960 }
961 }
962}
963
964void ODatabaseSource::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
965{
966 if ( !m_pImpl.is() )
967 return;
968
969 switch(nHandle)
970 {
972 rValue >>= m_pImpl->m_aTableFilter;
973 break;
975 rValue >>= m_pImpl->m_aTableTypeFilter;
976 break;
977 case PROPERTY_ID_USER:
978 rValue >>= m_pImpl->m_sUser;
979 // if the user name has changed, reset the password
980 m_pImpl->m_aPassword.clear();
981 break;
983 rValue >>= m_pImpl->m_aPassword;
984 break;
986 m_pImpl->m_bPasswordRequired = any2bool(rValue);
987 break;
989 m_pImpl->m_bSuppressVersionColumns = any2bool(rValue);
990 break;
991 case PROPERTY_ID_URL:
992 rValue >>= m_pImpl->m_sConnectURL;
993 break;
994 case PROPERTY_ID_INFO:
995 {
996 Sequence< PropertyValue > aInfo;
997 OSL_VERIFY( rValue >>= aInfo );
998 lcl_setPropertyValues_resetOrRemoveOther( m_pImpl->m_xSettings, aInfo );
999 }
1000 break;
1002 rValue >>= m_pImpl->m_aLayoutInformation;
1003 break;
1004 }
1005 m_pImpl->setModified(true);
1006}
1007
1008void ODatabaseSource::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
1009{
1010 if ( !m_pImpl.is() )
1011 return;
1012
1013 switch (nHandle)
1014 {
1016 rValue <<= m_pImpl->m_aTableFilter;
1017 break;
1019 rValue <<= m_pImpl->m_aTableTypeFilter;
1020 break;
1021 case PROPERTY_ID_USER:
1022 rValue <<= m_pImpl->m_sUser;
1023 break;
1025 rValue <<= m_pImpl->m_aPassword;
1026 break;
1028 rValue <<= m_pImpl->m_bPasswordRequired;
1029 break;
1031 rValue <<= m_pImpl->m_bSuppressVersionColumns;
1032 break;
1034 rValue <<= m_pImpl->m_bReadOnly;
1035 break;
1036 case PROPERTY_ID_INFO:
1037 {
1038 try
1039 {
1040 // collect the property attributes of all current settings
1041 Reference< XPropertySet > xSettingsAsProps( m_pImpl->m_xSettings, UNO_QUERY_THROW );
1042 Reference< XPropertySetInfo > xPST( xSettingsAsProps->getPropertySetInfo(), UNO_SET_THROW );
1043 const Sequence< Property > aSettings( xPST->getProperties() );
1044 std::map< OUString, sal_Int32 > aPropertyAttributes;
1045 for ( auto const & setting : aSettings )
1046 {
1047 aPropertyAttributes[ setting.Name ] = setting.Attributes;
1048 }
1049
1050 // get all current settings with their values
1051 Sequence< PropertyValue > aValues( m_pImpl->m_xSettings->getPropertyValues() );
1052
1053 // transform them so that only property values which fulfill certain
1054 // criteria survive
1055 Sequence< PropertyValue > aNonDefaultOrUserDefined( aValues.getLength() );
1056 auto [begin, end] = asNonConstRange(aValues);
1057 auto pCopyStart = aNonDefaultOrUserDefined.getArray();
1058 const PropertyValue* pCopyEnd = std::remove_copy_if(
1059 begin,
1060 end,
1061 pCopyStart,
1062 IsDefaultAndNotRemoveable( aPropertyAttributes )
1063 );
1064 aNonDefaultOrUserDefined.realloc( pCopyEnd - pCopyStart );
1065 rValue <<= aNonDefaultOrUserDefined;
1066 }
1067 catch( const Exception& )
1068 {
1069 DBG_UNHANDLED_EXCEPTION("dbaccess");
1070 }
1071 }
1072 break;
1074 rValue <<= m_pImpl->m_xSettings;
1075 break;
1076 case PROPERTY_ID_URL:
1077 rValue <<= m_pImpl->m_sConnectURL;
1078 break;
1080 rValue <<= m_pImpl->getNumberFormatsSupplier();
1081 break;
1082 case PROPERTY_ID_NAME:
1083 rValue <<= m_pImpl->m_sName;
1084 break;
1086 rValue <<= m_pImpl->m_aLayoutInformation;
1087 break;
1088 default:
1089 SAL_WARN("dbaccess","unknown Property");
1090 }
1091}
1092
1093// XDataSource
1095{
1096 ModelMethodGuard aGuard( *this );
1097 m_pImpl->m_nLoginTimeout = seconds;
1098}
1099
1101{
1102 ModelMethodGuard aGuard( *this );
1103 return m_pImpl->m_nLoginTimeout;
1104}
1105
1106// XCompletedConnection
1107Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler )
1108{
1109 return connectWithCompletion(_rxHandler,false);
1110}
1111
1112Reference< XConnection > ODatabaseSource::getConnection(const OUString& user, const OUString& password)
1113{
1114 return getConnection(user,password,false);
1115}
1116
1117Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnection( const OUString& user, const OUString& password )
1118{
1119 return getConnection(user,password,true);
1120}
1121
1122Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnectionWithCompletion( const Reference< XInteractionHandler >& _rxHandler )
1123{
1124 return connectWithCompletion(_rxHandler,true);
1125}
1126
1127Reference< XConnection > ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler,bool _bIsolated )
1128{
1129 ModelMethodGuard aGuard( *this );
1130
1131 if (!_rxHandler.is())
1132 {
1133 SAL_WARN("dbaccess","ODatabaseSource::connectWithCompletion: invalid interaction handler!");
1134 return getConnection(m_pImpl->m_sUser, m_pImpl->m_aPassword,_bIsolated);
1135 }
1136
1137 OUString sUser(m_pImpl->m_sUser), sPassword(m_pImpl->m_aPassword);
1138 bool bNewPasswordGiven = false;
1139
1140 if (m_pImpl->m_bPasswordRequired && sPassword.isEmpty())
1141 { // we need a password, but don't have one yet.
1142 // -> ask the user
1143
1144 // build an interaction request
1145 // two continuations (Ok and Cancel)
1147 rtl::Reference<OAuthenticationContinuation> pAuthenticate = new OAuthenticationContinuation;
1148
1149 // the name which should be referred in the login dialog
1150 OUString sServerName( m_pImpl->m_sName );
1151 INetURLObject aURLCheck( sServerName );
1152 if ( aURLCheck.GetProtocol() != INetProtocol::NotValid )
1153 sServerName = aURLCheck.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous );
1154
1155 // the request
1156 AuthenticationRequest aRequest;
1157 aRequest.ServerName = sServerName;
1158 aRequest.HasRealm = aRequest.HasAccount = false;
1159 aRequest.HasUserName = aRequest.HasPassword = true;
1160 aRequest.UserName = m_pImpl->m_sUser;
1161 aRequest.Password = m_pImpl->m_sFailedPassword.isEmpty() ? m_pImpl->m_aPassword : m_pImpl->m_sFailedPassword;
1162 rtl::Reference<OInteractionRequest> pRequest = new OInteractionRequest(Any(aRequest));
1163 // some knittings
1164 pRequest->addContinuation(pAbort);
1165 pRequest->addContinuation(pAuthenticate);
1166
1167 // handle the request
1168 try
1169 {
1170 _rxHandler->handle(pRequest);
1171 }
1172 catch(Exception&)
1173 {
1174 DBG_UNHANDLED_EXCEPTION("dbaccess");
1175 }
1176
1177 if (!pAuthenticate->wasSelected())
1178 return Reference< XConnection >();
1179
1180 // get the result
1181 sUser = m_pImpl->m_sUser = pAuthenticate->getUser();
1182 sPassword = pAuthenticate->getPassword();
1183
1184 if (pAuthenticate->getRememberPassword())
1185 {
1186 m_pImpl->m_aPassword = pAuthenticate->getPassword();
1187 bNewPasswordGiven = true;
1188 }
1189 m_pImpl->m_sFailedPassword.clear();
1190 }
1191
1192 try
1193 {
1194 return getConnection(sUser, sPassword,_bIsolated);
1195 }
1196 catch(Exception&)
1197 {
1198 if (bNewPasswordGiven)
1199 {
1200 m_pImpl->m_sFailedPassword = m_pImpl->m_aPassword;
1201 // assume that we had an authentication problem. Without this we may, after an unsuccessful connect, while
1202 // the user gave us a password and the order to remember it, never allow a password input again (at least
1203 // not without restarting the session)
1204 m_pImpl->m_aPassword.clear();
1205 }
1206 throw;
1207 }
1208}
1209
1210Reference< XConnection > ODatabaseSource::buildIsolatedConnection(const OUString& user, const OUString& password)
1211{
1212 Reference< XConnection > xConn;
1213 Reference< XConnection > xSdbcConn = buildLowLevelConnection(user, password);
1214 OSL_ENSURE( xSdbcConn.is(), "ODatabaseSource::buildIsolatedConnection: invalid return value of buildLowLevelConnection!" );
1215 // buildLowLevelConnection is expected to always succeed
1216 if ( xSdbcConn.is() )
1217 {
1218 // build a connection server and return it (no stubs)
1219 xConn = new OConnection(*this, xSdbcConn, m_pImpl->m_aContext);
1220 }
1221 return xConn;
1222}
1223
1224Reference< XConnection > ODatabaseSource::getConnection(const OUString& user, const OUString& password,bool _bIsolated)
1225{
1226 ModelMethodGuard aGuard( *this );
1227
1228 Reference< XConnection > xConn;
1229 if ( _bIsolated )
1230 {
1231 xConn = buildIsolatedConnection(user,password);
1232 }
1233 else
1234 { // create a new proxy for the connection
1235 if ( !m_pImpl->m_xSharedConnectionManager.is() )
1236 {
1237 // TODO ideally we could just have one field, but to make that work
1238 // we'd need to move OSharedConnectionManager into its own file and header
1240 new OSharedConnectionManager( m_pImpl->m_aContext );
1241 m_pImpl->m_pSharedConnectionManager = manager.get();
1242 m_pImpl->m_xSharedConnectionManager = m_pImpl->m_pSharedConnectionManager;
1243 }
1244 xConn = m_pImpl->m_pSharedConnectionManager->getConnection(
1245 m_pImpl->m_sConnectURL, user, password, m_pImpl->m_xSettings->getPropertyValues(), this );
1246 }
1247
1248 if ( xConn.is() )
1249 {
1250 Reference< XComponent> xComp(xConn,UNO_QUERY);
1251 if ( xComp.is() )
1252 xComp->addEventListener( static_cast< XContainerListener* >( this ) );
1253 m_pImpl->m_aConnections.emplace_back(xConn);
1254 }
1255
1256 return xConn;
1257}
1258
1259Reference< XNameAccess > SAL_CALL ODatabaseSource::getBookmarks( )
1260{
1261 ModelMethodGuard aGuard( *this );
1262 // tdf#114596 this may look nutty but see OBookmarkContainer::acquire()
1263 return static_cast<XNameContainer*>(&m_Bookmarks);
1264}
1265
1266Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( )
1267{
1268 ModelMethodGuard aGuard( *this );
1269
1270 Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions;
1271 if ( !xContainer.is() )
1272 {
1273 Any aValue;
1274 css::uno::Reference< css::uno::XInterface > xMy(*this);
1275 if ( dbtools::getDataSourceSetting(xMy,"CommandDefinitions",aValue) )
1276 {
1277 OUString sSupportService;
1278 aValue >>= sSupportService;
1279 if ( !sSupportService.isEmpty() )
1280 {
1281 Sequence<Any> aArgs{ Any(NamedValue("DataSource",Any(xMy))) };
1282 xContainer.set( m_pImpl->m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(sSupportService, aArgs, m_pImpl->m_aContext), UNO_QUERY);
1283 }
1284 }
1285 if ( !xContainer.is() )
1286 {
1287 TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::ObjectType::Query ) );
1288 xContainer = new OCommandContainer( m_pImpl->m_aContext, *this, rContainerData, false );
1289 }
1290 m_pImpl->m_xCommandDefinitions = xContainer;
1291 }
1292 return xContainer;
1293}
1294
1295// XTablesSupplier
1296Reference< XNameAccess > ODatabaseSource::getTables()
1297{
1298 ModelMethodGuard aGuard( *this );
1299
1300 Reference< XNameAccess > xContainer = m_pImpl->m_xTableDefinitions;
1301 if ( !xContainer.is() )
1302 {
1303 TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::ObjectType::Table ) );
1304 xContainer = new OCommandContainer( m_pImpl->m_aContext, *this, rContainerData, true );
1305 m_pImpl->m_xTableDefinitions = xContainer;
1306 }
1307 return xContainer;
1308}
1309
1311{
1312 try
1313 {
1314 // SYNCHRONIZED ->
1315 {
1316 ModelMethodGuard aGuard( *this );
1317
1318 typedef ::utl::SharedUNOComponent< XModel, ::utl::CloseableComponent > SharedModel;
1319 SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership );
1320
1321 if ( !xModel.is() )
1322 xModel.reset( m_pImpl->createNewModel_deliverOwnership(), SharedModel::TakeOwnership );
1323
1324 Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW );
1325 xStorable->store();
1326 }
1327 // <- SYNCHRONIZED
1328
1329 css::lang::EventObject aFlushedEvent(*this);
1330 m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent );
1331 }
1332 catch( const Exception& )
1333 {
1334 DBG_UNHANDLED_EXCEPTION("dbaccess");
1335 }
1336}
1337
1338void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ )
1339{
1340 ModelMethodGuard aGuard( *this );
1341
1342 // Okay, this is some hack.
1343 //
1344 // In general, we have the problem that embedded databases write into their underlying storage, which
1345 // logically is one of our sub storage, and practically is a temporary file maintained by the
1346 // package implementation. As long as we did not commit this storage and our main storage,
1347 // the changes made by the embedded database engine are not really reflected in the database document
1348 // file. This is Bad (TM) for a "real" database application - imagine somebody entering some
1349 // data, and then crashing: For a database application, you would expect that the data still is present
1350 // when you connect to the database next time.
1351 //
1352 // Since this is a conceptual problem as long as we do use those ZIP packages (in fact, we *cannot*
1353 // provide the desired functionality as long as we do not have a package format which allows O(1) writes),
1354 // we cannot completely fix this. However, we can relax the problem by committing more often - often
1355 // enough so that data loss is more seldom, and seldom enough so that there's no noticeable performance
1356 // decrease.
1357 //
1358 // For this, we introduced a few places which XFlushable::flush their connections, and register as
1359 // XFlushListener at the embedded connection (which needs to provide the XFlushable functionality).
1360 // Then, when the connection is flushed, we commit both the database storage and our main storage.
1361 //
1362 // #i55274#
1363
1364 OSL_ENSURE( m_pImpl->isEmbeddedDatabase(), "ODatabaseSource::flushed: no embedded database?!" );
1365 bool bWasModified = m_pImpl->m_bModified;
1366 m_pImpl->commitEmbeddedStorage();
1367 m_pImpl->setModified( bWasModified );
1368}
1369
1370void SAL_CALL ODatabaseSource::addFlushListener( const Reference< css::util::XFlushListener >& _xListener )
1371{
1372 m_aFlushListeners.addInterface(_xListener);
1373}
1374
1375void SAL_CALL ODatabaseSource::removeFlushListener( const Reference< css::util::XFlushListener >& _xListener )
1376{
1378}
1379
1380void SAL_CALL ODatabaseSource::elementInserted( const ContainerEvent& /*Event*/ )
1381{
1382 ModelMethodGuard aGuard( *this );
1383 if ( m_pImpl.is() )
1384 m_pImpl->setModified(true);
1385}
1386
1387void SAL_CALL ODatabaseSource::elementRemoved( const ContainerEvent& /*Event*/ )
1388{
1389 ModelMethodGuard aGuard( *this );
1390 if ( m_pImpl.is() )
1391 m_pImpl->setModified(true);
1392}
1393
1394void SAL_CALL ODatabaseSource::elementReplaced( const ContainerEvent& /*Event*/ )
1395{
1396 ModelMethodGuard aGuard( *this );
1397 if ( m_pImpl.is() )
1398 m_pImpl->setModified(true);
1399}
1400
1401// XDocumentDataSource
1402Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocument()
1403{
1404 ModelMethodGuard aGuard( *this );
1405
1406 Reference< XModel > xModel( m_pImpl->getModel_noCreate() );
1407 if ( !xModel.is() )
1408 xModel = m_pImpl->createNewModel_deliverOwnership();
1409
1410 return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW );
1411}
1412
1413void SAL_CALL ODatabaseSource::initialize( css::uno::Sequence< css::uno::Any > const & rArguments)
1414{
1416 if (aProperties.has("ParentWindow"))
1417 aProperties.get("ParentWindow") >>= m_pImpl->m_xDialogParent;
1418}
1419
1420Reference< XInterface > ODatabaseSource::getThis() const
1421{
1422 return *const_cast< ODatabaseSource* >( this );
1423}
1424
1425} // namespace dbaccess
1426
1427extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1428com_sun_star_comp_dba_ODatabaseSource(css::uno::XComponentContext* context,
1429 css::uno::Sequence<css::uno::Any> const &)
1430{
1431 css::uno::Reference<XInterface> inst(
1432 DatabaseContext::create(context)->createInstance());
1433 inst->acquire();
1434 return inst.get();
1435}
1436
1437/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
static weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
static bool IsHeadlessModeEnabled()
const css::uno::Any & get(const OUString &_rValueName) 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)
void disposing(std::unique_lock< std::mutex > &rGuard)
static void createUniqueId(const OUString &_rURL, css::uno::Sequence< css::beans::PropertyValue > &_rInfo, sal_uInt8 *_pBuffer, const OUString &_rUserName=OUString(), const OUString &_rPassword=OUString())
static css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL createPropertySetInfo(IPropertyArrayHelper &rProperties)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) SAL_OVERRIDE
css::uno::Type const & get()
a small base class for UNO components whose functionality depends on an ODatabaseModelImpl
Definition: ModelImpl.hxx:452
::rtl::Reference< ODatabaseModelImpl > m_pImpl
Definition: ModelImpl.hxx:454
a guard for public methods of objects dependent on an ODatabaseModelImpl instance
Definition: ModelImpl.hxx:513
void SAL_CALL setRememberPassword(css::ucb::RememberAuthentication Remember) override
Definition: datasource.cxx:227
css::uno::Sequence< css::ucb::RememberAuthentication > SAL_CALL getRememberAccountModes(css::ucb::RememberAuthentication &Default) override
Definition: datasource.cxx:242
sal_Bool SAL_CALL canSetPassword() override
Definition: datasource.cxx:211
void SAL_CALL setPassword(const OUString &Password) override
Definition: datasource.cxx:216
void SAL_CALL setAccount(const OUString &Account) override
Definition: datasource.cxx:237
void SAL_CALL setRememberAccount(css::ucb::RememberAuthentication Remember) override
Definition: datasource.cxx:248
sal_Bool SAL_CALL canSetAccount() override
Definition: datasource.cxx:232
sal_Bool SAL_CALL canSetUserName() override
Definition: datasource.cxx:199
sal_Bool SAL_CALL canSetRealm() override
Definition: datasource.cxx:189
void SAL_CALL setUserName(const OUString &UserName) override
Definition: datasource.cxx:206
css::uno::Sequence< css::ucb::RememberAuthentication > SAL_CALL getRememberPasswordModes(css::ucb::RememberAuthentication &Default) override
Definition: datasource.cxx:221
void SAL_CALL setRealm(const OUString &Realm) override
Definition: datasource.cxx:194
static void clearObjectContainer(css::uno::WeakReference< css::container::XNameAccess > &_rxContainer)
clears the given object container
static const AsciiPropertyValue * getDefaultDataSourceSettings()
returns all known data source settings, including their default values
Definition: ModelImpl.cxx:1033
css::uno::Reference< css::awt::XWindow > m_xDialogParent
Definition: ModelImpl.hxx:198
weld::Window * GetFrameWeld()
Definition: datasource.cxx:580
css::uno::Reference< css::frame::XModel > getModel_noCreate() const
returns the model, if there already exists one
Definition: ModelImpl.cxx:963
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &rValue, sal_Int32 nHandle) const override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: datasource.cxx:560
virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables() override
virtual css::uno::Reference< css::sdb::XOfficeDatabaseDocument > SAL_CALL getDatabaseDocument() override
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getIsolatedConnection(const OUString &user, const OUString &password) override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: datasource.cxx:507
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
Definition: datasource.cxx:525
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getIsolatedConnectionWithCompletion(const css::uno::Reference< css::task::XInteractionHandler > &handler) override
virtual void SAL_CALL addFlushListener(const css::uno::Reference< css::util::XFlushListener > &l) override
virtual OUString SAL_CALL getImplementationName() override
Definition: datasource.cxx:550
virtual void SAL_CALL disposing() override
Definition: datasource.cxx:566
virtual sal_Bool SAL_CALL convertFastPropertyValue(css::uno::Any &rConvertedValue, css::uno::Any &rOldValue, sal_Int32 nHandle, const css::uno::Any &rValue) override
Definition: datasource.cxx:826
css::uno::Reference< css::sdbc::XConnection > buildLowLevelConnection(const OUString &_rUid, const OUString &_rPwd)
open a connection for the current settings.
Definition: datasource.cxx:598
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
Definition: datasource.cxx:964
virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent &Event) override
virtual void SAL_CALL elementInserted(const css::container::ContainerEvent &Event) override
virtual void SAL_CALL flushed(const css::lang::EventObject &rEvent) override
virtual void SAL_CALL acquire() noexcept override
Definition: datasource.cxx:533
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getBookmarks() override
virtual void SAL_CALL removeFlushListener(const css::uno::Reference< css::util::XFlushListener > &l) override
virtual ::cppu::IPropertyArrayHelper * createArrayHelper() const override
Definition: datasource.cxx:797
virtual sal_Int32 SAL_CALL getLoginTimeout() override
virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getQueryDefinitions() override
virtual void SAL_CALL release() noexcept override
Definition: datasource.cxx:538
friend class OSharedConnectionManager
Definition: datasource.hxx:81
ODatabaseSource(const ::rtl::Reference< ODatabaseModelImpl > &_pImpl)
Definition: datasource.cxx:476
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection(const OUString &user, const OUString &password) override
::comphelper::OInterfaceContainerHelper3< css::util::XFlushListener > m_aFlushListeners
Definition: datasource.hxx:87
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL connectWithCompletion(const css::uno::Reference< css::task::XInteractionHandler > &handler) override
virtual css::uno::Reference< css::uno::XInterface > getThis() const override
returns the component itself
virtual ::cppu::IPropertyArrayHelper &SAL_CALL getInfoHelper() override
Definition: datasource.cxx:821
virtual ~ODatabaseSource() override
Definition: datasource.cxx:487
OBookmarkContainer m_Bookmarks
Definition: datasource.hxx:86
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Definition: datasource.cxx:519
virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent &Event) override
virtual void SAL_CALL flush() override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: datasource.cxx:555
virtual void SAL_CALL setLoginTimeout(sal_Int32 seconds) override
css::uno::Reference< css::sdbc::XConnection > buildIsolatedConnection(const OUString &user, const OUString &password)
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
Definition: datasource.cxx:791
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
TSharedConnectionMap m_aSharedConnection
Definition: datasource.cxx:298
std::map< Reference< XConnection >, TConnectionMap::iterator > TSharedConnectionMap
Definition: datasource.cxx:294
virtual ~OSharedConnectionManager() override
Definition: datasource.cxx:321
void addEventListener(const Reference< XConnection > &_rxConnection, TConnectionMap::iterator const &_rIter)
Definition: datasource.cxx:392
std::map< TDigestHolder, TConnectionHolder, TDigestLess > TConnectionMap
Definition: datasource.cxx:293
OSharedConnectionManager(const Reference< XComponentContext > &_rxContext)
Definition: datasource.cxx:316
void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: datasource.cxx:325
Reference< XProxyFactory > m_xProxyFactory
Definition: datasource.cxx:299
Reference< XConnection > getConnection(const OUString &url, const OUString &user, const OUString &password, const Sequence< PropertyValue > &_aInfo, ODatabaseSource *_pDataSource)
Definition: datasource.cxx:342
virtual short run()
rtl::Reference< ParseManager > manager
#define DBA_RES(id)
int nCount
const PropertyAttributeCache & m_rAttribs
Definition: datasource.cxx:453
WeakReference< XFlushListener > m_aListener
Definition: datasource.cxx:111
WeakReference< XFlushable > m_aBroadcaster
Definition: datasource.cxx:110
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_dba_ODatabaseSource(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
float u
float y
float x
sal_uInt16 nPos
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
std::unique_ptr< sal_Int32[]> pData
@ Exception
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OInteraction< css::task::XInteractionAbort > OInteractionAbort
Type
bool any2bool(const css::uno::Any &rAny)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
std::shared_ptr< OContentHelper_Impl > TContentPtr
::cppu::WeakComponentImplHelper< css::lang::XServiceInfo, css::sdbc::XDataSource, css::sdb::XBookmarksSupplier, css::sdb::XQueryDefinitionsSupplier, css::sdb::XCompletedConnection, css::container::XContainerListener, css::sdbc::XIsolatedConnection, css::sdbcx::XTablesSupplier, css::util::XFlushable, css::util::XFlushListener, css::sdb::XDocumentDataSource, css::lang::XInitialization > ODatabaseSource_Base
Definition: datasource.hxx:57
bool getDataSourceSetting(const Reference< XInterface > &_xChild, const OUString &_sAsciiSettingsName, Any &_rSettingsValue)
void throwGenericSQLException(const OUString &_rMsg, const css::uno::Reference< css::uno::XInterface > &_rxSource)
::osl::Mutex & getMutex()
int i
enumrange< T >::Iterator begin(enumrange< T >)
end
void dispose()
sal_Int16 nId
sal_Int32 nHandle
OUString sMessage
Definition: sqlmessage.cxx:159
#define PROPERTY_ID_NAME
#define PROPERTY_ID_USER
#define PROPERTY_ID_ISREADONLY
#define PROPERTY_ID_TABLEFILTER
#define PROPERTY_ID_PASSWORD
#define PROPERTY_ID_TABLETYPEFILTER
#define PROPERTY_ID_INFO
#define PROPERTY_ID_SETTINGS
#define PROPERTY_ID_ISPASSWORDREQUIRED
#define PROPERTY_ID_LAYOUTINFORMATION
#define PROPERTY_ID_NUMBERFORMATSSUPPLIER
#define PROPERTY_ID_URL
#define PROPERTY_ID_SUPPRESSVERSIONCL
constexpr OUStringLiteral PROPERTY_TABLEFILTER(u"TableFilter")
constexpr OUStringLiteral PROPERTY_USER(u"User")
constexpr OUStringLiteral PROPERTY_URL(u"URL")
constexpr OUStringLiteral PROPERTY_INFO(u"Info")
constexpr OUStringLiteral PROPERTY_ISREADONLY(u"IsReadOnly")
constexpr OUStringLiteral PROPERTY_NUMBERFORMATSSUPPLIER(u"NumberFormatsSupplier")
constexpr OUStringLiteral PROPERTY_SETTINGS(u"Settings")
constexpr OUStringLiteral PROPERTY_PASSWORD(u"Password")
constexpr OUStringLiteral PROPERTY_TABLETYPEFILTER(u"TableTypeFilter")
constexpr OUStringLiteral SERVICE_SDB_DATASOURCE
Definition: strings.hxx:181
constexpr OUStringLiteral PROPERTY_SUPPRESSVERSIONCL(u"SuppressVersionColumns")
constexpr OUStringLiteral PROPERTY_NAME(u"Name")
constexpr OUStringLiteral PROPERTY_LAYOUTINFORMATION(u"LayoutInformation")
constexpr OUStringLiteral PROPERTY_ISPASSWORDREQUIRED(u"IsPasswordRequired")
sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1]
bool operator()(const TDigestHolder &x, const TDigestHolder &y) const
Definition: datasource.cxx:284
Reference< XController > xController
the controller of the sub component. Must not be <NULL>
Reference< XFrame > xFrame
the frame which the component resides in. Must not be <NULL>
Reference< XModel > xModel
the model of the sub component. Might be <NULL>
unsigned char sal_uInt8
unsigned char sal_Bool
RET_OK
size_t pos