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