1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helper_purpenv_Proxy.cxx,v $
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"
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
45 # define LOG_LIFECYCLE_Proxy_emit(x) x
48 # define LOG_LIFECYCLE_Proxy_emit(x)
53 using namespace com::sun::star
;
56 static bool relatesToInterface(typelib_TypeDescription
* pTypeDescr
)
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
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
);
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
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
);
115 if (pComp
->pBaseTypeDescription
)
116 return relatesToInterface( (typelib_TypeDescription
*)pComp
->pBaseTypeDescription
);
119 case typelib_TypeClass_UNION
: // might relate to interface
120 case typelib_TypeClass_ANY
: // might relate to interface
121 case typelib_TypeClass_INTERFACE
:
130 extern "C" { static void SAL_CALL
s_Proxy_dispatch(
131 uno_Interface
* pUnoI
,
132 typelib_TypeDescription
const * pMemberType
,
135 uno_Any
** ppException
)
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
:
152 ((typelib_InterfaceAttributeTypeDescription
*)
153 pMemberType
)->pAttributeTypeRef
;
159 param
.pTypeRef
= ((typelib_InterfaceAttributeTypeDescription
*)
160 pMemberType
)->pAttributeTypeRef
;
161 param
.bIn
= sal_True
;
162 param
.bOut
= sal_False
;
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
;
177 OSL_ENSURE( sal_False
, "### illegal member typeclass!" );
181 pThis
->dispatch( pReturnTypeRef
,
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
));
197 static void SAL_CALL
s_Proxy_acquire(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
199 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
203 static void SAL_CALL
s_Proxy_release(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
205 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
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
,
234 m_from_to (pFrom
, pTo
),
237 m_pTypeDescr (pTypeDescr
),
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());
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
);
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
);
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
);
302 static uno::TypeDescription
s_acquireMethod(getAcquireMethod());
303 static uno::TypeDescription
s_releaseMethod(getReleaseMethod());
305 void Proxy::acquire(void)
311 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
314 s_acquireMethod
.get(),
319 if (osl_incrementInterlockedCount(&m_nRef
) == 1)
321 // rebirth of proxy zombie
323 m_from
.get()->pExtEnv
->registerProxyInterface(m_from
.get()->pExtEnv
,
328 OSL_ASSERT(pThis
== this);
335 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
338 s_acquireMethod
.get(),
345 void Proxy::release(void)
347 cppu::helper::purpenv::ProbeFun
* probeFun
= m_probeFun
;
348 void * pProbeContext
= m_pProbeContext
;
354 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
357 s_releaseMethod
.get(),
362 if (osl_decrementInterlockedCount(&m_nRef
) == 0)
363 m_from
.get()->pExtEnv
->revokeInterface(m_from
.get()->pExtEnv
, this);
369 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
372 s_releaseMethod
.get(),
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
,
404 typelib_TypeDescription
const * pMemberType
,
407 uno_Any
** ppException
)
421 void ** args
= (void **) alloca( sizeof (void *) * nParams
);
423 typelib_TypeDescription
* return_td
= 0;
424 void * ret
= pReturn
;
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
);
445 uno_copyAndConvertData(args
[nPos
], pArgs
[nPos
], td
, m_from_to
.get());
450 args
[nPos
] = pArgs
[nPos
];
452 TYPELIB_DANGER_RELEASE( td
);
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
);
463 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
465 if (args
[nPos
] != pArgs
[nPos
])
467 typelib_MethodParameter
const & param
= pParams
[nPos
];
470 if (param
.bIn
) // is inout
472 uno_type_destructData(pArgs
[nPos
], param
.pTypeRef
, 0);
474 uno_type_copyAndConvertData(pArgs
[ nPos
],
479 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
484 uno_type_copyAndConvertData(pReturn
,
489 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, ret
, pReturnTypeRef
, 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
];
503 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
508 uno_type_any_constructAndConvert(*ppException
,
513 // FIXME: need to destruct in m_to
514 uno_any_destruct(exc
, 0);