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