merge the formfield patch from ooo-build
[ooovba.git] / cppu / source / helper / purpenv / helper_purpenv_Proxy.cxx
blobbf21477c3d58e809c1e329a22d7a04326c8cd47c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helper_purpenv_Proxy.cxx,v $
10 * $Revision: 1.6 $
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_cppu.hxx"
34 #include "Proxy.hxx"
36 #include "sal/alloca.h"
37 #include "uno/dispatcher.h"
38 #include "typelib/typedescription.hxx"
39 #include "cppu/EnvDcp.hxx"
42 //#define LOG_LIFECYCLE_Proxy
43 #ifdef LOG_LIFECYCLE_Proxy
44 # include <iostream>
45 # define LOG_LIFECYCLE_Proxy_emit(x) x
47 #else
48 # define LOG_LIFECYCLE_Proxy_emit(x)
50 #endif
53 using namespace com::sun::star;
56 static bool relatesToInterface(typelib_TypeDescription * pTypeDescr)
57 SAL_THROW( () )
59 switch (pTypeDescr->eTypeClass)
61 // case typelib_TypeClass_TYPEDEF:
62 case typelib_TypeClass_SEQUENCE:
64 switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass)
66 case typelib_TypeClass_INTERFACE:
67 case typelib_TypeClass_UNION: // might relate to interface
68 case typelib_TypeClass_ANY: // might relate to interface
69 return true;
70 case typelib_TypeClass_SEQUENCE:
71 case typelib_TypeClass_STRUCT:
72 case typelib_TypeClass_EXCEPTION:
74 typelib_TypeDescription * pTD = 0;
75 TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
76 bool bRel = relatesToInterface( pTD );
77 TYPELIB_DANGER_RELEASE( pTD );
78 return bRel;
80 default:
83 return false;
85 case typelib_TypeClass_STRUCT:
86 case typelib_TypeClass_EXCEPTION:
88 // ...optimized... to avoid getDescription() calls!
89 typelib_CompoundTypeDescription * pComp = (typelib_CompoundTypeDescription *)pTypeDescr;
90 typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
91 for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
93 switch (pTypes[nPos]->eTypeClass)
95 case typelib_TypeClass_INTERFACE:
96 case typelib_TypeClass_UNION: // might relate to interface
97 case typelib_TypeClass_ANY: // might relate to interface
98 return true;
99 // case typelib_TypeClass_TYPEDEF:
100 case typelib_TypeClass_SEQUENCE:
101 case typelib_TypeClass_STRUCT:
102 case typelib_TypeClass_EXCEPTION:
104 typelib_TypeDescription * pTD = 0;
105 TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
106 bool bRel = relatesToInterface( pTD );
107 TYPELIB_DANGER_RELEASE( pTD );
108 if (bRel)
109 return true;
111 default:
115 if (pComp->pBaseTypeDescription)
116 return relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription );
117 break;
119 case typelib_TypeClass_UNION: // might relate to interface
120 case typelib_TypeClass_ANY: // might relate to interface
121 case typelib_TypeClass_INTERFACE:
122 return true;
124 default:
127 return false;
130 extern "C" { static void SAL_CALL s_Proxy_dispatch(
131 uno_Interface * pUnoI,
132 typelib_TypeDescription const * pMemberType,
133 void * pReturn,
134 void * pArgs[],
135 uno_Any ** ppException)
136 SAL_THROW_EXTERN_C()
138 Proxy * pThis = static_cast<Proxy *>(pUnoI);
140 typelib_MethodParameter param;
141 sal_Int32 nParams = 0;
142 typelib_MethodParameter * pParams = 0;
143 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
144 // sal_Int32 nOutParams = 0;
146 switch (pMemberType->eTypeClass)
148 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
149 if (pReturn)
151 pReturnTypeRef =
152 ((typelib_InterfaceAttributeTypeDescription *)
153 pMemberType)->pAttributeTypeRef;
154 nParams = 0;
155 pParams = NULL;
157 else
159 param.pTypeRef = ((typelib_InterfaceAttributeTypeDescription *)
160 pMemberType)->pAttributeTypeRef;
161 param.bIn = sal_True;
162 param.bOut = sal_False;
163 nParams = 1;
164 pParams = &param;
166 break;
167 case typelib_TypeClass_INTERFACE_METHOD:
169 typelib_InterfaceMethodTypeDescription * method_td =
170 (typelib_InterfaceMethodTypeDescription *) pMemberType;
171 pReturnTypeRef = method_td->pReturnTypeRef;
172 nParams = method_td->nParams;
173 pParams = method_td->pParams;
174 break;
176 default:
177 OSL_ENSURE( sal_False, "### illegal member typeclass!" );
178 abort();
181 pThis->dispatch( pReturnTypeRef,
182 pParams,
183 nParams,
184 pMemberType,
185 pReturn,
186 pArgs,
187 ppException );
190 extern "C" void SAL_CALL Proxy_free(uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C()
192 Proxy * pThis = static_cast<Proxy * >(reinterpret_cast<uno_Interface *>(pProxy));
193 delete pThis;
196 extern "C" {
197 static void SAL_CALL s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
199 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
200 pProxy->acquire();
203 static void SAL_CALL s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
205 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
206 pProxy->release();
209 static void s_acquireAndRegister_v(va_list * pParam)
211 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
212 rtl_uString * pOid = va_arg(*pParam, rtl_uString *);
213 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
214 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
216 pUnoI->acquire(pUnoI);
217 pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
221 Proxy::Proxy(uno::Mapping const & to_from,
222 uno_Environment * pTo,
223 uno_Environment * pFrom,
224 uno_Interface * pUnoI,
225 typelib_InterfaceTypeDescription * pTypeDescr,
226 rtl::OUString const & rOId,
227 cppu::helper::purpenv::ProbeFun * probeFun,
228 void * pProbeContext
230 SAL_THROW(())
231 : m_nRef (1),
232 m_from (pFrom),
233 m_to (pTo),
234 m_from_to (pFrom, pTo),
235 m_to_from (to_from),
236 m_pUnoI (pUnoI),
237 m_pTypeDescr (pTypeDescr),
238 m_aOId (rOId),
239 m_probeFun (probeFun),
240 m_pProbeContext(pProbeContext)
242 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this));
244 typelib_typedescription_acquire((typelib_TypeDescription *)m_pTypeDescr);
245 if (!((typelib_TypeDescription *)m_pTypeDescr)->bComplete)
246 typelib_typedescription_complete((typelib_TypeDescription **)&m_pTypeDescr);
248 OSL_ENSURE(((typelib_TypeDescription *)m_pTypeDescr)->bComplete, "### type is incomplete!");
250 uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());
252 // uno_Interface
253 uno_Interface::acquire = s_Proxy_acquire;
254 uno_Interface::release = s_Proxy_release;
255 uno_Interface::pDispatcher = s_Proxy_dispatch;
258 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
260 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
261 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
263 pEnv->revokeInterface(pEnv, reinterpret_cast<void *>(pUnoI));
264 pUnoI->release(pUnoI);
267 Proxy::~Proxy()
269 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this));
271 uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI);
273 typelib_typedescription_release((typelib_TypeDescription *)m_pTypeDescr);
276 static uno::TypeDescription getAcquireMethod(void)
278 typelib_TypeDescriptionReference * type_XInterface =
279 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
281 typelib_InterfaceTypeDescription * pTXInterfaceDescr = 0;
282 TYPELIB_DANGER_GET ((typelib_TypeDescription **)&pTXInterfaceDescr, type_XInterface);
283 uno::TypeDescription acquire(pTXInterfaceDescr->ppAllMembers[1]);
284 TYPELIB_DANGER_RELEASE((typelib_TypeDescription *)pTXInterfaceDescr);
286 return acquire;
289 static uno::TypeDescription getReleaseMethod(void)
291 typelib_TypeDescriptionReference * type_XInterface =
292 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
294 typelib_InterfaceTypeDescription * pTXInterfaceDescr = 0;
295 TYPELIB_DANGER_GET ((typelib_TypeDescription **)&pTXInterfaceDescr, type_XInterface);
296 uno::TypeDescription release(pTXInterfaceDescr->ppAllMembers[2]);
297 TYPELIB_DANGER_RELEASE((typelib_TypeDescription *)pTXInterfaceDescr);
299 return release;
302 static uno::TypeDescription s_acquireMethod(getAcquireMethod());
303 static uno::TypeDescription s_releaseMethod(getReleaseMethod());
305 void Proxy::acquire(void)
307 if (m_probeFun)
308 m_probeFun(true,
309 this,
310 m_pProbeContext,
311 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
312 NULL,
314 s_acquireMethod.get(),
315 NULL,
316 NULL,
317 NULL);
319 if (osl_incrementInterlockedCount(&m_nRef) == 1)
321 // rebirth of proxy zombie
322 void * pThis = this;
323 m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv,
324 &pThis,
325 Proxy_free,
326 m_aOId.pData,
327 m_pTypeDescr);
328 OSL_ASSERT(pThis == this);
331 if (m_probeFun)
332 m_probeFun(false,
333 this,
334 m_pProbeContext,
335 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
336 NULL,
338 s_acquireMethod.get(),
339 NULL,
340 NULL,
341 NULL);
345 void Proxy::release(void)
347 cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun;
348 void * pProbeContext = m_pProbeContext;
350 if (m_probeFun)
351 m_probeFun(true,
352 this,
353 m_pProbeContext,
354 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
355 NULL,
357 s_releaseMethod.get(),
358 NULL,
359 NULL,
360 NULL);
362 if (osl_decrementInterlockedCount(&m_nRef) == 0)
363 m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);
365 if (probeFun)
366 probeFun(false,
367 this,
368 pProbeContext,
369 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
370 NULL,
372 s_releaseMethod.get(),
373 NULL,
374 NULL,
375 NULL);
380 extern "C" {
381 static void s_type_destructData_v(va_list * pParam)
383 void * ret = va_arg(*pParam, void *);
384 typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);
386 uno_type_destructData(ret, pReturnTypeRef, 0);
389 static void s_dispatcher_v(va_list * pParam)
391 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
392 typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
393 void * pReturn = va_arg(*pParam, void *);
394 void ** pArgs = va_arg(*pParam, void **);
395 uno_Any ** ppException = va_arg(*pParam, uno_Any **);
397 pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
401 void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,
402 typelib_MethodParameter * pParams,
403 sal_Int32 nParams,
404 typelib_TypeDescription const * pMemberType,
405 void * pReturn,
406 void * pArgs[],
407 uno_Any ** ppException)
409 if (m_probeFun)
410 m_probeFun(true,
411 this,
412 m_pProbeContext,
413 pReturnTypeRef,
414 pParams,
415 nParams,
416 pMemberType,
417 pReturn,
418 pArgs,
419 ppException);
421 void ** args = (void **) alloca( sizeof (void *) * nParams );
423 typelib_TypeDescription * return_td = 0;
424 void * ret = pReturn;
425 if (pReturnTypeRef)
427 TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);
429 if (relatesToInterface(return_td))
430 ret = alloca(return_td->nSize);
432 TYPELIB_DANGER_RELEASE(return_td);
435 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
437 typelib_MethodParameter const & param = pParams[nPos];
438 typelib_TypeDescription * td = 0;
439 TYPELIB_DANGER_GET( &td, param.pTypeRef );
440 if (relatesToInterface(td))
442 args[nPos] = alloca(td->nSize);
443 if (param.bIn)
445 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
448 else
450 args[nPos] = pArgs[nPos];
452 TYPELIB_DANGER_RELEASE( td );
455 uno_Any exc_data;
456 uno_Any * exc = &exc_data;
458 // do the UNO call...
459 uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);
461 if (exc == 0)
463 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
465 if (args[nPos] != pArgs[nPos])
467 typelib_MethodParameter const & param = pParams[nPos];
468 if (param.bOut)
470 if (param.bIn) // is inout
472 uno_type_destructData(pArgs[nPos], param.pTypeRef, 0);
474 uno_type_copyAndConvertData(pArgs[ nPos ],
475 args[ nPos ],
476 param.pTypeRef,
477 m_to_from.get());
479 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
482 if (ret != pReturn)
484 uno_type_copyAndConvertData(pReturn,
485 ret,
486 pReturnTypeRef,
487 m_to_from.get());
489 uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
492 *ppException = 0;
494 else // exception occured
496 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
498 if (args[nPos] != pArgs[nPos])
500 typelib_MethodParameter const & param = pParams[nPos];
501 if (param.bIn)
503 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
508 uno_type_any_constructAndConvert(*ppException,
509 exc->pData,
510 exc->pType,
511 m_to_from.get());
513 // FIXME: need to destruct in m_to
514 uno_any_destruct(exc, 0);
517 if (m_probeFun)
518 m_probeFun(false,
519 this,
520 m_pProbeContext,
521 pReturnTypeRef,
522 pParams,
523 nParams,
524 pMemberType,
525 pReturn,
526 pArgs,
527 ppException);