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: cli_proxy.cxx,v $
11 * $RCSfile: cli_proxy.cxx,v $
14 * This file is part of OpenOffice.org.
16 * OpenOffice.org is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU Lesser General Public License version 3
18 * only, as published by the Free Software Foundation.
20 * OpenOffice.org is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Lesser General Public License version 3 for more details
24 * (a copy is included in the LICENSE file that accompanied this code).
26 * You should have received a copy of the GNU Lesser General Public License
27 * version 3 along with OpenOffice.org. If not, see
28 * <http://www.openoffice.org/license.html>
29 * for a copy of the LGPLv3 License.
31 ************************************************************************/
33 // MARKER(update_precomp.py): autogen include statement, do not remove
34 #include "precompiled_cli_ure.hxx"
35 #include "typelib/typedescription.h"
36 #include "rtl/ustrbuf.hxx"
37 #include "com/sun/star/uno/RuntimeException.hpp"
38 #include "osl/mutex.hxx"
39 #include "cli_proxy.h"
41 #include "cli_bridge.h"
45 #using <cli_uretypes.dll>
47 namespace sr
= System::Reflection
;
48 namespace st
= System::Text
;
49 namespace sre
= System::Reflection::Emit
;
50 namespace sc
= System::Collections
;
51 namespace srrm
= System::Runtime::Remoting::Messaging
;
52 namespace srr
= System::Runtime::Remoting
;
53 namespace srrp
= System::Runtime::Remoting::Proxies
;
54 namespace sri
= System::Runtime::InteropServices
;
55 namespace sd
= System::Diagnostics
;
56 namespace css
= com::sun::star
;
57 namespace ucss
= unoidl::com::sun::star
;
59 using namespace cli_uno
;
63 //------------------------------------------------------------------------------
64 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
* env
, void * proxy
)
66 //------------------------------------------------------------------------------
67 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
69 //------------------------------------------------------------------------------
70 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
72 //------------------------------------------------------------------------------
73 void SAL_CALL
cli_proxy_dispatch(
74 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
75 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
84 UnoInterfaceInfo::UnoInterfaceInfo(Bridge
const * bridge
, uno_Interface
* unoI
,
85 typelib_InterfaceTypeDescription
* td
):
92 m_type
= mapUnoType(reinterpret_cast<typelib_TypeDescription
*>(td
));
93 m_unoI
->acquire(m_unoI
);
94 typelib_typedescription_acquire(&m_typeDesc
->aBase
);
95 if ( ! m_typeDesc
->aBase
.bComplete
)
97 typelib_TypeDescription
* _pt
= &m_typeDesc
->aBase
;
98 sal_Bool bComplete
= ::typelib_typedescription_complete( & _pt
);
101 OUStringBuffer
buf( 128 );
102 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
103 "cannot make type complete: ") );
104 buf
.append( *reinterpret_cast< OUString
const * >(
105 & m_typeDesc
->aBase
.pTypeName
));
106 throw BridgeRuntimeError(buf
.makeStringAndClear());
110 UnoInterfaceInfo::~UnoInterfaceInfo()
112 //accessing unmanaged objects is ok.
113 m_bridge
->m_uno_env
->revokeInterface(
114 m_bridge
->m_uno_env
, m_unoI
);
117 m_unoI
->release(m_unoI
);
118 typelib_typedescription_release(
119 reinterpret_cast<typelib_TypeDescription
*>(m_typeDesc
));
122 UnoInterfaceProxy::UnoInterfaceProxy(
124 uno_Interface
* pUnoI
,
125 typelib_InterfaceTypeDescription
* pTD
,
126 const OUString
& oid
)
127 :RealProxy(__typeof(MarshalByRefObject
)),
129 m_oid(mapUnoString(oid
.pData
)),
130 m_sTypeName(m_system_Object_String
)
133 // create the list that holds all UnoInterfaceInfos
134 m_listIfaces
= new ArrayList(10);
136 m_listAdditionalProxies
= new ArrayList();
137 m_nlistAdditionalProxies
= 0;
138 //put the information of the first UNO interface into the arraylist
139 #if OSL_DEBUG_LEVEL >= 2
143 addUnoInterface(pUnoI
, pTD
);
147 UnoInterfaceProxy::~UnoInterfaceProxy()
149 #if OSL_DEBUG_LEVEL >= 2
150 sd::Trace::WriteLine(System::String::Format(
151 new System::String(S
"cli uno bridge: Destroying proxy "
152 S
"for UNO object, OID: \n\t{0} \n\twith uno interfaces: "),
155 sd::Trace::WriteLine( mapUnoString(_sInterfaces
));
156 rtl_uString_release(_sInterfaces
);
158 //m_bridge is unmanaged, therefore we can access it in this finalizer
159 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
);
164 System::Object
* UnoInterfaceProxy::create(
166 uno_Interface
* pUnoI
,
167 typelib_InterfaceTypeDescription
* pTD
,
170 UnoInterfaceProxy
* proxyHandler
=
171 new UnoInterfaceProxy(bridge
, pUnoI
, pTD
, oid
);
172 System::Object
* proxy
= proxyHandler
->GetTransparentProxy();
173 CliEnvHolder::g_cli_env
->registerInterface(proxy
, mapUnoString(oid
.pData
));
178 void UnoInterfaceProxy::addUnoInterface(uno_Interface
* pUnoI
,
179 typelib_InterfaceTypeDescription
* pTd
)
181 sc::IEnumerator
* enumInfos
= m_listIfaces
->GetEnumerator();
182 System::Threading::Monitor::Enter(this);
185 while (enumInfos
->MoveNext())
187 UnoInterfaceInfo
* info
= static_cast<UnoInterfaceInfo
*>(
189 #if OSL_DEBUG_LEVEL > 1
193 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
) );
195 reinterpret_cast<typelib_TypeDescription
*>(pTd
) );
197 if (typelib_typedescription_equals(
198 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
),
199 reinterpret_cast<typelib_TypeDescription
*>(pTd
)))
204 OUString
oid(mapCliString(m_oid
));
205 (*m_bridge
->m_uno_env
->registerInterface
)(
206 m_bridge
->m_uno_env
, reinterpret_cast< void ** >( &pUnoI
),
208 //This proxy does not contain the uno_Interface. Add it.
209 m_listIfaces
->Add(new UnoInterfaceInfo(m_bridge
, pUnoI
, pTd
));
210 m_numUnoIfaces
= m_listIfaces
->Count
;
211 #if OSL_DEBUG_LEVEL >= 2
212 System::String
* sInterfaceName
= static_cast<UnoInterfaceInfo
*>(
213 m_listIfaces
->get_Item(m_numUnoIfaces
- 1))->m_type
->FullName
;
214 sd::Trace::WriteLine(System::String::Format(
215 new System::String(S
"cli uno bridge: Creating proxy for uno object, "
216 S
"id:\n\t{0}\n\t{1}"), m_oid
, sInterfaceName
));
217 // add to the string that contains all interface names
219 OUStringBuffer
buf(512);
220 buf
.appendAscii("\t");
221 buf
.append( OUString::valueOf((sal_Int32
)_numInterfaces
));
222 buf
.appendAscii(". ");
223 buf
.append(mapCliString(sInterfaceName
));
224 buf
.appendAscii("\n");
225 OUString _sNewInterface
= buf
.makeStringAndClear();
226 rtl_uString
* __pin
* pp_sInterfaces
= & _sInterfaces
;
227 rtl_uString_newConcat( pp_sInterfaces
, * pp_sInterfaces
,
228 _sNewInterface
.pData
);
232 System::Threading::Monitor::Exit(this);
238 bool UnoInterfaceProxy::CanCastTo(System::Type
* fromType
,
241 if (fromType
== __typeof(System::Object
)) // trivial case
244 System::Threading::Monitor::Enter(this);
247 if (0 != findInfo( fromType
)) // proxy supports demanded interface
250 //query an uno interface for the required type
252 // we use the first interface in the list (m_listIfaces) to make
253 // the queryInterface call
254 UnoInterfaceInfo
* info
=
255 static_cast<UnoInterfaceInfo
*>(m_listIfaces
->get_Item(0));
256 css::uno::TypeDescription
membertd(
257 reinterpret_cast<typelib_InterfaceTypeDescription
*>(
258 info
->m_typeDesc
)->ppAllMembers
[0]);
259 System::Object
*args
[] = new System::Object
*[1];
262 __box
uno::Any
* pAny
;
263 System::Object
* pException
= NULL
;
265 pAny
= static_cast<__box
uno::Any
*>(
269 ((typelib_InterfaceMethodTypeDescription
*)
270 membertd
.get())->pReturnTypeRef
,
272 ((typelib_InterfaceMethodTypeDescription
*)
273 membertd
.get())->pParams
,
274 args
, NULL
, &pException
) );
276 // handle regular exception from target
280 mapCliString( pException
->ToString()),
281 RTL_TEXTENCODING_UTF8
).getStr() );
283 if (pAny
->Type
!= __typeof (void)) // has value?
285 if (0 != findInfo( fromType
))
287 // proxy now supports demanded interface
291 // via aggregation: it is possible that queryInterface() returns
292 // and interface with a different oid.
293 // That way, this type is supported for the CLI
294 // interpreter (CanCastTo() returns true)
295 ::System::Object
* obj
= pAny
->Value
;
296 OSL_ASSERT( srr::RemotingServices::IsTransparentProxy( obj
) );
297 if (srr::RemotingServices::IsTransparentProxy( obj
))
299 UnoInterfaceProxy
* proxy
=
300 static_cast< UnoInterfaceProxy
* >(
301 srr::RemotingServices::GetRealProxy( obj
) );
302 OSL_ASSERT( 0 != proxy
->findInfo( fromType
) );
303 m_listAdditionalProxies
->Add( proxy
);
304 m_nlistAdditionalProxies
= m_listAdditionalProxies
->Count
;
305 OSL_ASSERT( 0 != findInfo( fromType
) );
310 catch (BridgeRuntimeError
& e
)
312 (void) e
; // avoid warning
314 0, OUStringToOString(
315 e
.m_message
, RTL_TEXTENCODING_UTF8
).getStr() );
317 catch (System::Exception
* e
)
319 System::String
* msg
= new System::String(
320 S
"An unexpected CLI exception occurred in "
321 S
"UnoInterfaceProxy::CanCastTo(). Original"
323 msg
= System::String::Concat(msg
, e
->get_Message());
325 0, OUStringToOString(
326 mapCliString(msg
), RTL_TEXTENCODING_UTF8
).getStr() );
331 0, "An unexpected native C++ exception occurred in "
332 "UnoInterfaceProxy::CanCastTo()" );
336 System::Threading::Monitor::Exit(this);
341 srrm::IMessage
* UnoInterfaceProxy::invokeObject(
342 sc::IDictionary
* props
,
343 srrm::LogicalCallContext
* context
,
344 srrm::IMethodCallMessage
* mcm
)
346 System::Object
* retMethod
= 0;
347 System::String
* sMethod
= static_cast<System::String
*>
348 (props
->get_Item(m_methodNameString
));
349 System::Object
* args
[] = static_cast<System::Object
*[]>(
350 props
->get_Item(m_ArgsString
));
351 if (m_Equals_String
->Equals(sMethod
))
354 OSL_ASSERT(args
->get_Length() == 1);
355 srrp::RealProxy
* rProxy
= srr::RemotingServices::GetRealProxy(args
[0]);
359 UnoInterfaceProxy
* unoProxy
=
360 dynamic_cast<UnoInterfaceProxy
*>(rProxy
);
363 bool b
= m_oid
->Equals(unoProxy
->getOid());
364 retMethod
= __box(b
);
370 //no proxy or not our proxy, therefore Equals must be false
371 retMethod
= __box(false);
374 else if (m_GetHashCode_String
->Equals(sMethod
))
376 // Object.GetHashCode
377 int nHash
= m_oid
->GetHashCode();
378 retMethod
= __box(nHash
);
380 else if (m_GetType_String
->Equals(sMethod
))
383 retMethod
= __typeof(System::Object
);
385 else if (m_ToString_String
->Equals(sMethod
))
388 st::StringBuilder
* sb
= new st::StringBuilder(256);
389 // sb->AppendFormat(S"Uno object proxy. Implemented interface: {0}"
390 // S". OID: {1}", m_type->ToString(), m_oid);
391 sb
->AppendFormat(S
"Uno object proxy. OID: {0}", m_oid
);
392 retMethod
= sb
->ToString();
396 //Either Object has new functions or a protected method was called
397 //which should not be possible
400 srrm::IMessage
* retVal
= new srrm::ReturnMessage(
401 retMethod
, new System::Object
*[0], 0, context
, mcm
);
405 UnoInterfaceInfo
* UnoInterfaceProxy::findInfo( ::System::Type
* type
)
407 for (int i
= 0; i
< m_numUnoIfaces
; i
++)
409 UnoInterfaceInfo
* tmpInfo
= static_cast<UnoInterfaceInfo
*>(
410 m_listIfaces
->get_Item(i
));
411 if (type
->IsAssignableFrom(tmpInfo
->m_type
))
414 for ( int i
= 0; i
< m_nlistAdditionalProxies
; ++i
)
416 UnoInterfaceProxy
* proxy
=
417 static_cast< UnoInterfaceProxy
* >(
418 m_listAdditionalProxies
->get_Item( i
) );
419 UnoInterfaceInfo
* info
= proxy
->findInfo( type
);
426 srrm::IMessage
* UnoInterfaceProxy::Invoke(srrm::IMessage
* callmsg
)
430 sc::IDictionary
* props
= callmsg
->Properties
;
431 srrm::LogicalCallContext
* context
=
432 static_cast<srrm::LogicalCallContext
*>(
433 props
->get_Item(m_CallContextString
));
434 srrm::IMethodCallMessage
* mcm
=
435 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
437 //Find out which UNO interface is being called
438 System::String
* sTypeName
= static_cast<System::String
*>(
439 props
->get_Item(m_typeNameString
));
440 sTypeName
= sTypeName
->Substring(0, sTypeName
->IndexOf(','));
442 // Special Handling for System.Object methods
443 if(sTypeName
->IndexOf(m_system_Object_String
) != -1)
445 return invokeObject(props
, context
, mcm
);
448 System::Type
* typeBeingCalled
= loadCliType(sTypeName
);
449 UnoInterfaceInfo
* info
= findInfo( typeBeingCalled
);
450 OSL_ASSERT( 0 != info
);
452 // ToDo do without string conversion, a OUString is not needed here
453 // get the type description of the call
454 OUString
usMethodName(mapCliString(static_cast<System::String
*>(
455 props
->get_Item(m_methodNameString
))));
456 typelib_TypeDescriptionReference
** ppAllMembers
=
457 info
->m_typeDesc
->ppAllMembers
;
458 sal_Int32 numberMembers
= info
->m_typeDesc
->nAllMembers
;
459 for ( sal_Int32 nPos
= numberMembers
; nPos
--; )
461 typelib_TypeDescriptionReference
* member_type
= ppAllMembers
[nPos
];
463 // check usMethodName against fully qualified usTypeName
464 // of member_type; usTypeName is of the form
465 // <name> "::" <usMethodName> *(":@" <idx> "," <idx> ":" <name>)
466 OUString
const & usTypeName
=
467 OUString::unacquired( & member_type
->pTypeName
);
469 #if OSL_DEBUG_LEVEL >= 2
470 System::String
* pTypeName
;
471 pTypeName
= mapUnoString(usTypeName
.pData
);
473 sal_Int32 offset
= usTypeName
.indexOf( ':' ) + 2;
475 offset
>= 2 && offset
< usTypeName
.getLength()
476 && usTypeName
[offset
- 1] == ':' );
477 sal_Int32 remainder
= usTypeName
.getLength() - offset
;
479 if (typelib_TypeClass_INTERFACE_METHOD
== member_type
->eTypeClass
)
481 if ((usMethodName
.getLength() == remainder
482 || (usMethodName
.getLength() < remainder
483 && usTypeName
[offset
+ usMethodName
.getLength()] == ':'))
484 && usTypeName
.match(usMethodName
, offset
))
486 TypeDescr
member_td( member_type
);
487 typelib_InterfaceMethodTypeDescription
* method_td
=
488 (typelib_InterfaceMethodTypeDescription
*)
491 System::Object
* args
[] = static_cast<System::Object
*[]>(
492 props
->get_Item(m_ArgsString
));
493 System::Type
* argTypes
[] = static_cast<System::Type
*[]>(
494 props
->get_Item(m_methodSignatureString
));
495 System::Object
* pExc
= NULL
;
496 System::Object
* cli_ret
= m_bridge
->call_uno(
497 info
->m_unoI
, member_td
.get(),
498 method_td
->pReturnTypeRef
, method_td
->nParams
,
499 method_td
->pParams
, args
, argTypes
, &pExc
);
500 return constructReturnMessage(cli_ret
, args
, method_td
,
507 OSL_ASSERT( typelib_TypeClass_INTERFACE_ATTRIBUTE
==
508 member_type
->eTypeClass
);
509 if (usMethodName
.getLength() > 4
510 && (usMethodName
.getLength() - 4 == remainder
511 || (usMethodName
.getLength() - 4 < remainder
513 offset
+ (usMethodName
.getLength() - 4)] == ':'))
514 && usMethodName
[1] == 'e' && usMethodName
[2] == 't'
515 && rtl_ustr_compare_WithLength(
516 usTypeName
.getStr() + offset
,
517 usMethodName
.getLength() - 4,
518 usMethodName
.getStr() + 4,
519 usMethodName
.getLength() - 4) == 0)
521 if ('g' == usMethodName
[0])
523 TypeDescr
member_td( member_type
);
524 typelib_InterfaceAttributeTypeDescription
* attribute_td
=
525 (typelib_InterfaceAttributeTypeDescription
*)
528 System::Object
* pExc
= NULL
;
529 System::Object
* cli_ret
= m_bridge
->call_uno(
530 info
->m_unoI
, member_td
.get(),
531 attribute_td
->pAttributeTypeRef
,
534 return constructReturnMessage(cli_ret
, NULL
, NULL
,
537 else if ('s' == usMethodName
[0])
539 TypeDescr
member_td( member_type
);
540 typelib_InterfaceAttributeTypeDescription
* attribute_td
=
541 (typelib_InterfaceAttributeTypeDescription
*)
543 if (! attribute_td
->bReadOnly
)
545 typelib_MethodParameter param
;
546 param
.pTypeRef
= attribute_td
->pAttributeTypeRef
;
547 param
.bIn
= sal_True
;
548 param
.bOut
= sal_False
;
550 System::Object
* args
[] =
551 static_cast<System::Object
*[]>(
552 props
->get_Item(m_ArgsString
));
553 System::Object
* pExc
= NULL
;
555 info
->m_unoI
, member_td
.get(),
556 ::getCppuVoidType().getTypeLibType(),
557 1, ¶m
, args
, NULL
, &pExc
);
558 return constructReturnMessage(NULL
, NULL
, NULL
,
563 return constructReturnMessage(NULL
, NULL
, NULL
,
571 // ToDo check if the message of the exception is not crippled
572 // the thing that should not be... no method info found!
573 OUStringBuffer
buf( 64 );
574 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
575 "[cli_uno bridge]calling undeclared function on "
577 buf
.append( *reinterpret_cast< OUString
const * >(
578 & ((typelib_TypeDescription
*)info
->m_typeDesc
)->pTypeName
));
579 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
580 buf
.append( usMethodName
);
581 throw BridgeRuntimeError( buf
.makeStringAndClear() );
583 catch (BridgeRuntimeError
& err
)
585 srrm::IMethodCallMessage
* mcm
=
586 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
587 return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
588 mapUnoString(err
.m_message
.pData
), NULL
), mcm
);
590 catch (System::Exception
* e
)
592 st::StringBuilder
* sb
= new st::StringBuilder(512);
593 sb
->Append(new System::String(
594 S
"An unexpected CLI exception occurred in "
595 S
"UnoInterfaceProxy::Invoke. Original"
597 sb
->Append(e
->get_Message());
598 sb
->Append((__wchar_t
) '\n');
599 sb
->Append(e
->get_StackTrace());
600 srrm::IMethodCallMessage
* mcm
=
601 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
602 return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
603 sb
->ToString(), NULL
), mcm
);
607 System::String
* msg
= new System::String(
608 S
"An unexpected native C++ exception occurred in "
609 S
"UnoInterfaceProxy::Invoke.");
610 srrm::IMethodCallMessage
* mcm
=
611 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
612 return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
617 /** If the argument args is NULL then this function is called for an attribute
618 method (either setXXX or getXXX).
619 For attributes the argument mtd is also NULL.
621 srrm::IMessage
* UnoInterfaceProxy::constructReturnMessage(
622 System::Object
* cliReturn
,
623 System::Object
* args
[],
624 typelib_InterfaceMethodTypeDescription
* mtd
,
625 srrm::IMessage
* msg
, System::Object
* exc
)
627 srrm::IMessage
* retVal
= NULL
;
628 srrm::IMethodCallMessage
* mcm
= static_cast<srrm::IMethodCallMessage
*>(msg
);
631 retVal
= new srrm::ReturnMessage(
632 dynamic_cast<System::Exception
*>(exc
), mcm
);
636 sc::IDictionary
* props
= msg
->get_Properties();
637 srrm::LogicalCallContext
* context
=
638 static_cast<srrm::LogicalCallContext
*>(
639 props
->get_Item(m_CallContextString
));
643 //build the array of out parameters, allocate max length
644 System::Object
* arOut
[]= new System::Object
*[mtd
->nParams
];
646 for (int i
= 0; i
< mtd
->nParams
; i
++)
648 if (mtd
->pParams
[i
].bOut
)
654 retVal
= new srrm::ReturnMessage(cliReturn
, arOut
, nOut
,
659 // Attribute (getXXX)
660 retVal
= new srrm::ReturnMessage(cliReturn
, NULL
, 0,
667 //################################################################################
668 CliProxy::CliProxy(Bridge
const* bridge
, System::Object
* cliI
,
669 typelib_TypeDescription
const* td
,
670 const rtl::OUString
& usOid
):
674 m_unoType(const_cast<typelib_TypeDescription
*>(td
)),
676 m_oid(mapUnoString(usOid
.pData
)),
677 m_nInheritedInterfaces(0)
680 uno_Interface::acquire
= cli_proxy_acquire
;
681 uno_Interface::release
= cli_proxy_release
;
682 uno_Interface::pDispatcher
= cli_proxy_dispatch
;
684 m_unoType
.makeComplete();
685 m_type
= mapUnoType(m_unoType
.get());
688 #if OSL_DEBUG_LEVEL >= 2
689 sd::Trace::WriteLine(System::String::Format(
690 new System::String(S
"cli uno bridge: Creating proxy for cli object, "
691 S
"id:\n\t{0}\n\t{1}"), m_oid
, m_type
));
696 void CliProxy::makeMethodInfos()
698 #if OSL_DEBUG_LEVEL >= 2
699 System::Object
* cliI
;
705 if (m_type
->get_IsInterface() == false)
707 sr::MethodInfo
* arThisMethods
[] = m_type
->GetMethods();
708 //get the inherited interfaces
709 System::Type
* arInheritedIfaces
[] = m_type
->GetInterfaces();
710 m_nInheritedInterfaces
= arInheritedIfaces
->get_Length();
711 //array containing the number of methods for the interface and its
712 //inherited interfaces
713 m_arInterfaceMethodCount
= new int __gc
[m_nInheritedInterfaces
+ 1];
714 //determine the number of all interface methods, including the inherited
716 int numMethods
= arThisMethods
->get_Length();
717 for (int i
= 0; i
< m_nInheritedInterfaces
; i
++)
719 numMethods
+= arInheritedIfaces
[i
]->GetMethods()->get_Length();
721 //array containing MethodInfos of the cli object
722 m_arMethodInfos
= new sr::MethodInfo
*[numMethods
];
723 //array containing MethodInfos of the interface
724 m_arInterfaceMethodInfos
= new sr::MethodInfo
*[numMethods
];
725 //array containing the mapping of Uno interface pos to pos in
727 m_arUnoPosToCliPos
= new System::Int32
[numMethods
];
728 // initialize with -1
729 for (int i
= 0; i
< numMethods
; i
++)
730 m_arUnoPosToCliPos
[i
] = -1;
732 #if OSL_DEBUG_LEVEL >= 2
733 sr::MethodInfo
* arMethodInfosDbg
[];
734 sr::MethodInfo
* arInterfaceMethodInfosDbg
[];
735 System::Int32 arInterfaceMethodCountDbg
[];
736 arMethodInfosDbg
= m_arMethodInfos
;
737 arInterfaceMethodInfosDbg
= m_arInterfaceMethodInfos
;
738 arInterfaceMethodCountDbg
= m_arInterfaceMethodCount
;
742 //fill m_arMethodInfos with the mappings
743 // !!! InterfaceMapping.TargetMethods should be MethodInfo*[] according
745 // but it is Type*[] instead. Bug in the framework?
746 System::Type
* objType
= m_cliI
->GetType();
750 // now get the methods from the inherited interface
751 //arInheritedIfaces[0] is the direct base interface
752 //arInheritedIfaces[n] is the furthest inherited interface
753 //Start with the base interface
754 int nArLength
= arInheritedIfaces
->get_Length();
755 for (;nArLength
> 0; nArLength
--)
757 sr::InterfaceMapping mapInherited
= objType
->GetInterfaceMap(
758 arInheritedIfaces
[nArLength
- 1]);
759 int numMethods
= mapInherited
.TargetMethods
->get_Length();
760 m_arInterfaceMethodCount
[nArLength
- 1] = numMethods
;
761 for (int i
= 0; i
< numMethods
; i
++, index
++)
763 m_arMethodInfos
[index
] = __try_cast
<sr::MethodInfo
*>(
764 mapInherited
.TargetMethods
[i
]);
766 m_arInterfaceMethodInfos
[index
] = __try_cast
<sr::MethodInfo
*>(
767 mapInherited
.InterfaceMethods
[i
]);
770 //At last come the methods of the furthest derived interface
771 sr::InterfaceMapping map
= objType
->GetInterfaceMap(m_type
);
772 nArLength
= map
.TargetMethods
->get_Length();
773 m_arInterfaceMethodCount
[m_nInheritedInterfaces
] = nArLength
;
774 for (int i
= 0; i
< nArLength
; i
++,index
++)
776 m_arMethodInfos
[index
]= __try_cast
<sr::MethodInfo
*>(
777 map
.TargetMethods
[i
]);
778 m_arInterfaceMethodInfos
[index
]= __try_cast
<sr::MethodInfo
*>(
779 map
.InterfaceMethods
[i
]);
782 catch (System::InvalidCastException
* )
784 OUStringBuffer
buf( 128 );
785 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
786 "[cli_uno bridge] preparing proxy for "
787 "cli interface: ") );
788 buf
.append(mapCliString(m_type
->ToString() ));
789 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(" \nfailed!"));
790 throw BridgeRuntimeError( buf
.makeStringAndClear() );
794 sr::MethodInfo
* CliProxy::getMethodInfo(int nUnoFunctionPos
,
795 const rtl::OUString
& usMethodName
, MethodKind methodKind
)
797 sr::MethodInfo
* ret
= NULL
;
798 #if OSL_DEBUG_LEVEL >= 2
799 System::String
* sMethodNameDbg
;
800 sr::MethodInfo
* arMethodInfosDbg
[];
801 sr::MethodInfo
* arInterfaceMethodInfosDbg
[];
802 System::Int32 arInterfaceMethodCountDbg
[];
803 System::Int32 arUnoPosToCliPosDbg
[];
804 sMethodNameDbg
= mapUnoString(usMethodName
.pData
);
805 arMethodInfosDbg
= m_arMethodInfos
;
806 arInterfaceMethodInfosDbg
= m_arInterfaceMethodInfos
;
807 arInterfaceMethodCountDbg
= m_arInterfaceMethodCount
;
808 arUnoPosToCliPosDbg
= m_arUnoPosToCliPos
;
810 //deduct 3 for XInterface methods
811 nUnoFunctionPos
-= 3;
812 System::Threading::Monitor::Enter(m_arUnoPosToCliPos
);
815 int cliPos
= m_arUnoPosToCliPos
[nUnoFunctionPos
];
817 return m_arMethodInfos
[cliPos
];
819 //create the method function name
820 System::String
* sMethodName
= mapUnoString(usMethodName
.pData
);
826 sMethodName
= System::String::Concat(
827 const_cast<System::String
*>(Constants::sAttributeSet
),
831 sMethodName
= System::String::Concat(
832 const_cast<System::String
*>(Constants::sAttributeGet
),
838 //Find the cli interface method that corresponds to the Uno method
839 // System::String* sMethodName= mapUnoString(usMethodName.pData);
840 int indexCliMethod
= -1;
841 //If the cli interfaces and their methods are in the same order
842 //as they were declared (inheritance chain and within the interface)
843 //then nUnoFunctionPos should lead to the correct method. However,
844 //the documentation does not say that this ordering is given.
845 if (sMethodName
->Equals(m_arInterfaceMethodInfos
[nUnoFunctionPos
]->Name
))
846 indexCliMethod
= nUnoFunctionPos
;
849 int cMethods
= m_arInterfaceMethodInfos
->get_Length();
850 for (int i
= 0; i
< cMethods
; i
++)
852 System::String
* cliMethod
= m_arInterfaceMethodInfos
[i
]->Name
;
853 if (cliMethod
->Equals(sMethodName
))
860 if (indexCliMethod
== -1)
862 OUStringBuffer
buf(256);
863 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
864 "[cli_uno bridge] CliProxy::getMethodInfo():"
865 "cli object does not implement interface method: "));
866 buf
.append(usMethodName
);
867 throw BridgeRuntimeError(buf
.makeStringAndClear());
870 m_arUnoPosToCliPos
[nUnoFunctionPos
] = indexCliMethod
;
871 ret
= m_arMethodInfos
[indexCliMethod
];
875 System::Threading::Monitor::Exit(m_arUnoPosToCliPos
);
881 CliProxy::~CliProxy()
883 #if OSL_DEBUG_LEVEL >= 2
884 sd::Trace::WriteLine(System::String::Format(
886 S
"cli uno bridge: Destroying proxy for cli object, "
887 S
"id:\n\t{0}\n\t{1}\n"),
890 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
, mapUnoType(m_unoType
.get()));
894 uno_Interface
* CliProxy::create(Bridge
const * bridge
,
895 System::Object
* cliI
,
896 typelib_TypeDescription
const* pTD
,
897 const rtl::OUString
& ousOid
)
899 uno_Interface
* proxy
= static_cast<uno_Interface
*>(
900 new CliProxy(bridge
, cliI
, pTD
, ousOid
));
902 //register proxy with target environment (uno)
903 (*bridge
->m_uno_env
->registerProxyInterface
)(
905 reinterpret_cast<void**>(&proxy
),
907 ousOid
.pData
, (typelib_InterfaceTypeDescription
*) pTD
);
908 //register original interface
909 CliEnvHolder::g_cli_env
->registerInterface(cliI
, mapUnoString(ousOid
.pData
),
917 void SAL_CALL
CliProxy::uno_DispatchMethod(
918 struct _uno_Interface
*,
919 const struct _typelib_TypeDescription
*,
925 inline void CliProxy::acquire() const
927 if (1 == osl_incrementInterlockedCount( &m_ref
))
929 // rebirth of proxy zombie
930 void * that
= const_cast< CliProxy
* >( this );
931 // register at uno env
932 (*m_bridge
->m_uno_env
->registerProxyInterface
)(
933 m_bridge
->m_uno_env
, &that
,
934 cli_proxy_free
, m_usOid
.pData
,
935 (typelib_InterfaceTypeDescription
*)m_unoType
.get() );
936 #if OSL_DEBUG_LEVEL >= 2
937 OSL_ASSERT( this == (void const * const)that
);
941 //---------------------------------------------------------------------------
942 inline void CliProxy::release() const
944 if (0 == osl_decrementInterlockedCount( &m_ref
))
946 // revoke from uno env on last release,
947 // The proxy can be resurrected if acquire is called before the uno
948 // environment calls cli_proxy_free. cli_proxy_free will
949 //delete the proxy. The environment does not acquire a registered
951 (*m_bridge
->m_uno_env
->revokeInterface
)(
952 m_bridge
->m_uno_env
, const_cast< CliProxy
* >( this ) );
961 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
*, void * proxy
)
964 cli_uno::CliProxy
* cliProxy
= reinterpret_cast<
965 cli_uno::CliProxy
* >( proxy
);
971 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
974 CliProxy
const * cliProxy
= static_cast< CliProxy
const * >( pUnoI
);
977 //-----------------------------------------------------------------------------
979 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
982 CliProxy
* cliProxy
= static_cast< CliProxy
* >( pUnoI
);
986 //------------------------------------------------------------------------------
989 void SAL_CALL
cli_proxy_dispatch(
990 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
991 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
994 CliProxy
* proxy
= static_cast< CliProxy
* >( pUnoI
);
997 Bridge
const* bridge
= proxy
->m_bridge
;
999 switch (member_td
->eTypeClass
)
1001 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
1004 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
1005 member_td
)->nPosition
;
1006 typelib_InterfaceTypeDescription
* iface_td
=
1007 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
1009 member_pos
< iface_td
->nAllMembers
,
1010 "### member pos out of range!" );
1011 sal_Int32 function_pos
=
1012 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
1014 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
1015 "### illegal function index!" );
1017 if (uno_ret
) // is getter method
1019 OUString
const& usAttrName
= *(rtl_uString
**)&
1020 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1022 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
,
1023 usAttrName
, CliProxy::MK_GET
);
1027 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1028 ->pAttributeTypeRef
,
1030 uno_ret
, 0, uno_exc
);
1032 else // is setter method
1034 OUString
const& usAttrName
= *(rtl_uString
**) &
1035 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1037 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
+ 1,
1038 usAttrName
, CliProxy::MK_SET
);
1039 typelib_MethodParameter param
;
1041 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1042 ->pAttributeTypeRef
;
1043 param
.bIn
= sal_True
;
1044 param
.bOut
= sal_False
;
1048 // set follows get method
1050 0 /* indicates void return */, ¶m
, 1,
1051 0, uno_args
, uno_exc
);
1055 case typelib_TypeClass_INTERFACE_METHOD
:
1057 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
1058 member_td
)->nPosition
;
1059 typelib_InterfaceTypeDescription
* iface_td
=
1060 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
1062 member_pos
< iface_td
->nAllMembers
,
1063 "### member pos out of range!" );
1064 sal_Int32 function_pos
=
1065 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
1067 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
1068 "### illegal function index!" );
1070 switch (function_pos
)
1072 case 0: // queryInterface()
1074 TypeDescr
demanded_td(
1075 *reinterpret_cast<typelib_TypeDescriptionReference
**>(
1077 if (typelib_TypeClass_INTERFACE
1078 != demanded_td
.get()->eTypeClass
)
1080 throw BridgeRuntimeError(
1081 OUSTR("queryInterface() call demands an INTERFACE type!"));
1084 uno_Interface
* pInterface
= 0;
1085 (*bridge
->m_uno_env
->getRegisteredInterface
)(
1087 (void **)&pInterface
, proxy
->m_usOid
.pData
,
1088 (typelib_InterfaceTypeDescription
*)demanded_td
.get() );
1090 if (0 == pInterface
)
1092 System::Type
* mgdDemandedType
=
1093 mapUnoType(demanded_td
.get());
1094 if (mgdDemandedType
->IsInstanceOfType( proxy
->m_cliI
))
1096 #if OSL_DEBUG_LEVEL > 0
1099 CliEnvHolder::g_cli_env
->getObjectIdentifier(
1101 OSL_ENSURE(usOid
.equals( proxy
->m_usOid
),
1102 "### different oids!");
1104 uno_Interface
* pUnoI
= bridge
->map_cli2uno(
1105 proxy
->m_cliI
, demanded_td
.get() );
1107 (uno_Any
*)uno_ret
, &pUnoI
, demanded_td
.get(), 0 );
1108 (*pUnoI
->release
)( pUnoI
);
1110 else // object does not support demanded interface
1112 uno_any_construct( (uno_Any
*)uno_ret
, 0, 0, 0 );
1114 // no excetpion occured
1120 reinterpret_cast< uno_Any
* >( uno_ret
),
1121 &pInterface
, demanded_td
.get(), 0 );
1122 (*pInterface
->release
)( pInterface
);
1127 case 1: // acquire this proxy
1128 cli_proxy_acquire(proxy
);
1131 case 2: // release this proxy
1132 cli_proxy_release(proxy
);
1135 default: // arbitrary method call
1137 typelib_InterfaceMethodTypeDescription
* method_td
=
1138 (typelib_InterfaceMethodTypeDescription
*)member_td
;
1139 OUString
const& usMethodName
= *(rtl_uString
**) &
1140 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1143 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
,
1144 usMethodName
, CliProxy::MK_METHOD
);
1148 method_td
->pReturnTypeRef
, method_td
->pParams
,
1150 uno_ret
, uno_args
, uno_exc
);
1158 throw BridgeRuntimeError(
1159 OUSTR("illegal member type description!") );
1163 catch (BridgeRuntimeError
& err
)
1165 // binary identical struct
1166 ::com::sun::star::uno::RuntimeException
exc(
1167 OUSTR("[cli_uno bridge error] ") + err
.m_message
,
1168 ::com::sun::star::uno::Reference
<
1169 ::com::sun::star::uno::XInterface
>() );
1170 ::com::sun::star::uno::Type
const & exc_type
= ::getCppuType( & exc
);
1171 uno_type_any_construct( *uno_exc
, &exc
, exc_type
.getTypeLibType(), 0);
1172 #if OSL_DEBUG_LEVEL >= 1
1173 OString
cstr_msg(OUStringToOString(exc
.Message
,
1174 RTL_TEXTENCODING_ASCII_US
) );
1175 OSL_ENSURE(0, cstr_msg
.getStr());