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
)
45 switch (pTypeDescr
->eTypeClass
)
47 // case typelib_TypeClass_TYPEDEF:
48 case typelib_TypeClass_SEQUENCE
:
50 switch (reinterpret_cast<typelib_IndirectTypeDescription
*>(pTypeDescr
)->pType
->eTypeClass
)
52 case typelib_TypeClass_INTERFACE
:
53 case typelib_TypeClass_ANY
: // might relate to interface
55 case typelib_TypeClass_SEQUENCE
:
56 case typelib_TypeClass_STRUCT
:
57 case typelib_TypeClass_EXCEPTION
:
59 typelib_TypeDescription
* pTD
= 0;
60 TYPELIB_DANGER_GET( &pTD
, reinterpret_cast<typelib_IndirectTypeDescription
*>(pTypeDescr
)->pType
);
61 bool bRel
= relatesToInterface( pTD
);
62 TYPELIB_DANGER_RELEASE( pTD
);
70 case typelib_TypeClass_STRUCT
:
71 case typelib_TypeClass_EXCEPTION
:
73 // ...optimized... to avoid getDescription() calls!
74 typelib_CompoundTypeDescription
* pComp
= reinterpret_cast<typelib_CompoundTypeDescription
*>(pTypeDescr
);
75 typelib_TypeDescriptionReference
** pTypes
= pComp
->ppTypeRefs
;
76 for ( sal_Int32 nPos
= pComp
->nMembers
; nPos
--; )
78 switch (pTypes
[nPos
]->eTypeClass
)
80 case typelib_TypeClass_INTERFACE
:
81 case typelib_TypeClass_ANY
: // might relate to interface
83 // case typelib_TypeClass_TYPEDEF:
84 case typelib_TypeClass_SEQUENCE
:
85 case typelib_TypeClass_STRUCT
:
86 case typelib_TypeClass_EXCEPTION
:
88 typelib_TypeDescription
* pTD
= 0;
89 TYPELIB_DANGER_GET( &pTD
, pTypes
[nPos
] );
90 bool bRel
= relatesToInterface( pTD
);
91 TYPELIB_DANGER_RELEASE( pTD
);
99 if (pComp
->pBaseTypeDescription
)
100 return relatesToInterface( &pComp
->pBaseTypeDescription
->aBase
);
103 case typelib_TypeClass_ANY
: // might relate to interface
104 case typelib_TypeClass_INTERFACE
:
113 extern "C" { static void SAL_CALL
s_Proxy_dispatch(
114 uno_Interface
* pUnoI
,
115 typelib_TypeDescription
const * pMemberType
,
118 uno_Any
** ppException
)
121 Proxy
* pThis
= static_cast<Proxy
*>(pUnoI
);
123 typelib_MethodParameter param
;
124 sal_Int32 nParams
= 0;
125 typelib_MethodParameter
* pParams
= 0;
126 typelib_TypeDescriptionReference
* pReturnTypeRef
= 0;
127 // sal_Int32 nOutParams = 0;
129 switch (pMemberType
->eTypeClass
)
131 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
135 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(
136 pMemberType
)->pAttributeTypeRef
;
142 param
.pTypeRef
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(
143 pMemberType
)->pAttributeTypeRef
;
144 param
.bIn
= sal_True
;
145 param
.bOut
= sal_False
;
150 case typelib_TypeClass_INTERFACE_METHOD
:
152 typelib_InterfaceMethodTypeDescription
const * method_td
=
153 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberType
);
154 pReturnTypeRef
= method_td
->pReturnTypeRef
;
155 nParams
= method_td
->nParams
;
156 pParams
= method_td
->pParams
;
160 OSL_FAIL( "### illegal member typeclass!" );
164 pThis
->dispatch( pReturnTypeRef
,
173 extern "C" void SAL_CALL
Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment
* /*pEnv*/, void * pProxy
) SAL_THROW_EXTERN_C()
175 Proxy
* pThis
= static_cast<Proxy
* >(static_cast<uno_Interface
*>(pProxy
));
180 static void SAL_CALL
s_Proxy_acquire(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
182 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
186 static void SAL_CALL
s_Proxy_release(uno_Interface
* pUnoI
) SAL_THROW_EXTERN_C()
188 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
192 static void s_acquireAndRegister_v(va_list * pParam
)
194 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
195 rtl_uString
* pOid
= va_arg(*pParam
, rtl_uString
*);
196 typelib_InterfaceTypeDescription
* pTypeDescr
= va_arg(*pParam
, typelib_InterfaceTypeDescription
*);
197 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
199 pUnoI
->acquire(pUnoI
);
200 pEnv
->registerInterface(pEnv
, reinterpret_cast<void **>(&pUnoI
), pOid
, pTypeDescr
);
204 Proxy::Proxy(uno::Mapping
const & to_from
,
205 uno_Environment
* pTo
,
206 uno_Environment
* pFrom
,
207 uno_Interface
* pUnoI
,
208 typelib_InterfaceTypeDescription
* pTypeDescr
,
209 rtl::OUString
const & rOId
,
210 cppu::helper::purpenv::ProbeFun
* probeFun
,
216 m_from_to (pFrom
, pTo
),
219 m_pTypeDescr (pTypeDescr
),
221 m_probeFun (probeFun
),
222 m_pProbeContext(pProbeContext
)
224 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr
, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this));
226 typelib_typedescription_acquire(&m_pTypeDescr
->aBase
);
227 if (!m_pTypeDescr
->aBase
.bComplete
)
228 typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription
**>(&m_pTypeDescr
));
230 OSL_ENSURE(m_pTypeDescr
->aBase
.bComplete
, "### type is incomplete!");
232 uno_Environment_invoke(m_to
.get(), s_acquireAndRegister_v
, m_pUnoI
, rOId
.pData
, pTypeDescr
, m_to
.get());
235 uno_Interface::acquire
= s_Proxy_acquire
;
236 uno_Interface::release
= s_Proxy_release
;
237 uno_Interface::pDispatcher
= s_Proxy_dispatch
;
240 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam
)
242 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
243 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
245 pEnv
->revokeInterface(pEnv
, pUnoI
);
246 pUnoI
->release(pUnoI
);
251 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr
, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this));
253 uno_Environment_invoke(m_to
.get(), s_releaseAndRevoke_v
, m_to
.get(), m_pUnoI
);
255 typelib_typedescription_release(&m_pTypeDescr
->aBase
);
258 static uno::TypeDescription
getAcquireMethod()
260 typelib_TypeDescriptionReference
* type_XInterface
=
261 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE
);
263 typelib_TypeDescription
* pTXInterfaceDescr
= 0;
264 TYPELIB_DANGER_GET (&pTXInterfaceDescr
, type_XInterface
);
265 uno::TypeDescription
acquire(
266 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
267 pTXInterfaceDescr
)->ppAllMembers
[1]);
268 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr
);
273 static uno::TypeDescription
getReleaseMethod()
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
release(
281 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
282 pTXInterfaceDescr
)->ppAllMembers
[2]);
283 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr
);
288 static uno::TypeDescription
s_acquireMethod(getAcquireMethod());
289 static uno::TypeDescription
s_releaseMethod(getReleaseMethod());
291 void Proxy::acquire()
297 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
300 s_acquireMethod
.get(),
305 if (osl_atomic_increment(&m_nRef
) == 1)
307 // rebirth of proxy zombie
309 m_from
.get()->pExtEnv
->registerProxyInterface(m_from
.get()->pExtEnv
,
314 OSL_ASSERT(pThis
== this);
321 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
324 s_acquireMethod
.get(),
331 void Proxy::release()
333 cppu::helper::purpenv::ProbeFun
* probeFun
= m_probeFun
;
334 void * pProbeContext
= m_pProbeContext
;
340 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
343 s_releaseMethod
.get(),
348 if (osl_atomic_decrement(&m_nRef
) == 0)
349 m_from
.get()->pExtEnv
->revokeInterface(m_from
.get()->pExtEnv
, this);
355 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
358 s_releaseMethod
.get(),
367 static void s_type_destructData_v(va_list * pParam
)
369 void * ret
= va_arg(*pParam
, void *);
370 typelib_TypeDescriptionReference
* pReturnTypeRef
= va_arg(*pParam
, typelib_TypeDescriptionReference
*);
372 uno_type_destructData(ret
, pReturnTypeRef
, 0);
375 static void s_dispatcher_v(va_list * pParam
)
377 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
378 typelib_TypeDescription
const * pMemberType
= va_arg(*pParam
, typelib_TypeDescription
const *);
379 void * pReturn
= va_arg(*pParam
, void *);
380 void ** pArgs
= va_arg(*pParam
, void **);
381 uno_Any
** ppException
= va_arg(*pParam
, uno_Any
**);
383 pUnoI
->pDispatcher(pUnoI
, pMemberType
, pReturn
, pArgs
, ppException
);
387 void Proxy::dispatch(typelib_TypeDescriptionReference
* pReturnTypeRef
,
388 typelib_MethodParameter
* pParams
,
390 typelib_TypeDescription
const * pMemberType
,
393 uno_Any
** ppException
)
407 void ** args
= static_cast<void **>(alloca( sizeof (void *) * nParams
));
409 typelib_TypeDescription
* return_td
= 0;
410 void * ret
= pReturn
;
413 TYPELIB_DANGER_GET(&return_td
, pReturnTypeRef
);
415 if (relatesToInterface(return_td
))
416 ret
= alloca(return_td
->nSize
);
418 TYPELIB_DANGER_RELEASE(return_td
);
421 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
423 typelib_MethodParameter
const & param
= pParams
[nPos
];
424 typelib_TypeDescription
* td
= 0;
425 TYPELIB_DANGER_GET( &td
, param
.pTypeRef
);
426 if (relatesToInterface(td
))
428 args
[nPos
] = alloca(td
->nSize
);
431 uno_copyAndConvertData(args
[nPos
], pArgs
[nPos
], td
, m_from_to
.get());
436 args
[nPos
] = pArgs
[nPos
];
438 TYPELIB_DANGER_RELEASE( td
);
442 uno_Any
* exc
= &exc_data
;
444 // do the UNO call...
445 uno_Environment_invoke(m_to
.get(), s_dispatcher_v
, m_pUnoI
, pMemberType
, ret
, args
, &exc
);
449 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
451 if (args
[nPos
] != pArgs
[nPos
])
453 typelib_MethodParameter
const & param
= pParams
[nPos
];
456 if (param
.bIn
) // is inout
458 uno_type_destructData(pArgs
[nPos
], param
.pTypeRef
, 0);
460 uno_type_copyAndConvertData(pArgs
[ nPos
],
465 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
470 uno_type_copyAndConvertData(pReturn
,
475 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, ret
, pReturnTypeRef
, 0);
480 else // exception occurred
482 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
484 if (args
[nPos
] != pArgs
[nPos
])
486 typelib_MethodParameter
const & param
= pParams
[nPos
];
489 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
494 uno_type_any_constructAndConvert(*ppException
,
499 // FIXME: need to destruct in m_to
500 uno_any_destruct(exc
, 0);
516 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */