Update ooo320-m1
[ooovba.git] / connectivity / source / drivers / mysql / YDriver.cxx
bloba9ed1c9c8dc735c842daeb07769cf35f51415083
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: YDriver.cxx,v $
10 * $Revision: 1.20.30.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "mysql/YDriver.hxx"
34 #include "mysql/YCatalog.hxx"
35 #include <osl/diagnose.h>
36 #include <comphelper/namedvaluecollection.hxx>
37 #include "connectivity/dbexception.hxx"
38 #include <connectivity/dbcharset.hxx>
39 #include <com/sun/star/sdbc/XDriverAccess.hpp>
40 #include "TConnection.hxx"
41 #include "resource/common_res.hrc"
42 #include "resource/sharedresources.hxx"
44 //........................................................................
45 namespace connectivity
47 //........................................................................
48 using namespace mysql;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::sdbc;
51 using namespace ::com::sun::star::sdbcx;
52 using namespace ::com::sun::star::beans;
53 using namespace ::com::sun::star::lang;
55 namespace mysql
57 Reference< XInterface > SAL_CALL ODriverDelegator_CreateInstance(const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFac) throw( Exception )
59 return *(new ODriverDelegator(_rxFac));
64 //====================================================================
65 //= ODriverDelegator
66 //====================================================================
67 //--------------------------------------------------------------------
68 ODriverDelegator::ODriverDelegator(const Reference< XMultiServiceFactory >& _rxFactory)
69 : ODriverDelegator_BASE(m_aMutex)
70 ,m_xFactory(_rxFactory)
71 ,m_eDriverType(D_ODBC)
75 //--------------------------------------------------------------------
76 ODriverDelegator::~ODriverDelegator()
78 try
80 ::comphelper::disposeComponent(m_xODBCDriver);
81 ::comphelper::disposeComponent(m_xNativeDriver);
82 TJDBCDrivers::iterator aIter = m_aJdbcDrivers.begin();
83 TJDBCDrivers::iterator aEnd = m_aJdbcDrivers.end();
84 for ( ;aIter != aEnd;++aIter )
85 ::comphelper::disposeComponent(aIter->second);
87 catch(const Exception&)
92 // --------------------------------------------------------------------------------
93 void ODriverDelegator::disposing()
95 ::osl::MutexGuard aGuard(m_aMutex);
98 for (TWeakPairVector::iterator i = m_aConnections.begin(); m_aConnections.end() != i; ++i)
100 Reference<XInterface > xTemp = i->first.get();
101 ::comphelper::disposeComponent(xTemp);
103 m_aConnections.clear();
104 TWeakPairVector().swap(m_aConnections);
106 ODriverDelegator_BASE::disposing();
109 namespace
111 sal_Bool isOdbcUrl(const ::rtl::OUString& _sUrl)
113 return _sUrl.copy(0,16).equalsAscii("sdbc:mysql:odbc:");
115 //--------------------------------------------------------------------
116 sal_Bool isNativeUrl(const ::rtl::OUString& _sUrl)
118 return (!_sUrl.compareTo(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:mysql:mysqlc:")), sizeof("sdbc:mysql:mysqlc:")-1));
120 //--------------------------------------------------------------------
121 T_DRIVERTYPE lcl_getDriverType(const ::rtl::OUString& _sUrl)
123 T_DRIVERTYPE eRet = D_JDBC;
124 if ( isOdbcUrl(_sUrl ) )
125 eRet = D_ODBC;
126 else if ( isNativeUrl(_sUrl ) )
127 eRet = D_NATIVE;
128 return eRet;
130 //--------------------------------------------------------------------
131 ::rtl::OUString transformUrl(const ::rtl::OUString& _sUrl)
133 ::rtl::OUString sNewUrl = _sUrl.copy(11);
134 if ( isOdbcUrl( _sUrl ) )
135 sNewUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:")) + sNewUrl;
136 else if ( isNativeUrl( _sUrl ) )
137 sNewUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:")) + sNewUrl;
138 else
140 sNewUrl = sNewUrl.copy(5);
142 ::rtl::OUString sTempUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jdbc:mysql://"));
144 sTempUrl += sNewUrl;
145 sNewUrl = sTempUrl;
147 return sNewUrl;
149 //--------------------------------------------------------------------
150 Reference< XDriver > lcl_loadDriver(const Reference< XMultiServiceFactory >& _rxFactory,const ::rtl::OUString& _sUrl)
152 Reference<XDriverAccess> xDriverAccess(_rxFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdbc.DriverManager")) ),UNO_QUERY);
153 OSL_ENSURE(xDriverAccess.is(),"Could not load driver manager!");
154 Reference< XDriver > xDriver;
155 if ( xDriverAccess.is() )
156 xDriver = xDriverAccess->getDriverByURL(_sUrl);
157 return xDriver;
159 //--------------------------------------------------------------------
160 Sequence< PropertyValue > lcl_convertProperties(T_DRIVERTYPE _eType,const Sequence< PropertyValue >& info,const ::rtl::OUString& _sUrl)
162 ::std::vector<PropertyValue> aProps;
163 const PropertyValue* pSupported = info.getConstArray();
164 const PropertyValue* pEnd = pSupported + info.getLength();
166 aProps.reserve(info.getLength() + 5);
167 for (;pSupported != pEnd; ++pSupported)
169 aProps.push_back( *pSupported );
172 if ( _eType == D_ODBC )
174 aProps.push_back( PropertyValue(
175 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Silent"))
177 ,makeAny(sal_True)
178 ,PropertyState_DIRECT_VALUE) );
179 aProps.push_back( PropertyValue(
180 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PreventGetVersionColumns"))
182 ,makeAny(sal_True)
183 ,PropertyState_DIRECT_VALUE) );
185 else if ( _eType == D_JDBC )
187 aProps.push_back( PropertyValue(
188 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass"))
190 ,makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver")))
191 ,PropertyState_DIRECT_VALUE) );
193 else
195 aProps.push_back( PropertyValue(
196 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PublicConnectionURL"))
198 ,makeAny(_sUrl)
199 ,PropertyState_DIRECT_VALUE) );
201 aProps.push_back( PropertyValue(
202 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsAutoRetrievingEnabled"))
204 ,makeAny(sal_True)
205 ,PropertyState_DIRECT_VALUE) );
206 aProps.push_back( PropertyValue(
207 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AutoRetrievingStatement"))
209 ,makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT LAST_INSERT_ID()")))
210 ,PropertyState_DIRECT_VALUE) );
211 aProps.push_back( PropertyValue(
212 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParameterNameSubstitution"))
214 ,makeAny(sal_True)
215 ,PropertyState_DIRECT_VALUE) );
216 PropertyValue* pProps = aProps.empty() ? 0 : &aProps[0];
217 return Sequence< PropertyValue >(pProps, aProps.size());
220 //--------------------------------------------------------------------
221 Reference< XDriver > ODriverDelegator::loadDriver( const ::rtl::OUString& url, const Sequence< PropertyValue >& info )
223 Reference< XDriver > xDriver;
224 const ::rtl::OUString sCuttedUrl = transformUrl(url);
225 const T_DRIVERTYPE eType = lcl_getDriverType( url );
226 if ( eType == D_ODBC )
228 if ( !m_xODBCDriver.is() )
229 m_xODBCDriver = lcl_loadDriver(m_xFactory,sCuttedUrl);
230 xDriver = m_xODBCDriver;
231 } // if ( bIsODBC )
232 else if ( eType == D_NATIVE )
234 if ( !m_xNativeDriver.is() )
235 m_xNativeDriver = lcl_loadDriver(m_xFactory,sCuttedUrl);
236 xDriver = m_xNativeDriver;
238 else
240 ::comphelper::NamedValueCollection aSettings( info );
241 ::rtl::OUString sDriverClass(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver"));
242 sDriverClass = aSettings.getOrDefault( "JavaDriverClass", sDriverClass );
244 TJDBCDrivers::iterator aFind = m_aJdbcDrivers.find(sDriverClass);
245 if ( aFind == m_aJdbcDrivers.end() )
246 aFind = m_aJdbcDrivers.insert(TJDBCDrivers::value_type(sDriverClass,lcl_loadDriver(m_xFactory,sCuttedUrl))).first;
247 xDriver = aFind->second;
250 return xDriver;
253 //--------------------------------------------------------------------
254 Reference< XConnection > SAL_CALL ODriverDelegator::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException)
256 Reference< XConnection > xConnection;
257 if ( acceptsURL(url) )
259 Reference< XDriver > xDriver;
260 xDriver = loadDriver(url,info);
261 if ( xDriver.is() )
263 ::rtl::OUString sCuttedUrl = transformUrl(url);
264 const T_DRIVERTYPE eType = lcl_getDriverType( url );
265 Sequence< PropertyValue > aConvertedProperties = lcl_convertProperties(eType,info,url);
266 if ( eType == D_JDBC )
268 ::comphelper::NamedValueCollection aSettings( info );
269 ::rtl::OUString sIanaName = aSettings.getOrDefault( "CharSet", ::rtl::OUString() );
270 if ( sIanaName.getLength() )
272 ::dbtools::OCharsetMap aLookupIanaName;
273 ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
274 if (aLookup != aLookupIanaName.end() )
276 ::rtl::OUString sAdd;
277 if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
279 static const ::rtl::OUString s_sCharSetOp(RTL_CONSTASCII_USTRINGPARAM("useUnicode=true&"));
280 if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
282 sAdd = s_sCharSetOp;
283 } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
284 } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
285 if ( sCuttedUrl.indexOf('?') == -1 )
286 sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("?"));
287 else
288 sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("&"));
289 sCuttedUrl += sAdd;
290 sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("characterEncoding="));
291 sCuttedUrl += sIanaName;
294 } // if ( !bIsODBC )
296 xConnection = xDriver->connect( sCuttedUrl, aConvertedProperties );
297 if ( xConnection.is() )
299 OMetaConnection* pMetaConnection = NULL;
300 // now we have to set the URL to get the correct answer for metadata()->getURL()
301 Reference< XUnoTunnel> xTunnel(xConnection,UNO_QUERY);
302 if ( xTunnel.is() )
304 pMetaConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
305 if ( pMetaConnection )
306 pMetaConnection->setURL(url);
308 m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xConnection),TWeakConnectionPair(WeakReferenceHelper(),pMetaConnection)));
312 return xConnection;
315 //--------------------------------------------------------------------
316 sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const ::rtl::OUString& url ) throw (SQLException, RuntimeException)
318 Sequence< PropertyValue > info;
320 sal_Bool bOK = url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:odbc:" ) )
321 || url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:jdbc:" ) )
322 || ( url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc:" ) )
323 && loadDriver( url, info ).is()
325 return bOK;
328 //--------------------------------------------------------------------
329 Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const ::rtl::OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, RuntimeException)
331 ::std::vector< DriverPropertyInfo > aDriverInfo;
332 if ( !acceptsURL(url) )
333 return Sequence< DriverPropertyInfo >();
335 Sequence< ::rtl::OUString > aBoolean(2);
336 aBoolean[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0"));
337 aBoolean[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("1"));
340 aDriverInfo.push_back(DriverPropertyInfo(
341 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet"))
342 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet of the database."))
343 ,sal_False
344 ,::rtl::OUString()
345 ,Sequence< ::rtl::OUString >())
347 aDriverInfo.push_back(DriverPropertyInfo(
348 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SuppressVersionColumns"))
349 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Display version columns (when available)."))
350 ,sal_False
351 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0"))
352 ,aBoolean)
354 const T_DRIVERTYPE eType = lcl_getDriverType( url );
355 if ( eType == D_JDBC )
357 aDriverInfo.push_back(DriverPropertyInfo(
358 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass"))
359 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("The JDBC driver class name."))
360 ,sal_True
361 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver"))
362 ,Sequence< ::rtl::OUString >())
366 return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size());
369 //--------------------------------------------------------------------
370 sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion( ) throw (RuntimeException)
372 return 1;
375 //--------------------------------------------------------------------
376 sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion( ) throw (RuntimeException)
378 return 0;
381 //--------------------------------------------------------------------
382 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException)
384 ::osl::MutexGuard aGuard( m_aMutex );
385 checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed);
387 Reference< XTablesSupplier > xTab;
388 Reference< XUnoTunnel> xTunnel(connection,UNO_QUERY);
389 if ( xTunnel.is() )
391 OMetaConnection* pConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
392 if ( pConnection )
394 TWeakPairVector::iterator aEnd = m_aConnections.end();
395 for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
397 if ( i->second.second == pConnection )
399 xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY);
400 if ( !xTab.is() )
402 xTab = new OMySQLCatalog(connection);
403 i->second.first = WeakReferenceHelper(xTab);
405 break;
409 } // if ( xTunnel.is() )
410 if ( !xTab.is() )
412 TWeakPairVector::iterator aEnd = m_aConnections.end();
413 for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
415 Reference< XConnection > xTemp(i->first.get(),UNO_QUERY);
416 if ( xTemp == connection )
418 xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY);
419 if ( !xTab.is() )
421 xTab = new OMySQLCatalog(connection);
422 i->second.first = WeakReferenceHelper(xTab);
424 break;
428 return xTab;
431 //--------------------------------------------------------------------
432 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException)
434 if ( ! acceptsURL(url) )
436 ::connectivity::SharedResources aResources;
437 const ::rtl::OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
438 ::dbtools::throwGenericSQLException(sMessage ,*this);
439 } // if ( ! acceptsURL(url) )
441 return getDataDefinitionByConnection(connect(url,info));
444 // XServiceInfo
445 // --------------------------------------------------------------------------------
446 //------------------------------------------------------------------------------
447 rtl::OUString ODriverDelegator::getImplementationName_Static( ) throw(RuntimeException)
449 return rtl::OUString::createFromAscii("org.openoffice.comp.drivers.MySQL.Driver");
451 //------------------------------------------------------------------------------
452 Sequence< ::rtl::OUString > ODriverDelegator::getSupportedServiceNames_Static( ) throw (RuntimeException)
454 Sequence< ::rtl::OUString > aSNS( 2 );
455 aSNS[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.Driver");
456 aSNS[1] = ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.Driver");
457 return aSNS;
459 //------------------------------------------------------------------
460 ::rtl::OUString SAL_CALL ODriverDelegator::getImplementationName( ) throw(RuntimeException)
462 return getImplementationName_Static();
465 //------------------------------------------------------------------
466 sal_Bool SAL_CALL ODriverDelegator::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
468 Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
469 const ::rtl::OUString* pSupported = aSupported.getConstArray();
470 const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
471 for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
474 return pSupported != pEnd;
476 //------------------------------------------------------------------
477 Sequence< ::rtl::OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames( ) throw(RuntimeException)
479 return getSupportedServiceNames_Static();
481 //------------------------------------------------------------------
482 //........................................................................
483 } // namespace connectivity
484 //........................................................................