xref: /AOO41X/main/connectivity/source/drivers/mysql/YDriver.cxx (revision e53e79e9d20c3d2633dddcf583557f0eb06dec67)
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 #include "mysql/YDriver.hxx"
27 #include "mysql/YCatalog.hxx"
28 #include <osl/diagnose.h>
29 #include <comphelper/namedvaluecollection.hxx>
30 #include "connectivity/dbexception.hxx"
31 #include <connectivity/dbcharset.hxx>
32 #include <com/sun/star/sdbc/XDriverAccess.hpp>
33 #include "TConnection.hxx"
34 #include "resource/common_res.hrc"
35 #include "resource/sharedresources.hxx"
36 
37 //........................................................................
38 namespace connectivity
39 {
40 //........................................................................
41     using namespace mysql;
42     using namespace ::com::sun::star::uno;
43     using namespace ::com::sun::star::sdbc;
44     using namespace ::com::sun::star::sdbcx;
45     using namespace ::com::sun::star::beans;
46     using namespace ::com::sun::star::lang;
47 
48     namespace mysql
49     {
ODriverDelegator_CreateInstance(const Reference<::com::sun::star::lang::XMultiServiceFactory> & _rxFac)50         Reference< XInterface >  SAL_CALL ODriverDelegator_CreateInstance(const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFac) throw( Exception )
51         {
52             return *(new ODriverDelegator(_rxFac));
53         }
54     }
55 
56 
57     //====================================================================
58     //= ODriverDelegator
59     //====================================================================
60     //--------------------------------------------------------------------
ODriverDelegator(const Reference<XMultiServiceFactory> & _rxFactory)61     ODriverDelegator::ODriverDelegator(const Reference< XMultiServiceFactory >& _rxFactory)
62         : ODriverDelegator_BASE(m_aMutex)
63         ,m_xFactory(_rxFactory)
64         ,m_eDriverType(D_ODBC)
65     {
66     }
67 
68     //--------------------------------------------------------------------
~ODriverDelegator()69     ODriverDelegator::~ODriverDelegator()
70     {
71         try
72         {
73             ::comphelper::disposeComponent(m_xODBCDriver);
74             ::comphelper::disposeComponent(m_xNativeDriver);
75             TJDBCDrivers::iterator aIter = m_aJdbcDrivers.begin();
76             TJDBCDrivers::iterator aEnd = m_aJdbcDrivers.end();
77             for ( ;aIter != aEnd;++aIter )
78                 ::comphelper::disposeComponent(aIter->second);
79         }
80         catch(const Exception&)
81         {
82         }
83     }
84 
85     // --------------------------------------------------------------------------------
disposing()86     void ODriverDelegator::disposing()
87     {
88         ::osl::MutexGuard aGuard(m_aMutex);
89 
90 
91         for (TWeakPairVector::iterator i = m_aConnections.begin(); m_aConnections.end() != i; ++i)
92         {
93             Reference<XInterface > xTemp = i->first.get();
94             ::comphelper::disposeComponent(xTemp);
95         }
96         m_aConnections.clear();
97         TWeakPairVector().swap(m_aConnections);
98 
99         ODriverDelegator_BASE::disposing();
100     }
101 
102     namespace
103     {
isOdbcUrl(const::rtl::OUString & _sUrl)104         sal_Bool isOdbcUrl(const ::rtl::OUString& _sUrl)
105         {
106             return _sUrl.copy(0,16).equalsAscii("sdbc:mysql:odbc:");
107         }
108         //--------------------------------------------------------------------
isNativeUrl(const::rtl::OUString & _sUrl)109         sal_Bool isNativeUrl(const ::rtl::OUString& _sUrl)
110         {
111             return (!_sUrl.compareTo(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:mysql:mysqlc:")), sizeof("sdbc:mysql:mysqlc:")-1));
112         }
113         //--------------------------------------------------------------------
lcl_getDriverType(const::rtl::OUString & _sUrl)114         T_DRIVERTYPE lcl_getDriverType(const ::rtl::OUString& _sUrl)
115         {
116             T_DRIVERTYPE eRet = D_JDBC;
117             if ( isOdbcUrl(_sUrl ) )
118                 eRet = D_ODBC;
119             else if ( isNativeUrl(_sUrl ) )
120                 eRet = D_NATIVE;
121             return eRet;
122         }
123         //--------------------------------------------------------------------
transformUrl(const::rtl::OUString & _sUrl)124         ::rtl::OUString transformUrl(const ::rtl::OUString& _sUrl)
125         {
126             ::rtl::OUString sNewUrl = _sUrl.copy(11);
127             if ( isOdbcUrl( _sUrl ) )
128                 sNewUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:")) + sNewUrl;
129             else if ( isNativeUrl( _sUrl ) )
130                 sNewUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:")) + sNewUrl;
131             else
132             {
133                 sNewUrl = sNewUrl.copy(5);
134 
135                 ::rtl::OUString sTempUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jdbc:mysql://"));
136 
137                 sTempUrl += sNewUrl;
138                 sNewUrl = sTempUrl;
139             }
140             return sNewUrl;
141         }
142         //--------------------------------------------------------------------
lcl_loadDriver(const Reference<XMultiServiceFactory> & _rxFactory,const::rtl::OUString & _sUrl)143         Reference< XDriver > lcl_loadDriver(const Reference< XMultiServiceFactory >& _rxFactory,const ::rtl::OUString& _sUrl)
144         {
145             Reference<XDriverAccess> xDriverAccess(_rxFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdbc.DriverManager")) ),UNO_QUERY);
146             OSL_ENSURE(xDriverAccess.is(),"Could not load driver manager!");
147             Reference< XDriver > xDriver;
148             if ( xDriverAccess.is() )
149                 xDriver = xDriverAccess->getDriverByURL(_sUrl);
150             return xDriver;
151         }
152         //--------------------------------------------------------------------
lcl_convertProperties(T_DRIVERTYPE _eType,const Sequence<PropertyValue> & info,const::rtl::OUString & _sUrl)153         Sequence< PropertyValue > lcl_convertProperties(T_DRIVERTYPE _eType,const Sequence< PropertyValue >& info,const ::rtl::OUString& _sUrl)
154         {
155             ::std::vector<PropertyValue> aProps;
156             const PropertyValue* pSupported = info.getConstArray();
157             const PropertyValue* pEnd = pSupported + info.getLength();
158 
159             aProps.reserve(info.getLength() + 5);
160             for (;pSupported != pEnd; ++pSupported)
161             {
162                 aProps.push_back( *pSupported );
163             }
164 
165             if ( _eType == D_ODBC )
166             {
167                 aProps.push_back( PropertyValue(
168                                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Silent"))
169                                     ,0
170                                     ,makeAny(sal_True)
171                                     ,PropertyState_DIRECT_VALUE) );
172                 aProps.push_back( PropertyValue(
173                                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PreventGetVersionColumns"))
174                                     ,0
175                                     ,makeAny(sal_True)
176                                     ,PropertyState_DIRECT_VALUE) );
177             }
178             else if ( _eType == D_JDBC )
179             {
180                 aProps.push_back( PropertyValue(
181                                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass"))
182                                     ,0
183                                     ,makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver")))
184                                     ,PropertyState_DIRECT_VALUE) );
185             }
186             else
187             {
188                 aProps.push_back( PropertyValue(
189                                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PublicConnectionURL"))
190                                     ,0
191                                     ,makeAny(_sUrl)
192                                     ,PropertyState_DIRECT_VALUE) );
193             }
194             aProps.push_back( PropertyValue(
195                                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsAutoRetrievingEnabled"))
196                                 ,0
197                                 ,makeAny(sal_True)
198                                 ,PropertyState_DIRECT_VALUE) );
199             aProps.push_back( PropertyValue(
200                                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AutoRetrievingStatement"))
201                                 ,0
202                                 ,makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT LAST_INSERT_ID()")))
203                                 ,PropertyState_DIRECT_VALUE) );
204             aProps.push_back( PropertyValue(
205                                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParameterNameSubstitution"))
206                                 ,0
207                                 ,makeAny(sal_True)
208                                 ,PropertyState_DIRECT_VALUE) );
209             PropertyValue* pProps = aProps.empty() ? 0 : &aProps[0];
210             return Sequence< PropertyValue >(pProps, aProps.size());
211         }
212     }
213     //--------------------------------------------------------------------
loadDriver(const::rtl::OUString & url,const Sequence<PropertyValue> & info)214     Reference< XDriver > ODriverDelegator::loadDriver( const ::rtl::OUString& url, const Sequence< PropertyValue >& info )
215     {
216         Reference< XDriver > xDriver;
217         const ::rtl::OUString sCuttedUrl = transformUrl(url);
218         const T_DRIVERTYPE eType = lcl_getDriverType( url );
219         if ( eType == D_ODBC )
220         {
221             if ( !m_xODBCDriver.is() )
222                 m_xODBCDriver = lcl_loadDriver(m_xFactory,sCuttedUrl);
223             xDriver = m_xODBCDriver;
224         } // if ( bIsODBC )
225         else if ( eType == D_NATIVE )
226         {
227             if ( !m_xNativeDriver.is() )
228                 m_xNativeDriver = lcl_loadDriver(m_xFactory,sCuttedUrl);
229             xDriver = m_xNativeDriver;
230         }
231         else
232         {
233             ::comphelper::NamedValueCollection aSettings( info );
234             ::rtl::OUString sDriverClass(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver"));
235             sDriverClass = aSettings.getOrDefault( "JavaDriverClass", sDriverClass );
236 
237             TJDBCDrivers::iterator aFind = m_aJdbcDrivers.find(sDriverClass);
238             if ( aFind == m_aJdbcDrivers.end() )
239                 aFind = m_aJdbcDrivers.insert(TJDBCDrivers::value_type(sDriverClass,lcl_loadDriver(m_xFactory,sCuttedUrl))).first;
240             xDriver = aFind->second;
241         }
242 
243         return xDriver;
244     }
245 
246     //--------------------------------------------------------------------
connect(const::rtl::OUString & url,const Sequence<PropertyValue> & info)247     Reference< XConnection > SAL_CALL ODriverDelegator::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException)
248     {
249         Reference< XConnection > xConnection;
250         if ( acceptsURL(url) )
251         {
252             Reference< XDriver > xDriver;
253             xDriver = loadDriver(url,info);
254             if ( xDriver.is() )
255             {
256                 ::rtl::OUString sCuttedUrl = transformUrl(url);
257                 const T_DRIVERTYPE eType = lcl_getDriverType( url );
258                 Sequence< PropertyValue > aConvertedProperties = lcl_convertProperties(eType,info,url);
259                 if ( eType == D_JDBC )
260                 {
261                     ::comphelper::NamedValueCollection aSettings( info );
262                     ::rtl::OUString sIanaName = aSettings.getOrDefault( "CharSet", ::rtl::OUString() );
263                     if ( sIanaName.getLength() )
264                     {
265                         ::dbtools::OCharsetMap aLookupIanaName;
266                         ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
267                         if (aLookup != aLookupIanaName.end() )
268                         {
269                             ::rtl::OUString sAdd;
270                             if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
271                             {
272                                 static const ::rtl::OUString s_sCharSetOp(RTL_CONSTASCII_USTRINGPARAM("useUnicode=true&"));
273                                 if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
274                                 {
275                                     sAdd = s_sCharSetOp;
276                                 } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
277                             } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
278                             if ( sCuttedUrl.indexOf('?') == -1 )
279                                 sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("?"));
280                             else
281                                 sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("&"));
282                             sCuttedUrl += sAdd;
283                             sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("characterEncoding="));
284                             sCuttedUrl += sIanaName;
285                         }
286                     }
287                 } // if ( !bIsODBC )
288 
289                 xConnection = xDriver->connect( sCuttedUrl, aConvertedProperties );
290                 if ( xConnection.is() )
291                 {
292                     OMetaConnection* pMetaConnection = NULL;
293                     // now we have to set the URL to get the correct answer for metadata()->getURL()
294                     Reference< XUnoTunnel> xTunnel(xConnection,UNO_QUERY);
295                     if ( xTunnel.is() )
296                     {
297                         pMetaConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
298                         if ( pMetaConnection )
299                             pMetaConnection->setURL(url);
300                     }
301                     m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xConnection),TWeakConnectionPair(WeakReferenceHelper(),pMetaConnection)));
302                 }
303             }
304         }
305         return xConnection;
306     }
307 
308     //--------------------------------------------------------------------
acceptsURL(const::rtl::OUString & url)309     sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const ::rtl::OUString& url ) throw (SQLException, RuntimeException)
310     {
311         Sequence< PropertyValue > info;
312 
313         sal_Bool bOK =  url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:odbc:" ) )
314                     ||  url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:jdbc:" ) )
315                     ||  (   url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc:" ) )
316                         &&  loadDriver( url, info ).is()
317                         );
318         return bOK;
319     }
320 
321     //--------------------------------------------------------------------
getPropertyInfo(const::rtl::OUString & url,const Sequence<PropertyValue> &)322     Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const ::rtl::OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, RuntimeException)
323     {
324         ::std::vector< DriverPropertyInfo > aDriverInfo;
325         if ( !acceptsURL(url) )
326             return Sequence< DriverPropertyInfo >();
327 
328         Sequence< ::rtl::OUString > aBoolean(2);
329         aBoolean[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0"));
330         aBoolean[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("1"));
331 
332 
333         aDriverInfo.push_back(DriverPropertyInfo(
334                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet"))
335                 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet of the database."))
336                 ,sal_False
337                 ,::rtl::OUString()
338                 ,Sequence< ::rtl::OUString >())
339                 );
340         aDriverInfo.push_back(DriverPropertyInfo(
341                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SuppressVersionColumns"))
342                 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Display version columns (when available)."))
343                 ,sal_False
344                 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0"))
345                 ,aBoolean)
346                 );
347         const T_DRIVERTYPE eType = lcl_getDriverType( url );
348         if ( eType == D_JDBC )
349         {
350             aDriverInfo.push_back(DriverPropertyInfo(
351                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass"))
352                     ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("The JDBC driver class name."))
353                     ,sal_True
354                     ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver"))
355                     ,Sequence< ::rtl::OUString >())
356                     );
357         }
358         else if ( eType == D_NATIVE )
359         {
360             aDriverInfo.push_back(DriverPropertyInfo(
361                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LocalSocket"))
362                     ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
363                         "The file path of a socket to connect to a local MySQL server."))
364                     ,sal_False
365                     ,::rtl::OUString()
366                     ,Sequence< ::rtl::OUString >())
367                     );
368             aDriverInfo.push_back(DriverPropertyInfo(
369                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NamedPipe"))
370                     ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
371                         "The name of a pipe to connect to a local MySQL server."))
372                     ,sal_False
373                     ,::rtl::OUString()
374                     ,Sequence< ::rtl::OUString >())
375                     );
376         }
377 
378         return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size());
379     }
380 
381     //--------------------------------------------------------------------
getMajorVersion()382     sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion(  ) throw (RuntimeException)
383     {
384         return 1;
385     }
386 
387     //--------------------------------------------------------------------
getMinorVersion()388     sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion(  ) throw (RuntimeException)
389     {
390         return 0;
391     }
392 
393     //--------------------------------------------------------------------
getDataDefinitionByConnection(const Reference<XConnection> & connection)394     Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException)
395     {
396         ::osl::MutexGuard aGuard( m_aMutex );
397         checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed);
398 
399         Reference< XTablesSupplier > xTab;
400         Reference< XUnoTunnel> xTunnel(connection,UNO_QUERY);
401         if ( xTunnel.is() )
402         {
403             OMetaConnection* pConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
404             if ( pConnection )
405             {
406                 TWeakPairVector::iterator aEnd = m_aConnections.end();
407                 for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
408                 {
409                     if ( i->second.second == pConnection )
410                     {
411                         xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY);
412                         if ( !xTab.is() )
413                         {
414                             xTab = new OMySQLCatalog(connection);
415                             i->second.first = WeakReferenceHelper(xTab);
416                         }
417                         break;
418                     }
419                 }
420             }
421         } // if ( xTunnel.is() )
422         if ( !xTab.is() )
423         {
424             TWeakPairVector::iterator aEnd = m_aConnections.end();
425             for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
426             {
427                 Reference< XConnection > xTemp(i->first.get(),UNO_QUERY);
428                 if ( xTemp == connection )
429                 {
430                     xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY);
431                     if ( !xTab.is() )
432                     {
433                         xTab = new OMySQLCatalog(connection);
434                         i->second.first = WeakReferenceHelper(xTab);
435                     }
436                     break;
437                 }
438             }
439         }
440         return xTab;
441     }
442 
443     //--------------------------------------------------------------------
getDataDefinitionByURL(const::rtl::OUString & url,const Sequence<PropertyValue> & info)444     Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException)
445     {
446         if ( ! acceptsURL(url) )
447         {
448             ::connectivity::SharedResources aResources;
449             const ::rtl::OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
450             ::dbtools::throwGenericSQLException(sMessage ,*this);
451         } // if ( ! acceptsURL(url) )
452 
453         return getDataDefinitionByConnection(connect(url,info));
454     }
455 
456     // XServiceInfo
457     // --------------------------------------------------------------------------------
458     //------------------------------------------------------------------------------
getImplementationName_Static()459     rtl::OUString ODriverDelegator::getImplementationName_Static(  ) throw(RuntimeException)
460     {
461         return rtl::OUString::createFromAscii("org.openoffice.comp.drivers.MySQL.Driver");
462     }
463     //------------------------------------------------------------------------------
getSupportedServiceNames_Static()464     Sequence< ::rtl::OUString > ODriverDelegator::getSupportedServiceNames_Static(  ) throw (RuntimeException)
465     {
466         Sequence< ::rtl::OUString > aSNS( 2 );
467         aSNS[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.Driver");
468         aSNS[1] = ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.Driver");
469         return aSNS;
470     }
471     //------------------------------------------------------------------
getImplementationName()472     ::rtl::OUString SAL_CALL ODriverDelegator::getImplementationName(  ) throw(RuntimeException)
473     {
474         return getImplementationName_Static();
475     }
476 
477     //------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)478     sal_Bool SAL_CALL ODriverDelegator::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
479     {
480         Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
481         const ::rtl::OUString* pSupported = aSupported.getConstArray();
482         const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
483         for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
484             ;
485 
486         return pSupported != pEnd;
487     }
488     //------------------------------------------------------------------
getSupportedServiceNames()489     Sequence< ::rtl::OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames(  ) throw(RuntimeException)
490     {
491         return getSupportedServiceNames_Static();
492     }
493     //------------------------------------------------------------------
494 //........................................................................
495 }   // namespace connectivity
496 //........................................................................
497