merged tag ooo/DEV300_m102
[LibreOffice.git] / cppu / source / helper / purpenv / helper_purpenv_Proxy.cxx
blob344203e387627583bf6c997ded2364a588470060
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cppu.hxx"
31 #include "Proxy.hxx"
33 #include "sal/alloca.h"
34 #include "uno/dispatcher.h"
35 #include "typelib/typedescription.hxx"
36 #include "cppu/EnvDcp.hxx"
39 //#define LOG_LIFECYCLE_Proxy
40 #ifdef LOG_LIFECYCLE_Proxy
41 # include <iostream>
42 # define LOG_LIFECYCLE_Proxy_emit(x) x
44 #else
45 # define LOG_LIFECYCLE_Proxy_emit(x)
47 #endif
50 using namespace com::sun::star;
53 static bool relatesToInterface(typelib_TypeDescription * pTypeDescr)
54 SAL_THROW( () )
56 switch (pTypeDescr->eTypeClass)
58 // case typelib_TypeClass_TYPEDEF:
59 case typelib_TypeClass_SEQUENCE:
61 switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass)
63 case typelib_TypeClass_INTERFACE:
64 case typelib_TypeClass_UNION: // might relate to interface
65 case typelib_TypeClass_ANY: // might relate to interface
66 return true;
67 case typelib_TypeClass_SEQUENCE:
68 case typelib_TypeClass_STRUCT:
69 case typelib_TypeClass_EXCEPTION:
71 typelib_TypeDescription * pTD = 0;
72 TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
73 bool bRel = relatesToInterface( pTD );
74 TYPELIB_DANGER_RELEASE( pTD );
75 return bRel;
77 default:
80 return false;
82 case typelib_TypeClass_STRUCT:
83 case typelib_TypeClass_EXCEPTION:
85 // ...optimized... to avoid getDescription() calls!
86 typelib_CompoundTypeDescription * pComp = (typelib_CompoundTypeDescription *)pTypeDescr;
87 typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
88 for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
90 switch (pTypes[nPos]->eTypeClass)
92 case typelib_TypeClass_INTERFACE:
93 case typelib_TypeClass_UNION: // might relate to interface
94 case typelib_TypeClass_ANY: // might relate to interface
95 return true;
96 // case typelib_TypeClass_TYPEDEF:
97 case typelib_TypeClass_SEQUENCE:
98 case typelib_TypeClass_STRUCT:
99 case typelib_TypeClass_EXCEPTION:
101 typelib_TypeDescription * pTD = 0;
102 TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
103 bool bRel = relatesToInterface( pTD );
104 TYPELIB_DANGER_RELEASE( pTD );
105 if (bRel)
106 return true;
108 default:
112 if (pComp->pBaseTypeDescription)
113 return relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription );
114 break;
116 case typelib_TypeClass_UNION: // might relate to interface
117 case typelib_TypeClass_ANY: // might relate to interface
118 case typelib_TypeClass_INTERFACE:
119 return true;
121 default:
124 return false;
127 extern "C" { static void SAL_CALL s_Proxy_dispatch(
128 uno_Interface * pUnoI,
129 typelib_TypeDescription const * pMemberType,
130 void * pReturn,
131 void * pArgs[],
132 uno_Any ** ppException)
133 SAL_THROW_EXTERN_C()
135 Proxy * pThis = static_cast<Proxy *>(pUnoI);
137 typelib_MethodParameter param;
138 sal_Int32 nParams = 0;
139 typelib_MethodParameter * pParams = 0;
140 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
141 // sal_Int32 nOutParams = 0;
143 switch (pMemberType->eTypeClass)
145 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
146 if (pReturn)
148 pReturnTypeRef =
149 ((typelib_InterfaceAttributeTypeDescription *)
150 pMemberType)->pAttributeTypeRef;
151 nParams = 0;
152 pParams = NULL;
154 else
156 param.pTypeRef = ((typelib_InterfaceAttributeTypeDescription *)
157 pMemberType)->pAttributeTypeRef;
158 param.bIn = sal_True;
159 param.bOut = sal_False;
160 nParams = 1;
161 pParams = &param;
163 break;
164 case typelib_TypeClass_INTERFACE_METHOD:
166 typelib_InterfaceMethodTypeDescription * method_td =
167 (typelib_InterfaceMethodTypeDescription *) pMemberType;
168 pReturnTypeRef = method_td->pReturnTypeRef;
169 nParams = method_td->nParams;
170 pParams = method_td->pParams;
171 break;
173 default:
174 OSL_ENSURE( sal_False, "### illegal member typeclass!" );
175 abort();
178 pThis->dispatch( pReturnTypeRef,
179 pParams,
180 nParams,
181 pMemberType,
182 pReturn,
183 pArgs,
184 ppException );
187 extern "C" void SAL_CALL Proxy_free(uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C()
189 Proxy * pThis = static_cast<Proxy * >(reinterpret_cast<uno_Interface *>(pProxy));
190 delete pThis;
193 extern "C" {
194 static void SAL_CALL s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
196 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
197 pProxy->acquire();
200 static void SAL_CALL s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
202 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
203 pProxy->release();
206 static void s_acquireAndRegister_v(va_list * pParam)
208 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
209 rtl_uString * pOid = va_arg(*pParam, rtl_uString *);
210 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
211 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
213 pUnoI->acquire(pUnoI);
214 pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
218 Proxy::Proxy(uno::Mapping const & to_from,
219 uno_Environment * pTo,
220 uno_Environment * pFrom,
221 uno_Interface * pUnoI,
222 typelib_InterfaceTypeDescription * pTypeDescr,
223 rtl::OUString const & rOId,
224 cppu::helper::purpenv::ProbeFun * probeFun,
225 void * pProbeContext
227 SAL_THROW(())
228 : m_nRef (1),
229 m_from (pFrom),
230 m_to (pTo),
231 m_from_to (pFrom, pTo),
232 m_to_from (to_from),
233 m_pUnoI (pUnoI),
234 m_pTypeDescr (pTypeDescr),
235 m_aOId (rOId),
236 m_probeFun (probeFun),
237 m_pProbeContext(pProbeContext)
239 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this));
241 typelib_typedescription_acquire((typelib_TypeDescription *)m_pTypeDescr);
242 if (!((typelib_TypeDescription *)m_pTypeDescr)->bComplete)
243 typelib_typedescription_complete((typelib_TypeDescription **)&m_pTypeDescr);
245 OSL_ENSURE(((typelib_TypeDescription *)m_pTypeDescr)->bComplete, "### type is incomplete!");
247 uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());
249 // uno_Interface
250 uno_Interface::acquire = s_Proxy_acquire;
251 uno_Interface::release = s_Proxy_release;
252 uno_Interface::pDispatcher = s_Proxy_dispatch;
255 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
257 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
258 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
260 pEnv->revokeInterface(pEnv, reinterpret_cast<void *>(pUnoI));
261 pUnoI->release(pUnoI);
264 Proxy::~Proxy()
266 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this));
268 uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI);
270 typelib_typedescription_release((typelib_TypeDescription *)m_pTypeDescr);
273 static uno::TypeDescription getAcquireMethod(void)
275 typelib_TypeDescriptionReference * type_XInterface =
276 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
278 typelib_TypeDescription * pTXInterfaceDescr = 0;
279 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
280 uno::TypeDescription acquire(
281 reinterpret_cast< typelib_InterfaceTypeDescription * >(
282 pTXInterfaceDescr)->ppAllMembers[1]);
283 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
285 return acquire;
288 static uno::TypeDescription getReleaseMethod(void)
290 typelib_TypeDescriptionReference * type_XInterface =
291 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
293 typelib_TypeDescription * pTXInterfaceDescr = 0;
294 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
295 uno::TypeDescription release(
296 reinterpret_cast< typelib_InterfaceTypeDescription * >(
297 pTXInterfaceDescr)->ppAllMembers[2]);
298 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
300 return release;
303 static uno::TypeDescription s_acquireMethod(getAcquireMethod());
304 static uno::TypeDescription s_releaseMethod(getReleaseMethod());
306 void Proxy::acquire(void)
308 if (m_probeFun)
309 m_probeFun(true,
310 this,
311 m_pProbeContext,
312 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
313 NULL,
315 s_acquireMethod.get(),
316 NULL,
317 NULL,
318 NULL);
320 if (osl_incrementInterlockedCount(&m_nRef) == 1)
322 // rebirth of proxy zombie
323 void * pThis = this;
324 m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv,
325 &pThis,
326 Proxy_free,
327 m_aOId.pData,
328 m_pTypeDescr);
329 OSL_ASSERT(pThis == this);
332 if (m_probeFun)
333 m_probeFun(false,
334 this,
335 m_pProbeContext,
336 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
337 NULL,
339 s_acquireMethod.get(),
340 NULL,
341 NULL,
342 NULL);
346 void Proxy::release(void)
348 cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun;
349 void * pProbeContext = m_pProbeContext;
351 if (m_probeFun)
352 m_probeFun(true,
353 this,
354 m_pProbeContext,
355 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
356 NULL,
358 s_releaseMethod.get(),
359 NULL,
360 NULL,
361 NULL);
363 if (osl_decrementInterlockedCount(&m_nRef) == 0)
364 m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);
366 if (probeFun)
367 probeFun(false,
368 this,
369 pProbeContext,
370 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
371 NULL,
373 s_releaseMethod.get(),
374 NULL,
375 NULL,
376 NULL);
381 extern "C" {
382 static void s_type_destructData_v(va_list * pParam)
384 void * ret = va_arg(*pParam, void *);
385 typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);
387 uno_type_destructData(ret, pReturnTypeRef, 0);
390 static void s_dispatcher_v(va_list * pParam)
392 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
393 typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
394 void * pReturn = va_arg(*pParam, void *);
395 void ** pArgs = va_arg(*pParam, void **);
396 uno_Any ** ppException = va_arg(*pParam, uno_Any **);
398 pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
402 void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,
403 typelib_MethodParameter * pParams,
404 sal_Int32 nParams,
405 typelib_TypeDescription const * pMemberType,
406 void * pReturn,
407 void * pArgs[],
408 uno_Any ** ppException)
410 if (m_probeFun)
411 m_probeFun(true,
412 this,
413 m_pProbeContext,
414 pReturnTypeRef,
415 pParams,
416 nParams,
417 pMemberType,
418 pReturn,
419 pArgs,
420 ppException);
422 void ** args = (void **) alloca( sizeof (void *) * nParams );
424 typelib_TypeDescription * return_td = 0;
425 void * ret = pReturn;
426 if (pReturnTypeRef)
428 TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);
430 if (relatesToInterface(return_td))
431 ret = alloca(return_td->nSize);
433 TYPELIB_DANGER_RELEASE(return_td);
436 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
438 typelib_MethodParameter const & param = pParams[nPos];
439 typelib_TypeDescription * td = 0;
440 TYPELIB_DANGER_GET( &td, param.pTypeRef );
441 if (relatesToInterface(td))
443 args[nPos] = alloca(td->nSize);
444 if (param.bIn)
446 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
449 else
451 args[nPos] = pArgs[nPos];
453 TYPELIB_DANGER_RELEASE( td );
456 uno_Any exc_data;
457 uno_Any * exc = &exc_data;
459 // do the UNO call...
460 uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);
462 if (exc == 0)
464 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
466 if (args[nPos] != pArgs[nPos])
468 typelib_MethodParameter const & param = pParams[nPos];
469 if (param.bOut)
471 if (param.bIn) // is inout
473 uno_type_destructData(pArgs[nPos], param.pTypeRef, 0);
475 uno_type_copyAndConvertData(pArgs[ nPos ],
476 args[ nPos ],
477 param.pTypeRef,
478 m_to_from.get());
480 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
483 if (ret != pReturn)
485 uno_type_copyAndConvertData(pReturn,
486 ret,
487 pReturnTypeRef,
488 m_to_from.get());
490 uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
493 *ppException = 0;
495 else // exception occured
497 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
499 if (args[nPos] != pArgs[nPos])
501 typelib_MethodParameter const & param = pParams[nPos];
502 if (param.bIn)
504 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
509 uno_type_any_constructAndConvert(*ppException,
510 exc->pData,
511 exc->pType,
512 m_to_from.get());
514 // FIXME: need to destruct in m_to
515 uno_any_destruct(exc, 0);
518 if (m_probeFun)
519 m_probeFun(false,
520 this,
521 m_pProbeContext,
522 pReturnTypeRef,
523 pParams,
524 nParams,
525 pMemberType,
526 pReturn,
527 pArgs,
528 ppException);