Tag: cws_src680_kabrefine User: fs Date: 06/01/06 00:56:26 Modified: /dba/connectivity/source/drivers/kab/ KDEInit.cxx, KDriver.cxx, KDriver.hxx, kabdrv.map
Log: #i60062# some version checks for the proper KDE version File Changes: Directory: /dba/connectivity/source/drivers/kab/ ================================================ File [changed]: KDEInit.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/kab/KDEInit.cxx?r1=1.1.2.3&r2=1.1.2.4 Delta lines: +38 -4 -------------------- --- KDEInit.cxx 6 Jan 2006 07:20:25 -0000 1.1.2.3 +++ KDEInit.cxx 6 Jan 2006 08:56:17 -0000 1.1.2.4 @@ -4,9 +4,9 @@ * * $RCSfile: KDEInit.cxx,v $ * - * $Revision: 1.1.2.3 $ + * $Revision: 1.1.2.4 $ * - * last change: $Author: fs $ $Date: 2006/01/06 07:20:25 $ + * last change: $Author: fs $ $Date: 2006/01/06 08:56:17 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -33,6 +33,10 @@ * ************************************************************************/ +#ifndef CONNECTIVITY_KAB_KDEINIT_H +#include "KDEInit.h" +#endif + #ifndef _OSL_DIAGNOSE_H_ #include <osl/diagnose.h> #endif @@ -44,6 +48,7 @@ #include <kcmdlineargs.h> #include <kglobal.h> #include <klocale.h> +#include <kdeversion.h> namespace connectivity { @@ -112,13 +117,42 @@ // ======================================================================= // ----------------------------------------------------------------------- -extern "C" void initKApplication() +extern "C" void SAL_CALL initKApplication() { ::connectivity::kab::KDEInit::Init(); } // ----------------------------------------------------------------------- -extern "C" void shutdownKApplication() +extern "C" void SAL_CALL shutdownKApplication() { ::connectivity::kab::KDEInit::Shutdown(); +} +// ----------------------------------------------------------------------- +/** checks whether the KDE version on the system we're running at is supported + by the driver + + Has to be called before any other code from this library, in particular, + it has to be called before initKApplication() + + If this function returns <code>0</code>, then no other code from this library + has to be called, else the results are unpredictable. + + @return + <code>0</code> if the KDE version is not supported, non-<code>0</code> otherwise + + #i60062# / 2006-01-06 / [EMAIL PROTECTED] +*/ +extern "C" int SAL_CALL isKDEVersionSupported() +{ + if ( ::KDE::versionMajor() < MIN_KDE_VERSION_MAJOR ) + return 0; + if ( ( ::KDE::versionMajor() == MIN_KDE_VERSION_MAJOR ) && ( ::KDE::versionMinor() < MIN_KDE_VERSION_MINOR ) ) + return 0; + if ( ( ::KDE::versionMinor() == MIN_KDE_VERSION_MINOR ) && ( ::KDE::versionRelease() < MIN_KDE_VERSION_RELEASE ) ) + return 0; + return 1; + + // TODO: The problem described in #i60062# might happen again with newer KDE versions, in case they + // change their API incompatibly. In this case, we will most probably crash, again. Perhaps we should also + // add a check for a *maximum* supported KDE version. } File [changed]: KDriver.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/kab/KDriver.cxx?r1=1.2.10.2&r2=1.2.10.3 Delta lines: +195 -88 ---------------------- --- KDriver.cxx 4 Jan 2006 11:33:55 -0000 1.2.10.2 +++ KDriver.cxx 6 Jan 2006 08:56:21 -0000 1.2.10.3 @@ -4,9 +4,9 @@ * * $RCSfile: KDriver.cxx,v $ * - * $Revision: 1.2.10.2 $ + * $Revision: 1.2.10.3 $ * - * last change: $Author: fs $ $Date: 2006/01/04 11:33:55 $ + * last change: $Author: fs $ $Date: 2006/01/06 08:56:21 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -35,25 +35,207 @@ #include "KDriver.hxx" +#ifndef CONNECTIVITY_KAB_KDEINIT_H +#include "KDEInit.h" +#endif + #ifndef _CONNECTIVITY_KAB_CONNECTION_HXX_ #include "KConnection.hxx" #endif +#ifndef _RTL_USTRBUF_HXX_ +#include <rtl/ustrbuf.hxx> +#endif + using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::beans; using namespace com::sun::star::sdbc; using namespace connectivity::kab; +// ======================================================================= +// = KabImplModule +// ======================================================================= +// -------------------------------------------------------------------------------- +KabImplModule::KabImplModule() + :m_hConnectorModule(NULL) + ,m_bAttemptedLoadModule(false) + ,m_bAttemptedInitialize(false) + ,m_pConnectionFactoryFunc(NULL) + ,m_pApplicationInitFunc(NULL) + ,m_pApplicationShutdownFunc(NULL) + ,m_pKDEVersionCheckFunc(NULL) +{ +} + +// -------------------------------------------------------------------------------- +bool KabImplModule::isKDEPresent() +{ + if ( !impl_loadModule() ) + return false; + + return true; +} + +// -------------------------------------------------------------------------------- +bool KabImplModule::isKDEVersionSupported() +{ + if ( !impl_loadModule() ) + return false; + + return ( (*m_pKDEVersionCheckFunc)() != 0 ); +} + +// -------------------------------------------------------------------------------- +namespace +{ + template< typename FUNCTION > + void lcl_getFunctionFromModuleOrUnload( oslModule& _rModule, const sal_Char* _pAsciiSymbolName, FUNCTION& _rFunction ) + { + _rFunction = NULL; + if ( _rModule ) + { + // + const ::rtl::OUString sSymbolName = ::rtl::OUString::createFromAscii( _pAsciiSymbolName ); + _rFunction = (FUNCTION)( osl_getSymbol( _rModule, sSymbolName.pData ) ); + + if ( !_rFunction ) + { // did not find the symbol + OSL_ENSURE( false, ::rtl::OString( "lcl_getFunctionFromModuleOrUnload: could not find the symbol " ) + ::rtl::OString( _pAsciiSymbolName ) ); + osl_unloadModule( _rModule ); + _rModule = NULL; + } + } + } +} + +// -------------------------------------------------------------------------------- +bool KabImplModule::impl_loadModule() +{ + if ( m_bAttemptedLoadModule ) + return ( m_hConnectorModule != NULL ); + m_bAttemptedLoadModule = true; + + OSL_ENSURE( !m_hConnectorModule && !m_pConnectionFactoryFunc && !m_pApplicationInitFunc && !m_pApplicationShutdownFunc && !m_pKDEVersionCheckFunc, + "KabImplModule::impl_loadModule: inconsistence: inconsistency (never attempted load before, but some values already set)!"); + + const ::rtl::OUString sModuleName = ::rtl::OUString::createFromAscii( SAL_MODULENAME( "kabdrv1" ) ); + m_hConnectorModule = osl_loadModule( sModuleName.pData, 0 ); + OSL_ENSURE( m_hConnectorModule, "KabImplModule::impl_loadModule: could not load the implementation library!" ); + if ( !m_hConnectorModule ) + return false; + + lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "createKabConnection", m_pConnectionFactoryFunc ); + lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "initKApplication", m_pApplicationInitFunc ); + lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "shutdownKApplication", m_pApplicationShutdownFunc ); + lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "isKDEVersionSupported", m_pKDEVersionCheckFunc ); + + if ( !m_hConnectorModule ) + // one of the symbols did not exist + throw RuntimeException(); + + return true; +} + +// -------------------------------------------------------------------------------- +void KabImplModule::impl_unloadModule() +{ + OSL_PRECOND( m_hConnectorModule != NULL, "KabImplModule::impl_unloadModule: no module!" ); + + osl_unloadModule( m_hConnectorModule ); + m_hConnectorModule = NULL; + + m_pConnectionFactoryFunc = NULL; + m_pApplicationInitFunc = NULL; + m_pApplicationShutdownFunc = NULL; + m_pKDEVersionCheckFunc = NULL; + + m_bAttemptedLoadModule = false; +} + +// -------------------------------------------------------------------------------- +void KabImplModule::impl_throwNoKdeException() +{ + SQLException aError; + aError.Message = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No suitable KDE installation was found." ) ); + aError.SQLState = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ); + aError.ErrorCode = 0; + throw aError; +} + +// -------------------------------------------------------------------------------- +void KabImplModule::impl_throwWrongKdeVersionException() +{ + ::rtl::OUStringBuffer aMessage; + aMessage.appendAscii( "KDE version " ); + aMessage.append( (sal_Int32)MIN_KDE_VERSION_MAJOR ); + if ( MIN_KDE_VERSION_MINOR || MIN_KDE_VERSION_RELEASE ) + { + aMessage.append( (sal_Unicode)'.' ); + aMessage.append( (sal_Int32)MIN_KDE_VERSION_MINOR ); + if ( MIN_KDE_VERSION_RELEASE ) + { + aMessage.append( (sal_Unicode)'.' ); + aMessage.append( (sal_Int32)MIN_KDE_VERSION_RELEASE ); + } + } + aMessage.appendAscii( " or higher is required to access the KDE Address Book." ); + + SQLException aError; + aError.Message = aMessage.makeStringAndClear(); + aError.SQLState = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ); + aError.ErrorCode = 0; + throw aError; +} + +// -------------------------------------------------------------------------------- +void KabImplModule::init() +{ + if ( !impl_loadModule() ) + impl_throwNoKdeException(); + + // if we're not running on a supported version, throw + if ( !isKDEVersionSupported() ) + impl_throwWrongKdeVersionException(); + + if ( !m_bAttemptedInitialize ) + { + m_bAttemptedInitialize = true; + (*m_pApplicationInitFunc)(); + } +} + +// -------------------------------------------------------------------------------- +KabConnection* KabImplModule::createConnection( KabDriver* _pDriver ) const +{ + OSL_PRECOND( m_hConnectorModule, "KabImplModule::createConnection: not initialized!" ); + + void* pUntypedConnection = (*m_pConnectionFactoryFunc)( _pDriver ); + if ( !pUntypedConnection ) + throw RuntimeException(); + + return static_cast< KabConnection* >( pUntypedConnection ); +} + +// -------------------------------------------------------------------------------- +void KabImplModule::shutdown() +{ + if ( !m_hConnectorModule ) + return; + + (*m_pApplicationShutdownFunc)(); + m_bAttemptedInitialize = false; + + impl_unloadModule(); +} + +// ======================================================================= +// = KabDriver +// ======================================================================= KabDriver::KabDriver( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) : KDriver_BASE(m_aMutex), - m_xMSFactory(_rxFactory), - m_hConnectorModule(NULL), - m_bInitializedConnectorModule(false), - m_pConnectionFactoryFunc(NULL), - m_pApplicationInitFunc(NULL), - m_pApplicationShutdownFunc(NULL) + m_xMSFactory(_rxFactory) { } // -------------------------------------------------------------------------------- @@ -72,7 +254,7 @@ KDriver_BASE::disposing(); - impl_shutdownImplementationModule(); + m_aImplModule.shutdown(); } // static ServiceInfo //------------------------------------------------------------------------------ @@ -118,15 +300,11 @@ { ::osl::MutexGuard aGuard(m_aMutex); - if ( !impl_initImplementationModule() ) - return NULL; + m_aImplModule.init(); // create a new connection with the given properties and append it to our vector - void* pUntypedConnection = (*m_pConnectionFactoryFunc)( this ); - KabConnection* pConnection = static_cast< KabConnection* >( pUntypedConnection ); - OSL_ENSURE( pConnection, "KabDriver::connect: no connection has been created by the factory!" ); - if ( !pConnection ) - throw RuntimeException( ::rtl::OUString(), *this ); + KabConnection* pConnection = m_aImplModule.createConnection( this ); + OSL_POSTCOND( pConnection, "KabDriver::connect: no connection has been created by the factory!" ); // by definition, the factory function returned an object which was acquired once Reference< XConnection > xConnection = pConnection; @@ -146,7 +324,7 @@ { ::osl::MutexGuard aGuard(m_aMutex); - if ( !impl_initImplementationModule() ) + if ( !m_aImplModule.isKDEPresent() ) return sal_False; // here we have to look whether we support this URL format @@ -176,74 +354,3 @@ return *(new KabDriver(_rxFactory)); } -// -------------------------------------------------------------------------------- -namespace -{ - template< typename FUNCTION > - void lcl_getFunctionFromModuleOrUnload( oslModule& _rModule, const sal_Char* _pAsciiSymbolName, FUNCTION& _rFunction ) - { - _rFunction = NULL; - if ( _rModule ) - { - // - const ::rtl::OUString sSymbolName = ::rtl::OUString::createFromAscii( _pAsciiSymbolName ); - _rFunction = (FUNCTION)( osl_getSymbol( _rModule, sSymbolName.pData ) ); - - if ( !_rFunction ) - { // did not find the symbol - OSL_ENSURE( false, ::rtl::OString( "lcl_getFunctionFromModuleOrUnload: could not find the symbol " ) + ::rtl::OString( _pAsciiSymbolName ) ); - osl_unloadModule( _rModule ); - _rModule = NULL; - } - } - } -} - -// -------------------------------------------------------------------------------- -bool KabDriver::impl_initImplementationModule() -{ - if ( m_bInitializedConnectorModule ) - return ( m_hConnectorModule != NULL ); - - // prevent multiple attempts to load the lib. This could be expensive in case of errors. - m_bInitializedConnectorModule = true; - - if ( !m_hConnectorModule ) - { - OSL_ENSURE( !m_pConnectionFactoryFunc && !m_pApplicationInitFunc && !m_pApplicationShutdownFunc, - "KabDriver::impl_initImplementationModule: inconsistence: function pointers already intialized, but no module!"); - - const ::rtl::OUString sModuleName = ::rtl::OUString::createFromAscii( SAL_MODULENAME( "kabdrv1" ) ); - m_hConnectorModule = osl_loadModule( sModuleName.pData, 0 ); - OSL_ENSURE( m_hConnectorModule, "KabDriver::impl_initImplementationModule: could not load the implementation library!" ); - if ( !m_hConnectorModule ) - return false; - - lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "createKabConnection", m_pConnectionFactoryFunc ); - lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "initKApplication", m_pApplicationInitFunc ); - lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "shutdownKApplication", m_pApplicationShutdownFunc ); - } - - if ( m_pApplicationInitFunc ) - (*m_pApplicationInitFunc)(); - - return ( m_hConnectorModule != NULL ); -} -// -------------------------------------------------------------------------------- -void KabDriver::impl_shutdownImplementationModule() -{ - if ( m_pApplicationShutdownFunc ) - (*m_pApplicationShutdownFunc)(); - - if ( m_hConnectorModule ) - { - osl_unloadModule( m_hConnectorModule ); - m_hConnectorModule = NULL; - } - - m_pConnectionFactoryFunc = NULL; - m_pApplicationInitFunc = NULL; - m_pApplicationShutdownFunc = NULL; - - m_bInitializedConnectorModule = false; -} File [changed]: KDriver.hxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/kab/KDriver.hxx?r1=1.2.10.2&r2=1.2.10.3 Delta lines: +85 -20 --------------------- --- KDriver.hxx 4 Jan 2006 11:33:55 -0000 1.2.10.2 +++ KDriver.hxx 6 Jan 2006 08:56:24 -0000 1.2.10.3 @@ -4,9 +4,9 @@ * * $RCSfile: KDriver.hxx,v $ * - * $Revision: 1.2.10.2 $ + * $Revision: 1.2.10.3 $ * - * last change: $Author: fs $ $Date: 2006/01/04 11:33:55 $ + * last change: $Author: fs $ $Date: 2006/01/06 08:56:24 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -55,13 +55,92 @@ { namespace kab { + class KabConnection; + class KabDriver; + typedef void* (SAL_CALL * ConnectionFactoryFunction)( void* _pDriver ); typedef void (SAL_CALL * ApplicationInitFunction)( void ); typedef void (SAL_CALL * ApplicationShutdownFunction)( void ); + typedef int (SAL_CALL * KDEVersionCheckFunction)( void ); typedef std::vector< ::com::sun::star::uno::WeakReferenceHelper > OWeakRefArray; // =============================================================== + // = KabImplModule + // =============================================================== + class KabImplModule + { + private: + /// Did we already attempt to load the module and to retrieve the symbols? + bool m_bAttemptedLoadModule; + /// Did we already check the KDE version and initialize the impl module (or at least attempted to)? + bool m_bAttemptedInitialize; + + oslModule m_hConnectorModule; + ConnectionFactoryFunction m_pConnectionFactoryFunc; + ApplicationInitFunction m_pApplicationInitFunc; + ApplicationShutdownFunction m_pApplicationShutdownFunc; + KDEVersionCheckFunction m_pKDEVersionCheckFunc; + + public: + KabImplModule(); + + /** determines whether there is a KDE present in the environment + */ + bool isKDEPresent(); + + /** checks whether the KDE version we're running against is supported + */ + bool isKDEVersionSupported(); + + /** initializes the implementation module. + + @raises ::com::sun::star::uno::RuntimeException + if the module could be loaded, but required symbols are missing + @raises ::com::sun::star::sdbc::SQLException + if the KDE version we're running against is not supported, or no KDE was found at all + */ + void init(); + + /** shuts down the impl module (and the KDE application, if we own it) + */ + void shutdown(); + + /** creates a new connection + @precond + <member>init</member> has been called before + @raises ::com::sun::star::uno::RuntimeException + if no connection object could be created (which is a severe error, normally impossible) + */ + KabConnection* createConnection( KabDriver* _pDriver ) const; + + private: + /** loads the implementation module and retrieves the needed symbols + + Save against being called multiple times. + + @return <TRUE/> if the module could be loaded successfully. + + @raises ::com::sun::star::uno::RuntimeException + if the module could be loaded, but required symbols are missing + */ + bool impl_loadModule(); + + /** unloads the implementation module, and resets all function pointers to <NULL/> + @precond m_hConnectorModule is not <NULL/> + */ + void impl_unloadModule(); + + /** throws an SQLException saying than no KDE installation was found + */ + void impl_throwNoKdeException(); + + /** throws an SQLException saying that the found KDE version is not supported + */ + void impl_throwWrongKdeVersionException(); + }; + + // =============================================================== // = KabDriver // =============================================================== typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::sdbc::XDriver, @@ -74,13 +153,7 @@ // KabConnection objects for this Driver ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xMSFactory; // the multi-service factory - - // dynamic access to the library which implements the "real" functionality - oslModule m_hConnectorModule; - bool m_bInitializedConnectorModule; - ConnectionFactoryFunction m_pConnectionFactoryFunc; - ApplicationInitFunction m_pApplicationInitFunc; - ApplicationShutdownFunction m_pApplicationShutdownFunc; + KabImplModule m_aImplModule; public: static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) throw( ::com::sun::star::uno::Exception ); @@ -111,14 +184,6 @@ virtual sal_Int32 SAL_CALL getMinorVersion() throw(::com::sun::star::uno::RuntimeException); private: - /** initializes the library which contains the real implementations - - @return <TRUE/> if and only if loading the library succeeded, and <em>all</em> needed symbols were found - - @precond our mutex is locked - */ - bool impl_initImplementationModule(); - /** shuts down the library which contains the real implementations This method is safe against being called multiple times File [changed]: kabdrv.map Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/kab/kabdrv.map?r1=1.1.2.1&r2=1.1.2.2 Delta lines: +1 -0 ------------------- --- kabdrv.map 4 Jan 2006 11:25:13 -0000 1.1.2.1 +++ kabdrv.map 6 Jan 2006 08:56:24 -0000 1.1.2.2 @@ -3,6 +3,7 @@ createKabConnection; initKApplication; shutdownKApplication; + isKDEVersionSupported; local: *; }; --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
