1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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>
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 //........................................................................
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
126 WeakReference
< XFlushable
> m_aBroadcaster
;
127 WeakReference
< XFlushListener
> m_aListener
;
130 static void installAdapter( const Reference
< XFlushable
>& _rxBroadcaster
, const Reference
< XFlushListener
>& _rxListener
)
132 Reference
< XFlushListener
> xAdapter( new FlushNotificationAdapter( _rxBroadcaster
, _rxListener
) );
136 FlushNotificationAdapter( const Reference
< XFlushable
>& _rxBroadcaster
, const Reference
< XFlushListener
>& _rxListener
);
137 ~FlushNotificationAdapter();
139 void SAL_CALL
impl_dispose( bool _bRevokeListener
);
143 virtual void SAL_CALL
flushed( const ::com::sun::star::lang::EventObject
& rEvent
) throw (::com::sun::star::uno::RuntimeException
);
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
);
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
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
)
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.
268 //--------------------------------------------------------------------------
269 void SAL_CALL
OAuthenticationContinuation::setUserName( const ::rtl::OUString
& _rUser
) throw(RuntimeException
)
274 //--------------------------------------------------------------------------
275 sal_Bool SAL_CALL
OAuthenticationContinuation::canSetPassword( ) throw(RuntimeException
)
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
;
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
)
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
;
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
334 sal_uInt8 m_pBuffer
[RTL_DIGEST_LENGTH_SHA1
];
342 class OSharedConnectionManager
: public OConnectionHelper_BASE
345 // contains the currently used master connections
348 Reference
< XConnection
> xMasterConnection
;
349 oslInterlockedCount nALiveCount
;
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
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
;
373 ~OSharedConnectionManager();
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
);
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 //----------------------------------------------------------------------
476 //------------------------------------------------------------------
477 Sequence
< PropertyValue
> lcl_filterDriverProperties( const Reference
< XDriver
>& _xDriver
, const ::rtl::OUString
& _sUrl
,
478 const Sequence
< PropertyValue
>& _rDataSourceSettings
, const AsciiPropertyValue
* _pKnownSettings
)
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
;
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
);
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 >
530 const PropertyAttributeCache
& m_rAttribs
;
533 IsDefaultAndNotRemoveable( const PropertyAttributeCache
& _rAttribs
) : m_rAttribs( _rAttribs
) { }
535 bool operator()( const PropertyValue
& _rProp
)
537 if ( _rProp
.State
!= PropertyState_DEFAULT_VALUE
)
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 );
551 //============================================================
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
)
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;
621 MutexGuard
aGuard( Mutex::getGlobalMutex() );
624 static OImplementationId 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(
644 static_cast< XPropertySet
* >( this ),
645 static_cast< XFastPropertySet
* >( this ),
646 static_cast< XMultiPropertySet
* >( this ));
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" );
670 m_pImpl
->disposing(Source
);
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"));
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;
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
);
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
;
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
;
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
;
795 Sequence
< PropertyValue
> aDriverInfo
= lcl_filterDriverProperties(
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
);
815 xReturn
= xManager
->getConnectionWithInfo(m_pImpl
->m_sConnectURL
, ::comphelper::concatSequences(aUserPwd
,aDriverInfo
));
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
823 Reference
< XFlushable
> xFlushable( xReturn
, UNO_QUERY
);
824 if ( xFlushable
.is() )
825 FlushNotificationAdapter::installAdapter( xFlushable
, this );
830 nExceptionMessageId
= RID_STR_COULDNOTLOAD_MANAGER
;
834 ::rtl::OUString sMessage
= DBACORE_RESSTRING( nExceptionMessageId
);
837 aContext
.Message
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A connection for the following URL was requested: " ) );
839 aContext
.Message
+= m_pImpl
->m_sConnectURL
;
841 throwGenericSQLException( sMessage
, static_cast< XDataSource
* >( this ), makeAny( aContext
) );
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
);
893 case PROPERTY_ID_TABLEFILTER
:
894 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_aTableFilter
);
896 case PROPERTY_ID_TABLETYPEFILTER
:
897 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_aTableTypeFilter
);
899 case PROPERTY_ID_USER
:
900 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_sUser
);
902 case PROPERTY_ID_PASSWORD
:
903 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_aPassword
);
905 case PROPERTY_ID_ISPASSWORDREQUIRED
:
906 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_bPasswordRequired
);
908 case PROPERTY_ID_SUPPRESSVERSIONCL
:
909 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_bSuppressVersionColumns
);
911 case PROPERTY_ID_LAYOUTINFORMATION
:
912 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_aLayoutInformation
);
914 case PROPERTY_ID_URL
:
916 bModified
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_pImpl
->m_sConnectURL
);
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();
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
;
943 bModified
= !::comphelper::compare(checkValue
->Value
,pInfoIter
->Value
);
948 rConvertedValue
= rValue
;
949 rOldValue
<<= aSettings
;
953 DBG_ERROR( "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" );
959 //------------------------------------------------------------------------------
962 struct SelectPropertyName
: public ::std::unary_function
< PropertyValue
, ::rtl::OUString
>
965 const ::rtl::OUString
& operator()( const PropertyValue
& _lhs
)
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>
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
;
990 _rAllNewPropertyValues
.getConstArray(),
991 _rAllNewPropertyValues
.getConstArray() + _rAllNewPropertyValues
.getLength(),
992 ::std::insert_iterator
< StringSet
>( aToBeSetPropertyNames
, aToBeSetPropertyNames
.end() ),
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() )
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
);
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" );
1040 case PROPERTY_ID_TABLEFILTER
:
1041 rValue
>>= m_pImpl
->m_aTableFilter
;
1043 case PROPERTY_ID_TABLETYPEFILTER
:
1044 rValue
>>= m_pImpl
->m_aTableTypeFilter
;
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();
1051 case PROPERTY_ID_PASSWORD
:
1052 rValue
>>= m_pImpl
->m_aPassword
;
1054 case PROPERTY_ID_ISPASSWORDREQUIRED
:
1055 m_pImpl
->m_bPasswordRequired
= any2bool(rValue
);
1057 case PROPERTY_ID_SUPPRESSVERSIONCL
:
1058 m_pImpl
->m_bSuppressVersionColumns
= any2bool(rValue
);
1060 case PROPERTY_ID_URL
:
1061 rValue
>>= m_pImpl
->m_sConnectURL
;
1063 case PROPERTY_ID_INFO
:
1065 Sequence
< PropertyValue
> aInfo
;
1066 OSL_VERIFY( rValue
>>= aInfo
);
1067 lcl_setPropertyValues_resetOrRemoveOther( m_pImpl
->m_xSettings
, aInfo
);
1070 case PROPERTY_ID_LAYOUTINFORMATION
:
1071 rValue
>>= m_pImpl
->m_aLayoutInformation
;
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" );
1086 case PROPERTY_ID_TABLEFILTER
:
1087 rValue
<<= m_pImpl
->m_aTableFilter
;
1089 case PROPERTY_ID_TABLETYPEFILTER
:
1090 rValue
<<= m_pImpl
->m_aTableTypeFilter
;
1092 case PROPERTY_ID_USER
:
1093 rValue
<<= m_pImpl
->m_sUser
;
1095 case PROPERTY_ID_PASSWORD
:
1096 rValue
<<= m_pImpl
->m_aPassword
;
1098 case PROPERTY_ID_ISPASSWORDREQUIRED
:
1099 rValue
= bool2any(m_pImpl
->m_bPasswordRequired
);
1101 case PROPERTY_ID_SUPPRESSVERSIONCL
:
1102 rValue
= bool2any(m_pImpl
->m_bSuppressVersionColumns
);
1104 case PROPERTY_ID_ISREADONLY
:
1105 rValue
= bool2any(m_pImpl
->m_bReadOnly
);
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();
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();
1145 case PROPERTY_ID_SETTINGS
:
1146 rValue
<<= m_pImpl
->m_xSettings
;
1148 case PROPERTY_ID_URL
:
1149 rValue
<<= m_pImpl
->m_sConnectURL
;
1151 case PROPERTY_ID_NUMBERFORMATSSUPPLIER
:
1152 rValue
<<= m_pImpl
->getNumberFormatsSupplier();
1154 case PROPERTY_ID_NAME
:
1155 rValue
<<= m_pImpl
->m_sName
;
1157 case PROPERTY_ID_LAYOUTINFORMATION
:
1158 rValue
<<= m_pImpl
->m_aLayoutInformation
;
1161 DBG_ERROR("unknown Property");
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.
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
);
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
);
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
);
1261 DBG_UNHANDLED_EXCEPTION();
1264 if (!pAuthenticate
->wasSelected())
1265 return Reference
< XConnection
>();
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
);
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();
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());
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
;
1321 xConn
= buildIsolatedConnection(user
,password
);
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 );
1336 Reference
< XComponent
> xComp(xConn
,UNO_QUERY
);
1338 xComp
->addEventListener( static_cast< XContainerListener
* >( this ) );
1339 m_pImpl
->m_aConnections
.push_back(OWeakConnection(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
;
1368 //------------------------------------------------------------------------------
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
;
1385 // -----------------------------------------------------------------------------
1386 void SAL_CALL
ODatabaseSource::flush( ) throw (RuntimeException
)
1388 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flush" );
1393 ModelMethodGuard
aGuard( *this );
1395 typedef ::utl::SharedUNOComponent
< XModel
, ::utl::CloseableComponent
> SharedModel
;
1396 SharedModel
xModel( m_pImpl
->getModel_noCreate(), SharedModel::NoTakeOwnership
);
1399 xModel
.reset( m_pImpl
->createNewModel_deliverOwnership( false ), SharedModel::TakeOwnership
);
1401 Reference
< css::frame::XStorable
> xStorable( xModel
, UNO_QUERY_THROW
);
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
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 );
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 );
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 );
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() );
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 //........................................................................