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