build fix
[LibreOffice.git] / connectivity / source / drivers / mysql / YDriver.cxx
blob3655fa4f5a3d4845cba2d86f0c5a01dd29df56f1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "mysql/YDriver.hxx"
21 #include "mysql/YCatalog.hxx"
22 #include <osl/diagnose.h>
23 #include <comphelper/namedvaluecollection.hxx>
24 #include <comphelper/processfactory.hxx>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <connectivity/dbexception.hxx>
27 #include <connectivity/dbcharset.hxx>
28 #include <com/sun/star/sdbc/DriverManager.hpp>
29 #include <com/sun/star/uno/XComponentContext.hpp>
30 #include "TConnection.hxx"
31 #include "resource/common_res.hrc"
32 #include "resource/sharedresources.hxx"
35 namespace connectivity
38 using namespace mysql;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::sdbc;
41 using namespace ::com::sun::star::sdbcx;
42 using namespace ::com::sun::star::beans;
43 using namespace ::com::sun::star::lang;
45 namespace mysql
47 Reference< XInterface > SAL_CALL ODriverDelegator_CreateInstance(const Reference< css::lang::XMultiServiceFactory >& _rxFac) throw( Exception )
49 return *(new ODriverDelegator( comphelper::getComponentContext(_rxFac) ));
53 namespace
55 OUString getJavaDriverClass(
56 css::uno::Sequence<css::beans::PropertyValue> const & info)
58 return comphelper::NamedValueCollection(info).getOrDefault(
59 "JavaDriverClass", OUString("com.mysql.jdbc.Driver"));
63 ODriverDelegator::ODriverDelegator(const Reference< XComponentContext >& _rxContext)
64 : ODriverDelegator_BASE(m_aMutex)
65 ,m_xContext(_rxContext)
70 ODriverDelegator::~ODriverDelegator()
72 try
74 ::comphelper::disposeComponent(m_xODBCDriver);
75 ::comphelper::disposeComponent(m_xNativeDriver);
76 TJDBCDrivers::iterator aIter = m_aJdbcDrivers.begin();
77 TJDBCDrivers::const_iterator aEnd = m_aJdbcDrivers.end();
78 for ( ;aIter != aEnd;++aIter )
79 ::comphelper::disposeComponent(aIter->second);
81 catch(const Exception&)
87 void ODriverDelegator::disposing()
89 ::osl::MutexGuard aGuard(m_aMutex);
92 for (TWeakPairVector::iterator i = m_aConnections.begin(); m_aConnections.end() != i; ++i)
94 Reference<XInterface > xTemp = i->first.get();
95 ::comphelper::disposeComponent(xTemp);
97 m_aConnections.clear();
98 TWeakPairVector().swap(m_aConnections);
100 ODriverDelegator_BASE::disposing();
103 namespace
105 enum class T_DRIVERTYPE
107 Odbc,
108 Jdbc,
109 Native
112 bool isOdbcUrl(const OUString& _sUrl)
114 return _sUrl.startsWith("sdbc:mysql:odbc:");
117 bool isNativeUrl(const OUString& _sUrl)
119 return _sUrl.startsWith("sdbc:mysql:mysqlc:");
122 T_DRIVERTYPE lcl_getDriverType(const OUString& _sUrl)
124 T_DRIVERTYPE eRet = T_DRIVERTYPE::Jdbc;
125 if ( isOdbcUrl(_sUrl ) )
126 eRet = T_DRIVERTYPE::Odbc;
127 else if ( isNativeUrl(_sUrl ) )
128 eRet = T_DRIVERTYPE::Native;
129 return eRet;
132 OUString transformUrl(const OUString& _sUrl)
134 OUString sNewUrl = _sUrl.copy(11);
135 if ( isOdbcUrl( _sUrl ) )
136 sNewUrl = "sdbc:" + sNewUrl;
137 else if ( isNativeUrl( _sUrl ) )
138 sNewUrl = "sdbc:" + sNewUrl;
139 else
141 sNewUrl = "jdbc:mysql://" + sNewUrl.copy(5);
143 return sNewUrl;
146 Reference< XDriver > lcl_loadDriver(const Reference< XComponentContext >& _rxContext,const OUString& _sUrl)
148 Reference<XDriverManager2> xDriverAccess = DriverManager::create(_rxContext);
149 Reference< XDriver > xDriver = xDriverAccess->getDriverByURL(_sUrl);
150 return xDriver;
153 Sequence< PropertyValue > lcl_convertProperties(T_DRIVERTYPE _eType,const Sequence< PropertyValue >& info,const OUString& _sUrl)
155 ::std::vector<PropertyValue> aProps;
156 const PropertyValue* pSupported = info.getConstArray();
157 const PropertyValue* pEnd = pSupported + info.getLength();
159 aProps.reserve(info.getLength() + 5);
160 bool jdc = false;
161 for (;pSupported != pEnd; ++pSupported)
163 aProps.push_back( *pSupported );
164 if (pSupported->Name == "JavaDriverClass")
166 jdc = true;
170 if ( _eType == T_DRIVERTYPE::Odbc )
172 aProps.push_back( PropertyValue(
173 OUString("Silent")
175 ,makeAny(true)
176 ,PropertyState_DIRECT_VALUE) );
177 aProps.push_back( PropertyValue(
178 OUString("PreventGetVersionColumns")
180 ,makeAny(true)
181 ,PropertyState_DIRECT_VALUE) );
183 else if ( _eType == T_DRIVERTYPE::Jdbc )
185 if (!jdc)
187 aProps.push_back( PropertyValue(
188 OUString("JavaDriverClass")
190 ,makeAny(OUString("com.mysql.jdbc.Driver"))
191 ,PropertyState_DIRECT_VALUE) );
194 else
196 aProps.push_back( PropertyValue(
197 OUString("PublicConnectionURL")
199 ,makeAny(_sUrl)
200 ,PropertyState_DIRECT_VALUE) );
202 aProps.push_back( PropertyValue(
203 OUString("IsAutoRetrievingEnabled")
205 ,makeAny(true)
206 ,PropertyState_DIRECT_VALUE) );
207 aProps.push_back( PropertyValue(
208 OUString("AutoRetrievingStatement")
210 ,makeAny(OUString("SELECT LAST_INSERT_ID()"))
211 ,PropertyState_DIRECT_VALUE) );
212 aProps.push_back( PropertyValue(
213 OUString("ParameterNameSubstitution")
215 ,makeAny(true)
216 ,PropertyState_DIRECT_VALUE) );
217 return Sequence< PropertyValue >(aProps.data(), aProps.size());
221 Reference< XDriver > ODriverDelegator::loadDriver( const OUString& url, const Sequence< PropertyValue >& info )
223 Reference< XDriver > xDriver;
224 const OUString sCuttedUrl = transformUrl(url);
225 const T_DRIVERTYPE eType = lcl_getDriverType( url );
226 if ( eType == T_DRIVERTYPE::Odbc )
228 if ( !m_xODBCDriver.is() )
229 m_xODBCDriver = lcl_loadDriver(m_xContext,sCuttedUrl);
230 xDriver = m_xODBCDriver;
231 } // if ( bIsODBC )
232 else if ( eType == T_DRIVERTYPE::Native )
234 if ( !m_xNativeDriver.is() )
235 m_xNativeDriver = lcl_loadDriver(m_xContext,sCuttedUrl);
236 xDriver = m_xNativeDriver;
238 else
240 OUString sDriverClass(getJavaDriverClass(info));
241 TJDBCDrivers::iterator aFind = m_aJdbcDrivers.find(sDriverClass);
242 if ( aFind == m_aJdbcDrivers.end() )
243 aFind = m_aJdbcDrivers.insert(TJDBCDrivers::value_type(sDriverClass,lcl_loadDriver(m_xContext,sCuttedUrl))).first;
244 xDriver = aFind->second;
247 return xDriver;
251 Reference< XConnection > SAL_CALL ODriverDelegator::connect( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
253 Reference< XConnection > xConnection;
254 if ( acceptsURL(url) )
256 Reference< XDriver > xDriver;
257 xDriver = loadDriver(url,info);
258 if ( xDriver.is() )
260 OUString sCuttedUrl = transformUrl(url);
261 const T_DRIVERTYPE eType = lcl_getDriverType( url );
262 Sequence< PropertyValue > aConvertedProperties = lcl_convertProperties(eType,info,url);
263 if ( eType == T_DRIVERTYPE::Jdbc )
265 ::comphelper::NamedValueCollection aSettings( info );
266 OUString sIanaName = aSettings.getOrDefault( "CharSet", OUString() );
267 if ( !sIanaName.isEmpty() )
269 ::dbtools::OCharsetMap aLookupIanaName;
270 ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
271 if (aLookup != aLookupIanaName.end() )
273 OUString sAdd;
274 if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
276 static const char s_sCharSetOp[] = "useUnicode=true&";
277 if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
279 sAdd = s_sCharSetOp;
280 } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
281 } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
282 if ( sCuttedUrl.indexOf('?') == -1 )
283 sCuttedUrl += "?";
284 else
285 sCuttedUrl += "&";
286 sCuttedUrl += sAdd;
287 sCuttedUrl += "characterEncoding=";
288 sCuttedUrl += sIanaName;
291 } // if ( !bIsODBC )
293 xConnection = xDriver->connect( sCuttedUrl, aConvertedProperties );
294 if ( xConnection.is() )
296 OMetaConnection* pMetaConnection = nullptr;
297 // now we have to set the URL to get the correct answer for metadata()->getURL()
298 Reference< XUnoTunnel> xTunnel(xConnection,UNO_QUERY);
299 if ( xTunnel.is() )
301 pMetaConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
302 if ( pMetaConnection )
303 pMetaConnection->setURL(url);
305 m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xConnection),TWeakConnectionPair(WeakReferenceHelper(),pMetaConnection)));
309 return xConnection;
313 sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const OUString& url ) throw (SQLException, RuntimeException, std::exception)
315 Sequence< PropertyValue > info;
317 bool bOK = url.startsWith( "sdbc:mysql:odbc:" )
318 || url.startsWith( "sdbc:mysql:jdbc:" )
319 || ( url.startsWith( "sdbc:mysql:mysqlc:" )
320 && loadDriver( url, info ).is()
322 return bOK;
326 Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
328 ::std::vector< DriverPropertyInfo > aDriverInfo;
329 if ( !acceptsURL(url) )
330 return Sequence< DriverPropertyInfo >();
332 Sequence< OUString > aBoolean(2);
333 aBoolean[0] = "0";
334 aBoolean[1] = "1";
337 aDriverInfo.push_back(DriverPropertyInfo(
338 OUString("CharSet")
339 ,OUString("CharSet of the database.")
340 ,false
341 ,OUString()
342 ,Sequence< OUString >())
344 aDriverInfo.push_back(DriverPropertyInfo(
345 OUString("SuppressVersionColumns")
346 ,OUString("Display version columns (when available).")
347 ,false
348 ,OUString("0")
349 ,aBoolean)
351 const T_DRIVERTYPE eType = lcl_getDriverType( url );
352 if ( eType == T_DRIVERTYPE::Jdbc )
354 aDriverInfo.push_back(DriverPropertyInfo(
355 OUString("JavaDriverClass")
356 ,OUString("The JDBC driver class name.")
357 ,true
358 ,getJavaDriverClass(info)
359 ,Sequence< OUString >())
362 else if ( eType == T_DRIVERTYPE::Native )
364 aDriverInfo.push_back(DriverPropertyInfo(
365 OUString("LocalSocket")
366 ,OUString("The file path of a socket to connect to a local MySQL server.")
367 ,false
368 ,OUString()
369 ,Sequence< OUString >())
371 aDriverInfo.push_back(DriverPropertyInfo(
372 OUString("NamedPipe")
373 ,OUString("The name of a pipe to connect to a local MySQL server.")
374 ,false
375 ,OUString()
376 ,Sequence< OUString >())
380 return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size());
384 sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion( ) throw (RuntimeException, std::exception)
386 return 1;
390 sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion( ) throw (RuntimeException, std::exception)
392 return 0;
396 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException, std::exception)
398 ::osl::MutexGuard aGuard( m_aMutex );
399 checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed);
401 Reference< XTablesSupplier > xTab;
402 Reference< XUnoTunnel> xTunnel(connection,UNO_QUERY);
403 if ( xTunnel.is() )
405 OMetaConnection* pConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
406 if ( pConnection )
408 TWeakPairVector::const_iterator aEnd = m_aConnections.end();
409 for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
411 if ( i->second.second == pConnection )
413 xTab.set(i->second.first.get().get(),UNO_QUERY);
414 if ( !xTab.is() )
416 xTab = new OMySQLCatalog(connection);
417 i->second.first = WeakReferenceHelper(xTab);
419 break;
423 } // if ( xTunnel.is() )
424 if ( !xTab.is() )
426 TWeakPairVector::const_iterator aEnd = m_aConnections.end();
427 for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
429 Reference< XConnection > xTemp(i->first.get(),UNO_QUERY);
430 if ( xTemp == connection )
432 xTab.set(i->second.first.get().get(),UNO_QUERY);
433 if ( !xTab.is() )
435 xTab = new OMySQLCatalog(connection);
436 i->second.first = WeakReferenceHelper(xTab);
438 break;
442 return xTab;
446 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
448 if ( ! acceptsURL(url) )
450 ::connectivity::SharedResources aResources;
451 const OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
452 ::dbtools::throwGenericSQLException(sMessage ,*this);
453 } // if ( ! acceptsURL(url) )
455 return getDataDefinitionByConnection(connect(url,info));
458 // XServiceInfo
461 OUString ODriverDelegator::getImplementationName_Static( ) throw(RuntimeException)
463 return OUString("org.openoffice.comp.drivers.MySQL.Driver");
466 Sequence< OUString > ODriverDelegator::getSupportedServiceNames_Static( ) throw (RuntimeException)
468 Sequence< OUString > aSNS( 2 );
469 aSNS[0] = "com.sun.star.sdbc.Driver";
470 aSNS[1] = "com.sun.star.sdbcx.Driver";
471 return aSNS;
474 OUString SAL_CALL ODriverDelegator::getImplementationName( ) throw(RuntimeException, std::exception)
476 return getImplementationName_Static();
479 sal_Bool SAL_CALL ODriverDelegator::supportsService( const OUString& _rServiceName ) throw(RuntimeException, std::exception)
481 return cppu::supportsService(this, _rServiceName);
484 Sequence< OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames( ) throw(RuntimeException, std::exception)
486 return getSupportedServiceNames_Static();
490 } // namespace connectivity
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */