merge the formfield patch from ooo-build
[ooovba.git] / remotebridges / source / factory / bridgefactory.cxx
blob1a460f5741323004cdb5efa801dbf4b1b4c7611b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bridgefactory.cxx,v $
10 * $Revision: 1.13 $
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 ************************************************************************/
30 #include <hash_map>
32 #include <rtl/alloc.h>
34 #include <uno/mapping.hxx>
35 #include <osl/mutex.hxx>
37 #include <bridges/remote/context.h>
39 #include <cppuhelper/implementationentry.hxx>
40 #include <cppuhelper/component.hxx>
41 #include <cppuhelper/typeprovider.hxx>
42 #include "cppuhelper/unourl.hxx"
43 #include "rtl/malformeduriexception.hxx"
45 #include <com/sun/star/lang/XInitialization.hpp>
46 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/bridge/XBridgeFactory.hpp>
50 #include <com/sun/star/registry/XRegistryKey.hpp>
52 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
55 #include "bridgeimpl.hxx"
57 using namespace ::rtl;
58 using namespace ::osl;
59 using namespace ::cppu;
60 using namespace ::std;
61 using namespace ::com::sun::star::uno;
62 using namespace ::com::sun::star::lang;
63 using namespace ::com::sun::star::bridge;
64 using namespace ::com::sun::star::connection;
65 using namespace ::com::sun::star::registry;
66 using namespace ::com::sun::star::container;
68 #define SERVICE_NAME "com.sun.star.bridge.BridgeFactory"
69 #define IMPLEMENTATION_NAME "com.sun.star.comp.remotebridges.BridgeFactory"
71 namespace remotebridges_factory
73 rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
75 struct hashOUString
77 size_t operator()(const OUString & s) const
78 { return s.hashCode(); }
81 struct equalOUString
83 sal_Bool operator()(const OUString & s1 , const OUString &s2 ) const
85 return s1 == s2;
89 typedef ::std::hash_map
91 OUString,
92 WeakReference< XBridge >,
93 hashOUString,
94 equalOUString
95 > BridgeHashMap;
98 typedef ::std::hash_map
100 OUString,
101 OUString,
102 hashOUString,
103 equalOUString
104 > ServiceHashMap;
106 class OBridgeFactory :
107 public MyMutex,
108 public OComponentHelper,
109 public XBridgeFactory,
110 public XServiceInfo
112 public:
113 OBridgeFactory( const Reference < XComponentContext > &rCtx );
114 ~OBridgeFactory();
116 public: // XInterface
117 ::com::sun::star::uno::Any SAL_CALL
118 queryInterface( const ::com::sun::star::uno::Type & aType ) throw(RuntimeException);
120 void SAL_CALL acquire() throw()
121 { OComponentHelper::acquire(); }
122 void SAL_CALL release() throw()
123 { OComponentHelper::release(); }
125 public:
126 virtual ::com::sun::star::uno::Reference< ::com::sun::star::bridge::XBridge > SAL_CALL
127 createBridge(
128 const ::rtl::OUString& sName,
129 const ::rtl::OUString& sProtocol,
130 const ::com::sun::star::uno::Reference< ::com::sun::star::connection::XConnection >& aConnection,
131 const ::com::sun::star::uno::Reference< ::com::sun::star::bridge::XInstanceProvider >& anInstanceProvider )
132 throw(::com::sun::star::bridge::BridgeExistsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
134 virtual ::com::sun::star::uno::Reference< ::com::sun::star::bridge::XBridge > SAL_CALL
135 getBridge( const ::rtl::OUString& sName )
136 throw(::com::sun::star::uno::RuntimeException );
137 virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::bridge::XBridge > > SAL_CALL
138 getExistingBridges( ) throw(::com::sun::star::uno::RuntimeException);
140 public: //XTypeProvider
141 virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL
142 getTypes( ) throw(::com::sun::star::uno::RuntimeException);
143 virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL
144 getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
146 public: //XServiceInfo
147 virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException);
148 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
149 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException);
151 public:
152 static OUString getImplementationNameStatic( ) SAL_THROW( () );
153 static Sequence< OUString > getSupportedServiceNamesStatic() SAL_THROW( () );
155 private:
156 void init();
157 OUString getServiceNameForProtocol( const OUString &sProtocol );
159 private:
160 Reference < XMultiComponentFactory > m_rSMgr;
161 Reference < XComponentContext > m_rCtx;
162 BridgeHashMap m_mapBridge;
163 ServiceHashMap m_mapProtocolToService;
164 sal_Bool m_bInitialized;
165 ::osl::Mutex m_mutexInit;
168 OBridgeFactory::OBridgeFactory( const Reference < XComponentContext > &rCtx )
169 : OComponentHelper( m_mutex )
170 , m_rSMgr( rCtx->getServiceManager() )
171 , m_rCtx( rCtx )
172 , m_bInitialized( sal_False )
174 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
177 OBridgeFactory::~OBridgeFactory()
179 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
182 void OBridgeFactory::init()
184 MutexGuard guard( m_mutexInit );
185 if( ! m_bInitialized )
187 Reference< XContentEnumerationAccess > rContent( m_rSMgr , UNO_QUERY );
188 if( rContent.is() )
190 OUString sMetaService = OUString(
191 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.bridge.Bridge" ) );
192 Reference < XEnumeration > rEnum =
193 rContent->createContentEnumeration( sMetaService );
194 if ( rEnum.is() )
195 while( rEnum->hasMoreElements() )
197 Any a = rEnum->nextElement();
198 Reference <XServiceInfo> rInfo;
199 if( a >>= rInfo )
201 Sequence< OUString > seq = rInfo->getSupportedServiceNames();
202 sal_Int32 i;
203 for( i = 0 ; i < seq.getLength() ; i ++ )
205 if( seq.getConstArray()[i] != sMetaService )
207 sal_Int32 nIndex = seq.getConstArray()[i].lastIndexOf( '.' );
208 OUString sSuffix = seq.getConstArray()[i].copy(nIndex+1);
209 if( sSuffix.getLength() > 6 &&
210 0 == sSuffix.copy( sSuffix.getLength() - 6 ).compareToAscii( "Bridge" ) )
212 OUString sProtocol = sSuffix.copy(0 , sSuffix.getLength()-6 ).toAsciiLowerCase();
213 m_mapProtocolToService[ sProtocol ] = seq.getConstArray()[i];
220 m_bInitialized = sal_True;
224 OUString OBridgeFactory::getServiceNameForProtocol( const OUString & sProtocol )
226 init();
227 OUString sService;
228 OUString sProtocolName;
231 sProtocolName = cppu::UnoUrlDescriptor(sProtocol).getName();
233 catch (rtl::MalformedUriException &)
235 OSL_ENSURE(false, "MalformedUriException");
237 ServiceHashMap::iterator ii = m_mapProtocolToService.find( sProtocolName );
238 if( ii != m_mapProtocolToService.end() )
240 sService = (*ii).second;
242 else
244 // fallback to the old solution, deprecated, should be removed !
245 sService = OUString::createFromAscii( "com.sun.star.bridge.Bridge." );
246 sService += sProtocolName;
248 return sService;
251 Any OBridgeFactory::queryInterface( const Type &aType ) throw(RuntimeException)
253 Any a = ::cppu::queryInterface(
254 aType ,
255 ( XBridgeFactory * ) this );
256 if( a.hasValue() )
258 return a;
261 return OComponentHelper::queryInterface( aType );
265 Reference< XBridge > OBridgeFactory::createBridge(
266 const OUString& sName,
267 const OUString& sProtocol,
268 const Reference< XConnection >& aConnection,
269 const Reference< XInstanceProvider >& anInstanceProvider )
270 throw(::com::sun::star::bridge::BridgeExistsException,
271 ::com::sun::star::lang::IllegalArgumentException,
272 ::com::sun::star::uno::RuntimeException)
274 OUString sService = getServiceNameForProtocol( sProtocol );
276 Reference < XInterface > rXInterface =
277 m_rSMgr->createInstanceWithContext(sService, m_rCtx );
278 Reference < XInitialization > rInit(rXInterface, UNO_QUERY );
279 Reference < XBridge > rBridge( rInit , UNO_QUERY );
281 if( rInit.is() && rBridge.is() )
283 Sequence < Any > seqAny( 4 );
284 seqAny.getArray()[0] <<= sName;
285 seqAny.getArray()[1] <<= sProtocol;
286 seqAny.getArray()[2] <<= aConnection;
287 seqAny.getArray()[3] <<= anInstanceProvider;
289 // let the Exceptions fly ....
290 rInit->initialize( seqAny );
292 else
294 throw IllegalArgumentException();
297 if( sName.getLength() )
299 MutexGuard guard( m_mutex );
300 // put the bridge into the hashmap
301 m_mapBridge[ sName ] = rBridge;
303 return rBridge;
306 Reference< XBridge > OBridgeFactory::getBridge( const ::rtl::OUString& sName )
307 throw(::com::sun::star::uno::RuntimeException )
310 MutexGuard guard( m_mutex );
311 BridgeHashMap::iterator ii = m_mapBridge.find( sName );
313 Reference < XBridge > rBridge;
315 if( ii != m_mapBridge.end() )
317 rBridge = (*ii).second;
318 if( ! rBridge.is() )
320 m_mapBridge.erase( ii );
324 if( ! rBridge.is() )
326 // try to get it via the C-Context
327 remote_Context * pRemoteC = remote_getContext( sName.pData );
329 if( pRemoteC )
331 rBridge = Reference < XBridge > ((XBridge *) new OBridge( pRemoteC ) );
332 pRemoteC->aBase.release( (uno_Context * )pRemoteC );
333 m_mapBridge[ sName ] = rBridge;
336 return rBridge;
339 Sequence< Reference< XBridge > > OBridgeFactory::getExistingBridges( )
340 throw(::com::sun::star::uno::RuntimeException)
342 MutexGuard guard( m_mutex );
344 sal_Int32 nCount;
346 rtl_uString **ppName = remote_getContextList(
347 &nCount,
348 rtl_allocateMemory );
350 Sequence < Reference < XBridge > > seq( nCount );
351 if( nCount )
354 for( sal_Int32 i = 0;
355 i < nCount ;
356 i ++ )
358 seq.getArray()[i] = getBridge( OUString( ppName[i]) );
359 rtl_uString_release( ppName[i] );
361 rtl_freeMemory( ppName );
364 return seq;
367 // XTypeProvider
368 Sequence< Type > SAL_CALL OBridgeFactory::getTypes(void) throw( RuntimeException )
370 static OTypeCollection *pCollection = 0;
371 if( ! pCollection )
373 MutexGuard guard( Mutex::getGlobalMutex() );
374 if( ! pCollection )
376 static OTypeCollection collection(
377 getCppuType( (Reference< XBridgeFactory > * ) 0 ),
378 OComponentHelper::getTypes() );
379 pCollection = &collection;
382 return (*pCollection).getTypes();
385 Sequence< sal_Int8 > SAL_CALL OBridgeFactory::getImplementationId( ) throw( RuntimeException)
387 static OImplementationId *pId = 0;
388 if( ! pId )
390 MutexGuard guard( Mutex::getGlobalMutex() );
391 if( ! pId )
393 static OImplementationId id( sal_False );
394 pId = &id;
397 return (*pId).getImplementationId();
400 OUString OBridgeFactory::getImplementationNameStatic()
402 static OUString *pName = 0;
403 if( ! pName )
405 MutexGuard guard( Mutex::getGlobalMutex() );
406 if( ! pName )
408 static OUString name( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
409 pName = &name;
412 return *pName;
415 Sequence< OUString > OBridgeFactory::getSupportedServiceNamesStatic()
417 static Sequence < OUString > *pNames = 0;
418 if( ! pNames )
420 MutexGuard guard( Mutex::getGlobalMutex() );
421 if( !pNames )
423 static Sequence< OUString > seqNames(1);
424 seqNames.getArray()[0] = OUString::createFromAscii( SERVICE_NAME );
425 pNames = &seqNames;
428 return *pNames;
431 OUString OBridgeFactory::getImplementationName( ) throw(RuntimeException)
433 return getImplementationNameStatic();
436 sal_Bool SAL_CALL OBridgeFactory::supportsService( const OUString& ServiceName ) throw(RuntimeException)
438 Sequence< OUString > seq = getSupportedServiceNamesStatic();
439 sal_Bool bReturn = sal_False;
440 for( sal_Int32 i = 0 ; i < seq.getLength() ; i ++ )
442 if( seq.getConstArray()[i] == ServiceName )
444 bReturn = sal_True;
445 break;
448 return bReturn;
451 Sequence< OUString > SAL_CALL OBridgeFactory::getSupportedServiceNames( ) throw(RuntimeException)
453 return getSupportedServiceNamesStatic();
457 Reference< XInterface > SAL_CALL CreateInstance(Reference< XComponentContext > const & xContext)
459 return Reference < XInterface > ( *new OBridgeFactory( xContext ) );
463 using namespace remotebridges_factory;
464 static ImplementationEntry g_entries[] =
466 { CreateInstance, OBridgeFactory::getImplementationNameStatic,
467 OBridgeFactory::getSupportedServiceNamesStatic, createSingleComponentFactory ,
468 &g_moduleCount.modCnt , 0
470 { 0, 0, 0, 0, 0, 0 }
473 extern "C"
475 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime )
477 return g_moduleCount.canUnload( &g_moduleCount , pTime );
480 //==================================================================================================
481 void SAL_CALL component_getImplementationEnvironment(
482 const sal_Char ** ppEnvTypeName, uno_Environment ** )
484 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
486 //==================================================================================================
487 sal_Bool SAL_CALL component_writeInfo(
488 void * pServiceManager, void * pRegistryKey )
490 return component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries );
492 //==================================================================================================
493 void * SAL_CALL component_getFactory(
494 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
496 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );