1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <osl/diagnose.h>
22 #include <osl/interlck.h>
23 #include <osl/doublecheckedlocking.h>
24 #include <osl/mutex.hxx>
25 #include <rtl/ref.hxx>
26 #include <uno/dispatcher.hxx>
28 #include <uno/lbnames.h>
29 #include <uno/mapping.hxx>
30 #include <uno/environment.hxx>
31 #include <typelib/typedescription.hxx>
32 #include <cppuhelper/exc_hlp.hxx>
33 #include <cppuhelper/implbase2.hxx>
34 #include <cppuhelper/implementationentry.hxx>
35 #include <cppuhelper/factory.hxx>
36 #include <cppuhelper/supportsservice.hxx>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/registry/XRegistryKey.hpp>
39 #include <com/sun/star/reflection/XProxyFactory.hpp>
40 #include <com/sun/star/uno/RuntimeException.hpp>
42 #define SERVICE_NAME "com.sun.star.reflection.ProxyFactory"
43 #define IMPL_NAME "com.sun.star.comp.reflection.ProxyFactory"
46 using namespace ::com::sun::star
;
47 using namespace css::uno
;
53 static OUString
proxyfac_getImplementationName()
55 return OUString(IMPL_NAME
);
58 static Sequence
< OUString
> proxyfac_getSupportedServiceNames()
60 OUString str_name
= SERVICE_NAME
;
61 return Sequence
< OUString
>( &str_name
, 1 );
65 struct FactoryImpl
: public ::cppu::WeakImplHelper2
< lang::XServiceInfo
,
66 reflection::XProxyFactory
>
68 Environment m_uno_env
;
69 Environment m_cpp_env
;
73 UnoInterfaceReference
binuno_queryInterface(
74 UnoInterfaceReference
const & unoI
,
75 typelib_InterfaceTypeDescription
* pTypeDescr
);
78 virtual ~FactoryImpl();
81 virtual OUString SAL_CALL
getImplementationName()
82 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
83 virtual sal_Bool SAL_CALL
supportsService( const OUString
& rServiceName
)
84 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
85 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames()
86 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
89 virtual Reference
< XAggregation
> SAL_CALL
createProxy(
90 Reference
< XInterface
> const & xTarget
)
91 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
95 UnoInterfaceReference
FactoryImpl::binuno_queryInterface(
96 UnoInterfaceReference
const & unoI
,
97 typelib_InterfaceTypeDescription
* pTypeDescr
)
99 // init queryInterface() td
100 static typelib_TypeDescription
* s_pQITD
= 0;
103 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
106 typelib_TypeDescription
* pTXInterfaceDescr
= 0;
109 cppu::UnoType
<XInterface
>::get().getTypeLibType() );
110 typelib_TypeDescription
* pQITD
= 0;
111 typelib_typedescriptionreference_getDescription(
112 &pQITD
, reinterpret_cast< typelib_InterfaceTypeDescription
* >(
113 pTXInterfaceDescr
)->ppAllMembers
[ 0 ] );
114 TYPELIB_DANGER_RELEASE( pTXInterfaceDescr
);
115 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
121 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
125 args
[ 0 ] = &reinterpret_cast< typelib_TypeDescription
* >(
126 pTypeDescr
)->pWeakRef
;
127 uno_Any ret_val
, exc_space
;
128 uno_Any
* exc
= &exc_space
;
130 unoI
.dispatch( s_pQITD
, &ret_val
, args
, &exc
);
134 UnoInterfaceReference ret
;
135 if (ret_val
.pType
->eTypeClass
== typelib_TypeClass_INTERFACE
)
137 ret
.set( *static_cast< uno_Interface
** >(ret_val
.pData
),
139 typelib_typedescriptionreference_release( ret_val
.pType
);
143 uno_any_destruct( &ret_val
, 0 );
149 // exception occurred:
151 typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType
<RuntimeException
>::get().getTypeLibType(),
153 "### RuntimeException expected!" );
155 uno_type_copyAndConvertData(
156 &cpp_exc
, exc
, cppu::UnoType
<decltype(cpp_exc
)>::get().getTypeLibType(),
158 uno_any_destruct( exc
, 0 );
159 ::cppu::throwException( cpp_exc
);
160 OSL_ASSERT( false ); // way of no return
161 return UnoInterfaceReference(); // for dummy
166 struct ProxyRoot
: public ::cppu::OWeakAggObject
169 virtual Any SAL_CALL
queryAggregation( Type
const & rType
)
170 throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
172 virtual ~ProxyRoot();
173 inline ProxyRoot( ::rtl::Reference
< FactoryImpl
> const & factory
,
174 Reference
< XInterface
> const & xTarget
);
176 ::rtl::Reference
< FactoryImpl
> m_factory
;
179 UnoInterfaceReference m_target
;
183 struct binuno_Proxy
: public uno_Interface
185 oslInterlockedCount m_nRefCount
;
186 ::rtl::Reference
< ProxyRoot
> m_root
;
187 UnoInterfaceReference m_target
;
189 TypeDescription m_typeDescr
;
192 ::rtl::Reference
< ProxyRoot
> const & root
,
193 UnoInterfaceReference
const & target
,
194 OUString
const & oid
, TypeDescription
const & typeDescr
);
201 static void SAL_CALL
binuno_proxy_free(
202 uno_ExtEnvironment
* pEnv
, void * pProxy
)
204 (void) pEnv
; // avoid warning about unused parameter
205 binuno_Proxy
* proxy
= static_cast< binuno_Proxy
* >(
206 static_cast< uno_Interface
* >( pProxy
) );
207 OSL_ASSERT( proxy
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
== pEnv
);
212 static void SAL_CALL
binuno_proxy_acquire( uno_Interface
* pUnoI
)
214 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
215 if (osl_atomic_increment( &that
->m_nRefCount
) == 1)
218 uno_ExtEnvironment
* uno_env
=
219 that
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
;
220 OSL_ASSERT( uno_env
!= 0 );
221 (*uno_env
->registerProxyInterface
)(
222 uno_env
, reinterpret_cast< void ** >( &pUnoI
), binuno_proxy_free
,
224 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
225 that
->m_typeDescr
.get() ) );
226 OSL_ASSERT( that
== static_cast< binuno_Proxy
* >( pUnoI
) );
231 static void SAL_CALL
binuno_proxy_release( uno_Interface
* pUnoI
)
233 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
234 if (osl_atomic_decrement( &that
->m_nRefCount
) == 0)
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
->revokeInterface
)( uno_env
, pUnoI
);
244 static void SAL_CALL
binuno_proxy_dispatch(
245 uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberType
,
246 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
248 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
249 switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription
const * >(
250 pMemberType
)->nPosition
)
252 case 0: // queryInterface()
257 *static_cast< Type
const * >( pArgs
[ 0 ] );
258 Any
ret( that
->m_root
->queryInterface( rType
) );
259 uno_type_copyAndConvertData(
260 pReturn
, &ret
, cppu::UnoType
<decltype(ret
)>::get().getTypeLibType(),
261 that
->m_root
->m_factory
->m_cpp2uno
.get() );
262 *ppException
= 0; // no exc
264 catch (RuntimeException
&)
266 Any
exc( ::cppu::getCaughtException() );
267 uno_type_any_constructAndConvert(
268 *ppException
, const_cast< void * >(exc
.getValue()),
269 exc
.getValueTypeRef(),
270 that
->m_root
->m_factory
->m_cpp2uno
.get() );
275 binuno_proxy_acquire( pUnoI
);
276 *ppException
= 0; // no exc
279 binuno_proxy_release( pUnoI
);
280 *ppException
= 0; // no exc
283 that
->m_target
.dispatch( pMemberType
, pReturn
, pArgs
, ppException
);
291 inline binuno_Proxy::binuno_Proxy(
292 ::rtl::Reference
< ProxyRoot
> const & root
,
293 UnoInterfaceReference
const & target
,
294 OUString
const & oid
, TypeDescription
const & typeDescr
)
299 m_typeDescr( typeDescr
)
301 uno_Interface::acquire
= binuno_proxy_acquire
;
302 uno_Interface::release
= binuno_proxy_release
;
303 uno_Interface::pDispatcher
= binuno_proxy_dispatch
;
307 ProxyRoot::~ProxyRoot()
312 inline ProxyRoot::ProxyRoot(
313 ::rtl::Reference
< FactoryImpl
> const & factory
,
314 Reference
< XInterface
> const & xTarget
)
315 : m_factory( factory
)
317 m_factory
->m_cpp2uno
.mapInterface(
318 reinterpret_cast< void ** >( &m_target
.m_pUnoI
), xTarget
.get(),
319 cppu::UnoType
<decltype(xTarget
)>::get() );
320 OSL_ENSURE( m_target
.is(), "### mapping interface failed!" );
324 Any
ProxyRoot::queryAggregation( Type
const & rType
)
325 throw (RuntimeException
, std::exception
)
327 Any
ret( OWeakAggObject::queryAggregation( rType
) );
328 if (! ret
.hasValue())
330 typelib_TypeDescription
* pTypeDescr
= 0;
331 TYPELIB_DANGER_GET( &pTypeDescr
, rType
.getTypeLibType() );
334 Reference
< XInterface
> xProxy
;
335 uno_ExtEnvironment
* cpp_env
= m_factory
->m_cpp_env
.get()->pExtEnv
;
336 OSL_ASSERT( cpp_env
!= 0 );
338 // mind a new delegator, calculate current root:
339 Reference
< XInterface
> xRoot(
340 static_cast< OWeakObject
* >(this), UNO_QUERY_THROW
);
342 (*cpp_env
->getObjectIdentifier
)( cpp_env
, &oid
.pData
, xRoot
.get() );
343 OSL_ASSERT( !oid
.isEmpty() );
345 (*cpp_env
->getRegisteredInterface
)(
346 cpp_env
, reinterpret_cast< void ** >( &xProxy
),
347 oid
.pData
, reinterpret_cast<
348 typelib_InterfaceTypeDescription
* >(pTypeDescr
) );
351 // perform query on target:
352 UnoInterfaceReference
proxy_target(
353 m_factory
->binuno_queryInterface(
354 m_target
, reinterpret_cast<
355 typelib_InterfaceTypeDescription
* >(pTypeDescr
) ) );
356 if (proxy_target
.is())
358 // ensure root's object entries:
359 UnoInterfaceReference root
;
360 m_factory
->m_cpp2uno
.mapInterface(
361 reinterpret_cast< void ** >( &root
.m_pUnoI
),
362 xRoot
.get(), cppu::UnoType
<decltype(xRoot
)>::get() );
364 UnoInterfaceReference
proxy(
365 // ref count initially 1:
366 new binuno_Proxy( this, proxy_target
, oid
, pTypeDescr
),
368 uno_ExtEnvironment
* uno_env
=
369 m_factory
->m_uno_env
.get()->pExtEnv
;
370 OSL_ASSERT( uno_env
!= 0 );
371 (*uno_env
->registerProxyInterface
)(
372 uno_env
, reinterpret_cast< void ** >( &proxy
.m_pUnoI
),
373 binuno_proxy_free
, oid
.pData
,
374 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
377 m_factory
->m_uno2cpp
.mapInterface(
378 reinterpret_cast< void ** >( &xProxy
),
379 proxy
.get(), pTypeDescr
);
383 ret
.setValue( &xProxy
, pTypeDescr
);
385 catch (...) // finally
387 TYPELIB_DANGER_RELEASE( pTypeDescr
);
390 TYPELIB_DANGER_RELEASE( pTypeDescr
);
398 FactoryImpl::FactoryImpl()
400 OUString uno
= UNO_LB_UNO
;
401 OUString cpp
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
404 reinterpret_cast< uno_Environment
** >( &m_uno_env
), uno
.pData
, 0 );
405 OSL_ENSURE( m_uno_env
.is(), "### cannot get binary uno env!" );
408 reinterpret_cast< uno_Environment
** >( &m_cpp_env
), cpp
.pData
, 0 );
409 OSL_ENSURE( m_cpp_env
.is(), "### cannot get C++ uno env!" );
412 reinterpret_cast< uno_Mapping
** >( &m_uno2cpp
),
413 m_uno_env
.get(), m_cpp_env
.get(), 0 );
414 OSL_ENSURE( m_uno2cpp
.is(), "### cannot get bridge uno <-> C++!" );
417 reinterpret_cast< uno_Mapping
** >( &m_cpp2uno
),
418 m_cpp_env
.get(), m_uno_env
.get(), 0 );
419 OSL_ENSURE( m_cpp2uno
.is(), "### cannot get bridge C++ <-> uno!" );
423 FactoryImpl::~FactoryImpl() {}
427 Reference
< XAggregation
> FactoryImpl::createProxy(
428 Reference
< XInterface
> const & xTarget
)
429 throw (RuntimeException
, std::exception
)
431 return new ProxyRoot( this, xTarget
);
436 OUString
FactoryImpl::getImplementationName()
437 throw (RuntimeException
, std::exception
)
439 return proxyfac_getImplementationName();
442 sal_Bool
FactoryImpl::supportsService( const OUString
& rServiceName
)
443 throw (RuntimeException
, std::exception
)
445 return cppu::supportsService(this, rServiceName
);
448 Sequence
< OUString
> FactoryImpl::getSupportedServiceNames()
449 throw(css::uno::RuntimeException
, std::exception
)
451 return proxyfac_getSupportedServiceNames();
455 static Reference
< XInterface
> SAL_CALL
proxyfac_create(
456 SAL_UNUSED_PARAMETER Reference
< XComponentContext
> const & )
459 Reference
< XInterface
> xRet
;
461 ::osl::MutexGuard
guard( ::osl::Mutex::getGlobalMutex() );
462 static WeakReference
< XInterface
> rwInstance
;
467 xRet
= static_cast< ::cppu::OWeakObject
* >(new FactoryImpl
);
474 static const ::cppu::ImplementationEntry g_entries
[] =
477 proxyfac_create
, proxyfac_getImplementationName
,
478 proxyfac_getSupportedServiceNames
, ::cppu::createSingleComponentFactory
,
486 extern "C" SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
proxyfac_component_getFactory(
487 const sal_Char
* pImplName
, void * pServiceManager
, void * pRegistryKey
)
489 return ::cppu::component_getFactoryHelper(
490 pImplName
, pServiceManager
, pRegistryKey
, g_entries
);
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */