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