1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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
;
57 Reference
< XInterface
> SAL_CALL
ODriverDelegator_CreateInstance(const Reference
< ::com::sun::star::lang::XMultiServiceFactory
>& _rxFac
) throw( Exception
)
59 return *(new ODriverDelegator(_rxFac
));
64 //====================================================================
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()
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();
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
) )
126 else if ( isNativeUrl(_sUrl
) )
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
;
140 sNewUrl
= sNewUrl
.copy(5);
142 ::rtl::OUString sTempUrl
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jdbc:mysql://"));
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
);
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"))
178 ,PropertyState_DIRECT_VALUE
) );
179 aProps
.push_back( PropertyValue(
180 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PreventGetVersionColumns"))
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
) );
195 aProps
.push_back( PropertyValue(
196 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PublicConnectionURL"))
199 ,PropertyState_DIRECT_VALUE
) );
201 aProps
.push_back( PropertyValue(
202 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsAutoRetrievingEnabled"))
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"))
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
;
232 else if ( eType
== D_NATIVE
)
234 if ( !m_xNativeDriver
.is() )
235 m_xNativeDriver
= lcl_loadDriver(m_xFactory
,sCuttedUrl
);
236 xDriver
= m_xNativeDriver
;
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
;
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
);
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
) )
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("?"));
288 sCuttedUrl
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("&"));
290 sCuttedUrl
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("characterEncoding="));
291 sCuttedUrl
+= sIanaName
;
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
);
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
)));
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()
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."))
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)."))
351 ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0"))
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."))
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
)
375 //--------------------------------------------------------------------
376 sal_Int32 SAL_CALL
ODriverDelegator::getMinorVersion( ) throw (RuntimeException
)
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
);
391 OMetaConnection
* pConnection
= reinterpret_cast<OMetaConnection
*>(xTunnel
->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
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
);
402 xTab
= new OMySQLCatalog(connection
);
403 i
->second
.first
= WeakReferenceHelper(xTab
);
409 } // if ( xTunnel.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
);
421 xTab
= new OMySQLCatalog(connection
);
422 i
->second
.first
= WeakReferenceHelper(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
));
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");
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 //........................................................................