xref: /AOO41X/main/connectivity/source/manager/mdrivermanager.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
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