1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
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 // =======================================================================
58 // =======================================================================
59 // --------------------------------------------------------------------------------
60 KabImplModule::KabImplModule( const Reference
< XMultiServiceFactory
>& _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
)
71 throw NullPointerException();
74 // --------------------------------------------------------------------------------
75 bool KabImplModule::isKDEPresent()
77 if ( !impl_loadModule() )
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 )
91 if ( nVersionInfo
> 0 )
96 // --------------------------------------------------------------------------------
99 template< typename FUNCTION
>
100 void lcl_getFunctionFromModuleOrUnload( oslModule
& _rModule
, const sal_Char
* _pAsciiSymbolName
, FUNCTION
& _rFunction
)
106 const ::rtl::OUString sSymbolName
= ::rtl::OUString::createFromAscii( _pAsciiSymbolName
);
107 _rFunction
= (FUNCTION
)( osl_getSymbol( _rModule
, sSymbolName
.pData
) );
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
);
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
)
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();
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" ) ) ),
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" ) ),
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();
218 // --------------------------------------------------------------------------------
219 void KabImplModule::impl_throwNoKdeException()
221 ::connectivity::SharedResources aResources
;
222 const ::rtl::OUString
sError( aResources
.getResourceString(
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
)
237 impl_throwGenericSQLException( sError
);
240 // --------------------------------------------------------------------------------
241 void KabImplModule::impl_throwGenericSQLException( const ::rtl::OUString
& _rMessage
)
244 aError
.Message
= _rMessage
;
245 aError
.SQLState
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) );
246 aError
.ErrorCode
= 0;
250 // --------------------------------------------------------------------------------
251 void KabImplModule::impl_throwKdeTooNewException()
253 ::connectivity::SharedResources aResources
;
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;
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
;
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
)
305 (*m_pApplicationShutdownFunc
)();
306 m_bAttemptedInitialize
= false;
311 // =======================================================================
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" ) ) ),
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
);
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");
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
))
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
);
409 m_xConnections
.push_back( WeakReferenceHelper( *pConnection
) );
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() )
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
));