fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / connectivity / source / drivers / kab / KDriver.cxx
blob44b946d1ea63dca2acc6d81e11c930487fa5a5e7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "KDriver.hxx"
22 #include "KDEInit.h"
23 #include "KConnection.hxx"
24 #include "rtl/strbuf.hxx"
26 #include <com/sun/star/configuration/theDefaultProvider.hpp>
27 #include <com/sun/star/sdb/SQLContext.hpp>
28 #include <com/sun/star/lang/NullPointerException.hpp>
29 #include <com/sun/star/frame/Desktop.hpp>
30 #include <comphelper/processfactory.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <tools/diagnose_ex.h>
33 #include "resource/kab_res.hrc"
34 #include "resource/sharedresources.hxx"
36 using namespace com::sun::star::uno;
37 using namespace com::sun::star::lang;
38 using namespace com::sun::star::beans;
39 using namespace com::sun::star::sdbc;
40 using namespace com::sun::star::sdb;
41 using namespace com::sun::star::frame;
42 using namespace connectivity::kab;
44 // =======================================================================
45 // = KabImplModule
46 // =======================================================================
47 // --------------------------------------------------------------------------------
48 KabImplModule::KabImplModule( const Reference< XComponentContext >& _rxContext )
49 :m_xContext(_rxContext)
50 ,m_bAttemptedLoadModule(false)
51 ,m_bAttemptedInitialize(false)
52 ,m_hConnectorModule(NULL)
53 ,m_pConnectionFactoryFunc(NULL)
54 ,m_pApplicationInitFunc(NULL)
55 ,m_pApplicationShutdownFunc(NULL)
56 ,m_pKDEVersionCheckFunc(NULL)
58 if ( !m_xContext.is() )
59 throw NullPointerException();
62 // --------------------------------------------------------------------------------
63 bool KabImplModule::isKDEPresent()
65 if ( !impl_loadModule() )
66 return false;
68 return true;
71 // --------------------------------------------------------------------------------
72 KabImplModule::KDEVersionType KabImplModule::matchKDEVersion()
74 OSL_PRECOND( m_pKDEVersionCheckFunc, "KabImplModule::matchKDEVersion: module not loaded!" );
76 int nVersionInfo = (*m_pKDEVersionCheckFunc)();
77 if ( nVersionInfo < 0 )
78 return eTooOld;
79 if ( nVersionInfo > 0 )
80 return eToNew;
81 return eSupported;
84 // --------------------------------------------------------------------------------
85 namespace
87 template< typename FUNCTION >
88 void lcl_getFunctionFromModuleOrUnload( oslModule& _rModule, const sal_Char* _pAsciiSymbolName, FUNCTION& _rFunction )
90 _rFunction = NULL;
91 if ( _rModule )
94 const OUString sSymbolName = OUString::createFromAscii( _pAsciiSymbolName );
95 _rFunction = (FUNCTION)( osl_getSymbol( _rModule, sSymbolName.pData ) );
97 if ( !_rFunction )
98 { // did not find the symbol
99 OStringBuffer aBuf;
100 aBuf.append( "lcl_getFunctionFromModuleOrUnload: could not find the symbol " );
101 aBuf.append( _pAsciiSymbolName );
102 OSL_FAIL( aBuf.makeStringAndClear().getStr() );
103 osl_unloadModule( _rModule );
104 _rModule = NULL;
110 // --------------------------------------------------------------------------------
111 extern "C" { void SAL_CALL thisModule() {} }
113 bool KabImplModule::impl_loadModule()
115 if ( m_bAttemptedLoadModule )
116 return ( m_hConnectorModule != NULL );
117 m_bAttemptedLoadModule = true;
119 OSL_ENSURE( !m_hConnectorModule && !m_pConnectionFactoryFunc && !m_pApplicationInitFunc && !m_pApplicationShutdownFunc && !m_pKDEVersionCheckFunc,
120 "KabImplModule::impl_loadModule: inconsistence: inconsistency (never attempted load before, but some values already set)!");
122 const OUString sModuleName( SAL_MODULENAME( "kabdrv1" ));
123 m_hConnectorModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, SAL_LOADMODULE_NOW ); // LAZY! #i61335#
124 OSL_ENSURE( m_hConnectorModule, "KabImplModule::impl_loadModule: could not load the implementation library!" );
125 if ( !m_hConnectorModule )
126 return false;
128 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "createKabConnection", m_pConnectionFactoryFunc );
129 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "initKApplication", m_pApplicationInitFunc );
130 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "shutdownKApplication", m_pApplicationShutdownFunc );
131 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "matchKDEVersion", m_pKDEVersionCheckFunc );
133 if ( !m_hConnectorModule )
134 // one of the symbols did not exist
135 throw RuntimeException();
137 return true;
140 // --------------------------------------------------------------------------------
141 void KabImplModule::impl_unloadModule()
143 OSL_PRECOND( m_hConnectorModule != NULL, "KabImplModule::impl_unloadModule: no module!" );
145 osl_unloadModule( m_hConnectorModule );
146 m_hConnectorModule = NULL;
148 m_pConnectionFactoryFunc = NULL;
149 m_pApplicationInitFunc = NULL;
150 m_pApplicationShutdownFunc = NULL;
151 m_pKDEVersionCheckFunc = NULL;
153 m_bAttemptedLoadModule = false;
156 // --------------------------------------------------------------------------------
157 void KabImplModule::init()
159 if ( !impl_loadModule() )
160 impl_throwNoKdeException();
162 // if we're not running on a supported version, throw
163 KabImplModule::KDEVersionType eKDEVersion = matchKDEVersion();
165 if ( eKDEVersion == eTooOld )
166 impl_throwKdeTooOldException();
168 if ( ( eKDEVersion == eToNew ) && !impl_doAllowNewKDEVersion() )
169 impl_throwKdeTooNewException();
171 if ( !m_bAttemptedInitialize )
173 m_bAttemptedInitialize = true;
174 (*m_pApplicationInitFunc)();
178 // --------------------------------------------------------------------------------
179 bool KabImplModule::impl_doAllowNewKDEVersion()
183 Reference< XMultiServiceFactory > xConfigProvider(
184 com::sun::star::configuration::theDefaultProvider::get( m_xContext ) );
185 Sequence< Any > aCreationArgs(1);
186 aCreationArgs[0] <<= PropertyValue(
187 OUString( "nodepath" ),
189 makeAny( KabDriver::impl_getConfigurationSettingsPath() ),
190 PropertyState_DIRECT_VALUE );
191 Reference< XPropertySet > xSettings( xConfigProvider->createInstanceWithArguments(
192 OUString( "com.sun.star.configuration.ConfigurationAccess" ),
193 aCreationArgs ),
194 UNO_QUERY_THROW );
196 sal_Bool bDisableCheck = sal_False;
197 xSettings->getPropertyValue( OUString( "DisableKDEMaximumVersionCheck" ) ) >>= bDisableCheck;
199 return bDisableCheck != sal_False;
201 catch( const Exception& )
203 DBG_UNHANDLED_EXCEPTION();
205 return false;
208 // --------------------------------------------------------------------------------
209 void KabImplModule::impl_throwNoKdeException()
211 ::connectivity::SharedResources aResources;
212 const OUString sError( aResources.getResourceString(
213 STR_NO_KDE_INST
214 ) );
215 impl_throwGenericSQLException( sError );
218 // --------------------------------------------------------------------------------
219 void KabImplModule::impl_throwKdeTooOldException()
221 ::connectivity::SharedResources aResources;
222 const OUString sError( aResources.getResourceStringWithSubstitution(
223 STR_KDE_VERSION_TOO_OLD,
224 "$major$",OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MAJOR),
225 "$minor$",OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MINOR)
226 ) );
227 impl_throwGenericSQLException( sError );
230 // --------------------------------------------------------------------------------
231 void KabImplModule::impl_throwGenericSQLException( const OUString& _rMessage )
233 SQLException aError;
234 aError.Message = _rMessage;
235 aError.SQLState = OUString( "S1000" );
236 aError.ErrorCode = 0;
237 throw aError;
240 // --------------------------------------------------------------------------------
241 void KabImplModule::impl_throwKdeTooNewException()
243 ::connectivity::SharedResources aResources;
245 SQLException aError;
246 aError.Message = aResources.getResourceStringWithSubstitution(
247 STR_KDE_VERSION_TOO_NEW,
248 "$major$",OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MAJOR),
249 "$minor$",OUString::valueOf((sal_Int32)MIN_KDE_VERSION_MINOR)
251 aError.SQLState = OUString( "S1000" );
252 aError.ErrorCode = 0;
254 SQLContext aDetails;
255 OUStringBuffer aMessage;
256 aMessage.append( aResources.getResourceString(STR_KDE_VERSION_TOO_NEW_WORK_AROUND) );
258 aMessage.appendAscii( "Sub disableKDEMaxVersionCheck\n" );
259 aMessage.appendAscii( " BasicLibraries.LoadLibrary( \"Tools\" )\n" );
261 aMessage.appendAscii( " Dim configNode as Object\n" );
262 aMessage.appendAscii( " configNode = GetRegistryKeyContent( \"" );
263 aMessage.append( KabDriver::impl_getConfigurationSettingsPath() );
264 aMessage.appendAscii( "\", true )\n" );
266 aMessage.appendAscii( " configNode.DisableKDEMaximumVersionCheck = TRUE\n" );
267 aMessage.appendAscii( " configNode.commitChanges\n" );
268 aMessage.appendAscii( "End Sub\n" );
270 aDetails.Message = aMessage.makeStringAndClear();
272 aError.NextException <<= aDetails;
274 throw aError;
277 // --------------------------------------------------------------------------------
278 KabConnection* KabImplModule::createConnection( KabDriver* _pDriver ) const
280 OSL_PRECOND( m_hConnectorModule, "KabImplModule::createConnection: not initialized!" );
282 void* pUntypedConnection = (*m_pConnectionFactoryFunc)( _pDriver );
283 if ( !pUntypedConnection )
284 throw RuntimeException();
286 return static_cast< KabConnection* >( pUntypedConnection );
289 // --------------------------------------------------------------------------------
290 void KabImplModule::shutdown()
292 if ( !m_hConnectorModule )
293 return;
295 (*m_pApplicationShutdownFunc)();
296 m_bAttemptedInitialize = false;
298 impl_unloadModule();
301 // =======================================================================
302 // = KabDriver
303 // =======================================================================
304 KabDriver::KabDriver(
305 const Reference< ::com::sun::star::uno::XComponentContext >& _rxContext)
306 : KDriver_BASE(m_aMutex),
307 m_xContext(_rxContext),
308 m_aImplModule(_rxContext)
310 if ( !m_xContext.is() )
311 throw NullPointerException();
313 osl_atomic_increment( &m_refCount );
316 Reference< XDesktop2 > xDesktop = Desktop::create( m_xContext);
317 xDesktop->addTerminateListener( this );
319 catch( const Exception& )
321 DBG_UNHANDLED_EXCEPTION();
323 osl_atomic_decrement( &m_refCount );
325 // --------------------------------------------------------------------------------
326 void KabDriver::disposing()
328 ::osl::MutexGuard aGuard(m_aMutex);
330 // when driver will be destroied so all our connections have to be destroied as well
331 for (OWeakRefArray::iterator i = m_xConnections.begin(); m_xConnections.end() != i; ++i)
333 Reference< XComponent > xComp(i->get(), UNO_QUERY);
334 if (xComp.is())
335 xComp->dispose();
337 m_xConnections.clear();
339 WeakComponentImplHelperBase::disposing();
341 // static ServiceInfo
342 //------------------------------------------------------------------------------
343 OUString KabDriver::getImplementationName_Static( ) throw(RuntimeException)
345 return OUString::createFromAscii( impl_getAsciiImplementationName() );
347 //------------------------------------------------------------------------------
348 Sequence< OUString > KabDriver::getSupportedServiceNames_Static( ) throw (RuntimeException)
350 // which service is supported
351 // for more information @see com.sun.star.sdbc.Driver
352 Sequence< OUString > aSNS( 1 );
353 aSNS[0] = OUString("com.sun.star.sdbc.Driver");
355 return aSNS;
357 //------------------------------------------------------------------
358 OUString SAL_CALL KabDriver::getImplementationName( ) throw(RuntimeException)
360 return getImplementationName_Static();
362 //------------------------------------------------------------------
363 sal_Bool SAL_CALL KabDriver::supportsService( const OUString& _rServiceName ) throw(RuntimeException)
365 Sequence< OUString > aSupported(getSupportedServiceNames());
366 const OUString* pSupported = aSupported.getConstArray();
367 const OUString* pEnd = pSupported + aSupported.getLength();
369 while (pSupported != pEnd && !pSupported->equals(_rServiceName))
370 ++pSupported;
371 return pSupported != pEnd;
373 //------------------------------------------------------------------
374 Sequence< OUString > SAL_CALL KabDriver::getSupportedServiceNames( ) throw(RuntimeException)
376 return getSupportedServiceNames_Static();
378 // --------------------------------------------------------------------------------
379 Reference< XConnection > SAL_CALL KabDriver::connect( const OUString& url, const Sequence< PropertyValue >& info ) throw(SQLException, RuntimeException)
381 ::osl::MutexGuard aGuard(m_aMutex);
383 m_aImplModule.init();
385 // create a new connection with the given properties and append it to our vector
386 KabConnection* pConnection = m_aImplModule.createConnection( this );
387 OSL_POSTCOND( pConnection, "KabDriver::connect: no connection has been created by the factory!" );
389 // by definition, the factory function returned an object which was acquired once
390 Reference< XConnection > xConnection = pConnection;
391 pConnection->release();
393 // late constructor call which can throw exception and allows a correct dtor call when so
394 pConnection->construct( url, info );
396 // remember it
397 m_xConnections.push_back( WeakReferenceHelper( *pConnection ) );
399 return xConnection;
401 // --------------------------------------------------------------------------------
402 sal_Bool SAL_CALL KabDriver::acceptsURL( const OUString& url )
403 throw(SQLException, RuntimeException)
405 ::osl::MutexGuard aGuard(m_aMutex);
407 if ( !m_aImplModule.isKDEPresent() )
408 return sal_False;
410 // here we have to look whether we support this URL format
411 return url.startsWith("sdbc:address:kab:");
413 // --------------------------------------------------------------------------------
414 Sequence< DriverPropertyInfo > SAL_CALL KabDriver::getPropertyInfo( const OUString&, const Sequence< PropertyValue >& ) throw(SQLException, RuntimeException)
416 // if you have something special to say, return it here :-)
417 return Sequence< DriverPropertyInfo >();
419 // --------------------------------------------------------------------------------
420 sal_Int32 SAL_CALL KabDriver::getMajorVersion( ) throw(RuntimeException)
422 return KAB_DRIVER_VERSION_MAJOR;
424 // --------------------------------------------------------------------------------
425 sal_Int32 SAL_CALL KabDriver::getMinorVersion( ) throw(RuntimeException)
427 return KAB_DRIVER_VERSION_MINOR;
429 // --------------------------------------------------------------------------------
430 void SAL_CALL KabDriver::queryTermination( const EventObject& ) throw (TerminationVetoException, RuntimeException)
432 // nothing to do, nothing to veto
434 // --------------------------------------------------------------------------------
435 void SAL_CALL KabDriver::notifyTermination( const EventObject& ) throw (RuntimeException)
437 m_aImplModule.shutdown();
439 // --------------------------------------------------------------------------------
440 void SAL_CALL KabDriver::disposing( const EventObject& ) throw (RuntimeException)
442 // not interested in (this is the disposing of the desktop, if any)
444 // --------------------------------------------------------------------------------
445 const sal_Char* KabDriver::impl_getAsciiImplementationName()
447 return "com.sun.star.comp.sdbc.kab.Driver";
448 // this name is referenced in the configuration and in the kab.xml
449 // Please be careful when changing it.
451 // --------------------------------------------------------------------------------
452 OUString KabDriver::impl_getConfigurationSettingsPath()
454 OUStringBuffer aPath;
455 aPath.appendAscii( "/org.openoffice.Office.DataAccess/DriverSettings/" );
456 aPath.appendAscii( "com.sun.star.comp.sdbc.kab.Driver" );
457 return aPath.makeStringAndClear();
459 // --------------------------------------------------------------------------------
460 Reference< XInterface > SAL_CALL KabDriver::Create( const Reference< XMultiServiceFactory >& _rxFactory ) throw( Exception )
462 return *(new KabDriver( comphelper::getComponentContext(_rxFactory)));
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */