1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bridgefactory.cxx,v $
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 ************************************************************************/
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
;
77 size_t operator()(const OUString
& s
) const
78 { return s
.hashCode(); }
83 sal_Bool
operator()(const OUString
& s1
, const OUString
&s2
) const
89 typedef ::std::hash_map
92 WeakReference
< XBridge
>,
98 typedef ::std::hash_map
106 class OBridgeFactory
:
108 public OComponentHelper
,
109 public XBridgeFactory
,
113 OBridgeFactory( const Reference
< XComponentContext
> &rCtx
);
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(); }
126 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::bridge::XBridge
> SAL_CALL
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
);
152 static OUString
getImplementationNameStatic( ) SAL_THROW( () );
153 static Sequence
< OUString
> getSupportedServiceNamesStatic() SAL_THROW( () );
157 OUString
getServiceNameForProtocol( const OUString
&sProtocol
);
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() )
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
);
190 OUString sMetaService
= OUString(
191 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.bridge.Bridge" ) );
192 Reference
< XEnumeration
> rEnum
=
193 rContent
->createContentEnumeration( sMetaService
);
195 while( rEnum
->hasMoreElements() )
197 Any a
= rEnum
->nextElement();
198 Reference
<XServiceInfo
> rInfo
;
201 Sequence
< OUString
> seq
= rInfo
->getSupportedServiceNames();
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
)
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
;
244 // fallback to the old solution, deprecated, should be removed !
245 sService
= OUString::createFromAscii( "com.sun.star.bridge.Bridge." );
246 sService
+= sProtocolName
;
251 Any
OBridgeFactory::queryInterface( const Type
&aType
) throw(RuntimeException
)
253 Any a
= ::cppu::queryInterface(
255 ( XBridgeFactory
* ) this );
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
);
294 throw IllegalArgumentException();
297 if( sName
.getLength() )
299 MutexGuard
guard( m_mutex
);
300 // put the bridge into the hashmap
301 m_mapBridge
[ sName
] = 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
;
320 m_mapBridge
.erase( ii
);
326 // try to get it via the C-Context
327 remote_Context
* pRemoteC
= remote_getContext( sName
.pData
);
331 rBridge
= Reference
< XBridge
> ((XBridge
*) new OBridge( pRemoteC
) );
332 pRemoteC
->aBase
.release( (uno_Context
* )pRemoteC
);
333 m_mapBridge
[ sName
] = rBridge
;
339 Sequence
< Reference
< XBridge
> > OBridgeFactory::getExistingBridges( )
340 throw(::com::sun::star::uno::RuntimeException
)
342 MutexGuard
guard( m_mutex
);
346 rtl_uString
**ppName
= remote_getContextList(
348 rtl_allocateMemory
);
350 Sequence
< Reference
< XBridge
> > seq( nCount
);
354 for( sal_Int32 i
= 0;
358 seq
.getArray()[i
] = getBridge( OUString( ppName
[i
]) );
359 rtl_uString_release( ppName
[i
] );
361 rtl_freeMemory( ppName
);
368 Sequence
< Type
> SAL_CALL
OBridgeFactory::getTypes(void) throw( RuntimeException
)
370 static OTypeCollection
*pCollection
= 0;
373 MutexGuard
guard( Mutex::getGlobalMutex() );
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;
390 MutexGuard
guard( Mutex::getGlobalMutex() );
393 static OImplementationId
id( sal_False
);
397 return (*pId
).getImplementationId();
400 OUString
OBridgeFactory::getImplementationNameStatic()
402 static OUString
*pName
= 0;
405 MutexGuard
guard( Mutex::getGlobalMutex() );
408 static OUString
name( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME
) );
415 Sequence
< OUString
> OBridgeFactory::getSupportedServiceNamesStatic()
417 static Sequence
< OUString
> *pNames
= 0;
420 MutexGuard
guard( Mutex::getGlobalMutex() );
423 static Sequence
< OUString
> seqNames(1);
424 seqNames
.getArray()[0] = OUString::createFromAscii( SERVICE_NAME
);
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
)
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
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
);