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 <rtl/ref.hxx>
24 #include <uno/dispatcher.hxx>
26 #include <uno/lbnames.h>
27 #include <uno/mapping.hxx>
28 #include <uno/environment.hxx>
29 #include <typelib/typedescription.hxx>
30 #include <cppuhelper/exc_hlp.hxx>
31 #include <cppuhelper/implbase.hxx>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <cppuhelper/weak.hxx>
34 #include <cppuhelper/weakagg.hxx>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/reflection/XProxyFactory.hpp>
37 #include <com/sun/star/uno/RuntimeException.hpp>
38 #include <com/sun/star/uno/XComponentContext.hpp>
41 using namespace ::com::sun::star
;
42 using namespace css::uno
;
48 struct FactoryImpl
: public ::cppu::WeakImplHelper
< lang::XServiceInfo
,
49 reflection::XProxyFactory
>
51 Environment m_uno_env
;
52 Environment m_cpp_env
;
56 UnoInterfaceReference
binuno_queryInterface(
57 UnoInterfaceReference
const & unoI
,
58 typelib_InterfaceTypeDescription
* pTypeDescr
);
63 virtual OUString SAL_CALL
getImplementationName() override
;
64 virtual sal_Bool SAL_CALL
supportsService( const OUString
& rServiceName
) override
;
65 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
68 virtual Reference
< XAggregation
> SAL_CALL
createProxy(
69 Reference
< XInterface
> const & xTarget
) override
;
73 UnoInterfaceReference
FactoryImpl::binuno_queryInterface(
74 UnoInterfaceReference
const & unoI
,
75 typelib_InterfaceTypeDescription
* pTypeDescr
)
77 // init queryInterface() td
78 static typelib_TypeDescription
* s_pQITD
= []() {
79 typelib_TypeDescription
* pTXInterfaceDescr
= nullptr;
80 TYPELIB_DANGER_GET(&pTXInterfaceDescr
, cppu::UnoType
<XInterface
>::get().getTypeLibType());
81 typelib_TypeDescription
* pQITD
= nullptr;
82 typelib_typedescriptionreference_getDescription(
83 &pQITD
, reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTXInterfaceDescr
)
85 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr
);
90 args
[ 0 ] = &reinterpret_cast< typelib_TypeDescription
* >(
91 pTypeDescr
)->pWeakRef
;
92 uno_Any ret_val
, exc_space
;
93 uno_Any
* exc
= &exc_space
;
95 unoI
.dispatch( s_pQITD
, &ret_val
, args
, &exc
);
99 UnoInterfaceReference ret
;
100 if (ret_val
.pType
->eTypeClass
== typelib_TypeClass_INTERFACE
)
102 ret
.set( *static_cast< uno_Interface
** >(ret_val
.pData
),
104 typelib_typedescriptionreference_release( ret_val
.pType
);
108 uno_any_destruct( &ret_val
, nullptr );
114 // exception occurred:
116 typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType
<RuntimeException
>::get().getTypeLibType(),
118 "### RuntimeException expected!" );
120 uno_type_copyAndConvertData(
121 &cpp_exc
, exc
, cppu::UnoType
<decltype(cpp_exc
)>::get().getTypeLibType(),
123 uno_any_destruct( exc
, nullptr );
124 ::cppu::throwException( cpp_exc
);
125 OSL_ASSERT( false ); // way of no return
126 return UnoInterfaceReference(); // for dummy
131 struct ProxyRoot
: public ::cppu::OWeakAggObject
134 virtual Any SAL_CALL
queryAggregation( Type
const & rType
) override
;
136 ProxyRoot( ::rtl::Reference
< FactoryImpl
> const & factory
,
137 Reference
< XInterface
> const & xTarget
);
139 ::rtl::Reference
< FactoryImpl
> m_factory
;
142 UnoInterfaceReference m_target
;
146 struct binuno_Proxy
: public uno_Interface
148 oslInterlockedCount m_nRefCount
;
149 ::rtl::Reference
< ProxyRoot
> m_root
;
150 UnoInterfaceReference m_target
;
152 TypeDescription m_typeDescr
;
155 ::rtl::Reference
< ProxyRoot
> const & root
,
156 UnoInterfaceReference
const & target
,
157 OUString
const & oid
, TypeDescription
const & typeDescr
);
164 static void binuno_proxy_free(
165 uno_ExtEnvironment
* pEnv
, void * pProxy
)
167 binuno_Proxy
* proxy
= static_cast< binuno_Proxy
* >(
168 static_cast< uno_Interface
* >( pProxy
) );
169 OSL_ASSERT( proxy
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
== pEnv
);
174 static void binuno_proxy_acquire( uno_Interface
* pUnoI
)
176 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
177 if (osl_atomic_increment( &that
->m_nRefCount
) != 1)
181 uno_ExtEnvironment
* uno_env
=
182 that
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
;
183 OSL_ASSERT( uno_env
!= nullptr );
184 (*uno_env
->registerProxyInterface
)(
185 uno_env
, reinterpret_cast< void ** >( &pUnoI
), binuno_proxy_free
,
187 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
188 that
->m_typeDescr
.get() ) );
189 OSL_ASSERT( that
== static_cast< binuno_Proxy
* >( pUnoI
) );
193 static void binuno_proxy_release( uno_Interface
* pUnoI
)
195 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
196 if (osl_atomic_decrement( &that
->m_nRefCount
) == 0)
198 uno_ExtEnvironment
* uno_env
=
199 that
->m_root
->m_factory
->m_uno_env
.get()->pExtEnv
;
200 OSL_ASSERT( uno_env
!= nullptr );
201 (*uno_env
->revokeInterface
)( uno_env
, pUnoI
);
206 static void binuno_proxy_dispatch(
207 uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberType
,
208 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
210 binuno_Proxy
* that
= static_cast< binuno_Proxy
* >( pUnoI
);
211 switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription
const * >(
212 pMemberType
)->nPosition
)
214 case 0: // queryInterface()
219 *static_cast< Type
const * >( pArgs
[ 0 ] );
220 Any
ret( that
->m_root
->queryInterface( rType
) );
221 uno_type_copyAndConvertData(
222 pReturn
, &ret
, cppu::UnoType
<decltype(ret
)>::get().getTypeLibType(),
223 that
->m_root
->m_factory
->m_cpp2uno
.get() );
224 *ppException
= nullptr; // no exc
226 catch (RuntimeException
&)
228 Any
exc( ::cppu::getCaughtException() );
229 uno_type_any_constructAndConvert(
230 *ppException
, const_cast< void * >(exc
.getValue()),
231 exc
.getValueTypeRef(),
232 that
->m_root
->m_factory
->m_cpp2uno
.get() );
237 binuno_proxy_acquire( pUnoI
);
238 *ppException
= nullptr; // no exc
241 binuno_proxy_release( pUnoI
);
242 *ppException
= nullptr; // no exc
245 that
->m_target
.dispatch( pMemberType
, pReturn
, pArgs
, ppException
);
253 binuno_Proxy::binuno_Proxy(
254 ::rtl::Reference
< ProxyRoot
> const & root
,
255 UnoInterfaceReference
const & target
,
256 OUString
const & oid
, TypeDescription
const & typeDescr
)
261 m_typeDescr( typeDescr
)
263 uno_Interface::acquire
= binuno_proxy_acquire
;
264 uno_Interface::release
= binuno_proxy_release
;
265 uno_Interface::pDispatcher
= binuno_proxy_dispatch
;
268 ProxyRoot::ProxyRoot(
269 ::rtl::Reference
< FactoryImpl
> const & factory
,
270 Reference
< XInterface
> const & xTarget
)
271 : m_factory( factory
)
273 m_factory
->m_cpp2uno
.mapInterface(
274 reinterpret_cast< void ** >( &m_target
.m_pUnoI
), xTarget
.get(),
275 cppu::UnoType
<decltype(xTarget
)>::get() );
276 OSL_ENSURE( m_target
.is(), "### mapping interface failed!" );
280 Any
ProxyRoot::queryAggregation( Type
const & rType
)
282 Any
ret( OWeakAggObject::queryAggregation( rType
) );
283 if (! ret
.hasValue())
285 typelib_TypeDescription
* pTypeDescr
= nullptr;
286 TYPELIB_DANGER_GET( &pTypeDescr
, rType
.getTypeLibType() );
289 Reference
< XInterface
> xProxy
;
290 uno_ExtEnvironment
* cpp_env
= m_factory
->m_cpp_env
.get()->pExtEnv
;
291 OSL_ASSERT( cpp_env
!= nullptr );
293 // mind a new delegator, calculate current root:
294 Reference
< XInterface
> xRoot(
295 static_cast< OWeakObject
* >(this), UNO_QUERY_THROW
);
297 (*cpp_env
->getObjectIdentifier
)( cpp_env
, &oid
.pData
, xRoot
.get() );
298 OSL_ASSERT( !oid
.isEmpty() );
300 (*cpp_env
->getRegisteredInterface
)(
301 cpp_env
, reinterpret_cast< void ** >( &xProxy
),
302 oid
.pData
, reinterpret_cast<
303 typelib_InterfaceTypeDescription
* >(pTypeDescr
) );
306 // perform query on target:
307 UnoInterfaceReference
proxy_target(
308 m_factory
->binuno_queryInterface(
309 m_target
, reinterpret_cast<
310 typelib_InterfaceTypeDescription
* >(pTypeDescr
) ) );
311 if (proxy_target
.is())
313 // ensure root's object entries:
314 UnoInterfaceReference root
;
315 m_factory
->m_cpp2uno
.mapInterface(
316 reinterpret_cast< void ** >( &root
.m_pUnoI
),
317 xRoot
.get(), cppu::UnoType
<decltype(xRoot
)>::get() );
319 UnoInterfaceReference
proxy(
320 // ref count initially 1:
321 new binuno_Proxy( this, proxy_target
, oid
, pTypeDescr
),
323 uno_ExtEnvironment
* uno_env
=
324 m_factory
->m_uno_env
.get()->pExtEnv
;
325 OSL_ASSERT( uno_env
!= nullptr );
326 (*uno_env
->registerProxyInterface
)(
327 uno_env
, reinterpret_cast< void ** >( &proxy
.m_pUnoI
),
328 binuno_proxy_free
, oid
.pData
,
329 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
332 m_factory
->m_uno2cpp
.mapInterface(
333 reinterpret_cast< void ** >( &xProxy
),
334 proxy
.get(), pTypeDescr
);
338 ret
.setValue( &xProxy
, pTypeDescr
);
340 catch (...) // finally
342 TYPELIB_DANGER_RELEASE( pTypeDescr
);
345 TYPELIB_DANGER_RELEASE( pTypeDescr
);
351 FactoryImpl::FactoryImpl()
353 OUString uno
= UNO_LB_UNO
;
354 OUString cpp
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
357 reinterpret_cast< uno_Environment
** >( &m_uno_env
), uno
.pData
, nullptr );
358 OSL_ENSURE( m_uno_env
.is(), "### cannot get binary uno env!" );
361 reinterpret_cast< uno_Environment
** >( &m_cpp_env
), cpp
.pData
, nullptr );
362 OSL_ENSURE( m_cpp_env
.is(), "### cannot get C++ uno env!" );
365 reinterpret_cast< uno_Mapping
** >( &m_uno2cpp
),
366 m_uno_env
.get(), m_cpp_env
.get(), nullptr );
367 OSL_ENSURE( m_uno2cpp
.is(), "### cannot get bridge uno <-> C++!" );
370 reinterpret_cast< uno_Mapping
** >( &m_cpp2uno
),
371 m_cpp_env
.get(), m_uno_env
.get(), nullptr );
372 OSL_ENSURE( m_cpp2uno
.is(), "### cannot get bridge C++ <-> uno!" );
377 Reference
< XAggregation
> FactoryImpl::createProxy(
378 Reference
< XInterface
> const & xTarget
)
380 return new ProxyRoot( this, xTarget
);
385 OUString
FactoryImpl::getImplementationName()
387 return "com.sun.star.comp.reflection.ProxyFactory";
390 sal_Bool
FactoryImpl::supportsService( const OUString
& rServiceName
)
392 return cppu::supportsService(this, rServiceName
);
395 Sequence
< OUString
> FactoryImpl::getSupportedServiceNames()
397 return { "com.sun.star.reflection.ProxyFactory" };
400 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
401 stoc_FactoryImpl_get_implementation(
402 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
404 return cppu::acquire(static_cast< ::cppu::OWeakObject
* >(new FactoryImpl
));
410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */