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