1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #include "datasource.hxx"
32 #include "module_dba.hxx"
33 #include "userinformation.hxx"
34 #include "commandcontainer.hxx"
35 #include "dbastrings.hrc"
36 #include "core_resource.hxx"
37 #include "core_resource.hrc"
38 #include "connection.hxx"
39 #include "SharedConnection.hxx"
40 #include "databasedocument.hxx"
41 #include "OAuthenticationContinuation.hxx"
42 
43 
44 /** === begin UNO includes === **/
45 #include <com/sun/star/beans/NamedValue.hpp>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/beans/PropertyState.hpp>
48 #include <com/sun/star/beans/XPropertyContainer.hpp>
49 #include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
50 #include <com/sun/star/document/XEventBroadcaster.hpp>
51 #include <com/sun/star/embed/XTransactedObject.hpp>
52 #include <com/sun/star/lang/DisposedException.hpp>
53 #include <com/sun/star/reflection/XProxyFactory.hpp>
54 #include <com/sun/star/sdbc/XDriverAccess.hpp>
55 #include <com/sun/star/sdbc/XDriverManager.hpp>
56 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
57 #include <com/sun/star/ucb/AuthenticationRequest.hpp>
58 #include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
59 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
60 #include <com/sun/star/view/XPrintable.hpp>
61 /** === end UNO includes === **/
62 
63 #include <comphelper/extract.hxx>
64 #include <comphelper/guarding.hxx>
65 #include <comphelper/interaction.hxx>
66 #include <comphelper/namedvaluecollection.hxx>
67 #include <comphelper/property.hxx>
68 #include <comphelper/seqstream.hxx>
69 #include <comphelper/sequence.hxx>
70 #include <comphelper/string.hxx>
71 #include <connectivity/dbexception.hxx>
72 #include <connectivity/dbtools.hxx>
73 #include <cppuhelper/typeprovider.hxx>
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 <rtl/digest.h>
82 #include <algorithm>
83 
84 using namespace ::com::sun::star::sdbc;
85 using namespace ::com::sun::star::sdbcx;
86 using namespace ::com::sun::star::sdb;
87 using namespace ::com::sun::star::beans;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::lang;
90 using namespace ::com::sun::star::embed;
91 using namespace ::com::sun::star::container;
92 using namespace ::com::sun::star::util;
93 using namespace ::com::sun::star::io;
94 using namespace ::com::sun::star::task;
95 using namespace ::com::sun::star::ucb;
96 using namespace ::com::sun::star::frame;
97 using namespace ::com::sun::star::reflection;
98 using namespace ::cppu;
99 using namespace ::osl;
100 using namespace ::vos;
101 using namespace ::dbtools;
102 using namespace ::comphelper;
103 namespace css = ::com::sun::star;
104 
105 //........................................................................
106 namespace dbaccess
107 {
108 //........................................................................
109 
110 //============================================================
111 //= FlushNotificationAdapter
112 //============================================================
113 typedef ::cppu::WeakImplHelper1< XFlushListener > FlushNotificationAdapter_Base;
114 /** helper class which implements a XFlushListener, and forwards all
115     notification events to another XFlushListener
116 
117     The speciality is that the foreign XFlushListener instance, to which
118     the notifications are forwarded, is held weak.
119 
120     Thus, the class can be used with XFlushable instance which hold
121     their listeners with a hard reference, if you simply do not *want*
122     to be held hard-ref-wise.
123 */
124 class FlushNotificationAdapter : public FlushNotificationAdapter_Base
125 {
126 private:
127     WeakReference< XFlushable >     m_aBroadcaster;
128     WeakReference< XFlushListener > m_aListener;
129 
130 public:
131     static void installAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
132     {
133         Reference< XFlushListener > xAdapter( new FlushNotificationAdapter( _rxBroadcaster, _rxListener ) );
134     }
135 
136 protected:
137     FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener );
138     ~FlushNotificationAdapter();
139 
140     void SAL_CALL impl_dispose( bool _bRevokeListener );
141 
142 protected:
143     // XFlushListener
144     virtual void SAL_CALL flushed( const ::com::sun::star::lang::EventObject& rEvent ) throw (::com::sun::star::uno::RuntimeException);
145     // XEventListener
146     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
147 };
148 
149 //------------------------------------------------------------
150 DBG_NAME( FlushNotificationAdapter )
151 //------------------------------------------------------------
152 FlushNotificationAdapter::FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener )
153     :m_aBroadcaster( _rxBroadcaster )
154     ,m_aListener( _rxListener )
155 {
156     DBG_CTOR( FlushNotificationAdapter, NULL );
157     DBG_ASSERT( _rxBroadcaster.is(), "FlushNotificationAdapter::FlushNotificationAdapter: invalid flushable!" );
158 
159     osl_incrementInterlockedCount( &m_refCount );
160     {
161         if ( _rxBroadcaster.is() )
162             _rxBroadcaster->addFlushListener( this );
163     }
164     osl_decrementInterlockedCount( &m_refCount );
165     DBG_ASSERT( m_refCount == 1, "FlushNotificationAdapter::FlushNotificationAdapter: broadcaster isn't holding by hard ref!?" );
166 }
167 
168 //------------------------------------------------------------
169 FlushNotificationAdapter::~FlushNotificationAdapter()
170 {
171     DBG_DTOR( FlushNotificationAdapter, NULL );
172 }
173 
174 //--------------------------------------------------------------------
175 void SAL_CALL FlushNotificationAdapter::impl_dispose( bool _bRevokeListener )
176 {
177     Reference< XFlushListener > xKeepAlive( this );
178 
179     if ( _bRevokeListener )
180     {
181         Reference< XFlushable > xFlushable( m_aBroadcaster );
182         if ( xFlushable.is() )
183             xFlushable->removeFlushListener( this );
184     }
185 
186     m_aListener = Reference< XFlushListener >();
187     m_aBroadcaster = Reference< XFlushable >();
188 }
189 
190 //--------------------------------------------------------------------
191 void SAL_CALL FlushNotificationAdapter::flushed( const EventObject& rEvent ) throw (RuntimeException)
192 {
193     Reference< XFlushListener > xListener( m_aListener );
194     if ( xListener.is() )
195         xListener->flushed( rEvent );
196     else
197         impl_dispose( true );
198 }
199 
200 //--------------------------------------------------------------------
201 void SAL_CALL FlushNotificationAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
202 {
203     Reference< XFlushListener > xListener( m_aListener );
204     if ( xListener.is() )
205         xListener->disposing( Source );
206 
207     impl_dispose( true );
208 }
209 
210 //--------------------------------------------------------------------------
211 OAuthenticationContinuation::OAuthenticationContinuation()
212     :m_bRemberPassword(sal_True),   // TODO: a meaningfull default
213     m_bCanSetUserName(sal_True)
214 {
215 }
216 
217 //--------------------------------------------------------------------------
218 sal_Bool SAL_CALL OAuthenticationContinuation::canSetRealm(  ) throw(RuntimeException)
219 {
220 	return sal_False;
221 }
222 
223 //--------------------------------------------------------------------------
224 void SAL_CALL OAuthenticationContinuation::setRealm( const ::rtl::OUString& /*Realm*/ ) throw(RuntimeException)
225 {
226 	DBG_ERROR("OAuthenticationContinuation::setRealm: not supported!");
227 }
228 
229 //--------------------------------------------------------------------------
230 sal_Bool SAL_CALL OAuthenticationContinuation::canSetUserName(  ) throw(RuntimeException)
231 {
232     // we alwas allow this, even if the database document is read-only. In this case,
233     // it's simply that the user cannot store the new user name.
234     return m_bCanSetUserName;
235 }
236 
237 //--------------------------------------------------------------------------
238 void SAL_CALL OAuthenticationContinuation::setUserName( const ::rtl::OUString& _rUser ) throw(RuntimeException)
239 {
240 	m_sUser = _rUser;
241 }
242 
243 //--------------------------------------------------------------------------
244 sal_Bool SAL_CALL OAuthenticationContinuation::canSetPassword(  ) throw(RuntimeException)
245 {
246 	return sal_True;
247 }
248 
249 //--------------------------------------------------------------------------
250 void SAL_CALL OAuthenticationContinuation::setPassword( const ::rtl::OUString& _rPassword ) throw(RuntimeException)
251 {
252 	m_sPassword = _rPassword;
253 }
254 
255 //--------------------------------------------------------------------------
256 Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberPasswordModes( RememberAuthentication& _reDefault ) throw(RuntimeException)
257 {
258 	Sequence< RememberAuthentication > aReturn(1);
259 	_reDefault = aReturn[0] = RememberAuthentication_SESSION;
260 	return aReturn;
261 }
262 
263 //--------------------------------------------------------------------------
264 void SAL_CALL OAuthenticationContinuation::setRememberPassword( RememberAuthentication _eRemember ) throw(RuntimeException)
265 {
266 	m_bRemberPassword = (RememberAuthentication_NO != _eRemember);
267 }
268 
269 //--------------------------------------------------------------------------
270 sal_Bool SAL_CALL OAuthenticationContinuation::canSetAccount(  ) throw(RuntimeException)
271 {
272 	return sal_False;
273 }
274 
275 //--------------------------------------------------------------------------
276 void SAL_CALL OAuthenticationContinuation::setAccount( const ::rtl::OUString& ) throw(RuntimeException)
277 {
278 	DBG_ERROR("OAuthenticationContinuation::setAccount: not supported!");
279 }
280 
281 //--------------------------------------------------------------------------
282 Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberAccountModes( RememberAuthentication& _reDefault ) throw(RuntimeException)
283 {
284 	Sequence < RememberAuthentication > aReturn(1);
285 	aReturn[0] = RememberAuthentication_NO;
286 	_reDefault = RememberAuthentication_NO;
287 	return aReturn;
288 }
289 
290 //--------------------------------------------------------------------------
291 void SAL_CALL OAuthenticationContinuation::setRememberAccount( RememberAuthentication /*Remember*/ ) throw(RuntimeException)
292 {
293 	DBG_ERROR("OAuthenticationContinuation::setRememberAccount: not supported!");
294 }
295 
296 /** The class OSharedConnectionManager implements a structure to share connections.
297 	It owns the master connections which will be disposed when the last connection proxy is gone.
298 */
299 typedef ::cppu::WeakImplHelper1< XEventListener > OConnectionHelper_BASE;
300 // need to hold the digest
301 struct TDigestHolder
302 {
303 	sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1];
304 	TDigestHolder()
305 	{
306 		m_pBuffer[0] = 0;
307 	}
308 
309 };
310 
311 class OSharedConnectionManager : public OConnectionHelper_BASE
312 {
313 
314 	 // contains the currently used master connections
315 	typedef struct
316 	{
317 		Reference< XConnection >	xMasterConnection;
318 		oslInterlockedCount			nALiveCount;
319 	} TConnectionHolder;
320 
321 	// the less-compare functor, used for the stl::map
322 	struct TDigestLess : public ::std::binary_function< TDigestHolder, TDigestHolder, bool>
323 	{
324 		bool operator() (const TDigestHolder& x, const TDigestHolder& y) const
325 		{
326 			sal_uInt32 i;
327 			for(i=0;i < RTL_DIGEST_LENGTH_SHA1 && (x.m_pBuffer[i] >= y.m_pBuffer[i]); ++i)
328 				;
329 			return i < RTL_DIGEST_LENGTH_SHA1;
330 		}
331 	};
332 
333 	typedef ::std::map< TDigestHolder,TConnectionHolder,TDigestLess>		TConnectionMap;		 // holds the master connections
334 	typedef ::std::map< Reference< XConnection >,TConnectionMap::iterator>	TSharedConnectionMap;// holds the shared connections
335 
336 	::osl::Mutex				m_aMutex;
337 	TConnectionMap				m_aConnections;			// remeber the master connection in conjunction with the digest
338 	TSharedConnectionMap		m_aSharedConnection;	// the shared connections with conjunction with an iterator into the connections map
339 	Reference< XProxyFactory >	m_xProxyFactory;
340 
341 protected:
342 	~OSharedConnectionManager();
343 
344 public:
345 	OSharedConnectionManager(const Reference< XMultiServiceFactory >& _rxServiceFactory);
346 
347 	void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException);
348 	Reference<XConnection> getConnection(	const rtl::OUString& url,
349 											const rtl::OUString& user,
350 											const rtl::OUString& password,
351 											const Sequence< PropertyValue >& _aInfo,
352 											ODatabaseSource* _pDataSource);
353 	void addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter);
354 };
355 
356 DBG_NAME(OSharedConnectionManager)
357 OSharedConnectionManager::OSharedConnectionManager(const Reference< XMultiServiceFactory >& _rxServiceFactory)
358 {
359 	DBG_CTOR(OSharedConnectionManager,NULL);
360 	m_xProxyFactory.set(_rxServiceFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY);
361 }
362 
363 OSharedConnectionManager::~OSharedConnectionManager()
364 {
365 	DBG_DTOR(OSharedConnectionManager,NULL);
366 }
367 
368 void SAL_CALL OSharedConnectionManager::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException)
369 {
370 	MutexGuard aGuard(m_aMutex);
371 	Reference<XConnection> xConnection(Source.Source,UNO_QUERY);
372 	TSharedConnectionMap::iterator aFind = m_aSharedConnection.find(xConnection);
373 	if ( m_aSharedConnection.end() != aFind )
374 	{
375 		osl_decrementInterlockedCount(&aFind->second->second.nALiveCount);
376 		if ( !aFind->second->second.nALiveCount )
377 		{
378 			::comphelper::disposeComponent(aFind->second->second.xMasterConnection);
379 			m_aConnections.erase(aFind->second);
380 		}
381 		m_aSharedConnection.erase(aFind);
382 	}
383 }
384 
385 Reference<XConnection> OSharedConnectionManager::getConnection(	const rtl::OUString& url,
386 										const rtl::OUString& user,
387 										const rtl::OUString& password,
388 										const Sequence< PropertyValue >& _aInfo,
389 										ODatabaseSource* _pDataSource)
390 {
391 	MutexGuard aGuard(m_aMutex);
392 	TConnectionMap::key_type nId;
393 	Sequence< PropertyValue > aInfoCopy(_aInfo);
394 	sal_Int32 nPos = aInfoCopy.getLength();
395 	aInfoCopy.realloc( nPos + 2 );
396 	aInfoCopy[nPos].Name	  = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableFilter"));
397 	aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableFilter;
398 	aInfoCopy[nPos].Name	  = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableTypeFilter"));
399 	aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableTypeFilter; // #22377# OJ
400 
401 	::rtl::OUString sUser = user;
402 	::rtl::OUString sPassword = password;
403 	if ((0 == sUser.getLength()) && (0 == sPassword.getLength()) && (0 != _pDataSource->m_pImpl->m_sUser.getLength()))
404 	{	// ease the usage of this method. data source which are intended to have a user automatically
405 		// fill in the user/password combination if the caller of this method does not specify otherwise
406 		// 86951 - 05/08/2001 - frank.schoenheit@germany.sun.com
407 		sUser = _pDataSource->m_pImpl->m_sUser;
408 		if (0 != _pDataSource->m_pImpl->m_aPassword.getLength())
409 			sPassword = _pDataSource->m_pImpl->m_aPassword;
410 	}
411 
412 	::connectivity::OConnectionWrapper::createUniqueId(url,aInfoCopy,nId.m_pBuffer,sUser,sPassword);
413 	TConnectionMap::iterator aIter = m_aConnections.find(nId);
414 
415 	if ( m_aConnections.end() == aIter )
416 	{
417 		TConnectionHolder aHolder;
418 		aHolder.nALiveCount = 0; // will be incremented by addListener
419 		aHolder.xMasterConnection = _pDataSource->buildIsolatedConnection(user,password);
420 		aIter = m_aConnections.insert(TConnectionMap::value_type(nId,aHolder)).first;
421 	}
422 
423 	Reference<XConnection> xRet;
424 	if ( aIter->second.xMasterConnection.is() )
425 	{
426 		Reference< XAggregation > xConProxy = m_xProxyFactory->createProxy(aIter->second.xMasterConnection.get());
427 		xRet = new OSharedConnection(xConProxy);
428 		m_aSharedConnection.insert(TSharedConnectionMap::value_type(xRet,aIter));
429 		addEventListener(xRet,aIter);
430 	}
431 
432 	return xRet;
433 }
434 void OSharedConnectionManager::addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter)
435 {
436 	Reference<XComponent> xComp(_rxConnection,UNO_QUERY);
437 	xComp->addEventListener(this);
438 	OSL_ENSURE( m_aConnections.end() != _rIter , "Iterator is end!");
439 	osl_incrementInterlockedCount(&_rIter->second.nALiveCount);
440 }
441 
442 //----------------------------------------------------------------------
443 namespace
444 {
445     //------------------------------------------------------------------
446     Sequence< PropertyValue > lcl_filterDriverProperties( const Reference< XDriver >& _xDriver, const ::rtl::OUString& _sUrl,
447         const Sequence< PropertyValue >& _rDataSourceSettings, const AsciiPropertyValue* _pKnownSettings )
448 	{
449 		if ( _xDriver.is() )
450 		{
451 			Sequence< DriverPropertyInfo > aDriverInfo(_xDriver->getPropertyInfo(_sUrl,_rDataSourceSettings));
452 
453 			const PropertyValue* pDataSourceSetting = _rDataSourceSettings.getConstArray();
454 			const PropertyValue* pEnd = pDataSourceSetting + _rDataSourceSettings.getLength();
455 
456 			::std::vector< PropertyValue > aRet;
457 
458 			for ( ; pDataSourceSetting != pEnd ; ++pDataSourceSetting )
459 			{
460 				sal_Bool bAllowSetting = sal_False;
461                 const AsciiPropertyValue* pSetting = _pKnownSettings;
462 				for ( ; pSetting->AsciiName; ++pSetting )
463 				{
464 					if ( !pDataSourceSetting->Name.compareToAscii( pSetting->AsciiName ) )
465 					{   // the particular data source setting is known
466 
467                         const DriverPropertyInfo* pAllowedDriverSetting = aDriverInfo.getConstArray();
468 						const DriverPropertyInfo* pDriverSettingsEnd = pAllowedDriverSetting + aDriverInfo.getLength();
469 						for ( ; pAllowedDriverSetting != pDriverSettingsEnd; ++pAllowedDriverSetting )
470 						{
471 							if ( !pAllowedDriverSetting->Name.compareToAscii( pSetting->AsciiName ) )
472 							{   // the driver also allows this setting
473 								bAllowSetting = sal_True;
474 								break;
475 							}
476 						}
477 						break;
478 					}
479 				}
480 				if ( bAllowSetting || !pSetting->AsciiName )
481 				{   // if the driver allows this particular setting, or if the setting is completely unknown,
482                     // we pass it to the driver
483 					aRet.push_back( *pDataSourceSetting );
484 				}
485 			}
486 			if ( !aRet.empty() )
487 				return Sequence< PropertyValue >(&(*aRet.begin()),aRet.size());
488 		}
489 		return Sequence< PropertyValue >();
490 	}
491 
492     //------------------------------------------------------------------
493     typedef ::std::map< ::rtl::OUString, sal_Int32 > PropertyAttributeCache;
494 
495     //------------------------------------------------------------------
496     struct IsDefaultAndNotRemoveable : public ::std::unary_function< PropertyValue, bool >
497     {
498     private:
499         const PropertyAttributeCache& m_rAttribs;
500 
501     public:
502         IsDefaultAndNotRemoveable( const PropertyAttributeCache& _rAttribs ) : m_rAttribs( _rAttribs ) { }
503 
504         bool operator()( const PropertyValue& _rProp )
505         {
506             if ( _rProp.State != PropertyState_DEFAULT_VALUE )
507                 return false;
508 
509             bool bRemoveable = true;
510 
511             PropertyAttributeCache::const_iterator pos = m_rAttribs.find( _rProp.Name );
512             OSL_ENSURE( pos != m_rAttribs.end(), "IsDefaultAndNotRemoveable: illegal property name!" );
513             if ( pos != m_rAttribs.end() )
514                 bRemoveable = ( ( pos->second & PropertyAttribute::REMOVEABLE ) != 0 );
515 
516             return !bRemoveable;
517         }
518     };
519 }
520 //============================================================
521 //= ODatabaseContext
522 //============================================================
523 DBG_NAME(ODatabaseSource)
524 //--------------------------------------------------------------------------
525 extern "C" void SAL_CALL createRegistryInfo_ODatabaseSource()
526 {
527 	static ::dba::OAutoRegistration< ODatabaseSource > aAutoRegistration;
528 }
529 
530 //--------------------------------------------------------------------------
531 ODatabaseSource::ODatabaseSource(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl)
532 			:ModelDependentComponent( _pImpl )
533 			,ODatabaseSource_Base( getMutex() )
534             ,OPropertySetHelper( ODatabaseSource_Base::rBHelper )
535             ,m_aBookmarks( *this, getMutex() )
536             ,m_aFlushListeners( getMutex() )
537 {
538 	// some kind of default
539 	DBG_CTOR(ODatabaseSource,NULL);
540     OSL_TRACE( "DS: ctor: %p: %p", this, m_pImpl.get() );
541 }
542 
543 //--------------------------------------------------------------------------
544 ODatabaseSource::~ODatabaseSource()
545 {
546     OSL_TRACE( "DS: dtor: %p: %p", this, m_pImpl.get() );
547 	DBG_DTOR(ODatabaseSource,NULL);
548 	if ( !ODatabaseSource_Base::rBHelper.bInDispose && !ODatabaseSource_Base::rBHelper.bDisposed )
549 	{
550 		acquire();
551 		dispose();
552 	}
553 }
554 
555 //--------------------------------------------------------------------------
556 void ODatabaseSource::setName( const Reference< XDocumentDataSource >& _rxDocument, const ::rtl::OUString& _rNewName, DBContextAccess )
557 {
558     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setName" );
559     ODatabaseSource& rModelImpl = dynamic_cast< ODatabaseSource& >( *_rxDocument.get() );
560 
561     ::osl::MutexGuard aGuard( rModelImpl.m_aMutex );
562     if ( rModelImpl.m_pImpl.is() )
563         rModelImpl.m_pImpl->m_sName = _rNewName;
564 }
565 
566 // com::sun::star::lang::XTypeProvider
567 //--------------------------------------------------------------------------
568 Sequence< Type > ODatabaseSource::getTypes() throw (RuntimeException)
569 {
570     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTypes" );
571 	OTypeCollection aPropertyHelperTypes(	::getCppuType( (const Reference< XFastPropertySet > *)0 ),
572 											::getCppuType( (const Reference< XPropertySet > *)0 ),
573 											::getCppuType( (const Reference< XMultiPropertySet > *)0 ));
574 
575     return ::comphelper::concatSequences(
576 		ODatabaseSource_Base::getTypes(),
577 		aPropertyHelperTypes.getTypes()
578 	);
579 }
580 
581 //--------------------------------------------------------------------------
582 Sequence< sal_Int8 > ODatabaseSource::getImplementationId() throw (RuntimeException)
583 {
584     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationId" );
585 	static OImplementationId * pId = 0;
586 	if (! pId)
587 	{
588 		MutexGuard aGuard( Mutex::getGlobalMutex() );
589 		if (! pId)
590 		{
591 			static OImplementationId aId;
592 			pId = &aId;
593 		}
594 	}
595 	return pId->getImplementationId();
596 }
597 
598 // com::sun::star::uno::XInterface
599 //--------------------------------------------------------------------------
600 Any ODatabaseSource::queryInterface( const Type & rType ) throw (RuntimeException)
601 {
602     //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::queryInterface" );
603 	Any aIface = ODatabaseSource_Base::queryInterface( rType );
604 	if ( !aIface.hasValue() )
605 		aIface = ::cppu::OPropertySetHelper::queryInterface( rType );
606 	return aIface;
607 }
608 
609 //--------------------------------------------------------------------------
610 void ODatabaseSource::acquire() throw ()
611 {
612 	ODatabaseSource_Base::acquire();
613 }
614 
615 //--------------------------------------------------------------------------
616 void ODatabaseSource::release() throw ()
617 {
618 	ODatabaseSource_Base::release();
619 }
620 // -----------------------------------------------------------------------------
621 void SAL_CALL ODatabaseSource::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException)
622 {
623 	if ( m_pImpl.is() )
624 		m_pImpl->disposing(Source);
625 }
626 // XServiceInfo
627 //------------------------------------------------------------------------------
628 rtl::OUString ODatabaseSource::getImplementationName(  ) throw(RuntimeException)
629 {
630     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName" );
631 	return getImplementationName_static();
632 }
633 
634 //------------------------------------------------------------------------------
635 rtl::OUString ODatabaseSource::getImplementationName_static(  ) throw(RuntimeException)
636 {
637     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName_static" );
638 	return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ODatabaseSource");
639 }
640 
641 //------------------------------------------------------------------------------
642 Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames(  ) throw (RuntimeException)
643 {
644     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames" );
645 	return getSupportedServiceNames_static();
646 }
647 //------------------------------------------------------------------------------
648 Reference< XInterface > ODatabaseSource::Create( const Reference< XComponentContext >& _rxContext )
649 {
650     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::Create" );
651     ::comphelper::ComponentContext aContext( _rxContext );
652     Reference< XSingleServiceFactory > xDBContext( aContext.createComponent( (::rtl::OUString)SERVICE_SDB_DATABASECONTEXT ), UNO_QUERY_THROW );
653     return xDBContext->createInstance();
654 }
655 
656 //------------------------------------------------------------------------------
657 Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames_static(  ) throw (RuntimeException)
658 {
659     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames_static" );
660 	Sequence< ::rtl::OUString > aSNS( 2 );
661 	aSNS[0] = SERVICE_SDB_DATASOURCE;
662     aSNS[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.DocumentDataSource"));
663 	return aSNS;
664 }
665 
666 //------------------------------------------------------------------------------
667 sal_Bool ODatabaseSource::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
668 {
669     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::supportsService" );
670 	return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
671 }
672 // OComponentHelper
673 //------------------------------------------------------------------------------
674 void ODatabaseSource::disposing()
675 {
676     OSL_TRACE( "DS: disp: %p, %p", this, m_pImpl.get() );
677     ODatabaseSource_Base::WeakComponentImplHelperBase::disposing();
678 	OPropertySetHelper::disposing();
679 
680 	EventObject aDisposeEvent(static_cast<XWeak*>(this));
681 	m_aFlushListeners.disposeAndClear( aDisposeEvent );
682 
683     ODatabaseDocument::clearObjectContainer(m_pImpl->m_xCommandDefinitions);
684     ODatabaseDocument::clearObjectContainer(m_pImpl->m_xTableDefinitions);
685 	m_pImpl.clear();
686 }
687 //------------------------------------------------------------------------------
688 Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const ::rtl::OUString& _rUid, const ::rtl::OUString& _rPwd)
689 {
690     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildLowLevelConnection" );
691 	Reference< XConnection > xReturn;
692 
693     Reference< XDriverManager > xManager;
694     if ( !m_pImpl->m_aContext.createComponent( "com.sun.star.sdbc.ConnectionPool", xManager ) )
695         // no connection pool installed, fall back to driver manager
696         m_pImpl->m_aContext.createComponent( "com.sun.star.sdbc.DriverManager", xManager );
697 
698 	::rtl::OUString sUser(_rUid);
699 	::rtl::OUString sPwd(_rPwd);
700 	if ((0 == sUser.getLength()) && (0 == sPwd.getLength()) && (0 != m_pImpl->m_sUser.getLength()))
701 	{	// ease the usage of this method. data source which are intended to have a user automatically
702 		// fill in the user/password combination if the caller of this method does not specify otherwise
703 		// 86951 - 05/08/2001 - frank.schoenheit@germany.sun.com
704 		sUser = m_pImpl->m_sUser;
705 		if (0 != m_pImpl->m_aPassword.getLength())
706 			sPwd = m_pImpl->m_aPassword;
707 	}
708 
709 	sal_uInt16 nExceptionMessageId = RID_STR_COULDNOTCONNECT_UNSPECIFIED;
710 	if (xManager.is())
711 	{
712 		sal_Int32 nAdditionalArgs(0);
713 		if (sUser.getLength()) ++nAdditionalArgs;
714 		if (sPwd.getLength()) ++nAdditionalArgs;
715 
716 		Sequence< PropertyValue > aUserPwd(nAdditionalArgs);
717 		sal_Int32 nArgPos = 0;
718 		if (sUser.getLength())
719 		{
720 			aUserPwd[ nArgPos ].Name = ::rtl::OUString::createFromAscii("user");
721 			aUserPwd[ nArgPos ].Value <<= sUser;
722 			++nArgPos;
723 		}
724 		if (sPwd.getLength())
725 		{
726 			aUserPwd[ nArgPos ].Name = ::rtl::OUString::createFromAscii("password");
727 			aUserPwd[ nArgPos ].Value <<= sPwd;
728 		}
729 		Reference< XDriver > xDriver;
730 		try
731 		{
732 			Reference< XDriverAccess > xAccessDrivers( xManager, UNO_QUERY );
733 			if ( xAccessDrivers.is() )
734 				xDriver = xAccessDrivers->getDriverByURL( m_pImpl->m_sConnectURL );
735 		}
736 		catch( const Exception& )
737 		{
738 			DBG_ERROR( "ODatabaseSource::buildLowLevelConnection: got a strange exception while analyzing the error!" );
739 		}
740 		if ( !xDriver.is() || !xDriver->acceptsURL( m_pImpl->m_sConnectURL ) )
741         {
742             // Nowadays, it's allowed for a driver to be registered for a given URL, but actually not to accept it.
743             // This is because registration nowadays happens at compile time (by adding respective configuration data),
744             // but acceptance is decided at runtime.
745 			nExceptionMessageId = RID_STR_COULDNOTCONNECT_NODRIVER;
746         }
747 		else
748 		{
749             Sequence< PropertyValue > aDriverInfo = lcl_filterDriverProperties(
750                 xDriver,
751                 m_pImpl->m_sConnectURL,
752                 m_pImpl->m_xSettings->getPropertyValues(),
753                 m_pImpl->getDefaultDataSourceSettings()
754             );
755 
756 			if ( m_pImpl->isEmbeddedDatabase() )
757 			{
758 				sal_Int32 nCount = aDriverInfo.getLength();
759 				aDriverInfo.realloc(nCount + 2 );
760 				aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
761 				aDriverInfo[nCount++].Value <<= m_pImpl->getURL();
762 				aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Storage"));
763                 Reference< css::document::XDocumentSubStorageSupplier> xDocSup( m_pImpl->getDocumentSubStorageSupplier() );
764 				aDriverInfo[nCount++].Value <<= xDocSup->getDocumentSubStorage(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("database")),ElementModes::READWRITE);
765 			}
766 			if (nAdditionalArgs)
767 				xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL, ::comphelper::concatSequences(aUserPwd,aDriverInfo));
768 			else
769 				xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL,aDriverInfo);
770 
771             if ( m_pImpl->isEmbeddedDatabase() )
772             {
773                 // see ODatabaseSource::flushed for comment on why we register as FlushListener
774                 // at the connection
775                 Reference< XFlushable > xFlushable( xReturn, UNO_QUERY );
776                 if ( xFlushable.is() )
777                     FlushNotificationAdapter::installAdapter( xFlushable, this );
778             }
779 		}
780 	}
781 	else
782 		nExceptionMessageId = RID_STR_COULDNOTLOAD_MANAGER;
783 
784 	if ( !xReturn.is() )
785 	{
786 		::rtl::OUString sMessage = DBACORE_RESSTRING( nExceptionMessageId );
787 
788 		SQLContext aContext;
789         aContext.Message = DBACORE_RESSTRING( RID_STR_CONNECTION_REQUEST );
790         ::comphelper::string::searchAndReplaceAsciiI( aContext.Message, "$name$", m_pImpl->m_sConnectURL );
791 
792 		throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), makeAny( aContext ) );
793 	}
794 
795 	return xReturn;
796 }
797 
798 // OPropertySetHelper
799 //------------------------------------------------------------------------------
800 Reference< XPropertySetInfo >  ODatabaseSource::getPropertySetInfo() throw (RuntimeException)
801 {
802     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getPropertySetInfo" );
803 	return createPropertySetInfo( getInfoHelper() ) ;
804 }
805 
806 // comphelper::OPropertyArrayUsageHelper
807 //------------------------------------------------------------------------------
808 ::cppu::IPropertyArrayHelper* ODatabaseSource::createArrayHelper( ) const
809 {
810     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::createArrayHelper" );
811 	BEGIN_PROPERTY_HELPER(13)
812 		DECL_PROP1(INFO,						Sequence< PropertyValue >,  BOUND);
813 		DECL_PROP1_BOOL(ISPASSWORDREQUIRED,									BOUND);
814 		DECL_PROP1_BOOL(ISREADONLY,											READONLY);
815 		DECL_PROP1(LAYOUTINFORMATION,			Sequence< PropertyValue >,  BOUND);
816 		DECL_PROP1(NAME,						::rtl::OUString,			READONLY);
817 		DECL_PROP2_IFACE(NUMBERFORMATSSUPPLIER,	XNumberFormatsSupplier,		READONLY, TRANSIENT);
818 		DECL_PROP1(PASSWORD,					::rtl::OUString,			TRANSIENT);
819 		DECL_PROP2_IFACE(SETTINGS,              XPropertySet,               BOUND, READONLY);
820 		DECL_PROP1_BOOL(SUPPRESSVERSIONCL,									BOUND);
821 		DECL_PROP1(TABLEFILTER,					Sequence< ::rtl::OUString >,BOUND);
822 		DECL_PROP1(TABLETYPEFILTER,				Sequence< ::rtl::OUString >,BOUND);
823 		DECL_PROP1(URL,							::rtl::OUString,			BOUND);
824 		DECL_PROP1(USER,						::rtl::OUString,			BOUND);
825 	END_PROPERTY_HELPER();
826 }
827 
828 // cppu::OPropertySetHelper
829 //------------------------------------------------------------------------------
830 ::cppu::IPropertyArrayHelper& ODatabaseSource::getInfoHelper()
831 {
832 	return *getArrayHelper();
833 }
834 
835 //------------------------------------------------------------------------------
836 sal_Bool ODatabaseSource::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException  )
837 {
838     //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::convertFastPropertyValue" );
839     sal_Bool bModified(sal_False);
840     if ( m_pImpl.is() )
841     {
842 	    switch (nHandle)
843 	    {
844 		    case PROPERTY_ID_TABLEFILTER:
845 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableFilter);
846 			    break;
847 		    case PROPERTY_ID_TABLETYPEFILTER:
848 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableTypeFilter);
849 			    break;
850 		    case PROPERTY_ID_USER:
851 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sUser);
852 			    break;
853 		    case PROPERTY_ID_PASSWORD:
854 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aPassword);
855 			    break;
856 		    case PROPERTY_ID_ISPASSWORDREQUIRED:
857 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bPasswordRequired);
858 			    break;
859 		    case PROPERTY_ID_SUPPRESSVERSIONCL:
860 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bSuppressVersionColumns);
861 			    break;
862 		    case PROPERTY_ID_LAYOUTINFORMATION:
863 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aLayoutInformation);
864 			    break;
865 		    case PROPERTY_ID_URL:
866 		    {
867 			    bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sConnectURL);
868 		    }	break;
869 		    case PROPERTY_ID_INFO:
870 		    {
871 			    Sequence<PropertyValue> aValues;
872 			    if (!(rValue >>= aValues))
873 				    throw IllegalArgumentException();
874 
875 			    const PropertyValue* valueEnd = aValues.getConstArray() + aValues.getLength();
876 			    const PropertyValue* checkName = aValues.getConstArray();
877 			    for ( ;checkName != valueEnd; ++checkName )
878 			    {
879 				    if ( !checkName->Name.getLength() )
880 					    throw IllegalArgumentException();
881 			    }
882 
883                 Sequence< PropertyValue > aSettings = m_pImpl->m_xSettings->getPropertyValues();
884                 bModified = aSettings.getLength() != aValues.getLength();
885 			    if ( !bModified )
886 			    {
887                     const PropertyValue* pInfoIter = aSettings.getConstArray();
888 				    const PropertyValue* checkValue = aValues.getConstArray();
889 				    for ( ;!bModified && checkValue != valueEnd ; ++checkValue,++pInfoIter)
890 				    {
891 					    bModified = checkValue->Name != pInfoIter->Name;
892 					    if ( !bModified )
893 					    {
894 						    bModified = !::comphelper::compare(checkValue->Value,pInfoIter->Value);
895 					    }
896 				    }
897 			    }
898 
899 			    rConvertedValue = rValue;
900                 rOldValue <<= aSettings;
901             }
902             break;
903 		    default:
904                 DBG_ERROR( "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" );
905 	    }
906     }
907 	return bModified;
908 }
909 
910 //------------------------------------------------------------------------------
911 namespace
912 {
913     struct SelectPropertyName : public ::std::unary_function< PropertyValue, ::rtl::OUString >
914     {
915     public:
916         const ::rtl::OUString& operator()( const PropertyValue& _lhs )
917         {
918             return _lhs.Name;
919         }
920     };
921 
922     /** sets a new set of property values at a given property bag instance
923 
924         The methods takes a property bag, and a sequence of property values to set at this bag.
925         Upon return, every property which is not part of the given sequence is
926         <ul><li>removed from the bag, if it's a removeable property</li>
927             <li><em>or</em>reset to its default value, if it's not a removeable property</li>
928         </ul>.
929 
930         @param  _rxPropertyBag
931             the property bag to operate on
932         @param  _rAllNewPropertyValues
933             the new property values to set at the bag
934     */
935     void lcl_setPropertyValues_resetOrRemoveOther( const Reference< XPropertyAccess >& _rxPropertyBag, const Sequence< PropertyValue >& _rAllNewPropertyValues )
936     {
937         // sequences are ugly to operate on
938         typedef ::std::set< ::rtl::OUString >   StringSet;
939         StringSet aToBeSetPropertyNames;
940         ::std::transform(
941             _rAllNewPropertyValues.getConstArray(),
942             _rAllNewPropertyValues.getConstArray() + _rAllNewPropertyValues.getLength(),
943             ::std::insert_iterator< StringSet >( aToBeSetPropertyNames, aToBeSetPropertyNames.end() ),
944             SelectPropertyName()
945         );
946 
947         try
948         {
949             // obtain all properties currently known at the bag
950             Reference< XPropertySet > xPropertySet( _rxPropertyBag, UNO_QUERY_THROW );
951             Reference< XPropertySetInfo > xPSI( xPropertySet->getPropertySetInfo(), UNO_QUERY_THROW );
952             Sequence< Property > aAllExistentProperties( xPSI->getProperties() );
953 
954             Reference< XPropertyState > xPropertyState( _rxPropertyBag, UNO_QUERY_THROW );
955             Reference< XPropertyContainer > xPropertyContainer( _rxPropertyBag, UNO_QUERY_THROW );
956 
957             // loop through them, and reset resp. default properties which are not to be set
958             const Property* pExistentProperty( aAllExistentProperties.getConstArray() );
959             const Property* pExistentPropertyEnd( aAllExistentProperties.getConstArray() + aAllExistentProperties.getLength() );
960             for ( ; pExistentProperty != pExistentPropertyEnd; ++pExistentProperty )
961             {
962                 if ( aToBeSetPropertyNames.find( pExistentProperty->Name ) != aToBeSetPropertyNames.end() )
963                     continue;
964 
965                 // this property is not to be set, but currently exists in the bag.
966                 // -> Remove, respectively default, it
967                 if ( ( pExistentProperty->Attributes & PropertyAttribute::REMOVEABLE ) != 0 )
968                     xPropertyContainer->removeProperty( pExistentProperty->Name );
969                 else
970                     xPropertyState->setPropertyToDefault( pExistentProperty->Name );
971             }
972 
973             // finally, set the new property values
974             _rxPropertyBag->setPropertyValues( _rAllNewPropertyValues );
975         }
976         catch( const Exception& )
977         {
978         	DBG_UNHANDLED_EXCEPTION();
979         }
980     }
981 }
982 
983 //------------------------------------------------------------------------------
984 void ODatabaseSource::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
985 {
986     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setFastPropertyValue_NoBroadcast" );
987     if ( m_pImpl.is() )
988     {
989 	    switch(nHandle)
990 	    {
991 		    case PROPERTY_ID_TABLEFILTER:
992 			    rValue >>= m_pImpl->m_aTableFilter;
993 			    break;
994 		    case PROPERTY_ID_TABLETYPEFILTER:
995 			    rValue >>= m_pImpl->m_aTableTypeFilter;
996 			    break;
997 		    case PROPERTY_ID_USER:
998 			    rValue >>= m_pImpl->m_sUser;
999 			    // if the user name changed, reset the password
1000 			    m_pImpl->m_aPassword = ::rtl::OUString();
1001 			    break;
1002 		    case PROPERTY_ID_PASSWORD:
1003 			    rValue >>= m_pImpl->m_aPassword;
1004 			    break;
1005 		    case PROPERTY_ID_ISPASSWORDREQUIRED:
1006 			    m_pImpl->m_bPasswordRequired = any2bool(rValue);
1007 			    break;
1008 		    case PROPERTY_ID_SUPPRESSVERSIONCL:
1009 			    m_pImpl->m_bSuppressVersionColumns = any2bool(rValue);
1010 			    break;
1011 		    case PROPERTY_ID_URL:
1012 			    rValue >>= m_pImpl->m_sConnectURL;
1013 			    break;
1014 		    case PROPERTY_ID_INFO:
1015             {
1016                 Sequence< PropertyValue > aInfo;
1017                 OSL_VERIFY( rValue >>= aInfo );
1018                 lcl_setPropertyValues_resetOrRemoveOther( m_pImpl->m_xSettings, aInfo );
1019             }
1020             break;
1021 		    case PROPERTY_ID_LAYOUTINFORMATION:
1022 			    rValue >>= m_pImpl->m_aLayoutInformation;
1023 			    break;
1024 	    }
1025 	    m_pImpl->setModified(sal_True);
1026     }
1027 }
1028 
1029 //------------------------------------------------------------------------------
1030 void ODatabaseSource::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
1031 {
1032     //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getFastPropertyValue" );
1033     if ( m_pImpl.is() )
1034     {
1035 	    switch (nHandle)
1036 	    {
1037 		    case PROPERTY_ID_TABLEFILTER:
1038 			    rValue <<= m_pImpl->m_aTableFilter;
1039 			    break;
1040 		    case PROPERTY_ID_TABLETYPEFILTER:
1041 			    rValue <<= m_pImpl->m_aTableTypeFilter;
1042 			    break;
1043 		    case PROPERTY_ID_USER:
1044 			    rValue <<= m_pImpl->m_sUser;
1045 			    break;
1046 		    case PROPERTY_ID_PASSWORD:
1047 			    rValue <<= m_pImpl->m_aPassword;
1048 			    break;
1049 		    case PROPERTY_ID_ISPASSWORDREQUIRED:
1050 			    rValue = bool2any(m_pImpl->m_bPasswordRequired);
1051 			    break;
1052 		    case PROPERTY_ID_SUPPRESSVERSIONCL:
1053 			    rValue = bool2any(m_pImpl->m_bSuppressVersionColumns);
1054 			    break;
1055 		    case PROPERTY_ID_ISREADONLY:
1056 			    rValue = bool2any(m_pImpl->m_bReadOnly);
1057 			    break;
1058 		    case PROPERTY_ID_INFO:
1059             {
1060                 try
1061                 {
1062                     // collect the property attributes of all current settings
1063                     Reference< XPropertySet > xSettingsAsProps( m_pImpl->m_xSettings, UNO_QUERY_THROW );
1064                     Reference< XPropertySetInfo > xPST( xSettingsAsProps->getPropertySetInfo(), UNO_QUERY_THROW );
1065                     Sequence< Property > aSettings( xPST->getProperties() );
1066                     ::std::map< ::rtl::OUString, sal_Int32 > aPropertyAttributes;
1067                     for (   const Property* pSettings = aSettings.getConstArray();
1068                             pSettings != aSettings.getConstArray() + aSettings.getLength();
1069                             ++pSettings
1070                         )
1071                     {
1072                         aPropertyAttributes[ pSettings->Name ] = pSettings->Attributes;
1073                     }
1074 
1075                     // get all current settings with their values
1076                     Sequence< PropertyValue > aValues( m_pImpl->m_xSettings->getPropertyValues() );
1077 
1078                     // transform them so that only property values which fulfill certain
1079                     // criterions survive
1080                     Sequence< PropertyValue > aNonDefaultOrUserDefined( aValues.getLength() );
1081                     const PropertyValue* pCopyEnd = ::std::remove_copy_if(
1082                         aValues.getConstArray(),
1083                         aValues.getConstArray() + aValues.getLength(),
1084                         aNonDefaultOrUserDefined.getArray(),
1085                         IsDefaultAndNotRemoveable( aPropertyAttributes )
1086                     );
1087                     aNonDefaultOrUserDefined.realloc( pCopyEnd - aNonDefaultOrUserDefined.getArray() );
1088                     rValue <<= aNonDefaultOrUserDefined;
1089                 }
1090                 catch( const Exception& )
1091                 {
1092                 	DBG_UNHANDLED_EXCEPTION();
1093                 }
1094             }
1095             break;
1096             case PROPERTY_ID_SETTINGS:
1097                 rValue <<= m_pImpl->m_xSettings;
1098 			    break;
1099 		    case PROPERTY_ID_URL:
1100 			    rValue <<= m_pImpl->m_sConnectURL;
1101 			    break;
1102 		    case PROPERTY_ID_NUMBERFORMATSSUPPLIER:
1103 			    rValue <<= m_pImpl->getNumberFormatsSupplier();
1104 			    break;
1105 		    case PROPERTY_ID_NAME:
1106 			    rValue <<= m_pImpl->m_sName;
1107 			    break;
1108 		    case PROPERTY_ID_LAYOUTINFORMATION:
1109 			    rValue <<= m_pImpl->m_aLayoutInformation;
1110 			    break;
1111 		    default:
1112 			    DBG_ERROR("unknown Property");
1113 	    }
1114     }
1115 }
1116 
1117 // XDataSource
1118 //------------------------------------------------------------------------------
1119 void ODatabaseSource::setLoginTimeout(sal_Int32 seconds) throw( SQLException, RuntimeException )
1120 {
1121     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setLoginTimeout" );
1122     ModelMethodGuard aGuard( *this );
1123 	m_pImpl->m_nLoginTimeout = seconds;
1124 }
1125 
1126 //------------------------------------------------------------------------------
1127 sal_Int32 ODatabaseSource::getLoginTimeout(void) throw( SQLException, RuntimeException )
1128 {
1129     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getLoginTimeout" );
1130     ModelMethodGuard aGuard( *this );
1131 	return m_pImpl->m_nLoginTimeout;
1132 }
1133 
1134 
1135 // XCompletedConnection
1136 //------------------------------------------------------------------------------
1137 Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
1138 {
1139     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
1140 	return connectWithCompletion(_rxHandler,sal_False);
1141 }
1142 // -----------------------------------------------------------------------------
1143 Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password) throw( SQLException, RuntimeException )
1144 {
1145     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
1146 	return getConnection(user,password,sal_False);
1147 }
1148 // -----------------------------------------------------------------------------
1149 Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnection( const ::rtl::OUString& user, const ::rtl::OUString& password ) throw(SQLException, RuntimeException)
1150 {
1151     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnection" );
1152 	return getConnection(user,password,sal_True);
1153 }
1154 // -----------------------------------------------------------------------------
1155 Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnectionWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException)
1156 {
1157     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnectionWithCompletion" );
1158 	return connectWithCompletion(_rxHandler,sal_True);
1159 }
1160 // -----------------------------------------------------------------------------
1161 Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler,sal_Bool _bIsolated ) throw(SQLException, RuntimeException)
1162 {
1163     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" );
1164     ModelMethodGuard aGuard( *this );
1165 
1166 	if (!_rxHandler.is())
1167 	{
1168 		DBG_ERROR("ODatabaseSource::connectWithCompletion: invalid interaction handler!");
1169 		return getConnection(m_pImpl->m_sUser, m_pImpl->m_aPassword,_bIsolated);
1170 	}
1171 
1172 	::rtl::OUString sUser(m_pImpl->m_sUser), sPassword(m_pImpl->m_aPassword);
1173 	sal_Bool bNewPasswordGiven = sal_False;
1174 
1175 	if (m_pImpl->m_bPasswordRequired && (0 == sPassword.getLength()))
1176 	{	// we need a password, but don't have one yet.
1177 		// -> ask the user
1178 
1179 		// build an interaction request
1180 		// two continuations (Ok and Cancel)
1181 		OInteractionAbort* pAbort = new OInteractionAbort;
1182 		OAuthenticationContinuation* pAuthenticate = new OAuthenticationContinuation;
1183 
1184         // the name which should be referred in the login dialog
1185         ::rtl::OUString sServerName( m_pImpl->m_sName );
1186         INetURLObject aURLCheck( sServerName );
1187         if ( aURLCheck.GetProtocol() != INET_PROT_NOT_VALID )
1188             sServerName = aURLCheck.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_UNAMBIGUOUS );
1189 
1190 		// the request
1191 		AuthenticationRequest aRequest;
1192 		aRequest.ServerName = sServerName;
1193 		aRequest.HasRealm = aRequest.HasAccount = sal_False;
1194 		aRequest.HasUserName = aRequest.HasPassword = sal_True;
1195 		aRequest.UserName = m_pImpl->m_sUser;
1196         aRequest.Password = m_pImpl->m_sFailedPassword.getLength() ? m_pImpl->m_sFailedPassword : m_pImpl->m_aPassword;
1197 		OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest));
1198 		Reference< XInteractionRequest > xRequest(pRequest);
1199 		// some knittings
1200 		pRequest->addContinuation(pAbort);
1201 		pRequest->addContinuation(pAuthenticate);
1202 
1203 		// handle the request
1204 		try
1205 		{
1206 			MutexRelease aRelease( getMutex() );
1207 				// release the mutex when calling the handler, it may need to lock the SolarMutex
1208 			_rxHandler->handle(xRequest);
1209 		}
1210 		catch(Exception&)
1211 		{
1212             DBG_UNHANDLED_EXCEPTION();
1213 		}
1214 
1215 		if (!pAuthenticate->wasSelected())
1216 			return Reference< XConnection >();
1217 
1218 		// get the result
1219 		sUser = m_pImpl->m_sUser = pAuthenticate->getUser();
1220 		sPassword = pAuthenticate->getPassword();
1221 
1222 		if (pAuthenticate->getRememberPassword())
1223 		{
1224 			m_pImpl->m_aPassword = pAuthenticate->getPassword();
1225 			bNewPasswordGiven = sal_True;
1226 		}
1227         m_pImpl->m_sFailedPassword = ::rtl::OUString();
1228 	}
1229 
1230 	try
1231 	{
1232 		return getConnection(sUser, sPassword,_bIsolated);
1233 	}
1234 	catch(Exception&)
1235 	{
1236 		if (bNewPasswordGiven)
1237         {
1238             m_pImpl->m_sFailedPassword = m_pImpl->m_aPassword;
1239 			// assume that we had an authentication problem. Without this we may, after an unsucessful connect, while
1240 			// the user gave us a password an the order to remember it, never allow an password input again (at least
1241 			// not without restarting the session)
1242 			m_pImpl->m_aPassword = ::rtl::OUString();
1243         }
1244 		throw;
1245 	}
1246 }
1247 
1248 // -----------------------------------------------------------------------------
1249 Reference< XConnection > ODatabaseSource::buildIsolatedConnection(const rtl::OUString& user, const rtl::OUString& password)
1250 {
1251     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildIsolatedConnection" );
1252 	Reference< XConnection > xConn;
1253 	Reference< XConnection > xSdbcConn = buildLowLevelConnection(user, password);
1254 	DBG_ASSERT( xSdbcConn.is(), "ODatabaseSource::buildIsolatedConnection: invalid return value of buildLowLevelConnection!" );
1255 	// buildLowLevelConnection is expected to always succeed
1256 	if ( xSdbcConn.is() )
1257 	{
1258 		// build a connection server and return it (no stubs)
1259 		xConn = new OConnection(*this, xSdbcConn, m_pImpl->m_aContext.getLegacyServiceFactory());
1260 	}
1261 	return xConn;
1262 }
1263 //------------------------------------------------------------------------------
1264 Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password,sal_Bool _bIsolated) throw( SQLException, RuntimeException )
1265 {
1266     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" );
1267     ModelMethodGuard aGuard( *this );
1268 
1269 	Reference< XConnection > xConn;
1270 	if ( _bIsolated )
1271 	{
1272 		xConn = buildIsolatedConnection(user,password);
1273 	}
1274 	else
1275 	{ // create a new proxy for the connection
1276 		if ( !m_pImpl->m_xSharedConnectionManager.is() )
1277 		{
1278 			m_pImpl->m_pSharedConnectionManager = new OSharedConnectionManager( m_pImpl->m_aContext.getLegacyServiceFactory() );
1279 			m_pImpl->m_xSharedConnectionManager = m_pImpl->m_pSharedConnectionManager;
1280 		}
1281 		xConn = m_pImpl->m_pSharedConnectionManager->getConnection(
1282             m_pImpl->m_sConnectURL, user, password, m_pImpl->m_xSettings->getPropertyValues(), this );
1283 	}
1284 
1285 	if ( xConn.is() )
1286 	{
1287 		Reference< XComponent> xComp(xConn,UNO_QUERY);
1288 		if ( xComp.is() )
1289 			xComp->addEventListener( static_cast< XContainerListener* >( this ) );
1290 		m_pImpl->m_aConnections.push_back(OWeakConnection(xConn));
1291 	}
1292 
1293 	return xConn;
1294 }
1295 
1296 //------------------------------------------------------------------------------
1297 Reference< XNameAccess > SAL_CALL ODatabaseSource::getBookmarks(  ) throw (RuntimeException)
1298 {
1299     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getBookmarks" );
1300     ModelMethodGuard aGuard( *this );
1301 	return static_cast< XNameContainer* >(&m_aBookmarks);
1302 }
1303 
1304 //------------------------------------------------------------------------------
1305 Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( ) throw(RuntimeException)
1306 {
1307     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getQueryDefinitions" );
1308     ModelMethodGuard aGuard( *this );
1309 
1310     Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions;
1311 	if ( !xContainer.is() )
1312 	{
1313         Any aValue;
1314         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xMy(*this);
1315         if ( dbtools::getDataSourceSetting(xMy,"CommandDefinitions",aValue) )
1316         {
1317             ::rtl::OUString sSupportService;
1318             aValue >>= sSupportService;
1319             if ( sSupportService.getLength() )
1320             {
1321                 Sequence<Any> aArgs(1);
1322                 aArgs[0] <<= NamedValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSource")),makeAny(xMy));
1323                 xContainer.set(m_pImpl->m_aContext.createComponentWithArguments(sSupportService,aArgs),UNO_QUERY);
1324             }
1325         }
1326         if ( !xContainer.is() )
1327         {
1328             TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_QUERY ) );
1329 		    xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_False );
1330         }
1331         m_pImpl->m_xCommandDefinitions = xContainer;
1332 	}
1333 	return xContainer;
1334 }
1335 //------------------------------------------------------------------------------
1336 // XTablesSupplier
1337 //------------------------------------------------------------------------------
1338 Reference< XNameAccess >  ODatabaseSource::getTables() throw( RuntimeException )
1339 {
1340     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTables" );
1341     ModelMethodGuard aGuard( *this );
1342 
1343     Reference< XNameAccess > xContainer = m_pImpl->m_xTableDefinitions;
1344 	if ( !xContainer.is() )
1345 	{
1346         TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_TABLE ) );
1347 		xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_True );
1348 		m_pImpl->m_xTableDefinitions = xContainer;
1349 	}
1350 	return xContainer;
1351 }
1352 // -----------------------------------------------------------------------------
1353 void SAL_CALL ODatabaseSource::flush(  ) throw (RuntimeException)
1354 {
1355     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flush" );
1356 	try
1357 	{
1358         // SYNCHRONIZED ->
1359         {
1360             ModelMethodGuard aGuard( *this );
1361 
1362             typedef ::utl::SharedUNOComponent< XModel, ::utl::CloseableComponent > SharedModel;
1363             SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership );
1364 
1365             if ( !xModel.is() )
1366                 xModel.reset( m_pImpl->createNewModel_deliverOwnership( false ), SharedModel::TakeOwnership );
1367 
1368             Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW );
1369             xStorable->store();
1370         }
1371         // <- SYNCHRONIZED
1372 
1373         css::lang::EventObject aFlushedEvent(*this);
1374         m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent );
1375 	}
1376 	catch( const Exception& )
1377 	{
1378         DBG_UNHANDLED_EXCEPTION();
1379 	}
1380 }
1381 
1382 // -----------------------------------------------------------------------------
1383 void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ ) throw (RuntimeException)
1384 {
1385     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flushed" );
1386     ModelMethodGuard aGuard( *this );
1387 
1388     // Okay, this is some hack.
1389     //
1390     // In general, we have the problem that embedded databases write into their underlying storage, which
1391     // logically is one of our sub storage, and practically is a temporary file maintained by the
1392     // package implementation. As long as we did not commit this storage and our main storage,
1393     // the changes made by the embedded database engine are not really reflected in the database document
1394     // file. This is Bad (TM) for a "real" database application - imagine somebody entering some
1395     // data, and then crashing: For a database application, you would expect that the data still is present
1396     // when you connect to the database next time.
1397     //
1398     // Since this is a conceptual problem as long as we do use those ZIP packages (in fact, we *cannot*
1399     // provide the desired functionality as long as we do not have a package format which allows O(1) writes),
1400     // we cannot completely fix this. However, we can relax the problem by commiting more often - often
1401     // enough so that data loss is more seldom, and seldom enough so that there's no noticable performance
1402     // decrease.
1403     //
1404     // For this, we introduced a few places which XFlushable::flush their connections, and register as
1405     // XFlushListener at the embedded connection (which needs to provide the XFlushable functionality).
1406     // Then, when the connection is flushed, we commit both the database storage and our main storage.
1407     //
1408     // #i55274# / 2005-09-30 / frank.schoenheit@sun.com
1409 
1410     OSL_ENSURE( m_pImpl->isEmbeddedDatabase(), "ODatabaseSource::flushed: no embedded database?!" );
1411     sal_Bool bWasModified = m_pImpl->m_bModified;
1412     m_pImpl->commitEmbeddedStorage();
1413     m_pImpl->setModified( bWasModified );
1414 }
1415 
1416 // -----------------------------------------------------------------------------
1417 void SAL_CALL ODatabaseSource::addFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
1418 {
1419     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::addFlushListener" );
1420 	m_aFlushListeners.addInterface(_xListener);
1421 }
1422 // -----------------------------------------------------------------------------
1423 void SAL_CALL ODatabaseSource::removeFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException)
1424 {
1425     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::removeFlushListener" );
1426 	m_aFlushListeners.removeInterface(_xListener);
1427 }
1428 // -----------------------------------------------------------------------------
1429 void SAL_CALL ODatabaseSource::elementInserted( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1430 {
1431     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementInserted" );
1432     ModelMethodGuard aGuard( *this );
1433 	if ( m_pImpl.is() )
1434 		m_pImpl->setModified(sal_True);
1435 }
1436 // -----------------------------------------------------------------------------
1437 void SAL_CALL ODatabaseSource::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1438 {
1439     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementRemoved" );
1440     ModelMethodGuard aGuard( *this );
1441 	if ( m_pImpl.is() )
1442 		m_pImpl->setModified(sal_True);
1443 }
1444 // -----------------------------------------------------------------------------
1445 void SAL_CALL ODatabaseSource::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
1446 {
1447     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementReplaced" );
1448     ModelMethodGuard aGuard( *this );
1449 	if ( m_pImpl.is() )
1450 		m_pImpl->setModified(sal_True);
1451 }
1452 // -----------------------------------------------------------------------------
1453 // XDocumentDataSource
1454 Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocument() throw (RuntimeException)
1455 {
1456     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getDatabaseDocument" );
1457     ModelMethodGuard aGuard( *this );
1458 
1459     Reference< XModel > xModel( m_pImpl->getModel_noCreate() );
1460     if ( !xModel.is() )
1461         xModel = m_pImpl->createNewModel_deliverOwnership( false );
1462 
1463     return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW );
1464 }
1465 // -----------------------------------------------------------------------------
1466 Reference< XInterface > ODatabaseSource::getThis() const
1467 {
1468     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getThis" );
1469     return *const_cast< ODatabaseSource* >( this );
1470 }
1471 // -----------------------------------------------------------------------------
1472 //........................................................................
1473 }	// namespace dbaccess
1474 //........................................................................
1475 
1476 
1477