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 "connectivity/dbexception.hxx"
26 #include <connectivity/dbcharset.hxx>
27 #include <com/sun/star/sdbc/DriverManager.hpp>
28 #include <com/sun/star/uno/XComponentContext.hpp>
29 #include "TConnection.hxx"
30 #include "resource/common_res.hrc"
31 #include "resource/sharedresources.hxx"
33 //........................................................................
34 namespace connectivity
36 //........................................................................
37 using namespace mysql
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::sdbc
;
40 using namespace ::com::sun::star::sdbcx
;
41 using namespace ::com::sun::star::beans
;
42 using namespace ::com::sun::star::lang
;
46 Reference
< XInterface
> SAL_CALL
ODriverDelegator_CreateInstance(const Reference
< ::com::sun::star::lang::XMultiServiceFactory
>& _rxFac
) throw( Exception
)
48 return *(new ODriverDelegator( comphelper::getComponentContext(_rxFac
) ));
54 OUString
getJavaDriverClass(
55 css::uno::Sequence
<css::beans::PropertyValue
> const & info
)
57 return comphelper::NamedValueCollection(info
).getOrDefault(
58 "JavaDriverClass", OUString("com.mysql.jdbc.Driver"));
62 //====================================================================
64 //====================================================================
65 //--------------------------------------------------------------------
66 ODriverDelegator::ODriverDelegator(const Reference
< XComponentContext
>& _rxContext
)
67 : ODriverDelegator_BASE(m_aMutex
)
68 ,m_xContext(_rxContext
)
72 //--------------------------------------------------------------------
73 ODriverDelegator::~ODriverDelegator()
77 ::comphelper::disposeComponent(m_xODBCDriver
);
78 ::comphelper::disposeComponent(m_xNativeDriver
);
79 TJDBCDrivers::iterator aIter
= m_aJdbcDrivers
.begin();
80 TJDBCDrivers::iterator aEnd
= m_aJdbcDrivers
.end();
81 for ( ;aIter
!= aEnd
;++aIter
)
82 ::comphelper::disposeComponent(aIter
->second
);
84 catch(const Exception
&)
89 // --------------------------------------------------------------------------------
90 void ODriverDelegator::disposing()
92 ::osl::MutexGuard
aGuard(m_aMutex
);
95 for (TWeakPairVector::iterator i
= m_aConnections
.begin(); m_aConnections
.end() != i
; ++i
)
97 Reference
<XInterface
> xTemp
= i
->first
.get();
98 ::comphelper::disposeComponent(xTemp
);
100 m_aConnections
.clear();
101 TWeakPairVector().swap(m_aConnections
);
103 ODriverDelegator_BASE::disposing();
115 sal_Bool
isOdbcUrl(const OUString
& _sUrl
)
117 return _sUrl
.copy(0,16) == "sdbc:mysql:odbc:";
119 //--------------------------------------------------------------------
120 sal_Bool
isNativeUrl(const OUString
& _sUrl
)
122 return (!_sUrl
.compareTo(OUString("sdbc:mysql:mysqlc:"), sizeof("sdbc:mysql:mysqlc:")-1));
124 //--------------------------------------------------------------------
125 T_DRIVERTYPE
lcl_getDriverType(const OUString
& _sUrl
)
127 T_DRIVERTYPE eRet
= D_JDBC
;
128 if ( isOdbcUrl(_sUrl
) )
130 else if ( isNativeUrl(_sUrl
) )
134 //--------------------------------------------------------------------
135 OUString
transformUrl(const OUString
& _sUrl
)
137 OUString sNewUrl
= _sUrl
.copy(11);
138 if ( isOdbcUrl( _sUrl
) )
139 sNewUrl
= OUString("sdbc:") + sNewUrl
;
140 else if ( isNativeUrl( _sUrl
) )
141 sNewUrl
= OUString("sdbc:") + sNewUrl
;
144 sNewUrl
= sNewUrl
.copy(5);
146 OUString sTempUrl
= OUString("jdbc:mysql://");
153 //--------------------------------------------------------------------
154 Reference
< XDriver
> lcl_loadDriver(const Reference
< XComponentContext
>& _rxContext
,const OUString
& _sUrl
)
156 Reference
<XDriverManager2
> xDriverAccess
= DriverManager::create(_rxContext
);
157 Reference
< XDriver
> xDriver
= xDriverAccess
->getDriverByURL(_sUrl
);
160 //--------------------------------------------------------------------
161 Sequence
< PropertyValue
> lcl_convertProperties(T_DRIVERTYPE _eType
,const Sequence
< PropertyValue
>& info
,const OUString
& _sUrl
)
163 ::std::vector
<PropertyValue
> aProps
;
164 const PropertyValue
* pSupported
= info
.getConstArray();
165 const PropertyValue
* pEnd
= pSupported
+ info
.getLength();
167 aProps
.reserve(info
.getLength() + 5);
169 for (;pSupported
!= pEnd
; ++pSupported
)
171 aProps
.push_back( *pSupported
);
172 if (pSupported
->Name
== "JavaDriverClass")
178 if ( _eType
== D_ODBC
)
180 aProps
.push_back( PropertyValue(
184 ,PropertyState_DIRECT_VALUE
) );
185 aProps
.push_back( PropertyValue(
186 OUString("PreventGetVersionColumns")
189 ,PropertyState_DIRECT_VALUE
) );
191 else if ( _eType
== D_JDBC
)
195 aProps
.push_back( PropertyValue(
196 OUString("JavaDriverClass")
198 ,makeAny(OUString("com.mysql.jdbc.Driver"))
199 ,PropertyState_DIRECT_VALUE
) );
204 aProps
.push_back( PropertyValue(
205 OUString("PublicConnectionURL")
208 ,PropertyState_DIRECT_VALUE
) );
210 aProps
.push_back( PropertyValue(
211 OUString("IsAutoRetrievingEnabled")
214 ,PropertyState_DIRECT_VALUE
) );
215 aProps
.push_back( PropertyValue(
216 OUString("AutoRetrievingStatement")
218 ,makeAny(OUString("SELECT LAST_INSERT_ID()"))
219 ,PropertyState_DIRECT_VALUE
) );
220 aProps
.push_back( PropertyValue(
221 OUString("ParameterNameSubstitution")
224 ,PropertyState_DIRECT_VALUE
) );
225 PropertyValue
* pProps
= aProps
.empty() ? 0 : &aProps
[0];
226 return Sequence
< PropertyValue
>(pProps
, aProps
.size());
229 //--------------------------------------------------------------------
230 Reference
< XDriver
> ODriverDelegator::loadDriver( const OUString
& url
, const Sequence
< PropertyValue
>& info
)
232 Reference
< XDriver
> xDriver
;
233 const OUString sCuttedUrl
= transformUrl(url
);
234 const T_DRIVERTYPE eType
= lcl_getDriverType( url
);
235 if ( eType
== D_ODBC
)
237 if ( !m_xODBCDriver
.is() )
238 m_xODBCDriver
= lcl_loadDriver(m_xContext
,sCuttedUrl
);
239 xDriver
= m_xODBCDriver
;
241 else if ( eType
== D_NATIVE
)
243 if ( !m_xNativeDriver
.is() )
244 m_xNativeDriver
= lcl_loadDriver(m_xContext
,sCuttedUrl
);
245 xDriver
= m_xNativeDriver
;
249 OUString
sDriverClass(getJavaDriverClass(info
));
250 TJDBCDrivers::iterator aFind
= m_aJdbcDrivers
.find(sDriverClass
);
251 if ( aFind
== m_aJdbcDrivers
.end() )
252 aFind
= m_aJdbcDrivers
.insert(TJDBCDrivers::value_type(sDriverClass
,lcl_loadDriver(m_xContext
,sCuttedUrl
))).first
;
253 xDriver
= aFind
->second
;
259 //--------------------------------------------------------------------
260 Reference
< XConnection
> SAL_CALL
ODriverDelegator::connect( const OUString
& url
, const Sequence
< PropertyValue
>& info
) throw (SQLException
, RuntimeException
)
262 Reference
< XConnection
> xConnection
;
263 if ( acceptsURL(url
) )
265 Reference
< XDriver
> xDriver
;
266 xDriver
= loadDriver(url
,info
);
269 OUString sCuttedUrl
= transformUrl(url
);
270 const T_DRIVERTYPE eType
= lcl_getDriverType( url
);
271 Sequence
< PropertyValue
> aConvertedProperties
= lcl_convertProperties(eType
,info
,url
);
272 if ( eType
== D_JDBC
)
274 ::comphelper::NamedValueCollection
aSettings( info
);
275 OUString sIanaName
= aSettings
.getOrDefault( "CharSet", OUString() );
276 if ( !sIanaName
.isEmpty() )
278 ::dbtools::OCharsetMap aLookupIanaName
;
279 ::dbtools::OCharsetMap::const_iterator aLookup
= aLookupIanaName
.find(sIanaName
, ::dbtools::OCharsetMap::IANA());
280 if (aLookup
!= aLookupIanaName
.end() )
283 if ( RTL_TEXTENCODING_UTF8
== (*aLookup
).getEncoding() )
285 static const OUString
s_sCharSetOp("useUnicode=true&");
286 if ( !sCuttedUrl
.matchIgnoreAsciiCase(s_sCharSetOp
) )
289 } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
290 } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
291 if ( sCuttedUrl
.indexOf('?') == -1 )
292 sCuttedUrl
+= OUString("?");
294 sCuttedUrl
+= OUString("&");
296 sCuttedUrl
+= OUString("characterEncoding=");
297 sCuttedUrl
+= sIanaName
;
302 xConnection
= xDriver
->connect( sCuttedUrl
, aConvertedProperties
);
303 if ( xConnection
.is() )
305 OMetaConnection
* pMetaConnection
= NULL
;
306 // now we have to set the URL to get the correct answer for metadata()->getURL()
307 Reference
< XUnoTunnel
> xTunnel(xConnection
,UNO_QUERY
);
310 pMetaConnection
= reinterpret_cast<OMetaConnection
*>(xTunnel
->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
311 if ( pMetaConnection
)
312 pMetaConnection
->setURL(url
);
314 m_aConnections
.push_back(TWeakPair(WeakReferenceHelper(xConnection
),TWeakConnectionPair(WeakReferenceHelper(),pMetaConnection
)));
321 //--------------------------------------------------------------------
322 sal_Bool SAL_CALL
ODriverDelegator::acceptsURL( const OUString
& url
) throw (SQLException
, RuntimeException
)
324 Sequence
< PropertyValue
> info
;
326 sal_Bool bOK
= url
.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:odbc:" ) )
327 || url
.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:jdbc:" ) )
328 || ( url
.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc:" ) )
329 && loadDriver( url
, info
).is()
334 //--------------------------------------------------------------------
335 Sequence
< DriverPropertyInfo
> SAL_CALL
ODriverDelegator::getPropertyInfo( const OUString
& url
, const Sequence
< PropertyValue
>& info
) throw (SQLException
, RuntimeException
)
337 ::std::vector
< DriverPropertyInfo
> aDriverInfo
;
338 if ( !acceptsURL(url
) )
339 return Sequence
< DriverPropertyInfo
>();
341 Sequence
< OUString
> aBoolean(2);
342 aBoolean
[0] = OUString("0");
343 aBoolean
[1] = OUString("1");
346 aDriverInfo
.push_back(DriverPropertyInfo(
348 ,OUString("CharSet of the database.")
351 ,Sequence
< OUString
>())
353 aDriverInfo
.push_back(DriverPropertyInfo(
354 OUString("SuppressVersionColumns")
355 ,OUString("Display version columns (when available).")
360 const T_DRIVERTYPE eType
= lcl_getDriverType( url
);
361 if ( eType
== D_JDBC
)
363 aDriverInfo
.push_back(DriverPropertyInfo(
364 OUString("JavaDriverClass")
365 ,OUString("The JDBC driver class name.")
367 ,getJavaDriverClass(info
)
368 ,Sequence
< OUString
>())
372 return Sequence
< DriverPropertyInfo
>(&aDriverInfo
[0],aDriverInfo
.size());
375 //--------------------------------------------------------------------
376 sal_Int32 SAL_CALL
ODriverDelegator::getMajorVersion( ) throw (RuntimeException
)
381 //--------------------------------------------------------------------
382 sal_Int32 SAL_CALL
ODriverDelegator::getMinorVersion( ) throw (RuntimeException
)
387 //--------------------------------------------------------------------
388 Reference
< XTablesSupplier
> SAL_CALL
ODriverDelegator::getDataDefinitionByConnection( const Reference
< XConnection
>& connection
) throw (SQLException
, RuntimeException
)
390 ::osl::MutexGuard
aGuard( m_aMutex
);
391 checkDisposed(ODriverDelegator_BASE::rBHelper
.bDisposed
);
393 Reference
< XTablesSupplier
> xTab
;
394 Reference
< XUnoTunnel
> xTunnel(connection
,UNO_QUERY
);
397 OMetaConnection
* pConnection
= reinterpret_cast<OMetaConnection
*>(xTunnel
->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
400 TWeakPairVector::iterator aEnd
= m_aConnections
.end();
401 for (TWeakPairVector::iterator i
= m_aConnections
.begin(); aEnd
!= i
; ++i
)
403 if ( i
->second
.second
== pConnection
)
405 xTab
= Reference
< XTablesSupplier
>(i
->second
.first
.get().get(),UNO_QUERY
);
408 xTab
= new OMySQLCatalog(connection
);
409 i
->second
.first
= WeakReferenceHelper(xTab
);
415 } // if ( xTunnel.is() )
418 TWeakPairVector::iterator aEnd
= m_aConnections
.end();
419 for (TWeakPairVector::iterator i
= m_aConnections
.begin(); aEnd
!= i
; ++i
)
421 Reference
< XConnection
> xTemp(i
->first
.get(),UNO_QUERY
);
422 if ( xTemp
== connection
)
424 xTab
= Reference
< XTablesSupplier
>(i
->second
.first
.get().get(),UNO_QUERY
);
427 xTab
= new OMySQLCatalog(connection
);
428 i
->second
.first
= WeakReferenceHelper(xTab
);
437 //--------------------------------------------------------------------
438 Reference
< XTablesSupplier
> SAL_CALL
ODriverDelegator::getDataDefinitionByURL( const OUString
& url
, const Sequence
< PropertyValue
>& info
) throw (SQLException
, RuntimeException
)
440 if ( ! acceptsURL(url
) )
442 ::connectivity::SharedResources aResources
;
443 const OUString sMessage
= aResources
.getResourceString(STR_URI_SYNTAX_ERROR
);
444 ::dbtools::throwGenericSQLException(sMessage
,*this);
445 } // if ( ! acceptsURL(url) )
447 return getDataDefinitionByConnection(connect(url
,info
));
451 // --------------------------------------------------------------------------------
452 //------------------------------------------------------------------------------
453 OUString
ODriverDelegator::getImplementationName_Static( ) throw(RuntimeException
)
455 return OUString("org.openoffice.comp.drivers.MySQL.Driver");
457 //------------------------------------------------------------------------------
458 Sequence
< OUString
> ODriverDelegator::getSupportedServiceNames_Static( ) throw (RuntimeException
)
460 Sequence
< OUString
> aSNS( 2 );
461 aSNS
[0] = OUString("com.sun.star.sdbc.Driver");
462 aSNS
[1] = OUString("com.sun.star.sdbcx.Driver");
465 //------------------------------------------------------------------
466 OUString SAL_CALL
ODriverDelegator::getImplementationName( ) throw(RuntimeException
)
468 return getImplementationName_Static();
471 //------------------------------------------------------------------
472 sal_Bool SAL_CALL
ODriverDelegator::supportsService( const OUString
& _rServiceName
) throw(RuntimeException
)
474 Sequence
< OUString
> aSupported(getSupportedServiceNames());
475 const OUString
* pSupported
= aSupported
.getConstArray();
476 const OUString
* pEnd
= pSupported
+ aSupported
.getLength();
477 for (;pSupported
!= pEnd
&& !pSupported
->equals(_rServiceName
); ++pSupported
)
480 return pSupported
!= pEnd
;
482 //------------------------------------------------------------------
483 Sequence
< OUString
> SAL_CALL
ODriverDelegator::getSupportedServiceNames( ) throw(RuntimeException
)
485 return getSupportedServiceNames_Static();
487 //------------------------------------------------------------------
488 //........................................................................
489 } // namespace connectivity
490 //........................................................................
492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */