xref: /trunk/main/mysqlc/source/mysqlc_driver.cxx (revision fc9fd3f14a55d77b35643a64034752a178b2a5b0)
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