Update ooo320-m1
[ooovba.git] / dbaccess / source / core / dataaccess / datasource.cxx
blobcbf30c87d30462c954595dddc06fdc1fb7e53245
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: datasource.cxx,v $
10 * $Revision: 1.79.4.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #include "datasource.hxx"
35 #include "module_dba.hxx"
36 #include "userinformation.hxx"
37 #include "commandcontainer.hxx"
38 #include "dbastrings.hrc"
39 #include "core_resource.hxx"
40 #include "core_resource.hrc"
41 #include "connection.hxx"
42 #include "SharedConnection.hxx"
43 #include "databasedocument.hxx"
45 /** === begin UNO includes === **/
46 #include <com/sun/star/beans/NamedValue.hpp>
47 #include <com/sun/star/beans/PropertyAttribute.hpp>
48 #include <com/sun/star/beans/PropertyState.hpp>
49 #include <com/sun/star/beans/XPropertyContainer.hpp>
50 #include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
51 #include <com/sun/star/document/XEventBroadcaster.hpp>
52 #include <com/sun/star/embed/XTransactedObject.hpp>
53 #include <com/sun/star/lang/DisposedException.hpp>
54 #include <com/sun/star/reflection/XProxyFactory.hpp>
55 #include <com/sun/star/sdbc/XDriverAccess.hpp>
56 #include <com/sun/star/sdbc/XDriverManager.hpp>
57 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
58 #include <com/sun/star/ucb/AuthenticationRequest.hpp>
59 #include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
60 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
61 #include <com/sun/star/view/XPrintable.hpp>
62 /** === end UNO includes === **/
64 #include <comphelper/extract.hxx>
65 #include <comphelper/guarding.hxx>
66 #include <comphelper/interaction.hxx>
67 #include <comphelper/namedvaluecollection.hxx>
68 #include <comphelper/property.hxx>
69 #include <comphelper/seqstream.hxx>
70 #include <comphelper/sequence.hxx>
71 #include <connectivity/dbexception.hxx>
72 #include <cppuhelper/typeprovider.hxx>
73 #include <rtl/digest.h>
74 #include <tools/debug.hxx>
75 #include <tools/diagnose_ex.h>
76 #include <tools/urlobj.hxx>
77 #include <typelib/typedescription.hxx>
78 #include <unotools/confignode.hxx>
79 #include <unotools/sharedunocomponent.hxx>
80 #include <rtl/logfile.hxx>
81 #include <algorithm>
83 using namespace ::com::sun::star::sdbc;
84 using namespace ::com::sun::star::sdbcx;
85 using namespace ::com::sun::star::sdb;
86 using namespace ::com::sun::star::beans;
87 using namespace ::com::sun::star::uno;
88 using namespace ::com::sun::star::lang;
89 using namespace ::com::sun::star::embed;
90 using namespace ::com::sun::star::container;
91 using namespace ::com::sun::star::util;
92 using namespace ::com::sun::star::io;
93 using namespace ::com::sun::star::task;
94 using namespace ::com::sun::star::ucb;
95 using namespace ::com::sun::star::frame;
96 using namespace ::com::sun::star::reflection;
97 using namespace ::cppu;
98 using namespace ::osl;
99 using namespace ::vos;
100 using namespace ::dbtools;
101 using namespace ::comphelper;
102 namespace css = ::com::sun::star;
104 //........................................................................
105 namespace dbaccess
107 //........................................................................
109 //============================================================
110 //= FlushNotificationAdapter
111 //============================================================
112 typedef ::cppu::WeakImplHelper1< XFlushListener > FlushNotificationAdapter_Base;
113 /** helper class which implements a XFlushListener, and forwards all
114 notification events to another XFlushListener
116 The speciality is that the foreign XFlushListener instance, to which
117 the notifications are forwarded, is held weak.
119 Thus, the class can be used with XFlushable instance which hold
120 their listeners with a hard reference, if you simply do not *want*
121 to be held hard-ref-wise.
123 class FlushNotificationAdapter : public FlushNotificationAdapter_Base
125 private:
126 WeakReference< XFlushable > m_aBroadcaster;
127 WeakReference< XFlushListener > m_aListener;
129 public:
130 static void installAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
132 Reference< XFlushListener > xAdapter( new FlushNotificationAdapter( _rxBroadcaster, _rxListener ) );
135 protected:
136 FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener );
137 ~FlushNotificationAdapter();
139 void SAL_CALL impl_dispose( bool _bRevokeListener );
141 protected:
142 // XFlushListener
143 virtual void SAL_CALL flushed( const ::com::sun::star::lang::EventObject& rEvent ) throw (::com::sun::star::uno::RuntimeException);
144 // XEventListener
145 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
148 //------------------------------------------------------------
149 DBG_NAME( FlushNotificationAdapter )
150 //------------------------------------------------------------
151 FlushNotificationAdapter::FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
152 :m_aBroadcaster( _rxBroadcaster )
153 ,m_aListener( _rxListener )
155 DBG_CTOR( FlushNotificationAdapter, NULL );
156 DBG_ASSERT( _rxBroadcaster.is(), "FlushNotificationAdapter::FlushNotificationAdapter: invalid flushable!" );
158 osl_incrementInterlockedCount( &m_refCount );
160 if ( _rxBroadcaster.is() )
161 _rxBroadcaster->addFlushListener( this );
163 osl_decrementInterlockedCount( &m_refCount );
164 DBG_ASSERT( m_refCount == 1, "FlushNotificationAdapter::FlushNotificationAdapter: broadcaster isn't holding by hard ref!?" );
167 //------------------------------------------------------------
168 FlushNotificationAdapter::~FlushNotificationAdapter()
170 DBG_DTOR( FlushNotificationAdapter, NULL );
173 //--------------------------------------------------------------------
174 void SAL_CALL FlushNotificationAdapter::impl_dispose( bool _bRevokeListener )
176 Reference< XFlushListener > xKeepAlive( this );
178 if ( _bRevokeListener )
180 Reference< XFlushable > xFlushable( m_aBroadcaster );
181 if ( xFlushable.is() )
182 xFlushable->removeFlushListener( this );
185 m_aListener = Reference< XFlushListener >();
186 m_aBroadcaster = Reference< XFlushable >();
189 //--------------------------------------------------------------------
190 void SAL_CALL FlushNotificationAdapter::flushed( const EventObject& rEvent ) throw (RuntimeException)
192 Reference< XFlushListener > xListener( m_aListener );
193 if ( xListener.is() )
194 xListener->flushed( rEvent );
195 else
196 impl_dispose( true );
199 //--------------------------------------------------------------------
200 void SAL_CALL FlushNotificationAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
202 DBG_ASSERT( Source.Source == m_aBroadcaster.get(), "FlushNotificationAdapter::disposing: where did this come from?" );
204 Reference< XFlushListener > xListener( m_aListener );
205 if ( xListener.is() )
206 xListener->disposing( Source );
208 impl_dispose( false );
211 //============================================================
212 //= OAuthenticationContinuation
213 //============================================================
214 class OAuthenticationContinuation : public OInteraction< XInteractionSupplyAuthentication >
216 sal_Bool m_bRemberPassword : 1; // remember the password for this session ?
218 ::rtl::OUString m_sUser; // the user
219 ::rtl::OUString m_sPassword; // the user's password
221 public:
222 OAuthenticationContinuation();
224 sal_Bool SAL_CALL canSetRealm( ) throw(RuntimeException);
225 void SAL_CALL setRealm( const ::rtl::OUString& Realm ) throw(RuntimeException);
226 sal_Bool SAL_CALL canSetUserName( ) throw(RuntimeException);
227 void SAL_CALL setUserName( const ::rtl::OUString& UserName ) throw(RuntimeException);
228 sal_Bool SAL_CALL canSetPassword( ) throw(RuntimeException);
229 void SAL_CALL setPassword( const ::rtl::OUString& Password ) throw(RuntimeException);
230 Sequence< RememberAuthentication > SAL_CALL getRememberPasswordModes( RememberAuthentication& Default ) throw(RuntimeException);
231 void SAL_CALL setRememberPassword( RememberAuthentication Remember ) throw(RuntimeException);
232 sal_Bool SAL_CALL canSetAccount( ) throw(RuntimeException);
233 void SAL_CALL setAccount( const ::rtl::OUString& Account ) throw(RuntimeException);
234 Sequence< RememberAuthentication > SAL_CALL getRememberAccountModes( RememberAuthentication& Default ) throw(RuntimeException);
235 void SAL_CALL setRememberAccount( RememberAuthentication Remember ) throw(RuntimeException);
237 ::rtl::OUString getUser() const { return m_sUser; }
238 ::rtl::OUString getPassword() const { return m_sPassword; }
239 sal_Bool getRememberPassword() const { return m_bRemberPassword; }
242 //--------------------------------------------------------------------------
243 OAuthenticationContinuation::OAuthenticationContinuation()
244 :m_bRemberPassword(sal_True) // TODO: a meaningfull default
248 //--------------------------------------------------------------------------
249 sal_Bool SAL_CALL OAuthenticationContinuation::canSetRealm( ) throw(RuntimeException)
251 return sal_False;
254 //--------------------------------------------------------------------------
255 void SAL_CALL OAuthenticationContinuation::setRealm( const ::rtl::OUString& /*Realm*/ ) throw(RuntimeException)
257 DBG_ERROR("OAuthenticationContinuation::setRealm: not supported!");
260 //--------------------------------------------------------------------------
261 sal_Bool SAL_CALL OAuthenticationContinuation::canSetUserName( ) throw(RuntimeException)
263 // we alwas allow this, even if the database document is read-only. In this case,
264 // it's simply that the user cannot store the new user name.
265 return sal_True;
268 //--------------------------------------------------------------------------
269 void SAL_CALL OAuthenticationContinuation::setUserName( const ::rtl::OUString& _rUser ) throw(RuntimeException)
271 m_sUser = _rUser;
274 //--------------------------------------------------------------------------
275 sal_Bool SAL_CALL OAuthenticationContinuation::canSetPassword( ) throw(RuntimeException)
277 return sal_True;
280 //--------------------------------------------------------------------------
281 void SAL_CALL OAuthenticationContinuation::setPassword( const ::rtl::OUString& _rPassword ) throw(RuntimeException)
283 m_sPassword = _rPassword;
286 //--------------------------------------------------------------------------
287 Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberPasswordModes( RememberAuthentication& _reDefault ) throw(RuntimeException)
289 Sequence< RememberAuthentication > aReturn(1);
290 _reDefault = aReturn[0] = RememberAuthentication_SESSION;
291 return aReturn;
294 //--------------------------------------------------------------------------
295 void SAL_CALL OAuthenticationContinuation::setRememberPassword( RememberAuthentication _eRemember ) throw(RuntimeException)
297 m_bRemberPassword = (RememberAuthentication_NO != _eRemember);
300 //--------------------------------------------------------------------------
301 sal_Bool SAL_CALL OAuthenticationContinuation::canSetAccount( ) throw(RuntimeException)
303 return sal_False;
306 //--------------------------------------------------------------------------
307 void SAL_CALL OAuthenticationContinuation::setAccount( const ::rtl::OUString& ) throw(RuntimeException)
309 DBG_ERROR("OAuthenticationContinuation::setAccount: not supported!");
312 //--------------------------------------------------------------------------
313 Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberAccountModes( RememberAuthentication& _reDefault ) throw(RuntimeException)
315 Sequence < RememberAuthentication > aReturn(1);
316 aReturn[0] = RememberAuthentication_NO;
317 _reDefault = RememberAuthentication_NO;
318 return aReturn;
321 //--------------------------------------------------------------------------
322 void SAL_CALL OAuthenticationContinuation::setRememberAccount( RememberAuthentication /*Remember*/ ) throw(RuntimeException)
324 DBG_ERROR("OAuthenticationContinuation::setRememberAccount: not supported!");
327 /** The class OSharedConnectionManager implements a structure to share connections.
328 It owns the master connections which will be disposed when the last connection proxy is gone.
330 typedef ::cppu::WeakImplHelper1< XEventListener > OConnectionHelper_BASE;
331 // need to hold the digest
332 struct TDigestHolder
334 sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1];
335 TDigestHolder()
337 m_pBuffer[0] = 0;
342 class OSharedConnectionManager : public OConnectionHelper_BASE
345 // contains the currently used master connections
346 typedef struct
348 Reference< XConnection > xMasterConnection;
349 oslInterlockedCount nALiveCount;
350 } TConnectionHolder;
352 // the less-compare functor, used for the stl::map
353 struct TDigestLess : public ::std::binary_function< TDigestHolder, TDigestHolder, bool>
355 bool operator() (const TDigestHolder& x, const TDigestHolder& y) const
357 sal_uInt32 i;
358 for(i=0;i < RTL_DIGEST_LENGTH_SHA1 && (x.m_pBuffer[i] >= y.m_pBuffer[i]); ++i)
360 return i < RTL_DIGEST_LENGTH_SHA1;
364 typedef ::std::map< TDigestHolder,TConnectionHolder,TDigestLess> TConnectionMap; // holds the master connections
365 typedef ::std::map< Reference< XConnection >,TConnectionMap::iterator> TSharedConnectionMap;// holds the shared connections
367 ::osl::Mutex m_aMutex;
368 TConnectionMap m_aConnections; // remeber the master connection in conjunction with the digest
369 TSharedConnectionMap m_aSharedConnection; // the shared connections with conjunction with an iterator into the connections map
370 Reference< XProxyFactory > m_xProxyFactory;
372 protected:
373 ~OSharedConnectionManager();
375 public:
376 OSharedConnectionManager(const Reference< XMultiServiceFactory >& _rxServiceFactory);
378 void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException);
379 Reference<XConnection> getConnection( const rtl::OUString& url,
380 const rtl::OUString& user,
381 const rtl::OUString& password,
382 const Sequence< PropertyValue >& _aInfo,
383 ODatabaseSource* _pDataSource);
384 void addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter);
387 DBG_NAME(OSharedConnectionManager)
388 OSharedConnectionManager::OSharedConnectionManager(const Reference< XMultiServiceFactory >& _rxServiceFactory)
390 DBG_CTOR(OSharedConnectionManager,NULL);
391 m_xProxyFactory.set(_rxServiceFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY);
394 OSharedConnectionManager::~OSharedConnectionManager()
396 DBG_DTOR(OSharedConnectionManager,NULL);
399 void SAL_CALL OSharedConnectionManager::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException)
401 MutexGuard aGuard(m_aMutex);
402 Reference<XConnection> xConnection(Source.Source,UNO_QUERY);
403 TSharedConnectionMap::iterator aFind = m_aSharedConnection.find(xConnection);
404 if ( m_aSharedConnection.end() != aFind )
406 osl_decrementInterlockedCount(&aFind->second->second.nALiveCount);
407 if ( !aFind->second->second.nALiveCount )
409 ::comphelper::disposeComponent(aFind->second->second.xMasterConnection);
410 m_aConnections.erase(aFind->second);
412 m_aSharedConnection.erase(aFind);
416 Reference<XConnection> OSharedConnectionManager::getConnection( const rtl::OUString& url,
417 const rtl::OUString& user,
418 const rtl::OUString& password,
419 const Sequence< PropertyValue >& _aInfo,
420 ODatabaseSource* _pDataSource)
422 MutexGuard aGuard(m_aMutex);
423 TConnectionMap::key_type nId;
424 Sequence< PropertyValue > aInfoCopy(_aInfo);
425 sal_Int32 nPos = aInfoCopy.getLength();
426 aInfoCopy.realloc( nPos + 2 );
427 aInfoCopy[nPos].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableFilter"));
428 aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableFilter;
429 aInfoCopy[nPos].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableTypeFilter"));
430 aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableTypeFilter; // #22377# OJ
432 ::rtl::OUString sUser = user;
433 ::rtl::OUString sPassword = password;
434 if ((0 == sUser.getLength()) && (0 == sPassword.getLength()) && (0 != _pDataSource->m_pImpl->m_sUser.getLength()))
435 { // ease the usage of this method. data source which are intended to have a user automatically
436 // fill in the user/password combination if the caller of this method does not specify otherwise
437 // 86951 - 05/08/2001 - frank.schoenheit@germany.sun.com
438 sUser = _pDataSource->m_pImpl->m_sUser;
439 if (0 != _pDataSource->m_pImpl->m_aPassword.getLength())
440 sPassword = _pDataSource->m_pImpl->m_aPassword;
443 ::connectivity::OConnectionWrapper::createUniqueId(url,aInfoCopy,nId.m_pBuffer,sUser,sPassword);
444 TConnectionMap::iterator aIter = m_aConnections.find(nId);
446 if ( m_aConnections.end() == aIter )
448 TConnectionHolder aHolder;
449 aHolder.nALiveCount = 0; // will be incremented by addListener
450 aHolder.xMasterConnection = _pDataSource->buildIsolatedConnection(user,password);
451 aIter = m_aConnections.insert(TConnectionMap::value_type(nId,aHolder)).first;
454 Reference<XConnection> xRet;
455 if ( aIter->second.xMasterConnection.is() )
457 Reference< XAggregation > xConProxy = m_xProxyFactory->createProxy(aIter->second.xMasterConnection.get());
458 xRet = new OSharedConnection(xConProxy);
459 m_aSharedConnection.insert(TSharedConnectionMap::value_type(xRet,aIter));
460 addEventListener(xRet,aIter);
463 return xRet;
465 void OSharedConnectionManager::addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter)
467 Reference<XComponent> xComp(_rxConnection,UNO_QUERY);
468 xComp->addEventListener(this);
469 OSL_ENSURE( m_aConnections.end() != _rIter , "Iterator is end!");
470 osl_incrementInterlockedCount(&_rIter->second.nALiveCount);
473 //----------------------------------------------------------------------
474 namespace
476 //------------------------------------------------------------------
477 Sequence< PropertyValue > lcl_filterDriverProperties( const Reference< XDriver >& _xDriver, const ::rtl::OUString& _sUrl,
478 const Sequence< PropertyValue >& _rDataSourceSettings, const AsciiPropertyValue* _pKnownSettings )
480 if ( _xDriver.is() )
482 Sequence< DriverPropertyInfo > aDriverInfo(_xDriver->getPropertyInfo(_sUrl,_rDataSourceSettings));
484 const PropertyValue* pDataSourceSetting = _rDataSourceSettings.getConstArray();
485 const PropertyValue* pEnd = pDataSourceSetting + _rDataSourceSettings.getLength();
487 ::std::vector< PropertyValue > aRet;
489 for ( ; pDataSourceSetting != pEnd ; ++pDataSourceSetting )
491 sal_Bool bAllowSetting = sal_False;
492 const AsciiPropertyValue* pSetting = _pKnownSettings;
493 for ( ; pSetting->AsciiName; ++pSetting )
495 if ( !pDataSourceSetting->Name.compareToAscii( pSetting->AsciiName ) )
496 { // the particular data source setting is known
498 const DriverPropertyInfo* pAllowedDriverSetting = aDriverInfo.getConstArray();
499 const DriverPropertyInfo* pDriverSettingsEnd = pAllowedDriverSetting + aDriverInfo.getLength();
500 for ( ; pAllowedDriverSetting != pDriverSettingsEnd; ++pAllowedDriverSetting )
502 if ( !pAllowedDriverSetting->Name.compareToAscii( pSetting->AsciiName ) )
503 { // the driver also allows this setting
504 bAllowSetting = sal_True;
505 break;
508 break;
511 if ( bAllowSetting || !pSetting->AsciiName )
512 { // if the driver allows this particular setting, or if the setting is completely unknown,
513 // we pass it to the driver
514 aRet.push_back( *pDataSourceSetting );
517 if ( !aRet.empty() )
518 return Sequence< PropertyValue >(&(*aRet.begin()),aRet.size());
520 return Sequence< PropertyValue >();
523 //------------------------------------------------------------------
524 typedef ::std::map< ::rtl::OUString, sal_Int32 > PropertyAttributeCache;
526 //------------------------------------------------------------------
527 struct IsDefaultAndNotRemoveable : public ::std::unary_function< PropertyValue, bool >
529 private:
530 const PropertyAttributeCache& m_rAttribs;
532 public:
533 IsDefaultAndNotRemoveable( const PropertyAttributeCache& _rAttribs ) : m_rAttribs( _rAttribs ) { }
535 bool operator()( const PropertyValue& _rProp )
537 if ( _rProp.State != PropertyState_DEFAULT_VALUE )
538 return false;
540 bool bRemoveable = true;
542 PropertyAttributeCache::const_iterator pos = m_rAttribs.find( _rProp.Name );
543 OSL_ENSURE( pos != m_rAttribs.end(), "IsDefaultAndNotRemoveable: illegal property name!" );
544 if ( pos != m_rAttribs.end() )
545 bRemoveable = ( ( pos->second & PropertyAttribute::REMOVEABLE ) != 0 );
547 return !bRemoveable;
551 //============================================================
552 //= ODatabaseContext
553 //============================================================
554 DBG_NAME(ODatabaseSource)
555 //--------------------------------------------------------------------------
556 extern "C" void SAL_CALL createRegistryInfo_ODatabaseSource()
558 static ::dba::OAutoRegistration< ODatabaseSource > aAutoRegistration;
561 //--------------------------------------------------------------------------
562 ODatabaseSource::ODatabaseSource(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl)
563 :ModelDependentComponent( _pImpl )
564 ,OSubComponent( getMutex(), Reference< XInterface >() )
565 ,OPropertySetHelper(OComponentHelper::rBHelper)
566 ,m_aBookmarks( *this, getMutex() )
567 ,m_aFlushListeners( getMutex() )
569 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::ODatabaseSource" );
570 // some kind of default
571 DBG_CTOR(ODatabaseSource,NULL);
574 //--------------------------------------------------------------------------
575 ODatabaseSource::~ODatabaseSource()
577 DBG_DTOR(ODatabaseSource,NULL);
578 if ( !OComponentHelper::rBHelper.bInDispose && !OComponentHelper::rBHelper.bDisposed )
580 acquire();
581 dispose();
585 //--------------------------------------------------------------------------
586 void ODatabaseSource::setName( const Reference< XDocumentDataSource >& _rxDocument, const ::rtl::OUString& _rNewName, DBContextAccess )
588 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setName" );
589 ODatabaseSource& rModelImpl = dynamic_cast< ODatabaseSource& >( *_rxDocument.get() );
591 ::osl::MutexGuard aGuard( rModelImpl.m_aMutex );
592 if ( rModelImpl.m_pImpl.is() )
593 rModelImpl.m_pImpl->m_sName = _rNewName;
596 // com::sun::star::lang::XTypeProvider
597 //--------------------------------------------------------------------------
598 Sequence< Type > ODatabaseSource::getTypes() throw (RuntimeException)
600 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTypes" );
601 OTypeCollection aPropertyHelperTypes( ::getCppuType( (const Reference< XFastPropertySet > *)0 ),
602 ::getCppuType( (const Reference< XPropertySet > *)0 ),
603 ::getCppuType( (const Reference< XMultiPropertySet > *)0 ));
605 return ::comphelper::concatSequences(
606 ::comphelper::concatSequences(
607 OSubComponent::getTypes(),
608 aPropertyHelperTypes.getTypes()
610 ODatabaseSource_Base::getTypes()
614 //--------------------------------------------------------------------------
615 Sequence< sal_Int8 > ODatabaseSource::getImplementationId() throw (RuntimeException)
617 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationId" );
618 static OImplementationId * pId = 0;
619 if (! pId)
621 MutexGuard aGuard( Mutex::getGlobalMutex() );
622 if (! pId)
624 static OImplementationId aId;
625 pId = &aId;
628 return pId->getImplementationId();
631 // com::sun::star::uno::XInterface
632 //--------------------------------------------------------------------------
633 Any ODatabaseSource::queryInterface( const Type & rType ) throw (RuntimeException)
635 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::queryInterface" );
636 Any aIface = OSubComponent::queryInterface( rType );
637 if (!aIface.hasValue())
639 aIface = ODatabaseSource_Base::queryInterface( rType );
640 if ( !aIface.hasValue() )
642 aIface = ::cppu::queryInterface(
643 rType,
644 static_cast< XPropertySet* >( this ),
645 static_cast< XFastPropertySet* >( this ),
646 static_cast< XMultiPropertySet* >( this ));
649 return aIface;
652 //--------------------------------------------------------------------------
653 void ODatabaseSource::acquire() throw ()
655 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::acquire" );
656 OSubComponent::acquire();
659 //--------------------------------------------------------------------------
660 void ODatabaseSource::release() throw ()
662 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::release" );
663 OSubComponent::release();
665 // -----------------------------------------------------------------------------
666 void SAL_CALL ODatabaseSource::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException)
668 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::disposing" );
669 if ( m_pImpl.is() )
670 m_pImpl->disposing(Source);
672 // XServiceInfo
673 //------------------------------------------------------------------------------
674 rtl::OUString ODatabaseSource::getImplementationName( ) throw(RuntimeException)
676 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName" );
677 return getImplementationName_static();
680 //------------------------------------------------------------------------------
681 rtl::OUString ODatabaseSource::getImplementationName_static( ) throw(RuntimeException)
683 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName_static" );
684 return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ODatabaseSource");
687 //------------------------------------------------------------------------------
688 Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames( ) throw (RuntimeException)
690 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames" );
691 return getSupportedServiceNames_static();
693 //------------------------------------------------------------------------------
694 Reference< XInterface > ODatabaseSource::Create( const Reference< XComponentContext >& _rxContext )
696 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::Create" );
697 ::comphelper::ComponentContext aContext( _rxContext );
698 Reference< XSingleServiceFactory > xDBContext( aContext.createComponent( (::rtl::OUString)SERVICE_SDB_DATABASECONTEXT ), UNO_QUERY_THROW );
699 return xDBContext->createInstance();
702 //------------------------------------------------------------------------------
703 Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames_static( ) throw (RuntimeException)
705 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames_static" );
706 Sequence< ::rtl::OUString > aSNS( 2 );
707 aSNS[0] = SERVICE_SDB_DATASOURCE;
708 aSNS[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.DocumentDataSource"));
709 return aSNS;
712 //------------------------------------------------------------------------------
713 sal_Bool ODatabaseSource::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
715 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::supportsService" );
716 return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
718 // OComponentHelper
719 //------------------------------------------------------------------------------
720 void ODatabaseSource::disposing()
722 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::disposing" );
723 OSubComponent::disposing();
724 OPropertySetHelper::disposing();
726 EventObject aDisposeEvent(static_cast<XWeak*>(this));
727 m_aFlushListeners.disposeAndClear( aDisposeEvent );
729 ODatabaseDocument::clearObjectContainer(m_pImpl->m_xCommandDefinitions);
730 ODatabaseDocument::clearObjectContainer(m_pImpl->m_xTableDefinitions);
731 m_pImpl.clear();
733 //------------------------------------------------------------------------------
734 Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const ::rtl::OUString& _rUid, const ::rtl::OUString& _rPwd)
736 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildLowLevelConnection" );
737 Reference< XConnection > xReturn;
739 Reference< XDriverManager > xManager;
740 if ( !m_pImpl->m_aContext.createComponent( "com.sun.star.sdbc.ConnectionPool", xManager ) )
741 // no connection pool installed, fall back to driver manager
742 m_pImpl->m_aContext.createComponent( "com.sun.star.sdbc.DriverManager", xManager );
744 ::rtl::OUString sUser(_rUid);
745 ::rtl::OUString sPwd(_rPwd);
746 if ((0 == sUser.getLength()) && (0 == sPwd.getLength()) && (0 != m_pImpl->m_sUser.getLength()))
747 { // ease the usage of this method. data source which are intended to have a user automatically
748 // fill in the user/password combination if the caller of this method does not specify otherwise
749 // 86951 - 05/08/2001 - frank.schoenheit@germany.sun.com
750 sUser = m_pImpl->m_sUser;
751 if (0 != m_pImpl->m_aPassword.getLength())
752 sPwd = m_pImpl->m_aPassword;
755 sal_uInt16 nExceptionMessageId = RID_STR_COULDNOTCONNECT_UNSPECIFIED;
756 if (xManager.is())
758 sal_Int32 nAdditionalArgs(0);
759 if (sUser.getLength()) ++nAdditionalArgs;
760 if (sPwd.getLength()) ++nAdditionalArgs;
762 Sequence< PropertyValue > aUserPwd(nAdditionalArgs);
763 sal_Int32 nArgPos = 0;
764 if (sUser.getLength())
766 aUserPwd[ nArgPos ].Name = ::rtl::OUString::createFromAscii("user");
767 aUserPwd[ nArgPos ].Value <<= sUser;
768 ++nArgPos;
770 if (sPwd.getLength())
772 aUserPwd[ nArgPos ].Name = ::rtl::OUString::createFromAscii("password");
773 aUserPwd[ nArgPos ].Value <<= sPwd;
775 Reference< XDriver > xDriver;
778 Reference< XDriverAccess > xAccessDrivers( xManager, UNO_QUERY );
779 if ( xAccessDrivers.is() )
780 xDriver = xAccessDrivers->getDriverByURL( m_pImpl->m_sConnectURL );
782 catch( const Exception& )
784 DBG_ERROR( "ODatabaseSource::buildLowLevelConnection: got a strange exception while analyzing the error!" );
786 if ( !xDriver.is() || !xDriver->acceptsURL( m_pImpl->m_sConnectURL ) )
788 // Nowadays, it's allowed for a driver to be registered for a given URL, but actually not to accept it.
789 // This is because registration nowadays happens at compile time (by adding respective configuration data),
790 // but acceptance is decided at runtime.
791 nExceptionMessageId = RID_STR_COULDNOTCONNECT_NODRIVER;
793 else
795 Sequence< PropertyValue > aDriverInfo = lcl_filterDriverProperties(
796 xDriver,
797 m_pImpl->m_sConnectURL,
798 m_pImpl->m_xSettings->getPropertyValues(),
799 m_pImpl->getDefaultDataSourceSettings()
802 impl_insertJavaDriverClassPath_nothrow(aDriverInfo);
804 if ( m_pImpl->isEmbeddedDatabase() )
806 sal_Int32 nCount = aDriverInfo.getLength();
807 aDriverInfo.realloc(nCount + 2 );
808 aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
809 aDriverInfo[nCount++].Value <<= m_pImpl->getURL();
810 aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Storage"));
811 Reference< css::document::XDocumentSubStorageSupplier> xDocSup( m_pImpl->getDocumentSubStorageSupplier() );
812 aDriverInfo[nCount++].Value <<= xDocSup->getDocumentSubStorage(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("database")),ElementModes::READWRITE);
814 if (nAdditionalArgs)
815 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL, ::comphelper::concatSequences(aUserPwd,aDriverInfo));
816 else
817 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL,aDriverInfo);
819 if ( m_pImpl->isEmbeddedDatabase() )
821 // see ODatabaseSource::flushed for comment on why we register as FlushListener
822 // at the connection
823 Reference< XFlushable > xFlushable( xReturn, UNO_QUERY );
824 if ( xFlushable.is() )
825 FlushNotificationAdapter::installAdapter( xFlushable, this );
829 else
830 nExceptionMessageId = RID_STR_COULDNOTLOAD_MANAGER;
832 if ( !xReturn.is() )
834 ::rtl::OUString sMessage = DBACORE_RESSTRING( nExceptionMessageId );
836 SQLContext aContext;
837 aContext.Message = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A connection for the following URL was requested: " ) );
838 // TODO: resource
839 aContext.Message += m_pImpl->m_sConnectURL;
841 throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), makeAny( aContext ) );
844 return xReturn;
847 // OPropertySetHelper
848 //------------------------------------------------------------------------------
849 Reference< XPropertySetInfo > ODatabaseSource::getPropertySetInfo() throw (RuntimeException)
851 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getPropertySetInfo" );
852 return createPropertySetInfo( getInfoHelper() ) ;
855 // comphelper::OPropertyArrayUsageHelper
856 //------------------------------------------------------------------------------
857 ::cppu::IPropertyArrayHelper* ODatabaseSource::createArrayHelper( ) const
859 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::createArrayHelper" );
860 BEGIN_PROPERTY_HELPER(13)
861 DECL_PROP1(INFO, Sequence< PropertyValue >, BOUND);
862 DECL_PROP1_BOOL(ISPASSWORDREQUIRED, BOUND);
863 DECL_PROP1_BOOL(ISREADONLY, READONLY);
864 DECL_PROP1(LAYOUTINFORMATION, Sequence< PropertyValue >, BOUND);
865 DECL_PROP1(NAME, ::rtl::OUString, READONLY);
866 DECL_PROP2_IFACE(NUMBERFORMATSSUPPLIER, XNumberFormatsSupplier, READONLY, TRANSIENT);
867 DECL_PROP1(PASSWORD, ::rtl::OUString, TRANSIENT);
868 DECL_PROP2_IFACE(SETTINGS, XPropertySet, BOUND, READONLY);
869 DECL_PROP1_BOOL(SUPPRESSVERSIONCL, BOUND);
870 DECL_PROP1(TABLEFILTER, Sequence< ::rtl::OUString >,BOUND);
871 DECL_PROP1(TABLETYPEFILTER, Sequence< ::rtl::OUString >,BOUND);
872 DECL_PROP1(URL, ::rtl::OUString, BOUND);
873 DECL_PROP1(USER, ::rtl::OUString, BOUND);
874 END_PROPERTY_HELPER();
877 // cppu::OPropertySetHelper
878 //------------------------------------------------------------------------------
879 ::cppu::IPropertyArrayHelper& ODatabaseSource::getInfoHelper()
881 return *getArrayHelper();
884 //------------------------------------------------------------------------------
885 sal_Bool ODatabaseSource::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException )
887 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::convertFastPropertyValue" );
888 sal_Bool bModified(sal_False);
889 if ( m_pImpl.is() )
891 switch (nHandle)
893 case PROPERTY_ID_TABLEFILTER:
894 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableFilter);
895 break;
896 case PROPERTY_ID_TABLETYPEFILTER:
897 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableTypeFilter);
898 break;
899 case PROPERTY_ID_USER:
900 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sUser);
901 break;
902 case PROPERTY_ID_PASSWORD:
903 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aPassword);
904 break;
905 case PROPERTY_ID_ISPASSWORDREQUIRED:
906 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bPasswordRequired);
907 break;
908 case PROPERTY_ID_SUPPRESSVERSIONCL:
909 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bSuppressVersionColumns);
910 break;
911 case PROPERTY_ID_LAYOUTINFORMATION:
912 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aLayoutInformation);
913 break;
914 case PROPERTY_ID_URL:
916 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sConnectURL);
917 } break;
918 case PROPERTY_ID_INFO:
920 Sequence<PropertyValue> aValues;
921 if (!(rValue >>= aValues))
922 throw IllegalArgumentException();
924 const PropertyValue* valueEnd = aValues.getConstArray() + aValues.getLength();
925 const PropertyValue* checkName = aValues.getConstArray();
926 for ( ;checkName != valueEnd; ++checkName )
928 if ( !checkName->Name.getLength() )
929 throw IllegalArgumentException();
932 Sequence< PropertyValue > aSettings = m_pImpl->m_xSettings->getPropertyValues();
933 bModified = aSettings.getLength() != aValues.getLength();
934 if ( !bModified )
936 const PropertyValue* pInfoIter = aSettings.getConstArray();
937 const PropertyValue* checkValue = aValues.getConstArray();
938 for ( ;!bModified && checkValue != valueEnd ; ++checkValue,++pInfoIter)
940 bModified = checkValue->Name != pInfoIter->Name;
941 if ( !bModified )
943 bModified = !::comphelper::compare(checkValue->Value,pInfoIter->Value);
948 rConvertedValue = rValue;
949 rOldValue <<= aSettings;
951 break;
952 default:
953 DBG_ERROR( "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" );
956 return bModified;
959 //------------------------------------------------------------------------------
960 namespace
962 struct SelectPropertyName : public ::std::unary_function< PropertyValue, ::rtl::OUString >
964 public:
965 const ::rtl::OUString& operator()( const PropertyValue& _lhs )
967 return _lhs.Name;
971 /** sets a new set of property values at a given property bag instance
973 The methods takes a property bag, and a sequence of property values to set at this bag.
974 Upon return, every property which is not part of the given sequence is
975 <ul><li>removed from the bag, if it's a removeable property</li>
976 <li><em>or</em>reset to its default value, if it's not a removeable property</li>
977 </ul>.
979 @param _rxPropertyBag
980 the property bag to operate on
981 @param _rAllNewPropertyValues
982 the new property values to set at the bag
984 void lcl_setPropertyValues_resetOrRemoveOther( const Reference< XPropertyAccess >& _rxPropertyBag, const Sequence< PropertyValue >& _rAllNewPropertyValues )
986 // sequences are ugly to operate on
987 typedef ::std::set< ::rtl::OUString > StringSet;
988 StringSet aToBeSetPropertyNames;
989 ::std::transform(
990 _rAllNewPropertyValues.getConstArray(),
991 _rAllNewPropertyValues.getConstArray() + _rAllNewPropertyValues.getLength(),
992 ::std::insert_iterator< StringSet >( aToBeSetPropertyNames, aToBeSetPropertyNames.end() ),
993 SelectPropertyName()
998 // obtain all properties currently known at the bag
999 Reference< XPropertySet > xPropertySet( _rxPropertyBag, UNO_QUERY_THROW );
1000 Reference< XPropertySetInfo > xPSI( xPropertySet->getPropertySetInfo(), UNO_QUERY_THROW );
1001 Sequence< Property > aAllExistentProperties( xPSI->getProperties() );
1003 Reference< XPropertyState > xPropertyState( _rxPropertyBag, UNO_QUERY_THROW );
1004 Reference< XPropertyContainer > xPropertyContainer( _rxPropertyBag, UNO_QUERY_THROW );
1006 // loop through them, and reset resp. default properties which are not to be set
1007 const Property* pExistentProperty( aAllExistentProperties.getConstArray() );
1008 const Property* pExistentPropertyEnd( aAllExistentProperties.getConstArray() + aAllExistentProperties.getLength() );
1009 for ( ; pExistentProperty != pExistentPropertyEnd; ++pExistentProperty )
1011 if ( aToBeSetPropertyNames.find( pExistentProperty->Name ) != aToBeSetPropertyNames.end() )
1012 continue;
1014 // this property is not to be set, but currently exists in the bag.
1015 // -> Remove, respectively default, it
1016 if ( ( pExistentProperty->Attributes & PropertyAttribute::REMOVEABLE ) != 0 )
1017 xPropertyContainer->removeProperty( pExistentProperty->Name );
1018 else
1019 xPropertyState->setPropertyToDefault( pExistentProperty->Name );
1022 // finally, set the new property values
1023 _rxPropertyBag->setPropertyValues( _rAllNewPropertyValues );
1025 catch( const Exception& )
1027 DBG_UNHANDLED_EXCEPTION();
1032 //------------------------------------------------------------------------------
1033 void ODatabaseSource::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
1035 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setFastPropertyValue_NoBroadcast" );
1036 if ( m_pImpl.is() )
1038 switch(nHandle)
1040 case PROPERTY_ID_TABLEFILTER:
1041 rValue >>= m_pImpl->m_aTableFilter;
1042 break;
1043 case PROPERTY_ID_TABLETYPEFILTER:
1044 rValue >>= m_pImpl->m_aTableTypeFilter;
1045 break;
1046 case PROPERTY_ID_USER:
1047 rValue >>= m_pImpl->m_sUser;
1048 // if the user name changed, reset the password
1049 m_pImpl->m_aPassword = ::rtl::OUString();
1050 break;
1051 case PROPERTY_ID_PASSWORD:
1052 rValue >>= m_pImpl->m_aPassword;
1053 break;
1054 case PROPERTY_ID_ISPASSWORDREQUIRED:
1055 m_pImpl->m_bPasswordRequired = any2bool(rValue);
1056 break;
1057 case PROPERTY_ID_SUPPRESSVERSIONCL:
1058 m_pImpl->m_bSuppressVersionColumns = any2bool(rValue);
1059 break;
1060 case PROPERTY_ID_URL:
1061 rValue >>= m_pImpl->m_sConnectURL;
1062 break;
1063 case PROPERTY_ID_INFO:
1065 Sequence< PropertyValue > aInfo;
1066 OSL_VERIFY( rValue >>= aInfo );
1067 lcl_setPropertyValues_resetOrRemoveOther( m_pImpl->m_xSettings, aInfo );
1069 break;
1070 case PROPERTY_ID_LAYOUTINFORMATION:
1071 rValue >>= m_pImpl->m_aLayoutInformation;
1072 break;
1074 m_pImpl->setModified(sal_True);
1078 //------------------------------------------------------------------------------
1079 void ODatabaseSource::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
1081 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getFastPropertyValue" );
1082 if ( m_pImpl.is() )
1084 switch (nHandle)
1086 case PROPERTY_ID_TABLEFILTER:
1087 rValue <<= m_pImpl->m_aTableFilter;
1088 break;
1089 case PROPERTY_ID_TABLETYPEFILTER:
1090 rValue <<= m_pImpl->m_aTableTypeFilter;
1091 break;
1092 case PROPERTY_ID_USER:
1093 rValue <<= m_pImpl->m_sUser;
1094 break;
1095 case PROPERTY_ID_PASSWORD:
1096 rValue <<= m_pImpl->m_aPassword;
1097 break;
1098 case PROPERTY_ID_ISPASSWORDREQUIRED:
1099 rValue = bool2any(m_pImpl->m_bPasswordRequired);
1100 break;
1101 case PROPERTY_ID_SUPPRESSVERSIONCL:
1102 rValue = bool2any(m_pImpl->m_bSuppressVersionColumns);
1103 break;
1104 case PROPERTY_ID_ISREADONLY:
1105 rValue = bool2any(m_pImpl->m_bReadOnly);
1106 break;
1107 case PROPERTY_ID_INFO:
1111 // collect the property attributes of all current settings
1112 Reference< XPropertySet > xSettingsAsProps( m_pImpl->m_xSettings, UNO_QUERY_THROW );
1113 Reference< XPropertySetInfo > xPST( xSettingsAsProps->getPropertySetInfo(), UNO_QUERY_THROW );
1114 Sequence< Property > aSettings( xPST->getProperties() );
1115 ::std::map< ::rtl::OUString, sal_Int32 > aPropertyAttributes;
1116 for ( const Property* pSettings = aSettings.getConstArray();
1117 pSettings != aSettings.getConstArray() + aSettings.getLength();
1118 ++pSettings
1121 aPropertyAttributes[ pSettings->Name ] = pSettings->Attributes;
1124 // get all current settings with their values
1125 Sequence< PropertyValue > aValues( m_pImpl->m_xSettings->getPropertyValues() );
1127 // transform them so that only property values which fulfill certain
1128 // criterions survive
1129 Sequence< PropertyValue > aNonDefaultOrUserDefined( aValues.getLength() );
1130 const PropertyValue* pCopyEnd = ::std::remove_copy_if(
1131 aValues.getConstArray(),
1132 aValues.getConstArray() + aValues.getLength(),
1133 aNonDefaultOrUserDefined.getArray(),
1134 IsDefaultAndNotRemoveable( aPropertyAttributes )
1136 aNonDefaultOrUserDefined.realloc( pCopyEnd - aNonDefaultOrUserDefined.getArray() );
1137 rValue <<= aNonDefaultOrUserDefined;
1139 catch( const Exception& )
1141 DBG_UNHANDLED_EXCEPTION();
1144 break;
1145 case PROPERTY_ID_SETTINGS:
1146 rValue <<= m_pImpl->m_xSettings;
1147 break;
1148 case PROPERTY_ID_URL:
1149 rValue <<= m_pImpl->m_sConnectURL;
1150 break;
1151 case PROPERTY_ID_NUMBERFORMATSSUPPLIER:
1152 rValue <<= m_pImpl->getNumberFormatsSupplier();
1153 break;
1154 case PROPERTY_ID_NAME:
1155 rValue <<= m_pImpl->m_sName;
1156 break;
1157 case PROPERTY_ID_LAYOUTINFORMATION:
1158 rValue <<= m_pImpl->m_aLayoutInformation;
1159 break;
1160 default:
1161 DBG_ERROR("unknown Property");
1166 // XDataSource
1167 //------------------------------------------------------------------------------
1168 void ODatabaseSource::setLoginTimeout(sal_Int32 seconds) throw( SQLException, RuntimeException )
1170 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setLoginTimeout" );
1171 ModelMethodGuard aGuard( *this );
1172 m_pImpl->m_nLoginTimeout = seconds;
1175 //------------------------------------------------------------------------------
1176 sal_Int32 ODatabaseSource::getLoginTimeout(void) throw( SQLException, RuntimeException )
1178 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getLoginTimeout" );
1179 ModelMethodGuard aGuard( *this );
1180 return m_pImpl->m_nLoginTimeout;
1184 // XCompletedConnection
1185 //------------------------------------------------------------------------------
1186 Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
1188 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
1189 return connectWithCompletion(_rxHandler,sal_False);
1191 // -----------------------------------------------------------------------------
1192 Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password) throw( SQLException, RuntimeException )
1194 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
1195 return getConnection(user,password,sal_False);
1197 // -----------------------------------------------------------------------------
1198 Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnection( const ::rtl::OUString& user, const ::rtl::OUString& password ) throw(SQLException, RuntimeException)
1200 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnection" );
1201 return getConnection(user,password,sal_True);
1203 // -----------------------------------------------------------------------------
1204 Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnectionWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
1206 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnectionWithCompletion" );
1207 return connectWithCompletion(_rxHandler,sal_True);
1209 // -----------------------------------------------------------------------------
1210 Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler,sal_Bool _bIsolated ) throw(SQLException, RuntimeException)
1212 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
1213 ModelMethodGuard aGuard( *this );
1215 if (!_rxHandler.is())
1217 DBG_ERROR("ODatabaseSource::connectWithCompletion: invalid interaction handler!");
1218 return getConnection(m_pImpl->m_sUser, m_pImpl->m_aPassword,_bIsolated);
1221 ::rtl::OUString sUser(m_pImpl->m_sUser), sPassword(m_pImpl->m_aPassword);
1222 sal_Bool bNewPasswordGiven = sal_False;
1224 if (m_pImpl->m_bPasswordRequired && (0 == sPassword.getLength()))
1225 { // we need a password, but don't have one yet.
1226 // -> ask the user
1228 // build an interaction request
1229 // two continuations (Ok and Cancel)
1230 OInteractionAbort* pAbort = new OInteractionAbort;
1231 OAuthenticationContinuation* pAuthenticate = new OAuthenticationContinuation;
1233 // the name which should be referred in the login dialog
1234 ::rtl::OUString sServerName( m_pImpl->m_sName );
1235 INetURLObject aURLCheck( sServerName );
1236 if ( aURLCheck.GetProtocol() != INET_PROT_NOT_VALID )
1237 sServerName = aURLCheck.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_UNAMBIGUOUS );
1239 // the request
1240 AuthenticationRequest aRequest;
1241 aRequest.ServerName = sServerName;
1242 aRequest.HasRealm = aRequest.HasAccount = sal_False;
1243 aRequest.HasUserName = aRequest.HasPassword = sal_True;
1244 aRequest.UserName = m_pImpl->m_sUser;
1245 aRequest.Password = m_pImpl->m_sFailedPassword.getLength() ? m_pImpl->m_sFailedPassword : m_pImpl->m_aPassword;
1246 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1247 Reference< XInteractionRequest > xRequest(pRequest);
1248 // some knittings
1249 pRequest->addContinuation(pAbort);
1250 pRequest->addContinuation(pAuthenticate);
1252 // handle the request
1255 MutexRelease aRelease( getMutex() );
1256 // release the mutex when calling the handler, it may need to lock the SolarMutex
1257 _rxHandler->handle(xRequest);
1259 catch(Exception&)
1261 DBG_UNHANDLED_EXCEPTION();
1264 if (!pAuthenticate->wasSelected())
1265 return Reference< XConnection >();
1267 // get the result
1268 sUser = m_pImpl->m_sUser = pAuthenticate->getUser();
1269 sPassword = pAuthenticate->getPassword();
1271 if (pAuthenticate->getRememberPassword())
1273 m_pImpl->m_aPassword = pAuthenticate->getPassword();
1274 bNewPasswordGiven = sal_True;
1276 m_pImpl->m_sFailedPassword = ::rtl::OUString();
1281 return getConnection(sUser, sPassword,_bIsolated);
1283 catch(Exception&)
1285 if (bNewPasswordGiven)
1287 m_pImpl->m_sFailedPassword = m_pImpl->m_aPassword;
1288 // assume that we had an authentication problem. Without this we may, after an unsucessful connect, while
1289 // the user gave us a password an the order to remember it, never allow an password input again (at least
1290 // not without restarting the session)
1291 m_pImpl->m_aPassword = ::rtl::OUString();
1293 throw;
1297 // -----------------------------------------------------------------------------
1298 Reference< XConnection > ODatabaseSource::buildIsolatedConnection(const rtl::OUString& user, const rtl::OUString& password)
1300 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildIsolatedConnection" );
1301 Reference< XConnection > xConn;
1302 Reference< XConnection > xSdbcConn = buildLowLevelConnection(user, password);
1303 DBG_ASSERT( xSdbcConn.is(), "ODatabaseSource::buildIsolatedConnection: invalid return value of buildLowLevelConnection!" );
1304 // buildLowLevelConnection is expected to always succeed
1305 if ( xSdbcConn.is() )
1307 // build a connection server and return it (no stubs)
1308 xConn = new OConnection(*this, xSdbcConn, m_pImpl->m_aContext.getLegacyServiceFactory());
1310 return xConn;
1312 //------------------------------------------------------------------------------
1313 Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password,sal_Bool _bIsolated) throw( SQLException, RuntimeException )
1315 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
1316 ModelMethodGuard aGuard( *this );
1318 Reference< XConnection > xConn;
1319 if ( _bIsolated )
1321 xConn = buildIsolatedConnection(user,password);
1323 else
1324 { // create a new proxy for the connection
1325 if ( !m_pImpl->m_xSharedConnectionManager.is() )
1327 m_pImpl->m_pSharedConnectionManager = new OSharedConnectionManager( m_pImpl->m_aContext.getLegacyServiceFactory() );
1328 m_pImpl->m_xSharedConnectionManager = m_pImpl->m_pSharedConnectionManager;
1330 xConn = m_pImpl->m_pSharedConnectionManager->getConnection(
1331 m_pImpl->m_sConnectURL, user, password, m_pImpl->m_xSettings->getPropertyValues(), this );
1334 if ( xConn.is() )
1336 Reference< XComponent> xComp(xConn,UNO_QUERY);
1337 if ( xComp.is() )
1338 xComp->addEventListener( static_cast< XContainerListener* >( this ) );
1339 m_pImpl->m_aConnections.push_back(OWeakConnection(xConn));
1342 return xConn;
1345 //------------------------------------------------------------------------------
1346 Reference< XNameAccess > SAL_CALL ODatabaseSource::getBookmarks( ) throw (RuntimeException)
1348 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getBookmarks" );
1349 ModelMethodGuard aGuard( *this );
1350 return static_cast< XNameContainer* >(&m_aBookmarks);
1353 //------------------------------------------------------------------------------
1354 Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( ) throw(RuntimeException)
1356 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getQueryDefinitions" );
1357 ModelMethodGuard aGuard( *this );
1359 Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions;
1360 if ( !xContainer.is() )
1362 TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_QUERY ) );
1363 xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_False );
1364 m_pImpl->m_xCommandDefinitions = xContainer;
1366 return xContainer;
1368 //------------------------------------------------------------------------------
1369 // XTablesSupplier
1370 //------------------------------------------------------------------------------
1371 Reference< XNameAccess > ODatabaseSource::getTables() throw( RuntimeException )
1373 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTables" );
1374 ModelMethodGuard aGuard( *this );
1376 Reference< XNameAccess > xContainer = m_pImpl->m_xTableDefinitions;
1377 if ( !xContainer.is() )
1379 TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_TABLE ) );
1380 xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_True );
1381 m_pImpl->m_xTableDefinitions = xContainer;
1383 return xContainer;
1385 // -----------------------------------------------------------------------------
1386 void SAL_CALL ODatabaseSource::flush( ) throw (RuntimeException)
1388 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flush" );
1391 // SYNCHRONIZED ->
1393 ModelMethodGuard aGuard( *this );
1395 typedef ::utl::SharedUNOComponent< XModel, ::utl::CloseableComponent > SharedModel;
1396 SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership );
1398 if ( !xModel.is() )
1399 xModel.reset( m_pImpl->createNewModel_deliverOwnership( false ), SharedModel::TakeOwnership );
1401 Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW );
1402 xStorable->store();
1404 // <- SYNCHRONIZED
1406 css::lang::EventObject aFlushedEvent(*this);
1407 m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent );
1409 catch( const Exception& )
1411 DBG_UNHANDLED_EXCEPTION();
1415 // -----------------------------------------------------------------------------
1416 void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ ) throw (RuntimeException)
1418 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flushed" );
1419 ModelMethodGuard aGuard( *this );
1421 // Okay, this is some hack.
1423 // In general, we have the problem that embedded databases write into their underlying storage, which
1424 // logically is one of our sub storage, and practically is a temporary file maintained by the
1425 // package implementation. As long as we did not commit this storage and our main storage,
1426 // the changes made by the embedded database engine are not really reflected in the database document
1427 // file. This is Bad (TM) for a "real" database application - imagine somebody entering some
1428 // data, and then crashing: For a database application, you would expect that the data still is present
1429 // when you connect to the database next time.
1431 // Since this is a conceptual problem as long as we do use those ZIP packages (in fact, we *cannot*
1432 // provide the desired functionality as long as we do not have a package format which allows O(1) writes),
1433 // we cannot completely fix this. However, we can relax the problem by commiting more often - often
1434 // enough so that data loss is more seldom, and seldom enough so that there's no noticable performance
1435 // decrease.
1437 // For this, we introduced a few places which XFlushable::flush their connections, and register as
1438 // XFlushListener at the embedded connection (which needs to provide the XFlushable functionality).
1439 // Then, when the connection is flushed, we commit both the database storage and our main storage.
1441 // #i55274# / 2005-09-30 / frank.schoenheit@sun.com
1443 OSL_ENSURE( m_pImpl->isEmbeddedDatabase(), "ODatabaseSource::flushed: no embedded database?!" );
1444 sal_Bool bWasModified = m_pImpl->m_bModified;
1445 m_pImpl->commitEmbeddedStorage();
1446 m_pImpl->setModified( bWasModified );
1449 // -----------------------------------------------------------------------------
1450 void SAL_CALL ODatabaseSource::addFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
1452 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::addFlushListener" );
1453 m_aFlushListeners.addInterface(_xListener);
1455 // -----------------------------------------------------------------------------
1456 void SAL_CALL ODatabaseSource::removeFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
1458 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::removeFlushListener" );
1459 m_aFlushListeners.removeInterface(_xListener);
1461 // -----------------------------------------------------------------------------
1462 void SAL_CALL ODatabaseSource::elementInserted( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1464 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementInserted" );
1465 ModelMethodGuard aGuard( *this );
1466 if ( m_pImpl.is() )
1467 m_pImpl->setModified(sal_True);
1469 // -----------------------------------------------------------------------------
1470 void SAL_CALL ODatabaseSource::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1472 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementRemoved" );
1473 ModelMethodGuard aGuard( *this );
1474 if ( m_pImpl.is() )
1475 m_pImpl->setModified(sal_True);
1477 // -----------------------------------------------------------------------------
1478 void SAL_CALL ODatabaseSource::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1480 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementReplaced" );
1481 ModelMethodGuard aGuard( *this );
1482 if ( m_pImpl.is() )
1483 m_pImpl->setModified(sal_True);
1485 // -----------------------------------------------------------------------------
1486 // XDocumentDataSource
1487 Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocument() throw (RuntimeException)
1489 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getDatabaseDocument" );
1490 ModelMethodGuard aGuard( *this );
1492 Reference< XModel > xModel( m_pImpl->getModel_noCreate() );
1493 if ( !xModel.is() )
1494 xModel = m_pImpl->createNewModel_deliverOwnership( false );
1496 return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW );
1498 // -----------------------------------------------------------------------------
1499 Reference< XInterface > ODatabaseSource::getThis() const
1501 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getThis" );
1502 return *const_cast< ODatabaseSource* >( this );
1504 // -----------------------------------------------------------------------------
1505 void ODatabaseSource::impl_insertJavaDriverClassPath_nothrow(Sequence< PropertyValue >& _rDriverInfo)
1507 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::impl_insertJavaDriverClassPath_nothrow" );
1508 Reference< XPropertySet > xPropertySet( m_pImpl->m_xSettings, UNO_QUERY_THROW );
1509 ::rtl::OUString sJavaDriverClass;
1510 xPropertySet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass"))) >>= sJavaDriverClass;
1511 if ( sJavaDriverClass.getLength() )
1513 static const ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess/JDBC/DriverClassPaths"));
1514 ::utl::OConfigurationTreeRoot aNamesRoot = ::utl::OConfigurationTreeRoot::createWithServiceFactory(
1515 m_pImpl->m_aContext.getLegacyServiceFactory(), s_sNodeName, -1, ::utl::OConfigurationTreeRoot::CM_READONLY);
1516 if ( aNamesRoot.isValid() && aNamesRoot.hasByName( sJavaDriverClass ) )
1518 ::utl::OConfigurationNode aRegisterObj = aNamesRoot.openNode( sJavaDriverClass );
1519 ::rtl::OUString sURL;
1520 OSL_VERIFY( aRegisterObj.getNodeValue( "Path" ) >>= sURL );
1522 ::comphelper::NamedValueCollection aDriverSettings( _rDriverInfo );
1523 aDriverSettings.put( "JavaDriverClassPath", sURL );
1524 aDriverSettings >>= _rDriverInfo;
1528 //........................................................................
1529 } // namespace dbaccess
1530 //........................................................................