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