1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2008 by Sun Microsystems, Inc. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * $RCSfile: mysqlc_driver.cxx,v $ 9 * 10 * $Revision: 1.1.2.5 $ 11 * 12 * This file is part of OpenOffice.org. 13 * 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. 17 * 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). 23 * 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. 28 ************************************************************************/ 29 #include "mysqlc_driver.hxx" 30 #include "mysqlc_connection.hxx" 31 #include "mysqlc_general.hxx" 32 33 using namespace com::sun::star::uno; 34 using namespace com::sun::star::lang; 35 using namespace com::sun::star::beans; 36 using namespace com::sun::star::sdbc; 37 using namespace connectivity::mysqlc; 38 using ::rtl::OUString; 39 #include <stdio.h> 40 41 #include <preextstl.h> 42 #include <cppconn/exception.h> 43 #ifdef SYSTEM_MYSQL_CPPCONN 44 #include <mysql_driver.h> 45 #endif 46 #include <postextstl.h> 47 48 49 /* {{{ MysqlCDriver::MysqlCDriver() -I- */ 50 MysqlCDriver::MysqlCDriver(const Reference< XMultiServiceFactory >& _rxFactory) 51 : ODriver_BASE(m_aMutex) 52 ,m_xFactory(_rxFactory) 53 #ifndef SYSTEM_MYSQL_CPPCONN 54 ,m_hCppConnModule( NULL ) 55 ,m_bAttemptedLoadCppConn( false ) 56 #endif 57 { 58 OSL_TRACE("MysqlCDriver::MysqlCDriver"); 59 cppDriver = NULL; 60 } 61 /* }}} */ 62 63 64 /* {{{ MysqlCDriver::disposing() -I- */ 65 void MysqlCDriver::disposing() 66 { 67 OSL_TRACE("MysqlCDriver::disposing"); 68 ::osl::MutexGuard aGuard(m_aMutex); 69 70 // when driver will be destroied so all our connections have to be destroied as well 71 for (OWeakRefArray::iterator i = m_xConnections.begin(); m_xConnections.end() != i; ++i) 72 { 73 Reference< XComponent > xComp(i->get(), UNO_QUERY); 74 if (xComp.is()) { 75 xComp->dispose(); 76 } 77 } 78 m_xConnections.clear(); 79 80 ODriver_BASE::disposing(); 81 } 82 /* }}} */ 83 84 85 // static ServiceInfo 86 /* {{{ MysqlCDriver::getImplementationName_Static() -I- */ 87 OUString MysqlCDriver::getImplementationName_Static() 88 throw(RuntimeException) 89 { 90 OSL_TRACE("MysqlCDriver::getImplementationName_Static"); 91 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sdbc.mysqlc.MysqlCDriver" ) ); 92 } 93 /* }}} */ 94 95 96 /* {{{ MysqlCDriver::getSupportedServiceNames_Static() -I- */ 97 Sequence< OUString > MysqlCDriver::getSupportedServiceNames_Static() 98 throw(RuntimeException) 99 { 100 OSL_TRACE("MysqlCDriver::getSupportedServiceNames_Static"); 101 // which service is supported 102 // for more information @see com.sun.star.sdbc.Driver 103 Sequence< OUString > aSNS(1); 104 aSNS[0] = OUString::createFromAscii("com.sun.star.sdbc.Driver"); 105 return aSNS; 106 } 107 /* }}} */ 108 109 110 /* {{{ MysqlCDriver::getImplementationName() -I- */ 111 OUString SAL_CALL MysqlCDriver::getImplementationName() 112 throw(RuntimeException) 113 { 114 OSL_TRACE("MysqlCDriver::getImplementationName"); 115 return getImplementationName_Static(); 116 } 117 /* }}} */ 118 119 120 /* {{{ MysqlCDriver::supportsService() -I- */ 121 sal_Bool SAL_CALL MysqlCDriver::supportsService(const OUString& _rServiceName) 122 throw(RuntimeException) 123 { 124 OSL_TRACE("MysqlCDriver::supportsService"); 125 Sequence< OUString > aSupported(getSupportedServiceNames()); 126 const OUString* pSupported = aSupported.getConstArray(); 127 const OUString* pEnd = pSupported + aSupported.getLength(); 128 for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported){} 129 130 return (pSupported != pEnd); 131 } 132 /* }}} */ 133 134 135 /* {{{ MysqlCDriver::getSupportedServiceNames() -I- */ 136 Sequence< OUString > SAL_CALL MysqlCDriver::getSupportedServiceNames() 137 throw(RuntimeException) 138 { 139 OSL_TRACE("MysqlCDriver::getSupportedServiceNames"); 140 return getSupportedServiceNames_Static(); 141 } 142 /* }}} */ 143 144 145 extern "C" { static void SAL_CALL thisModule() {} } 146 147 void MysqlCDriver::impl_initCppConn_lck_throw() 148 { 149 #ifdef SYSTEM_MYSQL_CPPCONN 150 cppDriver = get_driver_instance(); 151 #else 152 if ( !m_bAttemptedLoadCppConn ) 153 { 154 const ::rtl::OUString sModuleName = ::rtl::OUString::createFromAscii( CPPCONN_LIB ); 155 m_hCppConnModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, 0 ); 156 m_bAttemptedLoadCppConn = true; 157 } 158 159 // attempted to load - was it successful? 160 if ( !m_hCppConnModule ) 161 { 162 OSL_ENSURE( false, "MysqlCDriver::impl_initCppConn_lck_throw: could not load the " CPPCONN_LIB " library!"); 163 throw SQLException( 164 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unable to load the " CPPCONN_LIB " library." ) ), 165 *this, 166 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "08001" ) ), // "unable to connect" 167 0, 168 Any() 169 ); 170 } 171 172 // find the factory symbol 173 const ::rtl::OUString sSymbolName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "sql_mysql_get_driver_instance" ) ); 174 typedef void* (* FGetMySQLDriver)(); 175 176 const FGetMySQLDriver pFactoryFunction = (FGetMySQLDriver)( osl_getFunctionSymbol( m_hCppConnModule, sSymbolName.pData ) ); 177 if ( !pFactoryFunction ) 178 { 179 OSL_ENSURE( false, "MysqlCDriver::impl_initCppConn_lck_throw: could not find the factory symbol in " CPPCONN_LIB "!"); 180 throw SQLException( 181 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CPPCONN_LIB " is invalid: missing the driver factory function." ) ), 182 *this, 183 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "08001" ) ), // "unable to connect" 184 0, 185 Any() 186 ); 187 } 188 189 cppDriver = static_cast< sql::Driver* >( (*pFactoryFunction)() ); 190 #endif 191 if ( !cppDriver ) 192 { 193 throw SQLException( 194 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unable to obtain the MySQL_Driver instance from Connector/C++." ) ), 195 *this, 196 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "08001" ) ), // "unable to connect" 197 0, 198 Any() 199 ); 200 } 201 } 202 203 /* {{{ MysqlCDriver::connect() -I- */ 204 Reference< XConnection > SAL_CALL MysqlCDriver::connect(const OUString& url, const Sequence< PropertyValue >& info) 205 throw(SQLException, RuntimeException) 206 { 207 ::osl::MutexGuard aGuard( m_aMutex ); 208 209 OSL_TRACE("MysqlCDriver::connect"); 210 if (!acceptsURL(url)) { 211 return NULL; 212 } 213 214 if ( !cppDriver ) 215 { 216 impl_initCppConn_lck_throw(); 217 OSL_POSTCOND( cppDriver, "MySQLCDriver::connect: internal error." ); 218 if ( !cppDriver ) 219 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MySQLCDriver::connect: internal error." ) ), *this ); 220 } 221 222 Reference< XConnection > xConn; 223 // create a new connection with the given properties and append it to our vector 224 try { 225 OConnection* pCon = new OConnection(*this, cppDriver); 226 xConn = pCon; 227 228 pCon->construct(url,info); 229 m_xConnections.push_back(WeakReferenceHelper(*pCon)); 230 } 231 catch (sql::SQLException &e) 232 { 233 mysqlc_sdbc_driver::translateAndThrow(e, *this, getDefaultEncoding()); 234 } 235 return xConn; 236 } 237 /* }}} */ 238 239 240 /* {{{ MysqlCDriver::acceptsURL() -I- */ 241 sal_Bool SAL_CALL MysqlCDriver::acceptsURL(const OUString& url) 242 throw(SQLException, RuntimeException) 243 { 244 OSL_TRACE("MysqlCDriver::acceptsURL"); 245 return (!url.compareTo(OUString::createFromAscii("sdbc:mysqlc:"), sizeof("sdbc:mysqlc:")-1)); 246 } 247 /* }}} */ 248 249 250 /* {{{ MysqlCDriver::getPropertyInfo() -I- */ 251 Sequence< DriverPropertyInfo > SAL_CALL MysqlCDriver::getPropertyInfo(const OUString& url, const Sequence< PropertyValue >& /* info */) 252 throw(SQLException, RuntimeException) 253 { 254 OSL_TRACE("MysqlCDriver::getPropertyInfo"); 255 if (acceptsURL(url)) { 256 ::std::vector< DriverPropertyInfo > aDriverInfo; 257 258 aDriverInfo.push_back(DriverPropertyInfo( 259 OUString(RTL_CONSTASCII_USTRINGPARAM("Hostname")) 260 ,OUString(RTL_CONSTASCII_USTRINGPARAM("Name of host")) 261 ,sal_True 262 ,OUString::createFromAscii("localhost") 263 ,Sequence< OUString >()) 264 ); 265 aDriverInfo.push_back(DriverPropertyInfo( 266 OUString(RTL_CONSTASCII_USTRINGPARAM("Port")) 267 ,OUString(RTL_CONSTASCII_USTRINGPARAM("Port")) 268 ,sal_True 269 ,OUString::createFromAscii("3306") 270 ,Sequence< OUString >()) 271 ); 272 return Sequence< DriverPropertyInfo >(&(aDriverInfo[0]),aDriverInfo.size()); 273 } 274 275 return Sequence< DriverPropertyInfo >(); 276 } 277 /* }}} */ 278 279 280 /* {{{ MysqlCDriver::getMajorVersion() -I- */ 281 sal_Int32 SAL_CALL MysqlCDriver::getMajorVersion() 282 throw(RuntimeException) 283 { 284 OSL_TRACE("MysqlCDriver::getMajorVersion"); 285 return MYSQLC_VERSION_MAJOR; 286 } 287 /* }}} */ 288 289 290 /* {{{ MysqlCDriver::getMinorVersion() -I- */ 291 sal_Int32 SAL_CALL MysqlCDriver::getMinorVersion() 292 throw(RuntimeException) 293 { 294 OSL_TRACE("MysqlCDriver::getMinorVersion"); 295 return MYSQLC_VERSION_MINOR; 296 } 297 /* }}} */ 298 299 300 namespace connectivity 301 { 302 namespace mysqlc 303 { 304 305 Reference< XInterface > SAL_CALL MysqlCDriver_CreateInstance(const Reference< XMultiServiceFactory >& _rxFactory) 306 throw(::com::sun::star::uno::Exception) 307 { 308 return(*(new MysqlCDriver(_rxFactory))); 309 } 310 311 /* {{{ connectivity::mysqlc::release() -I- */ 312 void release(oslInterlockedCount& _refCount, 313 ::cppu::OBroadcastHelper& rBHelper, 314 Reference< XInterface >& _xInterface, 315 ::com::sun::star::lang::XComponent* _pObject) 316 { 317 if (osl_decrementInterlockedCount(&_refCount) == 0) { 318 osl_incrementInterlockedCount(&_refCount); 319 320 if (!rBHelper.bDisposed && !rBHelper.bInDispose) { 321 // remember the parent 322 Reference< XInterface > xParent; 323 { 324 ::osl::MutexGuard aGuard(rBHelper.rMutex); 325 xParent = _xInterface; 326 _xInterface = NULL; 327 } 328 329 // First dispose 330 _pObject->dispose(); 331 332 // only the alive ref holds the object 333 OSL_ASSERT(_refCount == 1); 334 335 // release the parent in the destructor 336 if (xParent.is()) { 337 ::osl::MutexGuard aGuard(rBHelper.rMutex); 338 _xInterface = xParent; 339 } 340 } 341 } else { 342 osl_incrementInterlockedCount(&_refCount); 343 } 344 } 345 /* }}} */ 346 347 348 349 /* {{{ connectivity::mysqlc::checkDisposed() -I- */ 350 void checkDisposed(sal_Bool _bThrow) 351 throw (DisposedException) 352 { 353 if (_bThrow) { 354 throw DisposedException(); 355 } 356 } 357 /* }}} */ 358 359 } /* mysqlc */ 360 } /* connectivity */ 361 362 /* 363 * Local variables: 364 * tab-width: 4 365 * c-basic-offset: 4 366 * End: 367 * vim600: noet sw=4 ts=4 fdm=marker 368 * vim<600: noet sw=4 ts=4 369 */ 370