update dev300-m58
[ooovba.git] / connectivity / source / drivers / kab / KDriver.cxx
blob59398f2c141b1c8949ad204521af78ce33edb394
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: KDriver.cxx,v $
10 * $Revision: 1.10.56.2 $
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"
34 #include "KDriver.hxx"
35 #include "KDEInit.h"
36 #include "KConnection.hxx"
38 /** === begin UNO includes === **/
39 #include <com/sun/star/sdb/SQLContext.hpp>
40 #include <com/sun/star/lang/NullPointerException.hpp>
41 #include <com/sun/star/frame/XDesktop.hpp>
42 /** === end UNO includes === **/
43 #include <rtl/ustrbuf.hxx>
44 #include <tools/diagnose_ex.h>
45 #include "resource/kab_res.hrc"
46 #include "resource/sharedresources.hxx"
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::lang;
50 using namespace com::sun::star::beans;
51 using namespace com::sun::star::sdbc;
52 using namespace com::sun::star::sdb;
53 using namespace com::sun::star::frame;
54 using namespace connectivity::kab;
56 // =======================================================================
57 // = KabImplModule
58 // =======================================================================
59 // --------------------------------------------------------------------------------
60 KabImplModule::KabImplModule( const Reference< XMultiServiceFactory >& _rxFactory )
61 :m_xORB(_rxFactory)
62 ,m_bAttemptedLoadModule(false)
63 ,m_bAttemptedInitialize(false)
64 ,m_hConnectorModule(NULL)
65 ,m_pConnectionFactoryFunc(NULL)
66 ,m_pApplicationInitFunc(NULL)
67 ,m_pApplicationShutdownFunc(NULL)
68 ,m_pKDEVersionCheckFunc(NULL)
70 if ( !m_xORB.is() )
71 throw NullPointerException();
74 // --------------------------------------------------------------------------------
75 bool KabImplModule::isKDEPresent()
77 if ( !impl_loadModule() )
78 return false;
80 return true;
83 // --------------------------------------------------------------------------------
84 KabImplModule::KDEVersionType KabImplModule::matchKDEVersion()
86 OSL_PRECOND( m_pKDEVersionCheckFunc, "KabImplModule::matchKDEVersion: module not loaded!" );
88 int nVersionInfo = (*m_pKDEVersionCheckFunc)();
89 if ( nVersionInfo < 0 )
90 return eTooOld;
91 if ( nVersionInfo > 0 )
92 return eToNew;
93 return eSupported;
96 // --------------------------------------------------------------------------------
97 namespace
99 template< typename FUNCTION >
100 void lcl_getFunctionFromModuleOrUnload( oslModule& _rModule, const sal_Char* _pAsciiSymbolName, FUNCTION& _rFunction )
102 _rFunction = NULL;
103 if ( _rModule )
106 const ::rtl::OUString sSymbolName = ::rtl::OUString::createFromAscii( _pAsciiSymbolName );
107 _rFunction = (FUNCTION)( osl_getSymbol( _rModule, sSymbolName.pData ) );
109 if ( !_rFunction )
110 { // did not find the symbol
111 OSL_ENSURE( false, ::rtl::OString( "lcl_getFunctionFromModuleOrUnload: could not find the symbol " ) + ::rtl::OString( _pAsciiSymbolName ) );
112 osl_unloadModule( _rModule );
113 _rModule = NULL;
119 // --------------------------------------------------------------------------------
120 extern "C" { void SAL_CALL thisModule() {} }
122 bool KabImplModule::impl_loadModule()
124 if ( m_bAttemptedLoadModule )
125 return ( m_hConnectorModule != NULL );
126 m_bAttemptedLoadModule = true;
128 OSL_ENSURE( !m_hConnectorModule && !m_pConnectionFactoryFunc && !m_pApplicationInitFunc && !m_pApplicationShutdownFunc && !m_pKDEVersionCheckFunc,
129 "KabImplModule::impl_loadModule: inconsistence: inconsistency (never attempted load before, but some values already set)!");
131 const ::rtl::OUString sModuleName = ::rtl::OUString::createFromAscii( SAL_MODULENAME( "kabdrv1" ) );
132 m_hConnectorModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, SAL_LOADMODULE_NOW ); // LAZY! #i61335#
133 OSL_ENSURE( m_hConnectorModule, "KabImplModule::impl_loadModule: could not load the implementation library!" );
134 if ( !m_hConnectorModule )
135 return false;
137 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "createKabConnection", m_pConnectionFactoryFunc );
138 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "initKApplication", m_pApplicationInitFunc );
139 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "shutdownKApplication", m_pApplicationShutdownFunc );
140 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "matchKDEVersion", m_pKDEVersionCheckFunc );
142 if ( !m_hConnectorModule )
143 // one of the symbols did not exist
144 throw RuntimeException();
146 return true;
149 // --------------------------------------------------------------------------------
150 void KabImplModule::impl_unloadModule()
152 OSL_PRECOND( m_hConnectorModule != NULL, "KabImplModule::impl_unloadModule: no module!" );
154 osl_unloadModule( m_hConnectorModule );
155 m_hConnectorModule = NULL;
157 m_pConnectionFactoryFunc = NULL;
158 m_pApplicationInitFunc = NULL;
159 m_pApplicationShutdownFunc = NULL;
160 m_pKDEVersionCheckFunc = NULL;
162 m_bAttemptedLoadModule = false;
165 // --------------------------------------------------------------------------------
166 void KabImplModule::init()
168 if ( !impl_loadModule() )
169 impl_throwNoKdeException();
171 // if we're not running on a supported version, throw
172 KabImplModule::KDEVersionType eKDEVersion = matchKDEVersion();
174 if ( eKDEVersion == eTooOld )
175 impl_throwKdeTooOldException();
177 if ( ( eKDEVersion == eToNew ) && !impl_doAllowNewKDEVersion() )
178 impl_throwKdeTooNewException();
180 if ( !m_bAttemptedInitialize )
182 m_bAttemptedInitialize = true;
183 (*m_pApplicationInitFunc)();
187 // --------------------------------------------------------------------------------
188 bool KabImplModule::impl_doAllowNewKDEVersion()
192 Reference< XMultiServiceFactory > xConfigProvider(
193 m_xORB->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ) ),
194 UNO_QUERY_THROW );
195 Sequence< Any > aCreationArgs(1);
196 aCreationArgs[0] <<= PropertyValue(
197 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ),
199 makeAny( KabDriver::impl_getConfigurationSettingsPath() ),
200 PropertyState_DIRECT_VALUE );
201 Reference< XPropertySet > xSettings( xConfigProvider->createInstanceWithArguments(
202 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) ),
203 aCreationArgs ),
204 UNO_QUERY_THROW );
206 sal_Bool bDisableCheck = sal_False;
207 xSettings->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableKDEMaximumVersionCheck" ) ) ) >>= bDisableCheck;
209 return bDisableCheck != sal_False;
211 catch( const Exception& )
213 DBG_UNHANDLED_EXCEPTION();
215 return false;
218 // --------------------------------------------------------------------------------
219 void KabImplModule::impl_throwNoKdeException()
221 ::connectivity::SharedResources aResources;
222 const ::rtl::OUString sError( aResources.getResourceString(
223 STR_NO_KDE_INST
224 ) );
225 impl_throwGenericSQLException( sError );
228 // --------------------------------------------------------------------------------
229 void KabImplModule::impl_throwKdeTooOldException()
231 ::connectivity::SharedResources aResources;
232 const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(
233 STR_KDE_VERSION_TOO_OLD,
234 "$major$",::rtl::OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MAJOR),
235 "$minor$",::rtl::OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MINOR)
236 ) );
237 impl_throwGenericSQLException( sError );
240 // --------------------------------------------------------------------------------
241 void KabImplModule::impl_throwGenericSQLException( const ::rtl::OUString& _rMessage )
243 SQLException aError;
244 aError.Message = _rMessage;
245 aError.SQLState = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) );
246 aError.ErrorCode = 0;
247 throw aError;
250 // --------------------------------------------------------------------------------
251 void KabImplModule::impl_throwKdeTooNewException()
253 ::connectivity::SharedResources aResources;
255 SQLException aError;
256 aError.Message = aResources.getResourceStringWithSubstitution(
257 STR_KDE_VERSION_TOO_NEW,
258 "$major$",::rtl::OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MAJOR),
259 "$minor$",::rtl::OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MINOR)
261 aError.SQLState = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) );
262 aError.ErrorCode = 0;
264 SQLContext aDetails;
265 ::rtl::OUStringBuffer aMessage;
266 aMessage.append( aResources.getResourceString(STR_KDE_VERSION_TOO_NEW_WORK_AROUND) );
268 aMessage.appendAscii( "Sub disableKDEMaxVersionCheck\n" );
269 aMessage.appendAscii( " BasicLibraries.LoadLibrary( \"Tools\" )\n" );
271 aMessage.appendAscii( " Dim configNode as Object\n" );
272 aMessage.appendAscii( " configNode = GetRegistryKeyContent( \"" );
273 aMessage.append( KabDriver::impl_getConfigurationSettingsPath() );
274 aMessage.appendAscii( "\", true )\n" );
276 aMessage.appendAscii( " configNode.DisableKDEMaximumVersionCheck = TRUE\n" );
277 aMessage.appendAscii( " configNode.commitChanges\n" );
278 aMessage.appendAscii( "End Sub\n" );
280 aDetails.Message = aMessage.makeStringAndClear();
282 aError.NextException <<= aDetails;
284 throw aError;
287 // --------------------------------------------------------------------------------
288 KabConnection* KabImplModule::createConnection( KabDriver* _pDriver ) const
290 OSL_PRECOND( m_hConnectorModule, "KabImplModule::createConnection: not initialized!" );
292 void* pUntypedConnection = (*m_pConnectionFactoryFunc)( _pDriver );
293 if ( !pUntypedConnection )
294 throw RuntimeException();
296 return static_cast< KabConnection* >( pUntypedConnection );
299 // --------------------------------------------------------------------------------
300 void KabImplModule::shutdown()
302 if ( !m_hConnectorModule )
303 return;
305 (*m_pApplicationShutdownFunc)();
306 m_bAttemptedInitialize = false;
308 impl_unloadModule();
311 // =======================================================================
312 // = KabDriver
313 // =======================================================================
314 KabDriver::KabDriver(
315 const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory)
316 : KDriver_BASE(m_aMutex),
317 m_xMSFactory(_rxFactory),
318 m_aImplModule(_rxFactory)
320 if ( !m_xMSFactory.is() )
321 throw NullPointerException();
323 osl_incrementInterlockedCount( &m_refCount );
326 Reference< XDesktop > xDesktop(
327 m_xMSFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ),
328 UNO_QUERY_THROW );
329 xDesktop->addTerminateListener( this );
331 catch( const Exception& )
333 DBG_UNHANDLED_EXCEPTION();
335 osl_decrementInterlockedCount( &m_refCount );
337 // --------------------------------------------------------------------------------
338 void KabDriver::disposing()
340 ::osl::MutexGuard aGuard(m_aMutex);
342 // when driver will be destroied so all our connections have to be destroied as well
343 for (OWeakRefArray::iterator i = m_xConnections.begin(); m_xConnections.end() != i; ++i)
345 Reference< XComponent > xComp(i->get(), UNO_QUERY);
346 if (xComp.is())
347 xComp->dispose();
349 m_xConnections.clear();
351 WeakComponentImplHelperBase::disposing();
353 // static ServiceInfo
354 //------------------------------------------------------------------------------
355 rtl::OUString KabDriver::getImplementationName_Static( ) throw(RuntimeException)
357 return rtl::OUString::createFromAscii( impl_getAsciiImplementationName() );
359 //------------------------------------------------------------------------------
360 Sequence< ::rtl::OUString > KabDriver::getSupportedServiceNames_Static( ) throw (RuntimeException)
362 // which service is supported
363 // for more information @see com.sun.star.sdbc.Driver
364 Sequence< ::rtl::OUString > aSNS( 1 );
365 aSNS[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.Driver");
367 return aSNS;
369 //------------------------------------------------------------------
370 ::rtl::OUString SAL_CALL KabDriver::getImplementationName( ) throw(RuntimeException)
372 return getImplementationName_Static();
374 //------------------------------------------------------------------
375 sal_Bool SAL_CALL KabDriver::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
377 Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
378 const ::rtl::OUString* pSupported = aSupported.getConstArray();
379 const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
381 while (pSupported != pEnd && !pSupported->equals(_rServiceName))
382 ++pSupported;
383 return pSupported != pEnd;
385 //------------------------------------------------------------------
386 Sequence< ::rtl::OUString > SAL_CALL KabDriver::getSupportedServiceNames( ) throw(RuntimeException)
388 return getSupportedServiceNames_Static();
390 // --------------------------------------------------------------------------------
391 Reference< XConnection > SAL_CALL KabDriver::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw(SQLException, RuntimeException)
393 ::osl::MutexGuard aGuard(m_aMutex);
395 m_aImplModule.init();
397 // create a new connection with the given properties and append it to our vector
398 KabConnection* pConnection = m_aImplModule.createConnection( this );
399 OSL_POSTCOND( pConnection, "KabDriver::connect: no connection has been created by the factory!" );
401 // by definition, the factory function returned an object which was acquired once
402 Reference< XConnection > xConnection = pConnection;
403 pConnection->release();
405 // late constructor call which can throw exception and allows a correct dtor call when so
406 pConnection->construct( url, info );
408 // remember it
409 m_xConnections.push_back( WeakReferenceHelper( *pConnection ) );
411 return xConnection;
413 // --------------------------------------------------------------------------------
414 sal_Bool SAL_CALL KabDriver::acceptsURL( const ::rtl::OUString& url )
415 throw(SQLException, RuntimeException)
417 ::osl::MutexGuard aGuard(m_aMutex);
419 if ( !m_aImplModule.isKDEPresent() )
420 return sal_False;
422 // here we have to look whether we support this URL format
423 return (!url.compareTo(::rtl::OUString::createFromAscii("sdbc:address:kab:"), 16));
425 // --------------------------------------------------------------------------------
426 Sequence< DriverPropertyInfo > SAL_CALL KabDriver::getPropertyInfo( const ::rtl::OUString&, const Sequence< PropertyValue >& ) throw(SQLException, RuntimeException)
428 // if you have something special to say, return it here :-)
429 return Sequence< DriverPropertyInfo >();
431 // --------------------------------------------------------------------------------
432 sal_Int32 SAL_CALL KabDriver::getMajorVersion( ) throw(RuntimeException)
434 return KAB_DRIVER_VERSION_MAJOR;
436 // --------------------------------------------------------------------------------
437 sal_Int32 SAL_CALL KabDriver::getMinorVersion( ) throw(RuntimeException)
439 return KAB_DRIVER_VERSION_MINOR;
441 // --------------------------------------------------------------------------------
442 void SAL_CALL KabDriver::queryTermination( const EventObject& ) throw (TerminationVetoException, RuntimeException)
444 // nothing to do, nothing to veto
446 // --------------------------------------------------------------------------------
447 void SAL_CALL KabDriver::notifyTermination( const EventObject& ) throw (RuntimeException)
449 m_aImplModule.shutdown();
451 // --------------------------------------------------------------------------------
452 void SAL_CALL KabDriver::disposing( const EventObject& ) throw (RuntimeException)
454 // not interested in (this is the disposing of the desktop, if any)
456 // --------------------------------------------------------------------------------
457 const sal_Char* KabDriver::impl_getAsciiImplementationName()
459 return "com.sun.star.comp.sdbc.kab.Driver";
460 // this name is referenced in the configuration and in the kab.xml
461 // Please be careful when changing it.
463 // --------------------------------------------------------------------------------
464 ::rtl::OUString KabDriver::impl_getConfigurationSettingsPath()
466 ::rtl::OUStringBuffer aPath;
467 aPath.appendAscii( "/org.openoffice.Office.DataAccess/DriverSettings/" );
468 aPath.appendAscii( "com.sun.star.comp.sdbc.kab.Driver" );
469 return aPath.makeStringAndClear();
471 // --------------------------------------------------------------------------------
472 Reference< XInterface > SAL_CALL KabDriver::Create( const Reference< XMultiServiceFactory >& _rxFactory ) throw( Exception )
474 return *(new KabDriver(_rxFactory));