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: proxyfac.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 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
34 #include "osl/diagnose.h"
35 #include "osl/interlck.h"
36 #include "osl/doublecheckedlocking.h"
37 #include "osl/mutex.hxx"
38 #include "rtl/ref.hxx"
39 #include "uno/dispatcher.hxx"
41 #include "uno/mapping.hxx"
42 #include "uno/environment.hxx"
43 #include "typelib/typedescription.hxx"
44 #include "cppuhelper/exc_hlp.hxx"
45 #include "cppuhelper/implbase2.hxx"
46 #include "cppuhelper/implementationentry.hxx"
47 #include "cppuhelper/factory.hxx"
48 #include "com/sun/star/lang/XServiceInfo.hpp"
49 #include "com/sun/star/registry/XRegistryKey.hpp"
50 #include "com/sun/star/reflection/XProxyFactory.hpp"
51 #include "com/sun/star/uno/RuntimeException.hpp"
53 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
54 #define SERVICE_NAME "com.sun.star.reflection.ProxyFactory"
55 #define IMPL_NAME "com.sun.star.comp.reflection.ProxyFactory"
58 using namespace ::com::sun::star
;
59 using namespace ::com::sun::star::uno
;
60 using ::rtl::OUString
;
66 static rtl_StandardModuleCount g_moduleCount
= MODULE_COUNT_INIT
;
68 static OUString
proxyfac_getImplementationName()
70 return OUSTR(IMPL_NAME
);
73 static Sequence
< OUString
> proxyfac_getSupportedServiceNames()
75 OUString str_name
= OUSTR(SERVICE_NAME
);
76 return Sequence
< OUString
>( &str_name
, 1 );
79 //==============================================================================
80 struct FactoryImpl
: public ::cppu::WeakImplHelper2
< lang::XServiceInfo
,
81 reflection::XProxyFactory
>
83 Environment m_uno_env
;
84 Environment m_cpp_env
;
88 UnoInterfaceReference
binuno_queryInterface(
89 UnoInterfaceReference
const & unoI
,
90 typelib_InterfaceTypeDescription
* pTypeDescr
);
93 virtual ~FactoryImpl();
96 virtual OUString SAL_CALL
getImplementationName()
97 throw (RuntimeException
);
98 virtual sal_Bool SAL_CALL
supportsService( const OUString
& rServiceName
)
99 throw (RuntimeException
);
100 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames()
101 throw (RuntimeException
);
104 virtual Reference
< XAggregation
> SAL_CALL
createProxy(
105 Reference
< XInterface
> const & xTarget
)
106 throw (RuntimeException
);
109 //______________________________________________________________________________
110 UnoInterfaceReference
FactoryImpl::binuno_queryInterface(
111 UnoInterfaceReference
const & unoI
,
112 typelib_InterfaceTypeDescription
* pTypeDescr
)
114 // init queryInterface() td
115 static typelib_TypeDescription
* s_pQITD
= 0;
118 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
121 typelib_TypeDescription
* pTXInterfaceDescr
= 0;
124 ::getCppuType( reinterpret_cast< Reference
< XInterface
>
125 const * >(0) ).getTypeLibType() );
126 typelib_TypeDescription
* pQITD
= 0;
127 typelib_typedescriptionreference_getDescription(
128 &pQITD
, reinterpret_cast< typelib_InterfaceTypeDescription
* >(
129 pTXInterfaceDescr
)->ppAllMembers
[ 0 ] );
130 TYPELIB_DANGER_RELEASE( pTXInterfaceDescr
);
131 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
137 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
141 args
[ 0 ] = &reinterpret_cast< typelib_TypeDescription
* >(
142 pTypeDescr
)->pWeakRef
;
143 uno_Any ret_val
, exc_space
;
144 uno_Any
* exc
= &exc_space
;
146 unoI
.dispatch( s_pQITD
, &ret_val
, args
, &exc
);
150 UnoInterfaceReference ret
;
151 if (ret_val
.pType
->eTypeClass
== typelib_TypeClass_INTERFACE
)
153 ret
.set( *reinterpret_cast< uno_Interface
** >(ret_val
.pData
),
155 typelib_typedescriptionreference_release( ret_val
.pType
);
159 uno_any_destruct( &ret_val
, 0 );
165 // exception occured:
167 typelib_typedescriptionreference_isAssignableFrom(
168 ::getCppuType( reinterpret_cast<
169 RuntimeException
const * >(0) ).getTypeLibType(),
171 "### RuntimeException expected!" );
173 uno_type_copyAndConvertData(
174 &cpp_exc
, exc
, ::getCppuType( &cpp_exc
).getTypeLibType(),
176 uno_any_destruct( exc
, 0 );
177 ::cppu::throwException( cpp_exc
);
178 OSL_ASSERT( 0 ); // way of no return
179 return UnoInterfaceReference(); // for dummy
183 //==============================================================================
184 struct ProxyRoot
: public ::cppu::OWeakAggObject
187 virtual Any SAL_CALL
queryAggregation( Type
const & rType
)
188 throw (RuntimeException
);
190 virtual ~ProxyRoot();
191 inline ProxyRoot( ::rtl::Reference
< FactoryImpl
> const & factory
,
192 Reference
< XInterface
> const & xTarget
);
194 ::rtl::Reference
< FactoryImpl
> m_factory
;
197 UnoInterfaceReference m_target
;
200 //==============================================================================
201 struct binuno_Proxy
: public uno_Interface
203 oslInterlockedCount m_nRefCount
;
204 ::rtl::Reference
< ProxyRoot
> m_root
;
205 UnoInterfaceReference m_target
;
207 TypeDescription m_typeDescr
;
210 ::rtl::Reference
< ProxyRoot
> const & root
,
211 UnoInterfaceReference
const & target
,
212 OUString
const & oid
, TypeDescription
const & typeDescr
);
218 //------------------------------------------------------------------------------
219 static void SAL_CALL
binuno_proxy_free(
220 uno_ExtEnvironment
* pEnv
, void * pProxy
)
222 (void) pEnv
; // avoid warning about unused parameter
223 binuno_Proxy
* proxy
= static_cast< binuno_Proxy
* >(
224 reinterpret_cast< uno_Interface
* >( pProxy
) );
225 OSL_ASSERT( proxy
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
== pEnv
);
229 //------------------------------------------------------------------------------
230 static void SAL_CALL
binuno_proxy_acquire( uno_Interface
* pUnoI
)
232 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
233 if (osl_incrementInterlockedCount( &that
->m_nRefCount
) == 1)
236 uno_ExtEnvironment
* uno_env
=
237 that
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
;
238 OSL_ASSERT( uno_env
!= 0 );
239 (*uno_env
->registerProxyInterface
)(
240 uno_env
, reinterpret_cast< void ** >( &pUnoI
), binuno_proxy_free
,
242 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
243 that
->m_typeDescr
.get() ) );
244 OSL_ASSERT( that
== static_cast< binuno_Proxy
* >( pUnoI
) );
248 //------------------------------------------------------------------------------
249 static void SAL_CALL
binuno_proxy_release( uno_Interface
* pUnoI
)
251 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
252 if (osl_decrementInterlockedCount( &that
->m_nRefCount
) == 0)
254 uno_ExtEnvironment
* uno_env
=
255 that
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
;
256 OSL_ASSERT( uno_env
!= 0 );
257 (*uno_env
->revokeInterface
)( uno_env
, pUnoI
);
261 //------------------------------------------------------------------------------
262 static void SAL_CALL
binuno_proxy_dispatch(
263 uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberType
,
264 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
266 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
267 switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription
const * >(
268 pMemberType
)->nPosition
)
270 case 0: // queryInterface()
275 *reinterpret_cast< Type
const * >( pArgs
[ 0 ] );
276 Any
ret( that
->m_root
->queryInterface( rType
) );
277 uno_type_copyAndConvertData(
278 pReturn
, &ret
, ::getCppuType( &ret
).getTypeLibType(),
279 that
->m_root
->m_factory
->m_cpp2uno
.get() );
280 *ppException
= 0; // no exc
282 catch (RuntimeException
&)
284 Any
exc( ::cppu::getCaughtException() );
285 uno_type_any_constructAndConvert(
286 *ppException
, const_cast< void * >(exc
.getValue()),
287 exc
.getValueTypeRef(),
288 that
->m_root
->m_factory
->m_cpp2uno
.get() );
293 binuno_proxy_acquire( pUnoI
);
294 *ppException
= 0; // no exc
297 binuno_proxy_release( pUnoI
);
298 *ppException
= 0; // no exc
301 that
->m_target
.dispatch( pMemberType
, pReturn
, pArgs
, ppException
);
308 //______________________________________________________________________________
309 inline binuno_Proxy::binuno_Proxy(
310 ::rtl::Reference
< ProxyRoot
> const & root
,
311 UnoInterfaceReference
const & target
,
312 OUString
const & oid
, TypeDescription
const & typeDescr
)
317 m_typeDescr( typeDescr
)
319 uno_Interface::acquire
= binuno_proxy_acquire
;
320 uno_Interface::release
= binuno_proxy_release
;
321 uno_Interface::pDispatcher
= binuno_proxy_dispatch
;
324 //______________________________________________________________________________
325 ProxyRoot::~ProxyRoot()
329 //______________________________________________________________________________
330 inline ProxyRoot::ProxyRoot(
331 ::rtl::Reference
< FactoryImpl
> const & factory
,
332 Reference
< XInterface
> const & xTarget
)
333 : m_factory( factory
)
335 m_factory
->m_cpp2uno
.mapInterface(
336 reinterpret_cast< void ** >( &m_target
.m_pUnoI
), xTarget
.get(),
337 ::getCppuType( &xTarget
) );
338 OSL_ENSURE( m_target
.is(), "### mapping interface failed!" );
341 //______________________________________________________________________________
342 Any
ProxyRoot::queryAggregation( Type
const & rType
)
343 throw (RuntimeException
)
345 Any
ret( OWeakAggObject::queryAggregation( rType
) );
346 if (! ret
.hasValue())
348 typelib_TypeDescription
* pTypeDescr
= 0;
349 TYPELIB_DANGER_GET( &pTypeDescr
, rType
.getTypeLibType() );
352 Reference
< XInterface
> xProxy
;
353 uno_ExtEnvironment
* cpp_env
= m_factory
->m_cpp_env
.get()->pExtEnv
;
354 OSL_ASSERT( cpp_env
!= 0 );
356 // mind a new delegator, calculate current root:
357 Reference
< XInterface
> xRoot(
358 static_cast< OWeakObject
* >(this), UNO_QUERY_THROW
);
360 (*cpp_env
->getObjectIdentifier
)( cpp_env
, &oid
.pData
, xRoot
.get() );
361 OSL_ASSERT( oid
.getLength() > 0 );
363 (*cpp_env
->getRegisteredInterface
)(
364 cpp_env
, reinterpret_cast< void ** >( &xProxy
),
365 oid
.pData
, reinterpret_cast<
366 typelib_InterfaceTypeDescription
* >(pTypeDescr
) );
369 // perform query on target:
370 UnoInterfaceReference
proxy_target(
371 m_factory
->binuno_queryInterface(
372 m_target
, reinterpret_cast<
373 typelib_InterfaceTypeDescription
* >(pTypeDescr
) ) );
374 if (proxy_target
.is())
376 // ensure root's object entries:
377 UnoInterfaceReference root
;
378 m_factory
->m_cpp2uno
.mapInterface(
379 reinterpret_cast< void ** >( &root
.m_pUnoI
),
380 xRoot
.get(), ::getCppuType( &xRoot
) );
382 UnoInterfaceReference
proxy(
383 // ref count initially 1:
384 new binuno_Proxy( this, proxy_target
, oid
, pTypeDescr
),
386 uno_ExtEnvironment
* uno_env
=
387 m_factory
->m_uno_env
.get()->pExtEnv
;
388 OSL_ASSERT( uno_env
!= 0 );
389 (*uno_env
->registerProxyInterface
)(
390 uno_env
, reinterpret_cast< void ** >( &proxy
.m_pUnoI
),
391 binuno_proxy_free
, oid
.pData
,
392 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
395 m_factory
->m_uno2cpp
.mapInterface(
396 reinterpret_cast< void ** >( &xProxy
),
397 proxy
.get(), pTypeDescr
);
401 ret
.setValue( &xProxy
, pTypeDescr
);
403 catch (...) // finally
405 TYPELIB_DANGER_RELEASE( pTypeDescr
);
408 TYPELIB_DANGER_RELEASE( pTypeDescr
);
413 //##############################################################################
415 //______________________________________________________________________________
416 FactoryImpl::FactoryImpl()
418 OUString uno
= OUSTR(UNO_LB_UNO
);
419 OUString cpp
= OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME
);
422 reinterpret_cast< uno_Environment
** >( &m_uno_env
), uno
.pData
, 0 );
423 OSL_ENSURE( m_uno_env
.is(), "### cannot get binary uno env!" );
426 reinterpret_cast< uno_Environment
** >( &m_cpp_env
), cpp
.pData
, 0 );
427 OSL_ENSURE( m_cpp_env
.is(), "### cannot get C++ uno env!" );
430 reinterpret_cast< uno_Mapping
** >( &m_uno2cpp
),
431 m_uno_env
.get(), m_cpp_env
.get(), 0 );
432 OSL_ENSURE( m_uno2cpp
.is(), "### cannot get bridge uno <-> C++!" );
435 reinterpret_cast< uno_Mapping
** >( &m_cpp2uno
),
436 m_cpp_env
.get(), m_uno_env
.get(), 0 );
437 OSL_ENSURE( m_cpp2uno
.is(), "### cannot get bridge C++ <-> uno!" );
439 g_moduleCount
.modCnt
.acquire( &g_moduleCount
.modCnt
);
442 //______________________________________________________________________________
443 FactoryImpl::~FactoryImpl()
445 g_moduleCount
.modCnt
.release( &g_moduleCount
.modCnt
);
449 //______________________________________________________________________________
450 Reference
< XAggregation
> FactoryImpl::createProxy(
451 Reference
< XInterface
> const & xTarget
)
452 throw (RuntimeException
)
454 return new ProxyRoot( this, xTarget
);
458 //______________________________________________________________________________
459 OUString
FactoryImpl::getImplementationName()
460 throw (RuntimeException
)
462 return proxyfac_getImplementationName();;
465 //______________________________________________________________________________
466 sal_Bool
FactoryImpl::supportsService( const OUString
& rServiceName
)
467 throw (RuntimeException
)
469 Sequence
< OUString
> const & rSNL
= getSupportedServiceNames();
470 OUString
const * pArray
= rSNL
.getConstArray();
471 for ( sal_Int32 nPos
= rSNL
.getLength(); nPos
--; )
473 if (rServiceName
.equals( pArray
[ nPos
] ))
479 //______________________________________________________________________________
480 Sequence
< OUString
> FactoryImpl::getSupportedServiceNames()
481 throw(::com::sun::star::uno::RuntimeException
)
483 return proxyfac_getSupportedServiceNames();
486 //==============================================================================
487 static Reference
< XInterface
> SAL_CALL
proxyfac_create(
488 Reference
< XComponentContext
> const & )
491 Reference
< XInterface
> xRet
;
493 ::osl::MutexGuard
guard( ::osl::Mutex::getGlobalMutex() );
494 static WeakReference
< XInterface
> rwInstance
;
499 xRet
= static_cast< ::cppu::OWeakObject
* >(new FactoryImpl
);
506 static ::cppu::ImplementationEntry g_entries
[] =
509 proxyfac_create
, proxyfac_getImplementationName
,
510 proxyfac_getSupportedServiceNames
, ::cppu::createSingleComponentFactory
,
511 &g_moduleCount
.modCnt
, 0
521 sal_Bool SAL_CALL
component_canUnload( TimeValue
* pTime
)
523 return g_moduleCount
.canUnload( &g_moduleCount
, pTime
);
526 void SAL_CALL
component_getImplementationEnvironment(
527 const sal_Char
** ppEnvTypeName
, uno_Environment
** )
529 *ppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
532 sal_Bool SAL_CALL
component_writeInfo(
533 void * pServiceManager
, void * pRegistryKey
)
535 return ::cppu::component_writeInfoHelper(
536 pServiceManager
, pRegistryKey
, g_entries
);
539 void * SAL_CALL
component_getFactory(
540 const sal_Char
* pImplName
, void * pServiceManager
, void * pRegistryKey
)
542 return ::cppu::component_getFactoryHelper(
543 pImplName
, pServiceManager
, pRegistryKey
, g_entries
);