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