LibreOffice Module cppu (master) 1
helper_purpenv_Proxy.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include "Proxy.hxx"
22
23#include <sal/log.hxx>
24#include <uno/dispatcher.h>
25#include <typelib/typedescription.hxx>
26#include <utility>
27
28using namespace com::sun::star;
29
31{
32 switch (pTypeDescr->eTypeClass)
33 {
34// case typelib_TypeClass_TYPEDEF:
35 case typelib_TypeClass_SEQUENCE:
36 {
37 switch (reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType->eTypeClass)
38 {
39 case typelib_TypeClass_INTERFACE:
40 case typelib_TypeClass_ANY: // might relate to interface
41 return true;
42 case typelib_TypeClass_SEQUENCE:
43 case typelib_TypeClass_STRUCT:
44 case typelib_TypeClass_EXCEPTION:
45 {
46 typelib_TypeDescription * pTD = nullptr;
47 TYPELIB_DANGER_GET( &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
48 bool bRel = relatesToInterface( pTD );
49 TYPELIB_DANGER_RELEASE( pTD );
50 return bRel;
51 }
52 default:
53 ;
54 }
55 return false;
56 }
57 case typelib_TypeClass_STRUCT:
58 case typelib_TypeClass_EXCEPTION:
59 {
60 // ...optimized... to avoid getDescription() calls!
61 typelib_CompoundTypeDescription * pComp = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
62 typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
63 for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
64 {
65 switch (pTypes[nPos]->eTypeClass)
66 {
67 case typelib_TypeClass_INTERFACE:
68 case typelib_TypeClass_ANY: // might relate to interface
69 return true;
70// case typelib_TypeClass_TYPEDEF:
71 case typelib_TypeClass_SEQUENCE:
72 case typelib_TypeClass_STRUCT:
73 case typelib_TypeClass_EXCEPTION:
74 {
75 typelib_TypeDescription * pTD = nullptr;
76 TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
77 bool bRel = relatesToInterface( pTD );
78 TYPELIB_DANGER_RELEASE( pTD );
79 if (bRel)
80 return true;
81 break;
82 }
83 default:
84 break;
85 }
86 }
87 if (pComp->pBaseTypeDescription)
88 return relatesToInterface( &pComp->pBaseTypeDescription->aBase );
89 break;
90 }
91 case typelib_TypeClass_ANY: // might relate to interface
92 case typelib_TypeClass_INTERFACE:
93 return true;
94
95 default:
96 ;
97 }
98 return false;
99}
100
101extern "C" { static void s_Proxy_dispatch(
102 uno_Interface * pUnoI,
103 typelib_TypeDescription const * pMemberType,
104 void * pReturn,
105 void * pArgs[],
106 uno_Any ** ppException)
108{
109 Proxy * pThis = static_cast<Proxy *>(pUnoI);
110
111 typelib_MethodParameter param;
112 sal_Int32 nParams = 0;
113 typelib_MethodParameter * pParams = nullptr;
114 typelib_TypeDescriptionReference * pReturnTypeRef = nullptr;
115 // sal_Int32 nOutParams = 0;
116
117 switch (pMemberType->eTypeClass)
118 {
119 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
120 if (pReturn)
121 {
122 pReturnTypeRef =
123 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
124 pMemberType)->pAttributeTypeRef;
125 nParams = 0;
126 pParams = nullptr;
127 }
128 else
129 {
130 param.pTypeRef = reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
131 pMemberType)->pAttributeTypeRef;
132 param.bIn = true;
133 param.bOut = false;
134 nParams = 1;
135 pParams = &param;
136 }
137 break;
138 case typelib_TypeClass_INTERFACE_METHOD:
139 {
140 typelib_InterfaceMethodTypeDescription const * method_td =
141 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType);
142 pReturnTypeRef = method_td->pReturnTypeRef;
143 nParams = method_td->nParams;
144 pParams = method_td->pParams;
145 break;
146 }
147 default:
148 OSL_FAIL( "### illegal member typeclass!" );
149 abort();
150 }
151
152 pThis->dispatch( pReturnTypeRef,
153 pParams,
154 nParams,
155 pMemberType,
156 pReturn,
157 pArgs,
158 ppException );
159}}
160
161extern "C" void Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C()
162{
163 Proxy * pThis = static_cast<Proxy * >(static_cast<uno_Interface *>(pProxy));
164 delete pThis;
165}
166
167extern "C" {
168static void s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
169{
170 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
171 pProxy->acquire();
172}
173
174static void s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
175{
176 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
177 pProxy->release();
178}
179
180static void s_acquireAndRegister_v(va_list * pParam)
181{
182 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
183 rtl_uString * pOid = va_arg(*pParam, rtl_uString *);
184 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
185 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
186
187 pUnoI->acquire(pUnoI);
188 pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
189}
190}
191
192Proxy::Proxy(uno::Mapping to_from,
193 uno_Environment * pTo,
194 uno_Environment * pFrom,
195 uno_Interface * pUnoI,
196 typelib_InterfaceTypeDescription * pTypeDescr,
197 OUString const & rOId,
199 void * pProbeContext
200)
201 : m_nRef (1),
202 m_from (pFrom),
203 m_to (pTo),
204 m_from_to (pFrom, pTo),
205 m_to_from (std::move(to_from)),
206 m_pUnoI (pUnoI),
207 m_pTypeDescr (pTypeDescr),
208 m_aOId (rOId),
209 m_probeFun (probeFun),
210 m_pProbeContext(pProbeContext)
211{
212 SAL_INFO("cppu.purpenv", "LIFE: Proxy::Proxy(<>) -> " << this);
213
215 if (!m_pTypeDescr->aBase.bComplete)
216 typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription **>(&m_pTypeDescr));
217
218 OSL_ENSURE(m_pTypeDescr->aBase.bComplete, "### type is incomplete!");
219
220 uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());
221
222 // uno_Interface
223 uno_Interface::acquire = s_Proxy_acquire;
224 uno_Interface::release = s_Proxy_release;
225 uno_Interface::pDispatcher = s_Proxy_dispatch;
226}
227
228extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
229{
230 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
231 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
232
233 pEnv->revokeInterface(pEnv, pUnoI);
234 pUnoI->release(pUnoI);
235}}
236
238{
239 SAL_INFO("cppu.purpenv", "LIFE: Proxy::~Proxy() -> " << this);
240
242
244}
245
246static uno::TypeDescription getAcquireMethod()
247{
248 typelib_TypeDescriptionReference * type_XInterface =
249 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
250
251 typelib_TypeDescription * pTXInterfaceDescr = nullptr;
252 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
253 uno::TypeDescription acquire(
254 reinterpret_cast< typelib_InterfaceTypeDescription * >(
255 pTXInterfaceDescr)->ppAllMembers[1]);
256 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
257
258 return acquire;
259}
260
261static uno::TypeDescription getReleaseMethod()
262{
263 typelib_TypeDescriptionReference * type_XInterface =
264 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
265
266 typelib_TypeDescription * pTXInterfaceDescr = nullptr;
267 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
268 uno::TypeDescription release(
269 reinterpret_cast< typelib_InterfaceTypeDescription * >(
270 pTXInterfaceDescr)->ppAllMembers[2]);
271 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
272
273 return release;
274}
275
276static uno::TypeDescription s_acquireMethod(getAcquireMethod());
277static uno::TypeDescription s_releaseMethod(getReleaseMethod());
278
280{
281 if (m_probeFun)
282 m_probeFun(true,
283 this,
285 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
286 nullptr,
287 0,
288 s_acquireMethod.get(),
289 nullptr,
290 nullptr,
291 nullptr);
292
293 if (osl_atomic_increment(&m_nRef) == 1)
294 {
295 // rebirth of proxy zombie
296 void * pThis = this;
297 m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv,
298 &pThis,
300 m_aOId.pData,
302 OSL_ASSERT(pThis == this);
303 }
304
305 if (m_probeFun)
306 m_probeFun(false,
307 this,
309 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
310 nullptr,
311 0,
312 s_acquireMethod.get(),
313 nullptr,
314 nullptr,
315 nullptr);
316
317}
318
320{
322 void * pProbeContext = m_pProbeContext;
323
324 if (m_probeFun)
325 m_probeFun(true,
326 this,
328 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
329 nullptr,
330 0,
331 s_releaseMethod.get(),
332 nullptr,
333 nullptr,
334 nullptr);
335
336 if (osl_atomic_decrement(&m_nRef) == 0)
337 m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);
338
339 if (probeFun)
340 probeFun(false,
341 this,
342 pProbeContext,
343 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
344 nullptr,
345 0,
346 s_releaseMethod.get(),
347 nullptr,
348 nullptr,
349 nullptr);
350
351}
352
353
354extern "C" {
355static void s_type_destructData_v(va_list * pParam)
356{
357 void * ret = va_arg(*pParam, void *);
358 typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);
359
360 uno_type_destructData(ret, pReturnTypeRef, nullptr);
361}
362
363static void s_dispatcher_v(va_list * pParam)
364{
365 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
366 typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
367 void * pReturn = va_arg(*pParam, void *);
368 void ** pArgs = va_arg(*pParam, void **);
369 uno_Any ** ppException = va_arg(*pParam, uno_Any **);
370
371 pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
372}
373}
374
375void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,
376 typelib_MethodParameter * pParams,
377 sal_Int32 nParams,
378 typelib_TypeDescription const * pMemberType,
379 void * pReturn,
380 void * pArgs[],
381 uno_Any ** ppException)
382{
383 if (m_probeFun)
384 m_probeFun(true,
385 this,
387 pReturnTypeRef,
388 pParams,
389 nParams,
390 pMemberType,
391 pReturn,
392 pArgs,
393 ppException);
394
395 void ** args = static_cast<void **>(alloca( sizeof (void *) * nParams ));
396
397 typelib_TypeDescription * return_td = nullptr;
398 void * ret = pReturn;
399 if (pReturnTypeRef)
400 {
401 TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);
402
403 if (relatesToInterface(return_td))
404 ret = alloca(return_td->nSize);
405
406 TYPELIB_DANGER_RELEASE(return_td);
407 }
408
409 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
410 {
411 typelib_MethodParameter const & param = pParams[nPos];
412 typelib_TypeDescription * td = nullptr;
413 TYPELIB_DANGER_GET( &td, param.pTypeRef );
414 if (relatesToInterface(td))
415 {
416 args[nPos] = alloca(td->nSize);
417 if (param.bIn)
418 {
419 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
420 }
421 }
422 else
423 {
424 args[nPos] = pArgs[nPos];
425 }
426 TYPELIB_DANGER_RELEASE( td );
427 }
428
429 uno_Any exc_data;
430 uno_Any * exc = &exc_data;
431
432 // do the UNO call...
433 uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);
434
435 if (exc == nullptr)
436 {
437 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
438 {
439 if (args[nPos] != pArgs[nPos])
440 {
441 typelib_MethodParameter const & param = pParams[nPos];
442 if (param.bOut)
443 {
444 if (param.bIn) // is inout
445 {
446 uno_type_destructData(pArgs[nPos], param.pTypeRef, nullptr);
447 }
449 args[ nPos ],
450 param.pTypeRef,
451 m_to_from.get());
452 }
453 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
454 }
455 }
456 if (ret != pReturn)
457 {
459 ret,
460 pReturnTypeRef,
461 m_to_from.get());
462
463 uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
464 }
465
466 *ppException = nullptr;
467 }
468 else // exception occurred
469 {
470 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
471 {
472 if (args[nPos] != pArgs[nPos])
473 {
474 typelib_MethodParameter const & param = pParams[nPos];
475 if (param.bIn)
476 {
477 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
478 }
479 }
480 }
481
483 exc->pData,
484 exc->pType,
485 m_to_from.get());
486
487 // FIXME: need to destruct in m_to
488 uno_any_destruct(exc, nullptr);
489 }
490
491 if (m_probeFun)
492 m_probeFun(false,
493 this,
495 pReturnTypeRef,
496 pParams,
497 nParams,
498 pMemberType,
499 pReturn,
500 pArgs,
501 ppException);
502}
503
504/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SAL_CALL uno_Environment_invoke(uno_Environment *pEnv, uno_EnvCallee *pCallee,...) SAL_THROW_EXTERN_C()
Definition: EnvStack.cxx:315
void SAL_CALL uno_type_any_constructAndConvert(uno_Any *pDest, void *pSource, typelib_TypeDescriptionReference *pType, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
Definition: any.cxx:96
void SAL_CALL uno_any_destruct(uno_Any *pValue, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
Definition: any.cxx:128
Definition: Proxy.hxx:32
typelib_InterfaceTypeDescription * m_pTypeDescr
Definition: Proxy.hxx:43
css::uno::Mapping m_to_from
Definition: Proxy.hxx:39
OUString m_aOId
Definition: Proxy.hxx:44
css::uno::Mapping m_from_to
Definition: Proxy.hxx:38
css::uno::Environment m_to
Definition: Proxy.hxx:36
cppu::helper::purpenv::ProbeFun * m_probeFun
Definition: Proxy.hxx:46
void dispatch(typelib_TypeDescriptionReference *pReturnTypeRef, typelib_MethodParameter *pParams, sal_Int32 nParams, typelib_TypeDescription const *pMemberType, void *pReturn, void *pArgs[], uno_Any **ppException)
void * m_pProbeContext
Definition: Proxy.hxx:47
css::uno::Environment m_from
Definition: Proxy.hxx:35
uno_Interface * m_pUnoI
Definition: Proxy.hxx:42
oslInterlockedCount m_nRef
Definition: Proxy.hxx:33
Proxy(css::uno::Mapping to_from, uno_Environment *pTo, uno_Environment *pFrom, uno_Interface *pUnoI, typelib_InterfaceTypeDescription *pTypeDescr, OUString const &rOId, cppu::helper::purpenv::ProbeFun *probeFun, void *pProbeContext)
void SAL_CALL uno_type_destructData(void *pValue, typelib_TypeDescriptionReference *pType, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
Definition: data.cxx:185
void SAL_CALL uno_type_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescriptionReference *pType, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
Definition: data.cxx:220
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
Definition: data.cxx:229
struct _uno_Environment uno_Environment
static void s_Proxy_release(uno_Interface *pUnoI) SAL_THROW_EXTERN_C()
void Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void *pProxy) SAL_THROW_EXTERN_C()
static bool relatesToInterface(typelib_TypeDescription *pTypeDescr)
static uno::TypeDescription s_releaseMethod(getReleaseMethod())
static void s_Proxy_acquire(uno_Interface *pUnoI) SAL_THROW_EXTERN_C()
static uno::TypeDescription getAcquireMethod()
static void s_type_destructData_v(va_list *pParam)
static void s_Proxy_dispatch(uno_Interface *pUnoI, typelib_TypeDescription const *pMemberType, void *pReturn, void *pArgs[], uno_Any **ppException) SAL_THROW_EXTERN_C()
static uno::TypeDescription getReleaseMethod()
static void s_dispatcher_v(va_list *pParam)
static void s_acquireAndRegister_v(va_list *pParam)
static uno::TypeDescription s_acquireMethod(getAcquireMethod())
static void s_releaseAndRevoke_v(va_list *pParam)
oslInterlockedCount m_nRef
typelib_InterfaceTypeDescription * m_pTypeDescr
sal_uInt16 nPos
#define SAL_INFO(area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
struct _uno_Any uno_Any
void ProbeFun(bool pre, void *pThis, void *pContext, typelib_TypeDescriptionReference *pReturnTypeRef, typelib_MethodParameter *pParams, sal_Int32 nParams, typelib_TypeDescription const *pMemberType, void *pReturn, void *pArgs[], uno_Any **ppException)
C++ helper for implementing Purpose Environments.
Definition: Mapping.hxx:42
args
typelib_TypeDescriptionReference **SAL_CALL typelib_static_type_getByTypeClass(typelib_TypeClass eTypeClass) SAL_THROW_EXTERN_C()
void SAL_CALL typelib_typedescription_release(typelib_TypeDescription *pTD) SAL_THROW_EXTERN_C()
Definition: typelib.cxx:1325
sal_Bool SAL_CALL typelib_typedescription_complete(typelib_TypeDescription **ppTypeDescr) SAL_THROW_EXTERN_C()
Definition: typelib.cxx:2379
void SAL_CALL typelib_typedescription_acquire(typelib_TypeDescription *pTypeDescription) SAL_THROW_EXTERN_C()
Definition: typelib.cxx:1197
#define SAL_THROW_EXTERN_C()