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