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