1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 
31 #include <stdio.h>
32 
33 #include "mdrivermanager.hxx"
34 #include <com/sun/star/sdbc/XDriver.hpp>
35 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
36 #include <com/sun/star/container/ElementExistException.hpp>
37 #include <com/sun/star/beans/NamedValue.hpp>
38 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
39 
40 #include <tools/diagnose_ex.h>
41 #include <comphelper/extract.hxx>
42 #include <comphelper/stl_types.hxx>
43 #include <cppuhelper/implbase1.hxx>
44 #include <cppuhelper/weakref.hxx>
45 #include <osl/diagnose.h>
46 
47 #include <algorithm>
48 #include <functional>
49 
50 namespace drivermanager
51 {
52 
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::sdbc;
56 using namespace ::com::sun::star::beans;
57 using namespace ::com::sun::star::container;
58 using namespace ::com::sun::star::logging;
59 using namespace ::osl;
60 
61 #define SERVICE_SDBC_DRIVER		::rtl::OUString::createFromAscii("com.sun.star.sdbc.Driver")
62 
63 void throwNoSuchElementException() throw(NoSuchElementException)
64 {
65 	throw NoSuchElementException();
66 }
67 
68 //==========================================================================
69 //= ODriverEnumeration
70 //==========================================================================
71 class ODriverEnumeration : public ::cppu::WeakImplHelper1< XEnumeration >
72 {
73 	friend class OSDBCDriverManager;
74 
75 	DECLARE_STL_VECTOR( SdbcDriver, DriverArray );
76 	DriverArray					m_aDrivers;
77 	ConstDriverArrayIterator	m_aPos;
78 	// order matters!
79 
80 protected:
81 	virtual ~ODriverEnumeration();
82 public:
83 	ODriverEnumeration(const DriverArray& _rDriverSequence);
84 
85 // XEnumeration
86 	virtual sal_Bool SAL_CALL hasMoreElements( ) throw(RuntimeException);
87     virtual Any SAL_CALL nextElement( ) throw(NoSuchElementException, WrappedTargetException, RuntimeException);
88 };
89 
90 //--------------------------------------------------------------------------
91 ODriverEnumeration::ODriverEnumeration(const DriverArray& _rDriverSequence)
92 	:m_aDrivers( _rDriverSequence )
93 	,m_aPos( m_aDrivers.begin() )
94 {
95 }
96 
97 //--------------------------------------------------------------------------
98 ODriverEnumeration::~ODriverEnumeration()
99 {
100 }
101 
102 //--------------------------------------------------------------------------
103 sal_Bool SAL_CALL ODriverEnumeration::hasMoreElements(  ) throw(RuntimeException)
104 {
105 	return m_aPos != m_aDrivers.end();
106 }
107 
108 //--------------------------------------------------------------------------
109 Any SAL_CALL ODriverEnumeration::nextElement(  ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
110 {
111 	if ( !hasMoreElements() )
112 		throwNoSuchElementException();
113 
114 	return makeAny( *m_aPos++ );
115 }
116 
117 	//=====================================================================
118 	//= helper
119 	//=====================================================================
120 	//---------------------------------------------------------------------
121 	//--- 24.08.01 11:27:59 -----------------------------------------------
122 
123 	/// an STL functor which ensures that a SdbcDriver described by a DriverAccess is loaded
124 	struct EnsureDriver : public ::std::unary_function< DriverAccess, DriverAccess >
125 	{
126 		const DriverAccess& operator()( const DriverAccess& _rDescriptor ) const
127 		{
128 			if ( !_rDescriptor.xDriver.is() )
129 				// we did not load this driver, yet
130 				if ( _rDescriptor.xComponentFactory.is() )
131 					// we have a factory for it
132 					const_cast< DriverAccess& >( _rDescriptor ).xDriver = _rDescriptor.xDriver.query( _rDescriptor.xComponentFactory->createInstance() );
133 			return _rDescriptor;
134 		}
135 	};
136 
137 	//---------------------------------------------------------------------
138 	//--- 24.08.01 11:28:04 -----------------------------------------------
139 
140 	/// an STL functor which extracts a SdbcDriver from a DriverAccess
141 	struct ExtractDriverFromAccess : public ::std::unary_function< DriverAccess, SdbcDriver >
142 	{
143 		SdbcDriver operator()( const DriverAccess& _rAccess ) const
144 		{
145 			return _rAccess.xDriver;
146 		}
147 	};
148 
149 	//---------------------------------------------------------------------
150 	//--- 24.08.01 12:37:50 -----------------------------------------------
151 
152 	typedef ::std::unary_compose< ExtractDriverFromAccess, EnsureDriver > ExtractAfterLoad_BASE;
153 	/// an STL functor which loads a driver described by a DriverAccess, and extracts the SdbcDriver
154 	struct ExtractAfterLoad : public ExtractAfterLoad_BASE
155 	{
156 		ExtractAfterLoad() : ExtractAfterLoad_BASE( ExtractDriverFromAccess(), EnsureDriver() ) { }
157 	};
158 
159 	//---------------------------------------------------------------------
160 	//--- 24.08.01 11:42:36 -----------------------------------------------
161 
162 	struct ExtractDriverFromCollectionElement : public ::std::unary_function< DriverCollection::value_type, SdbcDriver >
163 	{
164 		SdbcDriver operator()( const DriverCollection::value_type& _rElement ) const
165 		{
166 			return _rElement.second;
167 		}
168 	};
169 
170 	//---------------------------------------------------------------------
171 	//--- 24.08.01 11:51:03 -----------------------------------------------
172 
173 	// predicate for checking whether or not a driver accepts a given URL
174 	class AcceptsURL : public ::std::unary_function< SdbcDriver, bool >
175 	{
176 	protected:
177 		const ::rtl::OUString& m_rURL;
178 
179 	public:
180 		// ctor
181 		AcceptsURL( const ::rtl::OUString& _rURL ) : m_rURL( _rURL ) { }
182 
183 		//.................................................................
184 		bool operator()( const SdbcDriver& _rDriver ) const
185 		{
186 			// ask the driver
187 			if ( _rDriver.is() && _rDriver->acceptsURL( m_rURL ) )
188 				return true;
189 
190 			// does not accept ...
191 			return false;
192 		}
193 	};
194 
195 	//---------------------------------------------------------------------
196 	//--- 24.08.01 12:51:54 -----------------------------------------------
197 
198     static sal_Int32 lcl_getDriverPrecedence( const ::comphelper::ComponentContext& _rContext, Sequence< ::rtl::OUString >& _rPrecedence )
199 	{
200 		_rPrecedence.realloc( 0 );
201 		try
202 		{
203 			// some strings we need
204 			const ::rtl::OUString sConfigurationProviderServiceName =
205 				::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
206 			const ::rtl::OUString sDriverManagerConfigLocation =
207 				::rtl::OUString::createFromAscii("org.openoffice.Office.DataAccess/DriverManager");
208 			const ::rtl::OUString sDriverPreferenceLocation =
209 				::rtl::OUString::createFromAscii("DriverPrecedence");
210 			const ::rtl::OUString sNodePathArgumentName =
211 				::rtl::OUString::createFromAscii("nodepath");
212 			const ::rtl::OUString sNodeAccessServiceName =
213 				::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
214 
215 			// create a configuration provider
216 			Reference< XMultiServiceFactory > xConfigurationProvider;
217             if ( !_rContext.createComponent( sConfigurationProviderServiceName, xConfigurationProvider ) )
218                 throw ServiceNotRegisteredException( sConfigurationProviderServiceName, NULL );
219 
220             // one argument for creating the node access: the path to the configuration node
221 			Sequence< Any > aCreationArgs(1);
222 			aCreationArgs[0] <<= NamedValue( sNodePathArgumentName, makeAny( sDriverManagerConfigLocation ) );
223 
224 			// create the node access
225 			Reference< XNameAccess > xDriverManagerNode(xConfigurationProvider->createInstanceWithArguments(sNodeAccessServiceName, aCreationArgs), UNO_QUERY);
226 
227 			OSL_ENSURE(xDriverManagerNode.is(), "lcl_getDriverPrecedence: could not open my configuration node!");
228 			if (xDriverManagerNode.is())
229 			{
230 				// obtain the preference list
231 				Any aPreferences = xDriverManagerNode->getByName(sDriverPreferenceLocation);
232 #if OSL_DEBUG_LEVEL > 0
233 				sal_Bool bSuccess =
234 #endif
235 				aPreferences >>= _rPrecedence;
236 				OSL_ENSURE(bSuccess || !aPreferences.hasValue(), "lcl_getDriverPrecedence: invalid value for the preferences node (no string sequence but not NULL)!");
237 			}
238 		}
239 		catch( const Exception& )
240 		{
241             DBG_UNHANDLED_EXCEPTION();
242 		}
243 
244 		return _rPrecedence.getLength();
245 	}
246 
247 	//---------------------------------------------------------------------
248 	//--- 24.08.01 13:01:56 -----------------------------------------------
249 
250 	/// an STL argorithm compatible predicate comparing two DriverAccess instances by their implementation names
251 	struct CompareDriverAccessByName : public ::std::binary_function< DriverAccess, DriverAccess, bool >
252 	{
253 		//.................................................................
254 		bool operator()( const DriverAccess& lhs, const DriverAccess& rhs )
255 		{
256 			return lhs.sImplementationName < rhs.sImplementationName ? true : false;
257 		}
258 	};
259 
260 	//---------------------------------------------------------------------
261 	//--- 24.08.01 13:08:17 -----------------------------------------------
262 
263 	/// and STL argorithm compatible predicate comparing a DriverAccess' impl name to a string
264 	struct CompareDriverAccessToName : public ::std::binary_function< DriverAccess, ::rtl::OUString, bool >
265 	{
266 		//.................................................................
267 		bool operator()( const DriverAccess& lhs, const ::rtl::OUString& rhs )
268 		{
269 			return lhs.sImplementationName < rhs ? true : false;
270 		}
271 		//.................................................................
272 		bool operator()( const ::rtl::OUString& lhs, const DriverAccess& rhs )
273 		{
274 			return lhs < rhs.sImplementationName ? true : false;
275 		}
276 	};
277 
278     /// and STL argorithm compatible predicate comparing a DriverAccess' impl name to a string
279 	struct EqualDriverAccessToName : public ::std::binary_function< DriverAccess, ::rtl::OUString, bool >
280 	{
281         ::rtl::OUString m_sImplName;
282         EqualDriverAccessToName(const ::rtl::OUString& _sImplName) : m_sImplName(_sImplName){}
283 		//.................................................................
284 		bool operator()( const DriverAccess& lhs)
285 		{
286 			return lhs.sImplementationName.equals(m_sImplName);
287 		}
288     };
289 
290 //==========================================================================
291 //= OSDBCDriverManager
292 //==========================================================================
293 //--------------------------------------------------------------------------
294 OSDBCDriverManager::OSDBCDriverManager( const Reference< XComponentContext >& _rxContext )
295 	:m_aContext( _rxContext )
296     ,m_aEventLogger( _rxContext, "org.openoffice.logging.sdbc.DriverManager" )
297     ,m_aDriverConfig(m_aContext.getLegacyServiceFactory())
298 	,m_nLoginTimeout(0)
299 {
300 	// bootstrap all objects supporting the .sdb.Driver service
301 	bootstrapDrivers();
302 
303 	// initialize the drivers order
304 	initializeDriverPrecedence();
305 }
306 
307 //---------------------------------------------------------------------
308 OSDBCDriverManager::~OSDBCDriverManager()
309 {
310 }
311 
312 //---------------------------------------------------------------------
313 //--- 24.08.01 11:15:32 -----------------------------------------------
314 
315 void OSDBCDriverManager::bootstrapDrivers()
316 {
317 	Reference< XContentEnumerationAccess > xEnumAccess( m_aContext.getLegacyServiceFactory(), UNO_QUERY );
318 	Reference< XEnumeration > xEnumDrivers;
319 	if (xEnumAccess.is())
320 		xEnumDrivers = xEnumAccess->createContentEnumeration(SERVICE_SDBC_DRIVER);
321 
322 	OSL_ENSURE( xEnumDrivers.is(), "OSDBCDriverManager::bootstrapDrivers: no enumeration for the drivers available!" );
323 	if (xEnumDrivers.is())
324 	{
325 		Reference< XSingleServiceFactory > xFactory;
326 		Reference< XServiceInfo > xSI;
327 		while (xEnumDrivers->hasMoreElements())
328 		{
329 			::cppu::extractInterface( xFactory, xEnumDrivers->nextElement() );
330 			OSL_ENSURE( xFactory.is(), "OSDBCDriverManager::bootstrapDrivers: no factory extracted" );
331 
332 			if ( xFactory.is() )
333 			{
334 				// we got a factory for the driver
335 				DriverAccess aDriverDescriptor;
336 				sal_Bool bValidDescriptor = sal_False;
337 
338 				// can it tell us something about the implementation name?
339 				xSI = xSI.query( xFactory );
340 				if ( xSI.is() )
341 				{	// yes -> no need to load the driver immediately (load it later when needed)
342 					aDriverDescriptor.sImplementationName = xSI->getImplementationName();
343 					aDriverDescriptor.xComponentFactory = xFactory;
344 					bValidDescriptor = sal_True;
345 
346                     m_aEventLogger.log( LogLevel::CONFIG,
347                         "found SDBC driver $1$, no need to load it",
348                         aDriverDescriptor.sImplementationName
349                     );
350 				}
351 				else
352 				{
353 					// no -> create the driver
354 					Reference< XDriver > xDriver( xFactory->createInstance(), UNO_QUERY );
355 					OSL_ENSURE( xDriver.is(), "OSDBCDriverManager::bootstrapDrivers: a driver which is no driver?!" );
356 
357 					if ( xDriver.is() )
358 					{
359 						aDriverDescriptor.xDriver = xDriver;
360 						// and obtain it's implementation name
361 						xSI = xSI.query( xDriver );
362 						OSL_ENSURE( xSI.is(), "OSDBCDriverManager::bootstrapDrivers: a driver without service info?" );
363 						if ( xSI.is() )
364 						{
365 							aDriverDescriptor.sImplementationName = xSI->getImplementationName();
366 							bValidDescriptor = sal_True;
367 
368                             m_aEventLogger.log( LogLevel::CONFIG,
369                                 "found SDBC driver $1$, needed to load it",
370                                 aDriverDescriptor.sImplementationName
371                             );
372 						}
373 					}
374 				}
375 
376 				if ( bValidDescriptor )
377 				{
378 					m_aDriversBS.push_back( aDriverDescriptor );
379 				}
380 			}
381 		}
382 	}
383 }
384 
385 //--------------------------------------------------------------------------
386 void OSDBCDriverManager::initializeDriverPrecedence()
387 {
388 	if ( m_aDriversBS.empty() )
389 		// nothing to do
390 		return;
391 
392 	try
393 	{
394 		// get the precedence of the drivers from the configuration
395 		Sequence< ::rtl::OUString > aDriverOrder;
396 		if ( 0 == lcl_getDriverPrecedence( m_aContext, aDriverOrder ) )
397 			// nothing to do
398 			return;
399 
400 		// aDriverOrder now is the list of driver implementation names in the order they should be used
401 
402         if ( m_aEventLogger.isLoggable( LogLevel::CONFIG ) )
403         {
404             sal_Int32 nOrderedCount = aDriverOrder.getLength();
405             for ( sal_Int32 i=0; i<nOrderedCount; ++i )
406             m_aEventLogger.log( LogLevel::CONFIG,
407                 "configuration's driver order: driver $1$ of $2$: $3$",
408                 (sal_Int32)(i + 1), nOrderedCount, aDriverOrder[i]
409             );
410         }
411 
412 		// sort our bootstrapped drivers
413 		::std::sort( m_aDriversBS.begin(), m_aDriversBS.end(), CompareDriverAccessByName() );
414 
415 		// loop through the names in the precedence order
416 		const ::rtl::OUString* pDriverOrder		=					aDriverOrder.getConstArray();
417 		const ::rtl::OUString* pDriverOrderEnd	=	pDriverOrder +	aDriverOrder.getLength();
418 
419 		// the first driver for which there is no preference
420 		DriverAccessArrayIterator aNoPrefDriversStart = m_aDriversBS.begin();
421 			// at the moment this is the first of all drivers we know
422 
423 		for ( ; ( pDriverOrder < pDriverOrderEnd ) && ( aNoPrefDriversStart != m_aDriversBS.end() ); ++pDriverOrder )
424 		{
425 			// look for the impl name in the DriverAccess array
426 			::std::pair< DriverAccessArrayIterator, DriverAccessArrayIterator > aPos =
427 				::std::equal_range( aNoPrefDriversStart, m_aDriversBS.end(), *pDriverOrder, CompareDriverAccessToName() );
428 
429 			if ( aPos.first != aPos.second )
430 			{	// we have a DriverAccess with this impl name
431 
432 				OSL_ENSURE( ::std::distance( aPos.first, aPos.second ) == 1,
433 					"OSDBCDriverManager::initializeDriverPrecedence: more than one driver with this impl name? How this?" );
434 				// move the DriverAccess pointed to by aPos.first to the position pointed to by aNoPrefDriversStart
435 
436 				if ( aPos.first != aNoPrefDriversStart )
437 				{	// if this does not hold, the DriverAccess alread has the correct position
438 
439 					// rotate the range [aNoPrefDriversStart, aPos.second) right 1 element
440 					::std::rotate( aNoPrefDriversStart, aPos.second - 1, aPos.second );
441 				}
442 
443 				// next round we start searching and pos right
444 				++aNoPrefDriversStart;
445 			}
446 		}
447 	}
448 	catch (Exception&)
449 	{
450 		OSL_ENSURE(sal_False, "OSDBCDriverManager::initializeDriverPrecedence: caught an exception while sorting the drivers!");
451 	}
452 }
453 
454 //--------------------------------------------------------------------------
455 Reference< XConnection > SAL_CALL OSDBCDriverManager::getConnection( const ::rtl::OUString& _rURL ) throw(SQLException, RuntimeException)
456 {
457 	MutexGuard aGuard(m_aMutex);
458 
459     m_aEventLogger.log( LogLevel::INFO,
460         "connection requested for URL $1$",
461         _rURL
462     );
463 
464 	Reference< XConnection > xConnection;
465 	Reference< XDriver > xDriver = implGetDriverForURL(_rURL);
466 	if (xDriver.is())
467     {
468 		// TODO : handle the login timeout
469 		xConnection = xDriver->connect(_rURL, Sequence< PropertyValue >());
470 		// may throw an exception
471         m_aEventLogger.log( LogLevel::INFO,
472             "connection retrieved for URL $1$",
473             _rURL
474         );
475     }
476 
477 	return xConnection;
478 }
479 
480 //--------------------------------------------------------------------------
481 Reference< XConnection > SAL_CALL OSDBCDriverManager::getConnectionWithInfo( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rInfo ) throw(SQLException, RuntimeException)
482 {
483 	MutexGuard aGuard(m_aMutex);
484 
485     m_aEventLogger.log( LogLevel::INFO,
486         "connection with info requested for URL $1$",
487         _rURL
488     );
489 
490     Reference< XConnection > xConnection;
491 	Reference< XDriver > xDriver = implGetDriverForURL(_rURL);
492 	if (xDriver.is())
493     {
494 		// TODO : handle the login timeout
495 		xConnection = xDriver->connect(_rURL, _rInfo);
496 		// may throw an exception
497         m_aEventLogger.log( LogLevel::INFO,
498             "connection with info retrieved for URL $1$",
499             _rURL
500         );
501     }
502 
503 	return xConnection;
504 }
505 
506 //--------------------------------------------------------------------------
507 void SAL_CALL OSDBCDriverManager::setLoginTimeout( sal_Int32 seconds ) throw(RuntimeException)
508 {
509 	MutexGuard aGuard(m_aMutex);
510 	m_nLoginTimeout = seconds;
511 }
512 
513 //--------------------------------------------------------------------------
514 sal_Int32 SAL_CALL OSDBCDriverManager::getLoginTimeout(  ) throw(RuntimeException)
515 {
516 	MutexGuard aGuard(m_aMutex);
517 	return m_nLoginTimeout;
518 }
519 
520 //--------------------------------------------------------------------------
521 Reference< XEnumeration > SAL_CALL OSDBCDriverManager::createEnumeration(  ) throw(RuntimeException)
522 {
523 	MutexGuard aGuard(m_aMutex);
524 
525 	ODriverEnumeration::DriverArray aDrivers;
526 
527 	// ensure that all our bootstrapped drivers are insatntiated
528 	::std::for_each( m_aDriversBS.begin(), m_aDriversBS.end(), EnsureDriver() );
529 
530 	// copy the bootstrapped drivers
531 	::std::transform(
532 		m_aDriversBS.begin(),				// "copy from" start
533 		m_aDriversBS.end(),					// "copy from" end
534 		::std::back_inserter( aDrivers ),	// insert into
535 		ExtractDriverFromAccess()			// transformation to apply (extract a driver from a driver access)
536 	);
537 
538 	// append the runtime drivers
539 	::std::transform(
540 		m_aDriversRT.begin(),					// "copy from" start
541 		m_aDriversRT.end(),						// "copy from" end
542 		::std::back_inserter( aDrivers ),		// insert into
543 		ExtractDriverFromCollectionElement()	// transformation to apply (extract a driver from a driver access)
544 	);
545 
546 	return new ODriverEnumeration( aDrivers );
547 }
548 
549 //--------------------------------------------------------------------------
550 ::com::sun::star::uno::Type SAL_CALL OSDBCDriverManager::getElementType(  ) throw(::com::sun::star::uno::RuntimeException)
551 {
552 	return ::getCppuType(static_cast< Reference< XDriver >* >(NULL));
553 }
554 
555 //--------------------------------------------------------------------------
556 sal_Bool SAL_CALL OSDBCDriverManager::hasElements(  ) throw(::com::sun::star::uno::RuntimeException)
557 {
558 	MutexGuard aGuard(m_aMutex);
559 	return !(m_aDriversBS.empty() && m_aDriversRT.empty());
560 }
561 
562 //--------------------------------------------------------------------------
563 ::rtl::OUString SAL_CALL OSDBCDriverManager::getImplementationName(  ) throw(RuntimeException)
564 {
565 	return getImplementationName_static();
566 }
567 
568 //--------------------------------------------------------------------------
569 sal_Bool SAL_CALL OSDBCDriverManager::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
570 {
571 	Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
572 	const ::rtl::OUString* pSupported = aSupported.getConstArray();
573 	const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
574 	for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
575 		;
576 
577 	return pSupported != pEnd;
578 }
579 
580 //--------------------------------------------------------------------------
581 Sequence< ::rtl::OUString > SAL_CALL OSDBCDriverManager::getSupportedServiceNames(  ) throw(RuntimeException)
582 {
583 	return getSupportedServiceNames_static();
584 }
585 
586 //--------------------------------------------------------------------------
587 Reference< XInterface > SAL_CALL OSDBCDriverManager::Create( const Reference< XMultiServiceFactory >& _rxFactory )
588 {
589     ::comphelper::ComponentContext aContext( _rxFactory );
590     return *( new OSDBCDriverManager( aContext.getUNOContext() ) );
591 }
592 
593 //--------------------------------------------------------------------------
594 ::rtl::OUString SAL_CALL OSDBCDriverManager::getImplementationName_static(  ) throw(RuntimeException)
595 {
596 	return ::rtl::OUString::createFromAscii("com.sun.star.comp.sdbc.OSDBCDriverManager");
597 }
598 
599 //--------------------------------------------------------------------------
600 Sequence< ::rtl::OUString > SAL_CALL OSDBCDriverManager::getSupportedServiceNames_static(  ) throw(RuntimeException)
601 {
602 	Sequence< ::rtl::OUString > aSupported(1);
603 	aSupported[0] = getSingletonName_static();
604 	return aSupported;
605 }
606 
607 //--------------------------------------------------------------------------
608 ::rtl::OUString SAL_CALL OSDBCDriverManager::getSingletonName_static(  ) throw(RuntimeException)
609 {
610     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdbc.DriverManager" ) );
611 }
612 
613 //--------------------------------------------------------------------------
614 Reference< XInterface > SAL_CALL OSDBCDriverManager::getRegisteredObject( const ::rtl::OUString& _rName ) throw(Exception, RuntimeException)
615 {
616 	MutexGuard aGuard(m_aMutex);
617 	ConstDriverCollectionIterator aSearch = m_aDriversRT.find(_rName);
618 	if (aSearch == m_aDriversRT.end())
619 		throwNoSuchElementException();
620 
621 	return aSearch->second.get();
622 }
623 
624 //--------------------------------------------------------------------------
625 void SAL_CALL OSDBCDriverManager::registerObject( const ::rtl::OUString& _rName, const Reference< XInterface >& _rxObject ) throw(Exception, RuntimeException)
626 {
627     MutexGuard aGuard(m_aMutex);
628 
629     m_aEventLogger.log( LogLevel::INFO,
630         "attempt to register new driver for name $1$",
631         _rName
632     );
633 
634 	ConstDriverCollectionIterator aSearch = m_aDriversRT.find(_rName);
635 	if (aSearch == m_aDriversRT.end())
636 	{
637 		Reference< XDriver > xNewDriver(_rxObject, UNO_QUERY);
638 		if (xNewDriver.is())
639 			m_aDriversRT.insert(DriverCollection::value_type(_rName, xNewDriver));
640 		else
641 			throw IllegalArgumentException();
642 	}
643 	else
644 		throw ElementExistException();
645 
646     m_aEventLogger.log( LogLevel::INFO,
647         "new driver registered for name $1$",
648         _rName
649     );
650 }
651 
652 //--------------------------------------------------------------------------
653 void SAL_CALL OSDBCDriverManager::revokeObject( const ::rtl::OUString& _rName ) throw(Exception, RuntimeException)
654 {
655 	MutexGuard aGuard(m_aMutex);
656 
657     m_aEventLogger.log( LogLevel::INFO,
658         "attempt to revoke driver for name $1$",
659         _rName
660     );
661 
662     DriverCollectionIterator aSearch = m_aDriversRT.find(_rName);
663 	if (aSearch == m_aDriversRT.end())
664 		throwNoSuchElementException();
665 
666 	m_aDriversRT.erase(aSearch); // we already have the iterator so we could use it
667 
668     m_aEventLogger.log( LogLevel::INFO,
669         "driver revoked for name $1$",
670         _rName
671     );
672 }
673 
674 //--------------------------------------------------------------------------
675 Reference< XDriver > SAL_CALL OSDBCDriverManager::getDriverByURL( const ::rtl::OUString& _rURL ) throw(RuntimeException)
676 {
677     m_aEventLogger.log( LogLevel::INFO,
678         "driver requested for URL $1$",
679         _rURL
680     );
681 
682     Reference< XDriver > xDriver( implGetDriverForURL( _rURL ) );
683 
684     if ( xDriver.is() )
685         m_aEventLogger.log( LogLevel::INFO,
686             "driver obtained for URL $1$",
687             _rURL
688         );
689 
690     return xDriver;
691 }
692 
693 //--------------------------------------------------------------------------
694 Reference< XDriver > OSDBCDriverManager::implGetDriverForURL(const ::rtl::OUString& _rURL)
695 {
696 	Reference< XDriver > xReturn;
697 
698 	{
699         const ::rtl::OUString sDriverFactoryName = m_aDriverConfig.getDriverFactoryName(_rURL);
700 
701         EqualDriverAccessToName aEqual(sDriverFactoryName);
702         DriverAccessArray::iterator aFind = ::std::find_if(m_aDriversBS.begin(),m_aDriversBS.end(),aEqual);
703         if ( aFind == m_aDriversBS.end() )
704         {
705 		    // search all bootstrapped drivers
706 		    aFind = ::std::find_if(
707 			    m_aDriversBS.begin(),		// begin of search range
708 			    m_aDriversBS.end(),			// end of search range
709 			    std::unary_compose< AcceptsURL, ExtractAfterLoad >( AcceptsURL( _rURL ), ExtractAfterLoad() )
710 										    // compose two functors: extract the driver from the access, then ask the resulting driver for acceptance
711 		    );
712         } // if ( m_aDriversBS.find(sDriverFactoryName ) == m_aDriversBS.end() )
713         else
714         {
715             EnsureDriver aEnsure;
716             aEnsure(*aFind);
717         }
718 
719 		// found something?
720 		if ( m_aDriversBS.end() != aFind && aFind->xDriver.is() && aFind->xDriver->acceptsURL(_rURL) )
721 			xReturn = aFind->xDriver;
722 	}
723 
724 	if ( !xReturn.is() )
725 	{
726 		// no -> search the runtime drivers
727 		DriverCollectionIterator aPos = ::std::find_if(
728 			m_aDriversRT.begin(),		// begin of search range
729 			m_aDriversRT.end(),			// end of search range
730 			std::unary_compose< AcceptsURL, ExtractDriverFromCollectionElement >( AcceptsURL( _rURL ), ExtractDriverFromCollectionElement() )
731 										// compose two functors: extract the driver from the access, then ask the resulting driver for acceptance
732 		);
733 
734 		if ( m_aDriversRT.end() != aPos )
735 			xReturn = aPos->second;
736 	}
737 
738 	return xReturn;
739 }
740 
741 }	// namespace drivermanager
742