xref: /trunk/main/connectivity/source/manager/mdrivermanager.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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