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"
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
42 # define LOG_LIFECYCLE_Proxy_emit(x) x
45 # define LOG_LIFECYCLE_Proxy_emit(x)
50 using namespace com::sun::star
;
53 static bool relatesToInterface(typelib_TypeDescription
* pTypeDescr
)
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
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
);
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
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
);
112 if (pComp
->pBaseTypeDescription
)
113 return relatesToInterface( (typelib_TypeDescription
*)pComp
->pBaseTypeDescription
);
116 case typelib_TypeClass_UNION
: // might relate to interface
117 case typelib_TypeClass_ANY
: // might relate to interface
118 case typelib_TypeClass_INTERFACE
:
127 extern "C" { static void SAL_CALL
s_Proxy_dispatch(
128 uno_Interface
* pUnoI
,
129 typelib_TypeDescription
const * pMemberType
,
132 uno_Any
** ppException
)
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
:
149 ((typelib_InterfaceAttributeTypeDescription
*)
150 pMemberType
)->pAttributeTypeRef
;
156 param
.pTypeRef
= ((typelib_InterfaceAttributeTypeDescription
*)
157 pMemberType
)->pAttributeTypeRef
;
158 param
.bIn
= sal_True
;
159 param
.bOut
= sal_False
;
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
;
174 OSL_ENSURE( sal_False
, "### illegal member typeclass!" );
178 pThis
->dispatch( pReturnTypeRef
,
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
));
194 static void SAL_CALL
s_Proxy_acquire(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
196 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
200 static void SAL_CALL
s_Proxy_release(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
202 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
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
,
231 m_from_to (pFrom
, pTo
),
234 m_pTypeDescr (pTypeDescr
),
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());
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
);
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
);
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
);
303 static uno::TypeDescription
s_acquireMethod(getAcquireMethod());
304 static uno::TypeDescription
s_releaseMethod(getReleaseMethod());
306 void Proxy::acquire(void)
312 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
315 s_acquireMethod
.get(),
320 if (osl_incrementInterlockedCount(&m_nRef
) == 1)
322 // rebirth of proxy zombie
324 m_from
.get()->pExtEnv
->registerProxyInterface(m_from
.get()->pExtEnv
,
329 OSL_ASSERT(pThis
== this);
336 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
339 s_acquireMethod
.get(),
346 void Proxy::release(void)
348 cppu::helper::purpenv::ProbeFun
* probeFun
= m_probeFun
;
349 void * pProbeContext
= m_pProbeContext
;
355 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
358 s_releaseMethod
.get(),
363 if (osl_decrementInterlockedCount(&m_nRef
) == 0)
364 m_from
.get()->pExtEnv
->revokeInterface(m_from
.get()->pExtEnv
, this);
370 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
373 s_releaseMethod
.get(),
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
,
405 typelib_TypeDescription
const * pMemberType
,
408 uno_Any
** ppException
)
422 void ** args
= (void **) alloca( sizeof (void *) * nParams
);
424 typelib_TypeDescription
* return_td
= 0;
425 void * ret
= pReturn
;
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
);
446 uno_copyAndConvertData(args
[nPos
], pArgs
[nPos
], td
, m_from_to
.get());
451 args
[nPos
] = pArgs
[nPos
];
453 TYPELIB_DANGER_RELEASE( td
);
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
);
464 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
466 if (args
[nPos
] != pArgs
[nPos
])
468 typelib_MethodParameter
const & param
= pParams
[nPos
];
471 if (param
.bIn
) // is inout
473 uno_type_destructData(pArgs
[nPos
], param
.pTypeRef
, 0);
475 uno_type_copyAndConvertData(pArgs
[ nPos
],
480 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
485 uno_type_copyAndConvertData(pReturn
,
490 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, ret
, pReturnTypeRef
, 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
];
504 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
509 uno_type_any_constructAndConvert(*ppException
,
514 // FIXME: need to destruct in m_to
515 uno_any_destruct(exc
, 0);