Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / mysql / YDriver.cxx
blob588845ecd2019f8cc18dce02ff55467d671a52e5
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< ::com::sun::star::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"));
64 //= ODriverDelegator
67 ODriverDelegator::ODriverDelegator(const Reference< XComponentContext >& _rxContext)
68 : ODriverDelegator_BASE(m_aMutex)
69 ,m_xContext(_rxContext)
74 ODriverDelegator::~ODriverDelegator()
76 try
78 ::comphelper::disposeComponent(m_xODBCDriver);
79 ::comphelper::disposeComponent(m_xNativeDriver);
80 TJDBCDrivers::iterator aIter = m_aJdbcDrivers.begin();
81 TJDBCDrivers::iterator aEnd = m_aJdbcDrivers.end();
82 for ( ;aIter != aEnd;++aIter )
83 ::comphelper::disposeComponent(aIter->second);
85 catch(const Exception&)
91 void ODriverDelegator::disposing()
93 ::osl::MutexGuard aGuard(m_aMutex);
96 for (TWeakPairVector::iterator i = m_aConnections.begin(); m_aConnections.end() != i; ++i)
98 Reference<XInterface > xTemp = i->first.get();
99 ::comphelper::disposeComponent(xTemp);
101 m_aConnections.clear();
102 TWeakPairVector().swap(m_aConnections);
104 ODriverDelegator_BASE::disposing();
107 namespace
109 typedef enum
111 D_ODBC,
112 D_JDBC,
113 D_NATIVE
114 } T_DRIVERTYPE;
116 bool isOdbcUrl(const OUString& _sUrl)
118 return _sUrl.copy(0,16) == "sdbc:mysql:odbc:";
121 bool isNativeUrl(const OUString& _sUrl)
123 return (!_sUrl.compareTo(OUString("sdbc:mysql:mysqlc:"), sizeof("sdbc:mysql:mysqlc:")-1));
126 T_DRIVERTYPE lcl_getDriverType(const OUString& _sUrl)
128 T_DRIVERTYPE eRet = D_JDBC;
129 if ( isOdbcUrl(_sUrl ) )
130 eRet = D_ODBC;
131 else if ( isNativeUrl(_sUrl ) )
132 eRet = D_NATIVE;
133 return eRet;
136 OUString transformUrl(const OUString& _sUrl)
138 OUString sNewUrl = _sUrl.copy(11);
139 if ( isOdbcUrl( _sUrl ) )
140 sNewUrl = "sdbc:" + sNewUrl;
141 else if ( isNativeUrl( _sUrl ) )
142 sNewUrl = "sdbc:" + sNewUrl;
143 else
145 sNewUrl = "jdbc:mysql://" + sNewUrl.copy(5);
147 return sNewUrl;
150 Reference< XDriver > lcl_loadDriver(const Reference< XComponentContext >& _rxContext,const OUString& _sUrl)
152 Reference<XDriverManager2> xDriverAccess = DriverManager::create(_rxContext);
153 Reference< XDriver > xDriver = xDriverAccess->getDriverByURL(_sUrl);
154 return xDriver;
157 Sequence< PropertyValue > lcl_convertProperties(T_DRIVERTYPE _eType,const Sequence< PropertyValue >& info,const OUString& _sUrl)
159 ::std::vector<PropertyValue> aProps;
160 const PropertyValue* pSupported = info.getConstArray();
161 const PropertyValue* pEnd = pSupported + info.getLength();
163 aProps.reserve(info.getLength() + 5);
164 bool jdc = false;
165 for (;pSupported != pEnd; ++pSupported)
167 aProps.push_back( *pSupported );
168 if (pSupported->Name == "JavaDriverClass")
170 jdc = true;
174 if ( _eType == D_ODBC )
176 aProps.push_back( PropertyValue(
177 OUString("Silent")
179 ,makeAny(sal_True)
180 ,PropertyState_DIRECT_VALUE) );
181 aProps.push_back( PropertyValue(
182 OUString("PreventGetVersionColumns")
184 ,makeAny(sal_True)
185 ,PropertyState_DIRECT_VALUE) );
187 else if ( _eType == D_JDBC )
189 if (!jdc)
191 aProps.push_back( PropertyValue(
192 OUString("JavaDriverClass")
194 ,makeAny(OUString("com.mysql.jdbc.Driver"))
195 ,PropertyState_DIRECT_VALUE) );
198 else
200 aProps.push_back( PropertyValue(
201 OUString("PublicConnectionURL")
203 ,makeAny(_sUrl)
204 ,PropertyState_DIRECT_VALUE) );
206 aProps.push_back( PropertyValue(
207 OUString("IsAutoRetrievingEnabled")
209 ,makeAny(sal_True)
210 ,PropertyState_DIRECT_VALUE) );
211 aProps.push_back( PropertyValue(
212 OUString("AutoRetrievingStatement")
214 ,makeAny(OUString("SELECT LAST_INSERT_ID()"))
215 ,PropertyState_DIRECT_VALUE) );
216 aProps.push_back( PropertyValue(
217 OUString("ParameterNameSubstitution")
219 ,makeAny(sal_True)
220 ,PropertyState_DIRECT_VALUE) );
221 PropertyValue* pProps = aProps.empty() ? 0 : &aProps[0];
222 return Sequence< PropertyValue >(pProps, aProps.size());
226 Reference< XDriver > ODriverDelegator::loadDriver( const OUString& url, const Sequence< PropertyValue >& info )
228 Reference< XDriver > xDriver;
229 const OUString sCuttedUrl = transformUrl(url);
230 const T_DRIVERTYPE eType = lcl_getDriverType( url );
231 if ( eType == D_ODBC )
233 if ( !m_xODBCDriver.is() )
234 m_xODBCDriver = lcl_loadDriver(m_xContext,sCuttedUrl);
235 xDriver = m_xODBCDriver;
236 } // if ( bIsODBC )
237 else if ( eType == D_NATIVE )
239 if ( !m_xNativeDriver.is() )
240 m_xNativeDriver = lcl_loadDriver(m_xContext,sCuttedUrl);
241 xDriver = m_xNativeDriver;
243 else
245 OUString sDriverClass(getJavaDriverClass(info));
246 TJDBCDrivers::iterator aFind = m_aJdbcDrivers.find(sDriverClass);
247 if ( aFind == m_aJdbcDrivers.end() )
248 aFind = m_aJdbcDrivers.insert(TJDBCDrivers::value_type(sDriverClass,lcl_loadDriver(m_xContext,sCuttedUrl))).first;
249 xDriver = aFind->second;
252 return xDriver;
256 Reference< XConnection > SAL_CALL ODriverDelegator::connect( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
258 Reference< XConnection > xConnection;
259 if ( acceptsURL(url) )
261 Reference< XDriver > xDriver;
262 xDriver = loadDriver(url,info);
263 if ( xDriver.is() )
265 OUString sCuttedUrl = transformUrl(url);
266 const T_DRIVERTYPE eType = lcl_getDriverType( url );
267 Sequence< PropertyValue > aConvertedProperties = lcl_convertProperties(eType,info,url);
268 if ( eType == D_JDBC )
270 ::comphelper::NamedValueCollection aSettings( info );
271 OUString sIanaName = aSettings.getOrDefault( "CharSet", OUString() );
272 if ( !sIanaName.isEmpty() )
274 ::dbtools::OCharsetMap aLookupIanaName;
275 ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
276 if (aLookup != aLookupIanaName.end() )
278 OUString sAdd;
279 if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
281 static const OUString s_sCharSetOp("useUnicode=true&");
282 if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
284 sAdd = s_sCharSetOp;
285 } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
286 } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
287 if ( sCuttedUrl.indexOf('?') == -1 )
288 sCuttedUrl += "?";
289 else
290 sCuttedUrl += "&";
291 sCuttedUrl += sAdd;
292 sCuttedUrl += "characterEncoding=";
293 sCuttedUrl += sIanaName;
296 } // if ( !bIsODBC )
298 xConnection = xDriver->connect( sCuttedUrl, aConvertedProperties );
299 if ( xConnection.is() )
301 OMetaConnection* pMetaConnection = NULL;
302 // now we have to set the URL to get the correct answer for metadata()->getURL()
303 Reference< XUnoTunnel> xTunnel(xConnection,UNO_QUERY);
304 if ( xTunnel.is() )
306 pMetaConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
307 if ( pMetaConnection )
308 pMetaConnection->setURL(url);
310 m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xConnection),TWeakConnectionPair(WeakReferenceHelper(),pMetaConnection)));
314 return xConnection;
318 sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const OUString& url ) throw (SQLException, RuntimeException, std::exception)
320 Sequence< PropertyValue > info;
322 bool bOK = url.startsWith( "sdbc:mysql:odbc:" )
323 || url.startsWith( "sdbc:mysql:jdbc:" )
324 || ( url.startsWith( "sdbc:mysql:mysqlc:" )
325 && loadDriver( url, info ).is()
327 return bOK;
331 Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
333 ::std::vector< DriverPropertyInfo > aDriverInfo;
334 if ( !acceptsURL(url) )
335 return Sequence< DriverPropertyInfo >();
337 Sequence< OUString > aBoolean(2);
338 aBoolean[0] = "0";
339 aBoolean[1] = "1";
342 aDriverInfo.push_back(DriverPropertyInfo(
343 OUString("CharSet")
344 ,OUString("CharSet of the database.")
345 ,sal_False
346 ,OUString()
347 ,Sequence< OUString >())
349 aDriverInfo.push_back(DriverPropertyInfo(
350 OUString("SuppressVersionColumns")
351 ,OUString("Display version columns (when available).")
352 ,sal_False
353 ,OUString("0")
354 ,aBoolean)
356 const T_DRIVERTYPE eType = lcl_getDriverType( url );
357 if ( eType == D_JDBC )
359 aDriverInfo.push_back(DriverPropertyInfo(
360 OUString("JavaDriverClass")
361 ,OUString("The JDBC driver class name.")
362 ,sal_True
363 ,getJavaDriverClass(info)
364 ,Sequence< OUString >())
367 else if ( eType == D_NATIVE )
369 aDriverInfo.push_back(DriverPropertyInfo(
370 OUString("LocalSocket")
371 ,OUString("The file path of a socket to connect to a local MySQL server.")
372 ,sal_False
373 ,OUString()
374 ,Sequence< OUString >())
376 aDriverInfo.push_back(DriverPropertyInfo(
377 OUString("NamedPipe")
378 ,OUString("The name of a pipe to connect to a local MySQL server.")
379 ,sal_False
380 ,OUString()
381 ,Sequence< OUString >())
385 return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size());
389 sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion( ) throw (RuntimeException, std::exception)
391 return 1;
395 sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion( ) throw (RuntimeException, std::exception)
397 return 0;
401 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException, std::exception)
403 ::osl::MutexGuard aGuard( m_aMutex );
404 checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed);
406 Reference< XTablesSupplier > xTab;
407 Reference< XUnoTunnel> xTunnel(connection,UNO_QUERY);
408 if ( xTunnel.is() )
410 OMetaConnection* pConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
411 if ( pConnection )
413 TWeakPairVector::iterator aEnd = m_aConnections.end();
414 for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
416 if ( i->second.second == pConnection )
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 } // if ( xTunnel.is() )
429 if ( !xTab.is() )
431 TWeakPairVector::iterator aEnd = m_aConnections.end();
432 for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
434 Reference< XConnection > xTemp(i->first.get(),UNO_QUERY);
435 if ( xTemp == connection )
437 xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY);
438 if ( !xTab.is() )
440 xTab = new OMySQLCatalog(connection);
441 i->second.first = WeakReferenceHelper(xTab);
443 break;
447 return xTab;
451 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
453 if ( ! acceptsURL(url) )
455 ::connectivity::SharedResources aResources;
456 const OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
457 ::dbtools::throwGenericSQLException(sMessage ,*this);
458 } // if ( ! acceptsURL(url) )
460 return getDataDefinitionByConnection(connect(url,info));
463 // XServiceInfo
466 OUString ODriverDelegator::getImplementationName_Static( ) throw(RuntimeException)
468 return OUString("org.openoffice.comp.drivers.MySQL.Driver");
471 Sequence< OUString > ODriverDelegator::getSupportedServiceNames_Static( ) throw (RuntimeException)
473 Sequence< OUString > aSNS( 2 );
474 aSNS[0] = "com.sun.star.sdbc.Driver";
475 aSNS[1] = "com.sun.star.sdbcx.Driver";
476 return aSNS;
479 OUString SAL_CALL ODriverDelegator::getImplementationName( ) throw(RuntimeException, std::exception)
481 return getImplementationName_Static();
484 sal_Bool SAL_CALL ODriverDelegator::supportsService( const OUString& _rServiceName ) throw(RuntimeException, std::exception)
486 return cppu::supportsService(this, _rServiceName);
489 Sequence< OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames( ) throw(RuntimeException, std::exception)
491 return getSupportedServiceNames_Static();
495 } // namespace connectivity
498 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */