1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
47 Reference
< XInterface
> SAL_CALL
ODriverDelegator_CreateInstance(const Reference
< ::com::sun::star::lang::XMultiServiceFactory
>& _rxFac
) throw( Exception
)
49 return *(new ODriverDelegator( comphelper::getComponentContext(_rxFac
) ));
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"));
67 ODriverDelegator::ODriverDelegator(const Reference
< XComponentContext
>& _rxContext
)
68 : ODriverDelegator_BASE(m_aMutex
)
69 ,m_xContext(_rxContext
)
74 ODriverDelegator::~ODriverDelegator()
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();
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
) )
131 else if ( isNativeUrl(_sUrl
) )
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
;
145 sNewUrl
= "jdbc:mysql://" + sNewUrl
.copy(5);
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
);
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);
165 for (;pSupported
!= pEnd
; ++pSupported
)
167 aProps
.push_back( *pSupported
);
168 if (pSupported
->Name
== "JavaDriverClass")
174 if ( _eType
== D_ODBC
)
176 aProps
.push_back( PropertyValue(
180 ,PropertyState_DIRECT_VALUE
) );
181 aProps
.push_back( PropertyValue(
182 OUString("PreventGetVersionColumns")
185 ,PropertyState_DIRECT_VALUE
) );
187 else if ( _eType
== D_JDBC
)
191 aProps
.push_back( PropertyValue(
192 OUString("JavaDriverClass")
194 ,makeAny(OUString("com.mysql.jdbc.Driver"))
195 ,PropertyState_DIRECT_VALUE
) );
200 aProps
.push_back( PropertyValue(
201 OUString("PublicConnectionURL")
204 ,PropertyState_DIRECT_VALUE
) );
206 aProps
.push_back( PropertyValue(
207 OUString("IsAutoRetrievingEnabled")
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")
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
;
237 else if ( eType
== D_NATIVE
)
239 if ( !m_xNativeDriver
.is() )
240 m_xNativeDriver
= lcl_loadDriver(m_xContext
,sCuttedUrl
);
241 xDriver
= m_xNativeDriver
;
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
;
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
);
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() )
279 if ( RTL_TEXTENCODING_UTF8
== (*aLookup
).getEncoding() )
281 static const OUString
s_sCharSetOp("useUnicode=true&");
282 if ( !sCuttedUrl
.matchIgnoreAsciiCase(s_sCharSetOp
) )
285 } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
286 } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
287 if ( sCuttedUrl
.indexOf('?') == -1 )
292 sCuttedUrl
+= "characterEncoding=";
293 sCuttedUrl
+= sIanaName
;
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
);
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
)));
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()
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);
342 aDriverInfo
.push_back(DriverPropertyInfo(
344 ,OUString("CharSet of the database.")
347 ,Sequence
< OUString
>())
349 aDriverInfo
.push_back(DriverPropertyInfo(
350 OUString("SuppressVersionColumns")
351 ,OUString("Display version columns (when available).")
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.")
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.")
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.")
381 ,Sequence
< OUString
>())
385 return Sequence
< DriverPropertyInfo
>(&aDriverInfo
[0],aDriverInfo
.size());
389 sal_Int32 SAL_CALL
ODriverDelegator::getMajorVersion( ) throw (RuntimeException
, std::exception
)
395 sal_Int32 SAL_CALL
ODriverDelegator::getMinorVersion( ) throw (RuntimeException
, std::exception
)
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
);
410 OMetaConnection
* pConnection
= reinterpret_cast<OMetaConnection
*>(xTunnel
->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
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
);
421 xTab
= new OMySQLCatalog(connection
);
422 i
->second
.first
= WeakReferenceHelper(xTab
);
428 } // if ( xTunnel.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
);
440 xTab
= new OMySQLCatalog(connection
);
441 i
->second
.first
= WeakReferenceHelper(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
));
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";
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: */