1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_connectivity.hxx" 30 31 #include "MacabDriver.hxx" 32 #include "MacabConnection.hxx" 33 34 /** === begin UNO includes === **/ 35 #include <com/sun/star/sdb/SQLContext.hpp> 36 #include <com/sun/star/lang/NullPointerException.hpp> 37 #include <com/sun/star/frame/XDesktop.hpp> 38 /** === end UNO includes === **/ 39 #include <rtl/ustrbuf.hxx> 40 #include <tools/diagnose_ex.h> 41 #include "resource/macab_res.hrc" 42 43 using namespace com::sun::star::uno; 44 using namespace com::sun::star::lang; 45 using namespace com::sun::star::beans; 46 using namespace com::sun::star::sdbc; 47 using namespace com::sun::star::sdb; 48 using namespace com::sun::star::frame; 49 using namespace connectivity::macab; 50 51 // ======================================================================= 52 // = MacabImplModule 53 // ======================================================================= 54 // -------------------------------------------------------------------------------- 55 MacabImplModule::MacabImplModule( const Reference< XMultiServiceFactory >& _rxFactory ) 56 :m_xORB(_rxFactory) 57 ,m_bAttemptedLoadModule(false) 58 ,m_hConnectorModule(NULL) 59 ,m_pConnectionFactoryFunc(NULL) 60 { 61 if ( !m_xORB.is() ) 62 throw NullPointerException(); 63 } 64 65 // -------------------------------------------------------------------------------- 66 bool MacabImplModule::isMacOSPresent() 67 { 68 return impl_loadModule(); 69 } 70 71 // -------------------------------------------------------------------------------- 72 namespace 73 { 74 template< typename FUNCTION > 75 void lcl_getFunctionFromModuleOrUnload( oslModule& _rModule, const sal_Char* _pAsciiSymbolName, FUNCTION& _rFunction ) 76 { 77 _rFunction = NULL; 78 if ( _rModule ) 79 { 80 // 81 const ::rtl::OUString sSymbolName = ::rtl::OUString::createFromAscii( _pAsciiSymbolName ); 82 _rFunction = (FUNCTION)( osl_getSymbol( _rModule, sSymbolName.pData ) ); 83 84 if ( !_rFunction ) 85 { // did not find the symbol 86 OSL_ENSURE( false, ::rtl::OString( "lcl_getFunctionFromModuleOrUnload: could not find the symbol " ) + ::rtl::OString( _pAsciiSymbolName ) ); 87 osl_unloadModule( _rModule ); 88 _rModule = NULL; 89 } 90 } 91 } 92 } 93 94 // -------------------------------------------------------------------------------- 95 extern "C" { static void SAL_CALL thisModule() {} } 96 97 bool MacabImplModule::impl_loadModule() 98 { 99 if ( m_bAttemptedLoadModule ) 100 return ( m_hConnectorModule != NULL ); 101 m_bAttemptedLoadModule = true; 102 103 OSL_ENSURE( !m_hConnectorModule && !m_pConnectionFactoryFunc, 104 "MacabImplModule::impl_loadModule: inconsistence: inconsistency (never attempted load before, but some values already set)!"); 105 106 const ::rtl::OUString sModuleName = ::rtl::OUString::createFromAscii( SAL_MODULENAME( "macabdrv1" ) ); 107 m_hConnectorModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, SAL_LOADMODULE_NOW ); // LAZY! #i61335# 108 OSL_ENSURE( m_hConnectorModule, "MacabImplModule::impl_loadModule: could not load the implementation library!" ); 109 if ( !m_hConnectorModule ) 110 return false; 111 112 lcl_getFunctionFromModuleOrUnload( m_hConnectorModule, "createMacabConnection", m_pConnectionFactoryFunc ); 113 114 if ( !m_hConnectorModule ) 115 // one of the symbols did not exist 116 throw RuntimeException(); 117 118 return true; 119 } 120 121 // -------------------------------------------------------------------------------- 122 void MacabImplModule::impl_unloadModule() 123 { 124 OSL_PRECOND( m_hConnectorModule != NULL, "MacabImplModule::impl_unloadModule: no module!" ); 125 126 osl_unloadModule( m_hConnectorModule ); 127 m_hConnectorModule = NULL; 128 129 m_pConnectionFactoryFunc = NULL; 130 131 m_bAttemptedLoadModule = false; 132 } 133 134 // -------------------------------------------------------------------------------- 135 void MacabImplModule::init() 136 { 137 if ( !impl_loadModule() ) 138 impl_throwNoMacOSException(); 139 140 } 141 142 // -------------------------------------------------------------------------------- 143 void MacabImplModule::impl_throwNoMacOSException() 144 { 145 ::connectivity::SharedResources aResources; 146 const ::rtl::OUString sError( aResources.getResourceString( 147 STR_NO_MAC_OS_FOUND 148 ) ); 149 impl_throwGenericSQLException( sError ); 150 } 151 152 // -------------------------------------------------------------------------------- 153 void MacabImplModule::impl_throwGenericSQLException( const ::rtl::OUString& _rMessage ) 154 { 155 SQLException aError; 156 aError.Message = _rMessage; 157 aError.SQLState = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ); 158 aError.ErrorCode = 0; 159 throw aError; 160 } 161 162 // -------------------------------------------------------------------------------- 163 MacabConnection* MacabImplModule::createConnection( MacabDriver* _pDriver ) const 164 { 165 OSL_PRECOND( m_hConnectorModule, "MacabImplModule::createConnection: not initialized!" ); 166 167 void* pUntypedConnection = (*m_pConnectionFactoryFunc)( _pDriver ); 168 if ( !pUntypedConnection ) 169 throw RuntimeException(); 170 171 return static_cast< MacabConnection* >( pUntypedConnection ); 172 } 173 174 // -------------------------------------------------------------------------------- 175 void MacabImplModule::shutdown() 176 { 177 if ( !m_hConnectorModule ) 178 return; 179 180 impl_unloadModule(); 181 } 182 183 // ======================================================================= 184 // = MacabDriver 185 // ======================================================================= 186 MacabDriver::MacabDriver( 187 const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) 188 : MacabDriver_BASE(m_aMutex), 189 m_xMSFactory(_rxFactory), 190 m_aImplModule(_rxFactory) 191 { 192 if ( !m_xMSFactory.is() ) 193 throw NullPointerException(); 194 195 osl_incrementInterlockedCount( &m_refCount ); 196 try 197 { 198 Reference< XDesktop > xDesktop( 199 m_xMSFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ), 200 UNO_QUERY_THROW ); 201 xDesktop->addTerminateListener( this ); 202 } 203 catch( const Exception& ) 204 { 205 DBG_UNHANDLED_EXCEPTION(); 206 } 207 osl_decrementInterlockedCount( &m_refCount ); 208 } 209 // -------------------------------------------------------------------------------- 210 void MacabDriver::disposing() 211 { 212 ::osl::MutexGuard aGuard(m_aMutex); 213 214 // when driver will be destroied so all our connections have to be destroied as well 215 for (OWeakRefArray::iterator i = m_xConnections.begin(); m_xConnections.end() != i; ++i) 216 { 217 Reference< XComponent > xComp(i->get(), UNO_QUERY); 218 if (xComp.is()) 219 xComp->dispose(); 220 } 221 m_xConnections.clear(); 222 223 WeakComponentImplHelperBase::disposing(); 224 } 225 // static ServiceInfo 226 //------------------------------------------------------------------------------ 227 rtl::OUString MacabDriver::getImplementationName_Static( ) throw(RuntimeException) 228 { 229 return rtl::OUString::createFromAscii( impl_getAsciiImplementationName() ); 230 } 231 //------------------------------------------------------------------------------ 232 Sequence< ::rtl::OUString > MacabDriver::getSupportedServiceNames_Static( ) throw (RuntimeException) 233 { 234 // which service is supported 235 // for more information @see com.sun.star.sdbc.Driver 236 Sequence< ::rtl::OUString > aSNS( 1 ); 237 aSNS[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.Driver"); 238 239 return aSNS; 240 } 241 //------------------------------------------------------------------ 242 ::rtl::OUString SAL_CALL MacabDriver::getImplementationName( ) throw(RuntimeException) 243 { 244 return getImplementationName_Static(); 245 } 246 //------------------------------------------------------------------ 247 sal_Bool SAL_CALL MacabDriver::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) 248 { 249 Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames()); 250 const ::rtl::OUString* pSupported = aSupported.getConstArray(); 251 const ::rtl::OUString* pEnd = pSupported + aSupported.getLength(); 252 253 while (pSupported != pEnd && !pSupported->equals(_rServiceName)) 254 ++pSupported; 255 return pSupported != pEnd; 256 } 257 //------------------------------------------------------------------ 258 Sequence< ::rtl::OUString > SAL_CALL MacabDriver::getSupportedServiceNames( ) throw(RuntimeException) 259 { 260 return getSupportedServiceNames_Static(); 261 } 262 // -------------------------------------------------------------------------------- 263 Reference< XConnection > SAL_CALL MacabDriver::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw(SQLException, RuntimeException) 264 { 265 ::osl::MutexGuard aGuard(m_aMutex); 266 267 m_aImplModule.init(); 268 269 // create a new connection with the given properties and append it to our vector 270 MacabConnection* pConnection = m_aImplModule.createConnection( this ); 271 OSL_POSTCOND( pConnection, "MacabDriver::connect: no connection has been created by the factory!" ); 272 273 // by definition, the factory function returned an object which was acquired once 274 Reference< XConnection > xConnection = pConnection; 275 pConnection->release(); 276 277 // late constructor call which can throw exception and allows a correct dtor call when so 278 pConnection->construct( url, info ); 279 280 // remember it 281 m_xConnections.push_back( WeakReferenceHelper( *pConnection ) ); 282 283 return xConnection; 284 } 285 // -------------------------------------------------------------------------------- 286 sal_Bool SAL_CALL MacabDriver::acceptsURL( const ::rtl::OUString& url ) 287 throw(SQLException, RuntimeException) 288 { 289 ::osl::MutexGuard aGuard(m_aMutex); 290 291 if ( !m_aImplModule.isMacOSPresent() ) 292 return sal_False; 293 294 // here we have to look whether we support this URL format 295 return (!url.compareTo(::rtl::OUString::createFromAscii("sdbc:address:macab:"), 18)); 296 } 297 // -------------------------------------------------------------------------------- 298 Sequence< DriverPropertyInfo > SAL_CALL MacabDriver::getPropertyInfo( const ::rtl::OUString&, const Sequence< PropertyValue >& ) throw(SQLException, RuntimeException) 299 { 300 // if you have something special to say, return it here :-) 301 return Sequence< DriverPropertyInfo >(); 302 } 303 // -------------------------------------------------------------------------------- 304 sal_Int32 SAL_CALL MacabDriver::getMajorVersion( ) throw(RuntimeException) 305 { 306 return MACAB_DRIVER_VERSION_MAJOR; 307 } 308 // -------------------------------------------------------------------------------- 309 sal_Int32 SAL_CALL MacabDriver::getMinorVersion( ) throw(RuntimeException) 310 { 311 return MACAB_DRIVER_VERSION_MINOR; 312 } 313 // -------------------------------------------------------------------------------- 314 void SAL_CALL MacabDriver::queryTermination( const EventObject& ) throw (TerminationVetoException, RuntimeException) 315 { 316 // nothing to do, nothing to veto 317 } 318 // -------------------------------------------------------------------------------- 319 void SAL_CALL MacabDriver::notifyTermination( const EventObject& ) throw (RuntimeException) 320 { 321 m_aImplModule.shutdown(); 322 } 323 // -------------------------------------------------------------------------------- 324 void SAL_CALL MacabDriver::disposing( const EventObject& ) throw (RuntimeException) 325 { 326 // not interested in (this is the disposing of the desktop, if any) 327 } 328 // -------------------------------------------------------------------------------- 329 const sal_Char* MacabDriver::impl_getAsciiImplementationName() 330 { 331 return "com.sun.star.comp.sdbc.macab.Driver"; 332 // this name is referenced in the configuration and in the macab.xml 333 // Please be careful when changing it. 334 } 335 // -------------------------------------------------------------------------------- 336 ::rtl::OUString MacabDriver::impl_getConfigurationSettingsPath() 337 { 338 ::rtl::OUStringBuffer aPath; 339 aPath.appendAscii( "/org.openoffice.Office.DataAccess/DriverSettings/" ); 340 aPath.appendAscii( "com.sun.star.comp.sdbc.macab.Driver" ); 341 return aPath.makeStringAndClear(); 342 } 343 // -------------------------------------------------------------------------------- 344 Reference< XInterface > SAL_CALL MacabDriver::Create( const Reference< XMultiServiceFactory >& _rxFactory ) throw( Exception ) 345 { 346 return *(new MacabDriver(_rxFactory)); 347 } 348 349