update dev300-m58
[ooovba.git] / dbaccess / source / core / dataaccess / datasource.cxx
blob33567da202f5274f5e7dc2d8ca255b5ff936f2f2
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() )
787 nExceptionMessageId = RID_STR_COULDNOTCONNECT_NODRIVER;
788 else
790 Sequence< PropertyValue > aDriverInfo = lcl_filterDriverProperties(
791 xDriver,
792 m_pImpl->m_sConnectURL,
793 m_pImpl->m_xSettings->getPropertyValues(),
794 m_pImpl->getDefaultDataSourceSettings()
797 impl_insertJavaDriverClassPath_nothrow(aDriverInfo);
799 if ( m_pImpl->isEmbeddedDatabase() )
801 sal_Int32 nCount = aDriverInfo.getLength();
802 aDriverInfo.realloc(nCount + 2 );
803 aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
804 aDriverInfo[nCount++].Value <<= m_pImpl->getURL();
805 aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Storage"));
806 Reference< css::document::XDocumentSubStorageSupplier> xDocSup( m_pImpl->getDocumentSubStorageSupplier() );
807 aDriverInfo[nCount++].Value <<= xDocSup->getDocumentSubStorage(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("database")),ElementModes::READWRITE);
809 if (nAdditionalArgs)
810 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL, ::comphelper::concatSequences(aUserPwd,aDriverInfo));
811 else
812 xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL,aDriverInfo);
814 if ( m_pImpl->isEmbeddedDatabase() )
816 // see ODatabaseSource::flushed for comment on why we register as FlushListener
817 // at the connection
818 Reference< XFlushable > xFlushable( xReturn, UNO_QUERY );
819 if ( xFlushable.is() )
820 FlushNotificationAdapter::installAdapter( xFlushable, this );
824 else
825 nExceptionMessageId = RID_STR_COULDNOTLOAD_MANAGER;
827 if ( !xReturn.is() )
829 ::rtl::OUString sMessage = DBACORE_RESSTRING( nExceptionMessageId );
831 SQLContext aContext;
832 aContext.Message = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A connection for the following URL was requested: " ) );
833 // TODO: resource
834 aContext.Message += m_pImpl->m_sConnectURL;
836 throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), makeAny( aContext ) );
839 return xReturn;
842 // OPropertySetHelper
843 //------------------------------------------------------------------------------
844 Reference< XPropertySetInfo > ODatabaseSource::getPropertySetInfo() throw (RuntimeException)
846 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getPropertySetInfo" );
847 return createPropertySetInfo( getInfoHelper() ) ;
850 // comphelper::OPropertyArrayUsageHelper
851 //------------------------------------------------------------------------------
852 ::cppu::IPropertyArrayHelper* ODatabaseSource::createArrayHelper( ) const
854 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::createArrayHelper" );
855 BEGIN_PROPERTY_HELPER(13)
856 DECL_PROP1(INFO, Sequence< PropertyValue >, BOUND);
857 DECL_PROP1_BOOL(ISPASSWORDREQUIRED, BOUND);
858 DECL_PROP1_BOOL(ISREADONLY, READONLY);
859 DECL_PROP1(LAYOUTINFORMATION, Sequence< PropertyValue >, BOUND);
860 DECL_PROP1(NAME, ::rtl::OUString, READONLY);
861 DECL_PROP2_IFACE(NUMBERFORMATSSUPPLIER, XNumberFormatsSupplier, READONLY, TRANSIENT);
862 DECL_PROP1(PASSWORD, ::rtl::OUString, TRANSIENT);
863 DECL_PROP2_IFACE(SETTINGS, XPropertySet, BOUND, READONLY);
864 DECL_PROP1_BOOL(SUPPRESSVERSIONCL, BOUND);
865 DECL_PROP1(TABLEFILTER, Sequence< ::rtl::OUString >,BOUND);
866 DECL_PROP1(TABLETYPEFILTER, Sequence< ::rtl::OUString >,BOUND);
867 DECL_PROP1(URL, ::rtl::OUString, BOUND);
868 DECL_PROP1(USER, ::rtl::OUString, BOUND);
869 END_PROPERTY_HELPER();
872 // cppu::OPropertySetHelper
873 //------------------------------------------------------------------------------
874 ::cppu::IPropertyArrayHelper& ODatabaseSource::getInfoHelper()
876 return *getArrayHelper();
879 //------------------------------------------------------------------------------
880 sal_Bool ODatabaseSource::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException )
882 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::convertFastPropertyValue" );
883 sal_Bool bModified(sal_False);
884 if ( m_pImpl.is() )
886 switch (nHandle)
888 case PROPERTY_ID_TABLEFILTER:
889 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableFilter);
890 break;
891 case PROPERTY_ID_TABLETYPEFILTER:
892 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableTypeFilter);
893 break;
894 case PROPERTY_ID_USER:
895 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sUser);
896 break;
897 case PROPERTY_ID_PASSWORD:
898 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aPassword);
899 break;
900 case PROPERTY_ID_ISPASSWORDREQUIRED:
901 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bPasswordRequired);
902 break;
903 case PROPERTY_ID_SUPPRESSVERSIONCL:
904 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bSuppressVersionColumns);
905 break;
906 case PROPERTY_ID_LAYOUTINFORMATION:
907 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aLayoutInformation);
908 break;
909 case PROPERTY_ID_URL:
911 bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sConnectURL);
912 } break;
913 case PROPERTY_ID_INFO:
915 Sequence<PropertyValue> aValues;
916 if (!(rValue >>= aValues))
917 throw IllegalArgumentException();
919 const PropertyValue* valueEnd = aValues.getConstArray() + aValues.getLength();
920 const PropertyValue* checkName = aValues.getConstArray();
921 for ( ;checkName != valueEnd; ++checkName )
923 if ( !checkName->Name.getLength() )
924 throw IllegalArgumentException();
927 Sequence< PropertyValue > aSettings = m_pImpl->m_xSettings->getPropertyValues();
928 bModified = aSettings.getLength() != aValues.getLength();
929 if ( !bModified )
931 const PropertyValue* pInfoIter = aSettings.getConstArray();
932 const PropertyValue* checkValue = aValues.getConstArray();
933 for ( ;!bModified && checkValue != valueEnd ; ++checkValue,++pInfoIter)
935 bModified = checkValue->Name != pInfoIter->Name;
936 if ( !bModified )
938 bModified = !::comphelper::compare(checkValue->Value,pInfoIter->Value);
943 rConvertedValue = rValue;
944 rOldValue <<= aSettings;
946 break;
947 default:
948 DBG_ERROR( "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" );
951 return bModified;
954 //------------------------------------------------------------------------------
955 namespace
957 struct SelectPropertyName : public ::std::unary_function< PropertyValue, ::rtl::OUString >
959 public:
960 const ::rtl::OUString& operator()( const PropertyValue& _lhs )
962 return _lhs.Name;
966 /** sets a new set of property values at a given property bag instance
968 The methods takes a property bag, and a sequence of property values to set at this bag.
969 Upon return, every property which is not part of the given sequence is
970 <ul><li>removed from the bag, if it's a removeable property</li>
971 <li><em>or</em>reset to its default value, if it's not a removeable property</li>
972 </ul>.
974 @param _rxPropertyBag
975 the property bag to operate on
976 @param _rAllNewPropertyValues
977 the new property values to set at the bag
979 void lcl_setPropertyValues_resetOrRemoveOther( const Reference< XPropertyAccess >& _rxPropertyBag, const Sequence< PropertyValue >& _rAllNewPropertyValues )
981 // sequences are ugly to operate on
982 typedef ::std::set< ::rtl::OUString > StringSet;
983 StringSet aToBeSetPropertyNames;
984 ::std::transform(
985 _rAllNewPropertyValues.getConstArray(),
986 _rAllNewPropertyValues.getConstArray() + _rAllNewPropertyValues.getLength(),
987 ::std::insert_iterator< StringSet >( aToBeSetPropertyNames, aToBeSetPropertyNames.end() ),
988 SelectPropertyName()
993 // obtain all properties currently known at the bag
994 Reference< XPropertySet > xPropertySet( _rxPropertyBag, UNO_QUERY_THROW );
995 Reference< XPropertySetInfo > xPSI( xPropertySet->getPropertySetInfo(), UNO_QUERY_THROW );
996 Sequence< Property > aAllExistentProperties( xPSI->getProperties() );
998 Reference< XPropertyState > xPropertyState( _rxPropertyBag, UNO_QUERY_THROW );
999 Reference< XPropertyContainer > xPropertyContainer( _rxPropertyBag, UNO_QUERY_THROW );
1001 // loop through them, and reset resp. default properties which are not to be set
1002 const Property* pExistentProperty( aAllExistentProperties.getConstArray() );
1003 const Property* pExistentPropertyEnd( aAllExistentProperties.getConstArray() + aAllExistentProperties.getLength() );
1004 for ( ; pExistentProperty != pExistentPropertyEnd; ++pExistentProperty )
1006 if ( aToBeSetPropertyNames.find( pExistentProperty->Name ) != aToBeSetPropertyNames.end() )
1007 continue;
1009 // this property is not to be set, but currently exists in the bag.
1010 // -> Remove, respectively default, it
1011 if ( ( pExistentProperty->Attributes & PropertyAttribute::REMOVEABLE ) != 0 )
1012 xPropertyContainer->removeProperty( pExistentProperty->Name );
1013 else
1014 xPropertyState->setPropertyToDefault( pExistentProperty->Name );
1017 // finally, set the new property values
1018 _rxPropertyBag->setPropertyValues( _rAllNewPropertyValues );
1020 catch( const Exception& )
1022 DBG_UNHANDLED_EXCEPTION();
1027 //------------------------------------------------------------------------------
1028 void ODatabaseSource::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
1030 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setFastPropertyValue_NoBroadcast" );
1031 if ( m_pImpl.is() )
1033 switch(nHandle)
1035 case PROPERTY_ID_TABLEFILTER:
1036 rValue >>= m_pImpl->m_aTableFilter;
1037 break;
1038 case PROPERTY_ID_TABLETYPEFILTER:
1039 rValue >>= m_pImpl->m_aTableTypeFilter;
1040 break;
1041 case PROPERTY_ID_USER:
1042 rValue >>= m_pImpl->m_sUser;
1043 // if the user name changed, reset the password
1044 m_pImpl->m_aPassword = ::rtl::OUString();
1045 break;
1046 case PROPERTY_ID_PASSWORD:
1047 rValue >>= m_pImpl->m_aPassword;
1048 break;
1049 case PROPERTY_ID_ISPASSWORDREQUIRED:
1050 m_pImpl->m_bPasswordRequired = any2bool(rValue);
1051 break;
1052 case PROPERTY_ID_SUPPRESSVERSIONCL:
1053 m_pImpl->m_bSuppressVersionColumns = any2bool(rValue);
1054 break;
1055 case PROPERTY_ID_URL:
1056 rValue >>= m_pImpl->m_sConnectURL;
1057 break;
1058 case PROPERTY_ID_INFO:
1060 Sequence< PropertyValue > aInfo;
1061 OSL_VERIFY( rValue >>= aInfo );
1062 lcl_setPropertyValues_resetOrRemoveOther( m_pImpl->m_xSettings, aInfo );
1064 break;
1065 case PROPERTY_ID_LAYOUTINFORMATION:
1066 rValue >>= m_pImpl->m_aLayoutInformation;
1067 break;
1069 m_pImpl->setModified(sal_True);
1073 //------------------------------------------------------------------------------
1074 void ODatabaseSource::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
1076 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getFastPropertyValue" );
1077 if ( m_pImpl.is() )
1079 switch (nHandle)
1081 case PROPERTY_ID_TABLEFILTER:
1082 rValue <<= m_pImpl->m_aTableFilter;
1083 break;
1084 case PROPERTY_ID_TABLETYPEFILTER:
1085 rValue <<= m_pImpl->m_aTableTypeFilter;
1086 break;
1087 case PROPERTY_ID_USER:
1088 rValue <<= m_pImpl->m_sUser;
1089 break;
1090 case PROPERTY_ID_PASSWORD:
1091 rValue <<= m_pImpl->m_aPassword;
1092 break;
1093 case PROPERTY_ID_ISPASSWORDREQUIRED:
1094 rValue = bool2any(m_pImpl->m_bPasswordRequired);
1095 break;
1096 case PROPERTY_ID_SUPPRESSVERSIONCL:
1097 rValue = bool2any(m_pImpl->m_bSuppressVersionColumns);
1098 break;
1099 case PROPERTY_ID_ISREADONLY:
1100 rValue = bool2any(m_pImpl->m_bReadOnly);
1101 break;
1102 case PROPERTY_ID_INFO:
1106 // collect the property attributes of all current settings
1107 Reference< XPropertySet > xSettingsAsProps( m_pImpl->m_xSettings, UNO_QUERY_THROW );
1108 Reference< XPropertySetInfo > xPST( xSettingsAsProps->getPropertySetInfo(), UNO_QUERY_THROW );
1109 Sequence< Property > aSettings( xPST->getProperties() );
1110 ::std::map< ::rtl::OUString, sal_Int32 > aPropertyAttributes;
1111 for ( const Property* pSettings = aSettings.getConstArray();
1112 pSettings != aSettings.getConstArray() + aSettings.getLength();
1113 ++pSettings
1116 aPropertyAttributes[ pSettings->Name ] = pSettings->Attributes;
1119 // get all current settings with their values
1120 Sequence< PropertyValue > aValues( m_pImpl->m_xSettings->getPropertyValues() );
1122 // transform them so that only property values which fulfill certain
1123 // criterions survive
1124 Sequence< PropertyValue > aNonDefaultOrUserDefined( aValues.getLength() );
1125 const PropertyValue* pCopyEnd = ::std::remove_copy_if(
1126 aValues.getConstArray(),
1127 aValues.getConstArray() + aValues.getLength(),
1128 aNonDefaultOrUserDefined.getArray(),
1129 IsDefaultAndNotRemoveable( aPropertyAttributes )
1131 aNonDefaultOrUserDefined.realloc( pCopyEnd - aNonDefaultOrUserDefined.getArray() );
1132 rValue <<= aNonDefaultOrUserDefined;
1134 catch( const Exception& )
1136 DBG_UNHANDLED_EXCEPTION();
1139 break;
1140 case PROPERTY_ID_SETTINGS:
1141 rValue <<= m_pImpl->m_xSettings;
1142 break;
1143 case PROPERTY_ID_URL:
1144 rValue <<= m_pImpl->m_sConnectURL;
1145 break;
1146 case PROPERTY_ID_NUMBERFORMATSSUPPLIER:
1147 rValue <<= m_pImpl->getNumberFormatsSupplier();
1148 break;
1149 case PROPERTY_ID_NAME:
1150 rValue <<= m_pImpl->m_sName;
1151 break;
1152 case PROPERTY_ID_LAYOUTINFORMATION:
1153 rValue <<= m_pImpl->m_aLayoutInformation;
1154 break;
1155 default:
1156 DBG_ERROR("unknown Property");
1161 // XDataSource
1162 //------------------------------------------------------------------------------
1163 void ODatabaseSource::setLoginTimeout(sal_Int32 seconds) throw( SQLException, RuntimeException )
1165 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setLoginTimeout" );
1166 ModelMethodGuard aGuard( *this );
1167 m_pImpl->m_nLoginTimeout = seconds;
1170 //------------------------------------------------------------------------------
1171 sal_Int32 ODatabaseSource::getLoginTimeout(void) throw( SQLException, RuntimeException )
1173 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getLoginTimeout" );
1174 ModelMethodGuard aGuard( *this );
1175 return m_pImpl->m_nLoginTimeout;
1179 // XCompletedConnection
1180 //------------------------------------------------------------------------------
1181 Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
1183 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
1184 return connectWithCompletion(_rxHandler,sal_False);
1186 // -----------------------------------------------------------------------------
1187 Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password) throw( SQLException, RuntimeException )
1189 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
1190 return getConnection(user,password,sal_False);
1192 // -----------------------------------------------------------------------------
1193 Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnection( const ::rtl::OUString& user, const ::rtl::OUString& password ) throw(SQLException, RuntimeException)
1195 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnection" );
1196 return getConnection(user,password,sal_True);
1198 // -----------------------------------------------------------------------------
1199 Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnectionWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
1201 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnectionWithCompletion" );
1202 return connectWithCompletion(_rxHandler,sal_True);
1204 // -----------------------------------------------------------------------------
1205 Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler,sal_Bool _bIsolated ) throw(SQLException, RuntimeException)
1207 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
1208 ModelMethodGuard aGuard( *this );
1210 if (!_rxHandler.is())
1212 DBG_ERROR("ODatabaseSource::connectWithCompletion: invalid interaction handler!");
1213 return getConnection(m_pImpl->m_sUser, m_pImpl->m_aPassword,_bIsolated);
1216 ::rtl::OUString sUser(m_pImpl->m_sUser), sPassword(m_pImpl->m_aPassword);
1217 sal_Bool bNewPasswordGiven = sal_False;
1219 if (m_pImpl->m_bPasswordRequired && (0 == sPassword.getLength()))
1220 { // we need a password, but don't have one yet.
1221 // -> ask the user
1223 // build an interaction request
1224 // two continuations (Ok and Cancel)
1225 OInteractionAbort* pAbort = new OInteractionAbort;
1226 OAuthenticationContinuation* pAuthenticate = new OAuthenticationContinuation;
1228 // the name which should be referred in the login dialog
1229 ::rtl::OUString sServerName( m_pImpl->m_sName );
1230 INetURLObject aURLCheck( sServerName );
1231 if ( aURLCheck.GetProtocol() != INET_PROT_NOT_VALID )
1232 sServerName = aURLCheck.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_UNAMBIGUOUS );
1234 // the request
1235 AuthenticationRequest aRequest;
1236 aRequest.ServerName = sServerName;
1237 aRequest.HasRealm = aRequest.HasAccount = sal_False;
1238 aRequest.HasUserName = aRequest.HasPassword = sal_True;
1239 aRequest.UserName = m_pImpl->m_sUser;
1240 aRequest.Password = m_pImpl->m_sFailedPassword.getLength() ? m_pImpl->m_sFailedPassword : m_pImpl->m_aPassword;
1241 OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1242 Reference< XInteractionRequest > xRequest(pRequest);
1243 // some knittings
1244 pRequest->addContinuation(pAbort);
1245 pRequest->addContinuation(pAuthenticate);
1247 // handle the request
1250 MutexRelease aRelease( getMutex() );
1251 // release the mutex when calling the handler, it may need to lock the SolarMutex
1252 _rxHandler->handle(xRequest);
1254 catch(Exception&)
1256 DBG_UNHANDLED_EXCEPTION();
1259 if (!pAuthenticate->wasSelected())
1260 return Reference< XConnection >();
1262 // get the result
1263 sUser = m_pImpl->m_sUser = pAuthenticate->getUser();
1264 sPassword = pAuthenticate->getPassword();
1266 if (pAuthenticate->getRememberPassword())
1268 m_pImpl->m_aPassword = pAuthenticate->getPassword();
1269 bNewPasswordGiven = sal_True;
1271 m_pImpl->m_sFailedPassword = ::rtl::OUString();
1276 return getConnection(sUser, sPassword,_bIsolated);
1278 catch(Exception&)
1280 if (bNewPasswordGiven)
1282 m_pImpl->m_sFailedPassword = m_pImpl->m_aPassword;
1283 // assume that we had an authentication problem. Without this we may, after an unsucessful connect, while
1284 // the user gave us a password an the order to remember it, never allow an password input again (at least
1285 // not without restarting the session)
1286 m_pImpl->m_aPassword = ::rtl::OUString();
1288 throw;
1292 // -----------------------------------------------------------------------------
1293 Reference< XConnection > ODatabaseSource::buildIsolatedConnection(const rtl::OUString& user, const rtl::OUString& password)
1295 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildIsolatedConnection" );
1296 Reference< XConnection > xConn;
1297 Reference< XConnection > xSdbcConn = buildLowLevelConnection(user, password);
1298 DBG_ASSERT( xSdbcConn.is(), "ODatabaseSource::buildIsolatedConnection: invalid return value of buildLowLevelConnection!" );
1299 // buildLowLevelConnection is expected to always succeed
1300 if ( xSdbcConn.is() )
1302 // build a connection server and return it (no stubs)
1303 xConn = new OConnection(*this, xSdbcConn, m_pImpl->m_aContext.getLegacyServiceFactory());
1305 return xConn;
1307 //------------------------------------------------------------------------------
1308 Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password,sal_Bool _bIsolated) throw( SQLException, RuntimeException )
1310 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
1311 ModelMethodGuard aGuard( *this );
1313 Reference< XConnection > xConn;
1314 if ( _bIsolated )
1316 xConn = buildIsolatedConnection(user,password);
1318 else
1319 { // create a new proxy for the connection
1320 if ( !m_pImpl->m_xSharedConnectionManager.is() )
1322 m_pImpl->m_pSharedConnectionManager = new OSharedConnectionManager( m_pImpl->m_aContext.getLegacyServiceFactory() );
1323 m_pImpl->m_xSharedConnectionManager = m_pImpl->m_pSharedConnectionManager;
1325 xConn = m_pImpl->m_pSharedConnectionManager->getConnection(
1326 m_pImpl->m_sConnectURL, user, password, m_pImpl->m_xSettings->getPropertyValues(), this );
1329 if ( xConn.is() )
1331 Reference< XComponent> xComp(xConn,UNO_QUERY);
1332 if ( xComp.is() )
1333 xComp->addEventListener( static_cast< XContainerListener* >( this ) );
1334 m_pImpl->m_aConnections.push_back(OWeakConnection(xConn));
1337 return xConn;
1340 //------------------------------------------------------------------------------
1341 Reference< XNameAccess > SAL_CALL ODatabaseSource::getBookmarks( ) throw (RuntimeException)
1343 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getBookmarks" );
1344 ModelMethodGuard aGuard( *this );
1345 return static_cast< XNameContainer* >(&m_aBookmarks);
1348 //------------------------------------------------------------------------------
1349 Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( ) throw(RuntimeException)
1351 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getQueryDefinitions" );
1352 ModelMethodGuard aGuard( *this );
1354 Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions;
1355 if ( !xContainer.is() )
1357 TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_QUERY ) );
1358 xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_False );
1359 m_pImpl->m_xCommandDefinitions = xContainer;
1361 return xContainer;
1363 //------------------------------------------------------------------------------
1364 // XTablesSupplier
1365 //------------------------------------------------------------------------------
1366 Reference< XNameAccess > ODatabaseSource::getTables() throw( RuntimeException )
1368 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTables" );
1369 ModelMethodGuard aGuard( *this );
1371 Reference< XNameAccess > xContainer = m_pImpl->m_xTableDefinitions;
1372 if ( !xContainer.is() )
1374 TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_TABLE ) );
1375 xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_True );
1376 m_pImpl->m_xTableDefinitions = xContainer;
1378 return xContainer;
1380 // -----------------------------------------------------------------------------
1381 void SAL_CALL ODatabaseSource::flush( ) throw (RuntimeException)
1383 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flush" );
1386 // SYNCHRONIZED ->
1388 ModelMethodGuard aGuard( *this );
1390 typedef ::utl::SharedUNOComponent< XModel, ::utl::CloseableComponent > SharedModel;
1391 SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership );
1393 if ( !xModel.is() )
1394 xModel.reset( m_pImpl->createNewModel_deliverOwnership( false ), SharedModel::TakeOwnership );
1396 Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW );
1397 xStorable->store();
1399 // <- SYNCHRONIZED
1401 css::lang::EventObject aFlushedEvent(*this);
1402 m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent );
1404 catch( const Exception& )
1406 DBG_UNHANDLED_EXCEPTION();
1410 // -----------------------------------------------------------------------------
1411 void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ ) throw (RuntimeException)
1413 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flushed" );
1414 ModelMethodGuard aGuard( *this );
1416 // Okay, this is some hack.
1418 // In general, we have the problem that embedded databases write into their underlying storage, which
1419 // logically is one of our sub storage, and practically is a temporary file maintained by the
1420 // package implementation. As long as we did not commit this storage and our main storage,
1421 // the changes made by the embedded database engine are not really reflected in the database document
1422 // file. This is Bad (TM) for a "real" database application - imagine somebody entering some
1423 // data, and then crashing: For a database application, you would expect that the data still is present
1424 // when you connect to the database next time.
1426 // Since this is a conceptual problem as long as we do use those ZIP packages (in fact, we *cannot*
1427 // provide the desired functionality as long as we do not have a package format which allows O(1) writes),
1428 // we cannot completely fix this. However, we can relax the problem by commiting more often - often
1429 // enough so that data loss is more seldom, and seldom enough so that there's no noticable performance
1430 // decrease.
1432 // For this, we introduced a few places which XFlushable::flush their connections, and register as
1433 // XFlushListener at the embedded connection (which needs to provide the XFlushable functionality).
1434 // Then, when the connection is flushed, we commit both the database storage and our main storage.
1436 // #i55274# / 2005-09-30 / frank.schoenheit@sun.com
1438 OSL_ENSURE( m_pImpl->isEmbeddedDatabase(), "ODatabaseSource::flushed: no embedded database?!" );
1439 sal_Bool bWasModified = m_pImpl->m_bModified;
1440 m_pImpl->commitEmbeddedStorage();
1441 m_pImpl->setModified( bWasModified );
1444 // -----------------------------------------------------------------------------
1445 void SAL_CALL ODatabaseSource::addFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
1447 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::addFlushListener" );
1448 m_aFlushListeners.addInterface(_xListener);
1450 // -----------------------------------------------------------------------------
1451 void SAL_CALL ODatabaseSource::removeFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
1453 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::removeFlushListener" );
1454 m_aFlushListeners.removeInterface(_xListener);
1456 // -----------------------------------------------------------------------------
1457 void SAL_CALL ODatabaseSource::elementInserted( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1459 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementInserted" );
1460 ModelMethodGuard aGuard( *this );
1461 if ( m_pImpl.is() )
1462 m_pImpl->setModified(sal_True);
1464 // -----------------------------------------------------------------------------
1465 void SAL_CALL ODatabaseSource::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1467 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementRemoved" );
1468 ModelMethodGuard aGuard( *this );
1469 if ( m_pImpl.is() )
1470 m_pImpl->setModified(sal_True);
1472 // -----------------------------------------------------------------------------
1473 void SAL_CALL ODatabaseSource::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1475 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementReplaced" );
1476 ModelMethodGuard aGuard( *this );
1477 if ( m_pImpl.is() )
1478 m_pImpl->setModified(sal_True);
1480 // -----------------------------------------------------------------------------
1481 // XDocumentDataSource
1482 Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocument() throw (RuntimeException)
1484 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getDatabaseDocument" );
1485 ModelMethodGuard aGuard( *this );
1487 Reference< XModel > xModel( m_pImpl->getModel_noCreate() );
1488 if ( !xModel.is() )
1489 xModel = m_pImpl->createNewModel_deliverOwnership( false );
1491 return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW );
1493 // -----------------------------------------------------------------------------
1494 Reference< XInterface > ODatabaseSource::getThis() const
1496 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getThis" );
1497 return *const_cast< ODatabaseSource* >( this );
1499 // -----------------------------------------------------------------------------
1500 void ODatabaseSource::impl_insertJavaDriverClassPath_nothrow(Sequence< PropertyValue >& _rDriverInfo)
1502 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::impl_insertJavaDriverClassPath_nothrow" );
1503 Reference< XPropertySet > xPropertySet( m_pImpl->m_xSettings, UNO_QUERY_THROW );
1504 ::rtl::OUString sJavaDriverClass;
1505 xPropertySet->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass"))) >>= sJavaDriverClass;
1506 if ( sJavaDriverClass.getLength() )
1508 static const ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess/JDBC/DriverClassPaths"));
1509 ::utl::OConfigurationTreeRoot aNamesRoot = ::utl::OConfigurationTreeRoot::createWithServiceFactory(
1510 m_pImpl->m_aContext.getLegacyServiceFactory(), s_sNodeName, -1, ::utl::OConfigurationTreeRoot::CM_READONLY);
1511 if ( aNamesRoot.isValid() && aNamesRoot.hasByName( sJavaDriverClass ) )
1513 ::utl::OConfigurationNode aRegisterObj = aNamesRoot.openNode( sJavaDriverClass );
1514 ::rtl::OUString sURL;
1515 OSL_VERIFY( aRegisterObj.getNodeValue( "Path" ) >>= sURL );
1517 ::comphelper::NamedValueCollection aDriverSettings( _rDriverInfo );
1518 aDriverSettings.put( "JavaDriverClassPath", sURL );
1519 aDriverSettings >>= _rDriverInfo;
1523 //........................................................................
1524 } // namespace dbaccess
1525 //........................................................................