1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
23 #include "sal/alloca.h"
24 #include "uno/dispatcher.h"
25 #include "typelib/typedescription.hxx"
26 #include "cppu/EnvDcp.hxx"
29 //#define LOG_LIFECYCLE_Proxy
30 #ifdef LOG_LIFECYCLE_Proxy
32 # define LOG_LIFECYCLE_Proxy_emit(x) x
35 # define LOG_LIFECYCLE_Proxy_emit(x)
40 using namespace com::sun::star
;
43 static bool relatesToInterface(typelib_TypeDescription
* pTypeDescr
)
46 switch (pTypeDescr
->eTypeClass
)
48 // case typelib_TypeClass_TYPEDEF:
49 case typelib_TypeClass_SEQUENCE
:
51 switch (((typelib_IndirectTypeDescription
*)pTypeDescr
)->pType
->eTypeClass
)
53 case typelib_TypeClass_INTERFACE
:
54 case typelib_TypeClass_UNION
: // might relate to interface
55 case typelib_TypeClass_ANY
: // might relate to interface
57 case typelib_TypeClass_SEQUENCE
:
58 case typelib_TypeClass_STRUCT
:
59 case typelib_TypeClass_EXCEPTION
:
61 typelib_TypeDescription
* pTD
= 0;
62 TYPELIB_DANGER_GET( &pTD
, ((typelib_IndirectTypeDescription
*)pTypeDescr
)->pType
);
63 bool bRel
= relatesToInterface( pTD
);
64 TYPELIB_DANGER_RELEASE( pTD
);
72 case typelib_TypeClass_STRUCT
:
73 case typelib_TypeClass_EXCEPTION
:
75 // ...optimized... to avoid getDescription() calls!
76 typelib_CompoundTypeDescription
* pComp
= (typelib_CompoundTypeDescription
*)pTypeDescr
;
77 typelib_TypeDescriptionReference
** pTypes
= pComp
->ppTypeRefs
;
78 for ( sal_Int32 nPos
= pComp
->nMembers
; nPos
--; )
80 switch (pTypes
[nPos
]->eTypeClass
)
82 case typelib_TypeClass_INTERFACE
:
83 case typelib_TypeClass_UNION
: // might relate to interface
84 case typelib_TypeClass_ANY
: // might relate to interface
86 // case typelib_TypeClass_TYPEDEF:
87 case typelib_TypeClass_SEQUENCE
:
88 case typelib_TypeClass_STRUCT
:
89 case typelib_TypeClass_EXCEPTION
:
91 typelib_TypeDescription
* pTD
= 0;
92 TYPELIB_DANGER_GET( &pTD
, pTypes
[nPos
] );
93 bool bRel
= relatesToInterface( pTD
);
94 TYPELIB_DANGER_RELEASE( pTD
);
102 if (pComp
->pBaseTypeDescription
)
103 return relatesToInterface( (typelib_TypeDescription
*)pComp
->pBaseTypeDescription
);
106 case typelib_TypeClass_UNION
: // might relate to interface
107 case typelib_TypeClass_ANY
: // might relate to interface
108 case typelib_TypeClass_INTERFACE
:
117 extern "C" { static void SAL_CALL
s_Proxy_dispatch(
118 uno_Interface
* pUnoI
,
119 typelib_TypeDescription
const * pMemberType
,
122 uno_Any
** ppException
)
125 Proxy
* pThis
= static_cast<Proxy
*>(pUnoI
);
127 typelib_MethodParameter param
;
128 sal_Int32 nParams
= 0;
129 typelib_MethodParameter
* pParams
= 0;
130 typelib_TypeDescriptionReference
* pReturnTypeRef
= 0;
131 // sal_Int32 nOutParams = 0;
133 switch (pMemberType
->eTypeClass
)
135 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
139 ((typelib_InterfaceAttributeTypeDescription
*)
140 pMemberType
)->pAttributeTypeRef
;
146 param
.pTypeRef
= ((typelib_InterfaceAttributeTypeDescription
*)
147 pMemberType
)->pAttributeTypeRef
;
148 param
.bIn
= sal_True
;
149 param
.bOut
= sal_False
;
154 case typelib_TypeClass_INTERFACE_METHOD
:
156 typelib_InterfaceMethodTypeDescription
* method_td
=
157 (typelib_InterfaceMethodTypeDescription
*) pMemberType
;
158 pReturnTypeRef
= method_td
->pReturnTypeRef
;
159 nParams
= method_td
->nParams
;
160 pParams
= method_td
->pParams
;
164 OSL_FAIL( "### illegal member typeclass!" );
168 pThis
->dispatch( pReturnTypeRef
,
177 extern "C" void SAL_CALL
Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment
* /*pEnv*/, void * pProxy
) SAL_THROW_EXTERN_C()
179 Proxy
* pThis
= static_cast<Proxy
* >(reinterpret_cast<uno_Interface
*>(pProxy
));
184 static void SAL_CALL
s_Proxy_acquire(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
186 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
190 static void SAL_CALL
s_Proxy_release(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
192 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
196 static void s_acquireAndRegister_v(va_list * pParam
)
198 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
199 rtl_uString
* pOid
= va_arg(*pParam
, rtl_uString
*);
200 typelib_InterfaceTypeDescription
* pTypeDescr
= va_arg(*pParam
, typelib_InterfaceTypeDescription
*);
201 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
203 pUnoI
->acquire(pUnoI
);
204 pEnv
->registerInterface(pEnv
, reinterpret_cast<void **>(&pUnoI
), pOid
, pTypeDescr
);
208 Proxy::Proxy(uno::Mapping
const & to_from
,
209 uno_Environment
* pTo
,
210 uno_Environment
* pFrom
,
211 uno_Interface
* pUnoI
,
212 typelib_InterfaceTypeDescription
* pTypeDescr
,
213 rtl::OUString
const & rOId
,
214 cppu::helper::purpenv::ProbeFun
* probeFun
,
221 m_from_to (pFrom
, pTo
),
224 m_pTypeDescr (pTypeDescr
),
226 m_probeFun (probeFun
),
227 m_pProbeContext(pProbeContext
)
229 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr
, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this));
231 typelib_typedescription_acquire((typelib_TypeDescription
*)m_pTypeDescr
);
232 if (!((typelib_TypeDescription
*)m_pTypeDescr
)->bComplete
)
233 typelib_typedescription_complete((typelib_TypeDescription
**)&m_pTypeDescr
);
235 OSL_ENSURE(((typelib_TypeDescription
*)m_pTypeDescr
)->bComplete
, "### type is incomplete!");
237 uno_Environment_invoke(m_to
.get(), s_acquireAndRegister_v
, m_pUnoI
, rOId
.pData
, pTypeDescr
, m_to
.get());
240 uno_Interface::acquire
= s_Proxy_acquire
;
241 uno_Interface::release
= s_Proxy_release
;
242 uno_Interface::pDispatcher
= s_Proxy_dispatch
;
245 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam
)
247 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
248 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
250 pEnv
->revokeInterface(pEnv
, reinterpret_cast<void *>(pUnoI
));
251 pUnoI
->release(pUnoI
);
256 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr
, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this));
258 uno_Environment_invoke(m_to
.get(), s_releaseAndRevoke_v
, m_to
.get(), m_pUnoI
);
260 typelib_typedescription_release((typelib_TypeDescription
*)m_pTypeDescr
);
263 static uno::TypeDescription
getAcquireMethod(void)
265 typelib_TypeDescriptionReference
* type_XInterface
=
266 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE
);
268 typelib_TypeDescription
* pTXInterfaceDescr
= 0;
269 TYPELIB_DANGER_GET (&pTXInterfaceDescr
, type_XInterface
);
270 uno::TypeDescription
acquire(
271 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
272 pTXInterfaceDescr
)->ppAllMembers
[1]);
273 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr
);
278 static uno::TypeDescription
getReleaseMethod(void)
280 typelib_TypeDescriptionReference
* type_XInterface
=
281 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE
);
283 typelib_TypeDescription
* pTXInterfaceDescr
= 0;
284 TYPELIB_DANGER_GET (&pTXInterfaceDescr
, type_XInterface
);
285 uno::TypeDescription
release(
286 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
287 pTXInterfaceDescr
)->ppAllMembers
[2]);
288 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr
);
293 static uno::TypeDescription
s_acquireMethod(getAcquireMethod());
294 static uno::TypeDescription
s_releaseMethod(getReleaseMethod());
296 void Proxy::acquire(void)
302 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
305 s_acquireMethod
.get(),
310 if (osl_atomic_increment(&m_nRef
) == 1)
312 // rebirth of proxy zombie
314 m_from
.get()->pExtEnv
->registerProxyInterface(m_from
.get()->pExtEnv
,
319 OSL_ASSERT(pThis
== this);
326 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
329 s_acquireMethod
.get(),
336 void Proxy::release(void)
338 cppu::helper::purpenv::ProbeFun
* probeFun
= m_probeFun
;
339 void * pProbeContext
= m_pProbeContext
;
345 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
348 s_releaseMethod
.get(),
353 if (osl_atomic_decrement(&m_nRef
) == 0)
354 m_from
.get()->pExtEnv
->revokeInterface(m_from
.get()->pExtEnv
, this);
360 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
363 s_releaseMethod
.get(),
372 static void s_type_destructData_v(va_list * pParam
)
374 void * ret
= va_arg(*pParam
, void *);
375 typelib_TypeDescriptionReference
* pReturnTypeRef
= va_arg(*pParam
, typelib_TypeDescriptionReference
*);
377 uno_type_destructData(ret
, pReturnTypeRef
, 0);
380 static void s_dispatcher_v(va_list * pParam
)
382 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
383 typelib_TypeDescription
const * pMemberType
= va_arg(*pParam
, typelib_TypeDescription
const *);
384 void * pReturn
= va_arg(*pParam
, void *);
385 void ** pArgs
= va_arg(*pParam
, void **);
386 uno_Any
** ppException
= va_arg(*pParam
, uno_Any
**);
388 pUnoI
->pDispatcher(pUnoI
, pMemberType
, pReturn
, pArgs
, ppException
);
392 void Proxy::dispatch(typelib_TypeDescriptionReference
* pReturnTypeRef
,
393 typelib_MethodParameter
* pParams
,
395 typelib_TypeDescription
const * pMemberType
,
398 uno_Any
** ppException
)
412 void ** args
= (void **) alloca( sizeof (void *) * nParams
);
414 typelib_TypeDescription
* return_td
= 0;
415 void * ret
= pReturn
;
418 TYPELIB_DANGER_GET(&return_td
, pReturnTypeRef
);
420 if (relatesToInterface(return_td
))
421 ret
= alloca(return_td
->nSize
);
423 TYPELIB_DANGER_RELEASE(return_td
);
426 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
428 typelib_MethodParameter
const & param
= pParams
[nPos
];
429 typelib_TypeDescription
* td
= 0;
430 TYPELIB_DANGER_GET( &td
, param
.pTypeRef
);
431 if (relatesToInterface(td
))
433 args
[nPos
] = alloca(td
->nSize
);
436 uno_copyAndConvertData(args
[nPos
], pArgs
[nPos
], td
, m_from_to
.get());
441 args
[nPos
] = pArgs
[nPos
];
443 TYPELIB_DANGER_RELEASE( td
);
447 uno_Any
* exc
= &exc_data
;
449 // do the UNO call...
450 uno_Environment_invoke(m_to
.get(), s_dispatcher_v
, m_pUnoI
, pMemberType
, ret
, args
, &exc
);
454 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
456 if (args
[nPos
] != pArgs
[nPos
])
458 typelib_MethodParameter
const & param
= pParams
[nPos
];
461 if (param
.bIn
) // is inout
463 uno_type_destructData(pArgs
[nPos
], param
.pTypeRef
, 0);
465 uno_type_copyAndConvertData(pArgs
[ nPos
],
470 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
475 uno_type_copyAndConvertData(pReturn
,
480 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, ret
, pReturnTypeRef
, 0);
485 else // exception occurred
487 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
489 if (args
[nPos
] != pArgs
[nPos
])
491 typelib_MethodParameter
const & param
= pParams
[nPos
];
494 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
499 uno_type_any_constructAndConvert(*ppException
,
504 // FIXME: need to destruct in m_to
505 uno_any_destruct(exc
, 0);
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */