Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : : #include "mysql/YDriver.hxx"
21 : : #include "mysql/YCatalog.hxx"
22 : : #include <osl/diagnose.h>
23 : : #include <comphelper/namedvaluecollection.hxx>
24 : : #include "connectivity/dbexception.hxx"
25 : : #include <connectivity/dbcharset.hxx>
26 : : #include <com/sun/star/sdbc/XDriverAccess.hpp>
27 : : #include "TConnection.hxx"
28 : : #include "resource/common_res.hrc"
29 : : #include "resource/sharedresources.hxx"
30 : :
31 : : //........................................................................
32 : : namespace connectivity
33 : : {
34 : : //........................................................................
35 : : using namespace mysql;
36 : : using namespace ::com::sun::star::uno;
37 : : using namespace ::com::sun::star::sdbc;
38 : : using namespace ::com::sun::star::sdbcx;
39 : : using namespace ::com::sun::star::beans;
40 : : using namespace ::com::sun::star::lang;
41 : :
42 : : namespace mysql
43 : : {
44 : 0 : Reference< XInterface > SAL_CALL ODriverDelegator_CreateInstance(const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFac) throw( Exception )
45 : : {
46 : 0 : return *(new ODriverDelegator(_rxFac));
47 : : }
48 : : }
49 : :
50 : :
51 : : //====================================================================
52 : : //= ODriverDelegator
53 : : //====================================================================
54 : : //--------------------------------------------------------------------
55 : 0 : ODriverDelegator::ODriverDelegator(const Reference< XMultiServiceFactory >& _rxFactory)
56 : : : ODriverDelegator_BASE(m_aMutex)
57 : : ,m_xFactory(_rxFactory)
58 : 0 : ,m_eDriverType(D_ODBC)
59 : : {
60 : 0 : }
61 : :
62 : : //--------------------------------------------------------------------
63 : 0 : ODriverDelegator::~ODriverDelegator()
64 : : {
65 : : try
66 : : {
67 : 0 : ::comphelper::disposeComponent(m_xODBCDriver);
68 : 0 : ::comphelper::disposeComponent(m_xNativeDriver);
69 : 0 : TJDBCDrivers::iterator aIter = m_aJdbcDrivers.begin();
70 : 0 : TJDBCDrivers::iterator aEnd = m_aJdbcDrivers.end();
71 : 0 : for ( ;aIter != aEnd;++aIter )
72 : 0 : ::comphelper::disposeComponent(aIter->second);
73 : : }
74 : 0 : catch(const Exception&)
75 : : {
76 : : }
77 : 0 : }
78 : :
79 : : // --------------------------------------------------------------------------------
80 : 0 : void ODriverDelegator::disposing()
81 : : {
82 : 0 : ::osl::MutexGuard aGuard(m_aMutex);
83 : :
84 : :
85 : 0 : for (TWeakPairVector::iterator i = m_aConnections.begin(); m_aConnections.end() != i; ++i)
86 : : {
87 : 0 : Reference<XInterface > xTemp = i->first.get();
88 : 0 : ::comphelper::disposeComponent(xTemp);
89 : 0 : }
90 : 0 : m_aConnections.clear();
91 : 0 : TWeakPairVector().swap(m_aConnections);
92 : :
93 : 0 : ODriverDelegator_BASE::disposing();
94 : 0 : }
95 : :
96 : : namespace
97 : : {
98 : 0 : sal_Bool isOdbcUrl(const ::rtl::OUString& _sUrl)
99 : : {
100 : 0 : return _sUrl.copy(0,16) == "sdbc:mysql:odbc:";
101 : : }
102 : : //--------------------------------------------------------------------
103 : 0 : sal_Bool isNativeUrl(const ::rtl::OUString& _sUrl)
104 : : {
105 : 0 : return (!_sUrl.compareTo(::rtl::OUString("sdbc:mysql:mysqlc:"), sizeof("sdbc:mysql:mysqlc:")-1));
106 : : }
107 : : //--------------------------------------------------------------------
108 : 0 : T_DRIVERTYPE lcl_getDriverType(const ::rtl::OUString& _sUrl)
109 : : {
110 : 0 : T_DRIVERTYPE eRet = D_JDBC;
111 : 0 : if ( isOdbcUrl(_sUrl ) )
112 : 0 : eRet = D_ODBC;
113 : 0 : else if ( isNativeUrl(_sUrl ) )
114 : 0 : eRet = D_NATIVE;
115 : 0 : return eRet;
116 : : }
117 : : //--------------------------------------------------------------------
118 : 0 : ::rtl::OUString transformUrl(const ::rtl::OUString& _sUrl)
119 : : {
120 : 0 : ::rtl::OUString sNewUrl = _sUrl.copy(11);
121 : 0 : if ( isOdbcUrl( _sUrl ) )
122 : 0 : sNewUrl = ::rtl::OUString("sdbc:") + sNewUrl;
123 : 0 : else if ( isNativeUrl( _sUrl ) )
124 : 0 : sNewUrl = ::rtl::OUString("sdbc:") + sNewUrl;
125 : : else
126 : : {
127 : 0 : sNewUrl = sNewUrl.copy(5);
128 : :
129 : 0 : ::rtl::OUString sTempUrl = ::rtl::OUString("jdbc:mysql://");
130 : :
131 : 0 : sTempUrl += sNewUrl;
132 : 0 : sNewUrl = sTempUrl;
133 : : }
134 : 0 : return sNewUrl;
135 : : }
136 : : //--------------------------------------------------------------------
137 : 0 : Reference< XDriver > lcl_loadDriver(const Reference< XMultiServiceFactory >& _rxFactory,const ::rtl::OUString& _sUrl)
138 : : {
139 : 0 : Reference<XDriverAccess> xDriverAccess(_rxFactory->createInstance(::rtl::OUString("com.sun.star.sdbc.DriverManager") ),UNO_QUERY);
140 : : OSL_ENSURE(xDriverAccess.is(),"Could not load driver manager!");
141 : 0 : Reference< XDriver > xDriver;
142 : 0 : if ( xDriverAccess.is() )
143 : 0 : xDriver = xDriverAccess->getDriverByURL(_sUrl);
144 : 0 : return xDriver;
145 : : }
146 : : //--------------------------------------------------------------------
147 : 0 : Sequence< PropertyValue > lcl_convertProperties(T_DRIVERTYPE _eType,const Sequence< PropertyValue >& info,const ::rtl::OUString& _sUrl)
148 : : {
149 : 0 : ::std::vector<PropertyValue> aProps;
150 : 0 : const PropertyValue* pSupported = info.getConstArray();
151 : 0 : const PropertyValue* pEnd = pSupported + info.getLength();
152 : :
153 : 0 : aProps.reserve(info.getLength() + 5);
154 : 0 : for (;pSupported != pEnd; ++pSupported)
155 : : {
156 : 0 : aProps.push_back( *pSupported );
157 : : }
158 : :
159 : 0 : if ( _eType == D_ODBC )
160 : : {
161 : : aProps.push_back( PropertyValue(
162 : : ::rtl::OUString("Silent")
163 : : ,0
164 : : ,makeAny(sal_True)
165 : 0 : ,PropertyState_DIRECT_VALUE) );
166 : : aProps.push_back( PropertyValue(
167 : : ::rtl::OUString("PreventGetVersionColumns")
168 : : ,0
169 : : ,makeAny(sal_True)
170 : 0 : ,PropertyState_DIRECT_VALUE) );
171 : : }
172 : 0 : else if ( _eType == D_JDBC )
173 : : {
174 : : aProps.push_back( PropertyValue(
175 : : ::rtl::OUString("JavaDriverClass")
176 : : ,0
177 : : ,makeAny(::rtl::OUString("com.mysql.jdbc.Driver"))
178 : 0 : ,PropertyState_DIRECT_VALUE) );
179 : : }
180 : : else
181 : : {
182 : : aProps.push_back( PropertyValue(
183 : : ::rtl::OUString("PublicConnectionURL")
184 : : ,0
185 : : ,makeAny(_sUrl)
186 : 0 : ,PropertyState_DIRECT_VALUE) );
187 : : }
188 : : aProps.push_back( PropertyValue(
189 : : ::rtl::OUString("IsAutoRetrievingEnabled")
190 : : ,0
191 : : ,makeAny(sal_True)
192 : 0 : ,PropertyState_DIRECT_VALUE) );
193 : : aProps.push_back( PropertyValue(
194 : : ::rtl::OUString("AutoRetrievingStatement")
195 : : ,0
196 : : ,makeAny(::rtl::OUString("SELECT LAST_INSERT_ID()"))
197 : 0 : ,PropertyState_DIRECT_VALUE) );
198 : : aProps.push_back( PropertyValue(
199 : : ::rtl::OUString("ParameterNameSubstitution")
200 : : ,0
201 : : ,makeAny(sal_True)
202 : 0 : ,PropertyState_DIRECT_VALUE) );
203 : 0 : PropertyValue* pProps = aProps.empty() ? 0 : &aProps[0];
204 : 0 : return Sequence< PropertyValue >(pProps, aProps.size());
205 : : }
206 : : }
207 : : //--------------------------------------------------------------------
208 : 0 : Reference< XDriver > ODriverDelegator::loadDriver( const ::rtl::OUString& url, const Sequence< PropertyValue >& info )
209 : : {
210 : 0 : Reference< XDriver > xDriver;
211 : 0 : const ::rtl::OUString sCuttedUrl = transformUrl(url);
212 : 0 : const T_DRIVERTYPE eType = lcl_getDriverType( url );
213 : 0 : if ( eType == D_ODBC )
214 : : {
215 : 0 : if ( !m_xODBCDriver.is() )
216 : 0 : m_xODBCDriver = lcl_loadDriver(m_xFactory,sCuttedUrl);
217 : 0 : xDriver = m_xODBCDriver;
218 : : } // if ( bIsODBC )
219 : 0 : else if ( eType == D_NATIVE )
220 : : {
221 : 0 : if ( !m_xNativeDriver.is() )
222 : 0 : m_xNativeDriver = lcl_loadDriver(m_xFactory,sCuttedUrl);
223 : 0 : xDriver = m_xNativeDriver;
224 : : }
225 : : else
226 : : {
227 : 0 : ::comphelper::NamedValueCollection aSettings( info );
228 : 0 : ::rtl::OUString sDriverClass("com.mysql.jdbc.Driver");
229 : 0 : sDriverClass = aSettings.getOrDefault( "JavaDriverClass", sDriverClass );
230 : :
231 : 0 : TJDBCDrivers::iterator aFind = m_aJdbcDrivers.find(sDriverClass);
232 : 0 : if ( aFind == m_aJdbcDrivers.end() )
233 : 0 : aFind = m_aJdbcDrivers.insert(TJDBCDrivers::value_type(sDriverClass,lcl_loadDriver(m_xFactory,sCuttedUrl))).first;
234 : 0 : xDriver = aFind->second;
235 : : }
236 : :
237 : 0 : return xDriver;
238 : : }
239 : :
240 : : //--------------------------------------------------------------------
241 : 0 : Reference< XConnection > SAL_CALL ODriverDelegator::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException)
242 : : {
243 : 0 : Reference< XConnection > xConnection;
244 : 0 : if ( acceptsURL(url) )
245 : : {
246 : 0 : Reference< XDriver > xDriver;
247 : 0 : xDriver = loadDriver(url,info);
248 : 0 : if ( xDriver.is() )
249 : : {
250 : 0 : ::rtl::OUString sCuttedUrl = transformUrl(url);
251 : 0 : const T_DRIVERTYPE eType = lcl_getDriverType( url );
252 : 0 : Sequence< PropertyValue > aConvertedProperties = lcl_convertProperties(eType,info,url);
253 : 0 : if ( eType == D_JDBC )
254 : : {
255 : 0 : ::comphelper::NamedValueCollection aSettings( info );
256 : 0 : ::rtl::OUString sIanaName = aSettings.getOrDefault( "CharSet", ::rtl::OUString() );
257 : 0 : if ( !sIanaName.isEmpty() )
258 : : {
259 : 0 : ::dbtools::OCharsetMap aLookupIanaName;
260 : 0 : ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
261 : 0 : if (aLookup != aLookupIanaName.end() )
262 : : {
263 : 0 : ::rtl::OUString sAdd;
264 : 0 : if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
265 : : {
266 : 0 : static const ::rtl::OUString s_sCharSetOp("useUnicode=true&");
267 : 0 : if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
268 : : {
269 : 0 : sAdd = s_sCharSetOp;
270 : : } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) )
271 : : } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() )
272 : 0 : if ( sCuttedUrl.indexOf('?') == -1 )
273 : 0 : sCuttedUrl += ::rtl::OUString("?");
274 : : else
275 : 0 : sCuttedUrl += ::rtl::OUString("&");
276 : 0 : sCuttedUrl += sAdd;
277 : 0 : sCuttedUrl += ::rtl::OUString("characterEncoding=");
278 : 0 : sCuttedUrl += sIanaName;
279 : 0 : }
280 : 0 : }
281 : : } // if ( !bIsODBC )
282 : :
283 : 0 : xConnection = xDriver->connect( sCuttedUrl, aConvertedProperties );
284 : 0 : if ( xConnection.is() )
285 : : {
286 : 0 : OMetaConnection* pMetaConnection = NULL;
287 : : // now we have to set the URL to get the correct answer for metadata()->getURL()
288 : 0 : Reference< XUnoTunnel> xTunnel(xConnection,UNO_QUERY);
289 : 0 : if ( xTunnel.is() )
290 : : {
291 : 0 : pMetaConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
292 : 0 : if ( pMetaConnection )
293 : 0 : pMetaConnection->setURL(url);
294 : : }
295 : 0 : m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xConnection),TWeakConnectionPair(WeakReferenceHelper(),pMetaConnection)));
296 : 0 : }
297 : 0 : }
298 : : }
299 : 0 : return xConnection;
300 : : }
301 : :
302 : : //--------------------------------------------------------------------
303 : 0 : sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const ::rtl::OUString& url ) throw (SQLException, RuntimeException)
304 : : {
305 : 0 : Sequence< PropertyValue > info;
306 : :
307 : 0 : sal_Bool bOK = url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:odbc:" ) )
308 : 0 : || url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:jdbc:" ) )
309 : 0 : || ( url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc:" ) )
310 : 0 : && loadDriver( url, info ).is()
311 : 0 : );
312 : 0 : return bOK;
313 : : }
314 : :
315 : : //--------------------------------------------------------------------
316 : 0 : Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const ::rtl::OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, RuntimeException)
317 : : {
318 : 0 : ::std::vector< DriverPropertyInfo > aDriverInfo;
319 : 0 : if ( !acceptsURL(url) )
320 : 0 : return Sequence< DriverPropertyInfo >();
321 : :
322 : 0 : Sequence< ::rtl::OUString > aBoolean(2);
323 : 0 : aBoolean[0] = ::rtl::OUString("0");
324 : 0 : aBoolean[1] = ::rtl::OUString("1");
325 : :
326 : :
327 : : aDriverInfo.push_back(DriverPropertyInfo(
328 : : ::rtl::OUString("CharSet")
329 : : ,::rtl::OUString("CharSet of the database.")
330 : : ,sal_False
331 : : ,::rtl::OUString()
332 : : ,Sequence< ::rtl::OUString >())
333 : 0 : );
334 : : aDriverInfo.push_back(DriverPropertyInfo(
335 : : ::rtl::OUString("SuppressVersionColumns")
336 : : ,::rtl::OUString("Display version columns (when available).")
337 : : ,sal_False
338 : : ,::rtl::OUString("0")
339 : : ,aBoolean)
340 : 0 : );
341 : 0 : const T_DRIVERTYPE eType = lcl_getDriverType( url );
342 : 0 : if ( eType == D_JDBC )
343 : : {
344 : : aDriverInfo.push_back(DriverPropertyInfo(
345 : : ::rtl::OUString("JavaDriverClass")
346 : : ,::rtl::OUString("The JDBC driver class name.")
347 : : ,sal_True
348 : : ,::rtl::OUString("com.mysql.jdbc.Driver")
349 : : ,Sequence< ::rtl::OUString >())
350 : 0 : );
351 : : }
352 : :
353 : 0 : return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size());
354 : : }
355 : :
356 : : //--------------------------------------------------------------------
357 : 0 : sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion( ) throw (RuntimeException)
358 : : {
359 : 0 : return 1;
360 : : }
361 : :
362 : : //--------------------------------------------------------------------
363 : 0 : sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion( ) throw (RuntimeException)
364 : : {
365 : 0 : return 0;
366 : : }
367 : :
368 : : //--------------------------------------------------------------------
369 : 0 : Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException)
370 : : {
371 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
372 : 0 : checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed);
373 : :
374 : 0 : Reference< XTablesSupplier > xTab;
375 : 0 : Reference< XUnoTunnel> xTunnel(connection,UNO_QUERY);
376 : 0 : if ( xTunnel.is() )
377 : : {
378 : 0 : OMetaConnection* pConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
379 : 0 : if ( pConnection )
380 : : {
381 : 0 : TWeakPairVector::iterator aEnd = m_aConnections.end();
382 : 0 : for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
383 : : {
384 : 0 : if ( i->second.second == pConnection )
385 : : {
386 : 0 : xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY);
387 : 0 : if ( !xTab.is() )
388 : : {
389 : 0 : xTab = new OMySQLCatalog(connection);
390 : 0 : i->second.first = WeakReferenceHelper(xTab);
391 : : }
392 : 0 : break;
393 : : }
394 : : }
395 : : }
396 : : } // if ( xTunnel.is() )
397 : 0 : if ( !xTab.is() )
398 : : {
399 : 0 : TWeakPairVector::iterator aEnd = m_aConnections.end();
400 : 0 : for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
401 : : {
402 : 0 : Reference< XConnection > xTemp(i->first.get(),UNO_QUERY);
403 : 0 : if ( xTemp == connection )
404 : : {
405 : 0 : xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY);
406 : 0 : if ( !xTab.is() )
407 : : {
408 : 0 : xTab = new OMySQLCatalog(connection);
409 : 0 : i->second.first = WeakReferenceHelper(xTab);
410 : : }
411 : : break;
412 : : }
413 : 0 : }
414 : : }
415 : 0 : return xTab;
416 : : }
417 : :
418 : : //--------------------------------------------------------------------
419 : 0 : Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException)
420 : : {
421 : 0 : if ( ! acceptsURL(url) )
422 : : {
423 : 0 : ::connectivity::SharedResources aResources;
424 : 0 : const ::rtl::OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
425 : 0 : ::dbtools::throwGenericSQLException(sMessage ,*this);
426 : : } // if ( ! acceptsURL(url) )
427 : :
428 : 0 : return getDataDefinitionByConnection(connect(url,info));
429 : : }
430 : :
431 : : // XServiceInfo
432 : : // --------------------------------------------------------------------------------
433 : : //------------------------------------------------------------------------------
434 : 0 : rtl::OUString ODriverDelegator::getImplementationName_Static( ) throw(RuntimeException)
435 : : {
436 : 0 : return rtl::OUString("org.openoffice.comp.drivers.MySQL.Driver");
437 : : }
438 : : //------------------------------------------------------------------------------
439 : 0 : Sequence< ::rtl::OUString > ODriverDelegator::getSupportedServiceNames_Static( ) throw (RuntimeException)
440 : : {
441 : 0 : Sequence< ::rtl::OUString > aSNS( 2 );
442 : 0 : aSNS[0] = ::rtl::OUString("com.sun.star.sdbc.Driver");
443 : 0 : aSNS[1] = ::rtl::OUString("com.sun.star.sdbcx.Driver");
444 : 0 : return aSNS;
445 : : }
446 : : //------------------------------------------------------------------
447 : 0 : ::rtl::OUString SAL_CALL ODriverDelegator::getImplementationName( ) throw(RuntimeException)
448 : : {
449 : 0 : return getImplementationName_Static();
450 : : }
451 : :
452 : : //------------------------------------------------------------------
453 : 0 : sal_Bool SAL_CALL ODriverDelegator::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
454 : : {
455 : 0 : Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
456 : 0 : const ::rtl::OUString* pSupported = aSupported.getConstArray();
457 : 0 : const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
458 : 0 : for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
459 : : ;
460 : :
461 : 0 : return pSupported != pEnd;
462 : : }
463 : : //------------------------------------------------------------------
464 : 0 : Sequence< ::rtl::OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames( ) throw(RuntimeException)
465 : : {
466 : 0 : return getSupportedServiceNames_Static();
467 : : }
468 : : //------------------------------------------------------------------
469 : : //........................................................................
470 : : } // namespace connectivity
471 : : //........................................................................
472 : :
473 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|