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_cli_ure.hxx"
30 #include "typelib/typedescription.h"
31 #include "rtl/ustrbuf.hxx"
32 #include "com/sun/star/uno/RuntimeException.hpp"
33 #include "osl/mutex.hxx"
34 #include "cli_proxy.h"
36 #include "cli_bridge.h"
40 #using <cli_uretypes.dll>
42 namespace sr
= System::Reflection
;
43 namespace st
= System::Text
;
44 namespace sre
= System::Reflection::Emit
;
45 namespace sc
= System::Collections
;
46 namespace srrm
= System::Runtime::Remoting::Messaging
;
47 namespace srr
= System::Runtime::Remoting
;
48 namespace srrp
= System::Runtime::Remoting::Proxies
;
49 namespace sri
= System::Runtime::InteropServices
;
50 namespace sd
= System::Diagnostics
;
51 namespace css
= com::sun::star
;
52 namespace ucss
= unoidl::com::sun::star
;
54 using namespace cli_uno
;
58 //------------------------------------------------------------------------------
59 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
* env
, void * proxy
)
61 //------------------------------------------------------------------------------
62 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
64 //------------------------------------------------------------------------------
65 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
67 //------------------------------------------------------------------------------
68 void SAL_CALL
cli_proxy_dispatch(
69 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
70 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
79 UnoInterfaceInfo::UnoInterfaceInfo(Bridge
const * bridge
, uno_Interface
* unoI
,
80 typelib_InterfaceTypeDescription
* td
):
87 m_type
= mapUnoType(reinterpret_cast<typelib_TypeDescription
*>(td
));
88 m_unoI
->acquire(m_unoI
);
89 typelib_typedescription_acquire(&m_typeDesc
->aBase
);
90 if ( ! m_typeDesc
->aBase
.bComplete
)
92 typelib_TypeDescription
* _pt
= &m_typeDesc
->aBase
;
93 sal_Bool bComplete
= ::typelib_typedescription_complete( & _pt
);
96 OUStringBuffer
buf( 128 );
97 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
98 "cannot make type complete: ") );
99 buf
.append( *reinterpret_cast< OUString
const * >(
100 & m_typeDesc
->aBase
.pTypeName
));
101 throw BridgeRuntimeError(buf
.makeStringAndClear());
105 UnoInterfaceInfo::~UnoInterfaceInfo()
107 //accessing unmanaged objects is ok.
108 m_bridge
->m_uno_env
->revokeInterface(
109 m_bridge
->m_uno_env
, m_unoI
);
112 m_unoI
->release(m_unoI
);
113 typelib_typedescription_release(
114 reinterpret_cast<typelib_TypeDescription
*>(m_typeDesc
));
117 UnoInterfaceProxy::UnoInterfaceProxy(
119 uno_Interface
* pUnoI
,
120 typelib_InterfaceTypeDescription
* pTD
,
121 const OUString
& oid
)
122 :RealProxy(__typeof(MarshalByRefObject
)),
124 m_oid(mapUnoString(oid
.pData
)),
125 m_sTypeName(m_system_Object_String
)
128 // create the list that holds all UnoInterfaceInfos
129 m_listIfaces
= new ArrayList(10);
131 m_listAdditionalProxies
= new ArrayList();
132 m_nlistAdditionalProxies
= 0;
133 //put the information of the first UNO interface into the arraylist
134 #if OSL_DEBUG_LEVEL >= 2
138 addUnoInterface(pUnoI
, pTD
);
142 UnoInterfaceProxy::~UnoInterfaceProxy()
144 #if OSL_DEBUG_LEVEL >= 2
145 sd::Trace::WriteLine(System::String::Format(
146 new System::String(S
"cli uno bridge: Destroying proxy "
147 S
"for UNO object, OID: \n\t{0} \n\twith uno interfaces: "),
150 sd::Trace::WriteLine( mapUnoString(_sInterfaces
));
151 rtl_uString_release(_sInterfaces
);
153 //m_bridge is unmanaged, therefore we can access it in this finalizer
154 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
);
159 System::Object
* UnoInterfaceProxy::create(
161 uno_Interface
* pUnoI
,
162 typelib_InterfaceTypeDescription
* pTD
,
165 UnoInterfaceProxy
* proxyHandler
=
166 new UnoInterfaceProxy(bridge
, pUnoI
, pTD
, oid
);
167 System::Object
* proxy
= proxyHandler
->GetTransparentProxy();
168 CliEnvHolder::g_cli_env
->registerInterface(proxy
, mapUnoString(oid
.pData
));
173 void UnoInterfaceProxy::addUnoInterface(uno_Interface
* pUnoI
,
174 typelib_InterfaceTypeDescription
* pTd
)
176 sc::IEnumerator
* enumInfos
= m_listIfaces
->GetEnumerator();
177 System::Threading::Monitor::Enter(this);
180 while (enumInfos
->MoveNext())
182 UnoInterfaceInfo
* info
= static_cast<UnoInterfaceInfo
*>(
184 #if OSL_DEBUG_LEVEL > 1
188 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
) );
190 reinterpret_cast<typelib_TypeDescription
*>(pTd
) );
192 if (typelib_typedescription_equals(
193 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
),
194 reinterpret_cast<typelib_TypeDescription
*>(pTd
)))
199 OUString
oid(mapCliString(m_oid
));
200 (*m_bridge
->m_uno_env
->registerInterface
)(
201 m_bridge
->m_uno_env
, reinterpret_cast< void ** >( &pUnoI
),
203 //This proxy does not contain the uno_Interface. Add it.
204 m_listIfaces
->Add(new UnoInterfaceInfo(m_bridge
, pUnoI
, pTd
));
205 m_numUnoIfaces
= m_listIfaces
->Count
;
206 #if OSL_DEBUG_LEVEL >= 2
207 System::String
* sInterfaceName
= static_cast<UnoInterfaceInfo
*>(
208 m_listIfaces
->get_Item(m_numUnoIfaces
- 1))->m_type
->FullName
;
209 sd::Trace::WriteLine(System::String::Format(
210 new System::String(S
"cli uno bridge: Creating proxy for uno object, "
211 S
"id:\n\t{0}\n\t{1}"), m_oid
, sInterfaceName
));
212 // add to the string that contains all interface names
214 OUStringBuffer
buf(512);
215 buf
.appendAscii("\t");
216 buf
.append( OUString::valueOf((sal_Int32
)_numInterfaces
));
217 buf
.appendAscii(". ");
218 buf
.append(mapCliString(sInterfaceName
));
219 buf
.appendAscii("\n");
220 OUString _sNewInterface
= buf
.makeStringAndClear();
221 rtl_uString
* __pin
* pp_sInterfaces
= & _sInterfaces
;
222 rtl_uString_newConcat( pp_sInterfaces
, * pp_sInterfaces
,
223 _sNewInterface
.pData
);
227 System::Threading::Monitor::Exit(this);
233 bool UnoInterfaceProxy::CanCastTo(System::Type
* fromType
,
236 if (fromType
== __typeof(System::Object
)) // trivial case
239 System::Threading::Monitor::Enter(this);
242 if (0 != findInfo( fromType
)) // proxy supports demanded interface
245 //query an uno interface for the required type
247 // we use the first interface in the list (m_listIfaces) to make
248 // the queryInterface call
249 UnoInterfaceInfo
* info
=
250 static_cast<UnoInterfaceInfo
*>(m_listIfaces
->get_Item(0));
251 css::uno::TypeDescription
membertd(
252 reinterpret_cast<typelib_InterfaceTypeDescription
*>(
253 info
->m_typeDesc
)->ppAllMembers
[0]);
254 System::Object
*args
[] = new System::Object
*[1];
257 __box
uno::Any
* pAny
;
258 System::Object
* pException
= NULL
;
260 pAny
= static_cast<__box
uno::Any
*>(
264 ((typelib_InterfaceMethodTypeDescription
*)
265 membertd
.get())->pReturnTypeRef
,
267 ((typelib_InterfaceMethodTypeDescription
*)
268 membertd
.get())->pParams
,
269 args
, NULL
, &pException
) );
271 // handle regular exception from target
275 mapCliString( pException
->ToString()),
276 RTL_TEXTENCODING_UTF8
).getStr() );
278 if (pAny
->Type
!= __typeof (void)) // has value?
280 if (0 != findInfo( fromType
))
282 // proxy now supports demanded interface
286 // via aggregation: it is possible that queryInterface() returns
287 // and interface with a different oid.
288 // That way, this type is supported for the CLI
289 // interpreter (CanCastTo() returns true)
290 ::System::Object
* obj
= pAny
->Value
;
291 OSL_ASSERT( srr::RemotingServices::IsTransparentProxy( obj
) );
292 if (srr::RemotingServices::IsTransparentProxy( obj
))
294 UnoInterfaceProxy
* proxy
=
295 static_cast< UnoInterfaceProxy
* >(
296 srr::RemotingServices::GetRealProxy( obj
) );
297 OSL_ASSERT( 0 != proxy
->findInfo( fromType
) );
298 m_listAdditionalProxies
->Add( proxy
);
299 m_nlistAdditionalProxies
= m_listAdditionalProxies
->Count
;
300 OSL_ASSERT( 0 != findInfo( fromType
) );
305 catch (BridgeRuntimeError
& e
)
307 (void) e
; // avoid warning
309 0, OUStringToOString(
310 e
.m_message
, RTL_TEXTENCODING_UTF8
).getStr() );
312 catch (System::Exception
* e
)
314 System::String
* msg
= new System::String(
315 S
"An unexpected CLI exception occurred in "
316 S
"UnoInterfaceProxy::CanCastTo(). Original"
318 msg
= System::String::Concat(msg
, e
->get_Message());
320 0, OUStringToOString(
321 mapCliString(msg
), RTL_TEXTENCODING_UTF8
).getStr() );
326 0, "An unexpected native C++ exception occurred in "
327 "UnoInterfaceProxy::CanCastTo()" );
331 System::Threading::Monitor::Exit(this);
336 srrm::IMessage
* UnoInterfaceProxy::invokeObject(
337 sc::IDictionary
* props
,
338 srrm::LogicalCallContext
* context
,
339 srrm::IMethodCallMessage
* mcm
)
341 System::Object
* retMethod
= 0;
342 System::String
* sMethod
= static_cast<System::String
*>
343 (props
->get_Item(m_methodNameString
));
344 System::Object
* args
[] = static_cast<System::Object
*[]>(
345 props
->get_Item(m_ArgsString
));
346 if (m_Equals_String
->Equals(sMethod
))
349 OSL_ASSERT(args
->get_Length() == 1);
350 srrp::RealProxy
* rProxy
= srr::RemotingServices::GetRealProxy(args
[0]);
354 UnoInterfaceProxy
* unoProxy
=
355 dynamic_cast<UnoInterfaceProxy
*>(rProxy
);
358 bool b
= m_oid
->Equals(unoProxy
->getOid());
359 retMethod
= __box(b
);
365 //no proxy or not our proxy, therefore Equals must be false
366 retMethod
= __box(false);
369 else if (m_GetHashCode_String
->Equals(sMethod
))
371 // Object.GetHashCode
372 int nHash
= m_oid
->GetHashCode();
373 retMethod
= __box(nHash
);
375 else if (m_GetType_String
->Equals(sMethod
))
378 retMethod
= __typeof(System::Object
);
380 else if (m_ToString_String
->Equals(sMethod
))
383 st::StringBuilder
* sb
= new st::StringBuilder(256);
384 // sb->AppendFormat(S"Uno object proxy. Implemented interface: {0}"
385 // S". OID: {1}", m_type->ToString(), m_oid);
386 sb
->AppendFormat(S
"Uno object proxy. OID: {0}", m_oid
);
387 retMethod
= sb
->ToString();
391 //Either Object has new functions or a protected method was called
392 //which should not be possible
395 srrm::IMessage
* retVal
= new srrm::ReturnMessage(
396 retMethod
, new System::Object
*[0], 0, context
, mcm
);
400 UnoInterfaceInfo
* UnoInterfaceProxy::findInfo( ::System::Type
* type
)
402 for (int i
= 0; i
< m_numUnoIfaces
; i
++)
404 UnoInterfaceInfo
* tmpInfo
= static_cast<UnoInterfaceInfo
*>(
405 m_listIfaces
->get_Item(i
));
406 if (type
->IsAssignableFrom(tmpInfo
->m_type
))
409 for ( int i
= 0; i
< m_nlistAdditionalProxies
; ++i
)
411 UnoInterfaceProxy
* proxy
=
412 static_cast< UnoInterfaceProxy
* >(
413 m_listAdditionalProxies
->get_Item( i
) );
414 UnoInterfaceInfo
* info
= proxy
->findInfo( type
);
421 srrm::IMessage
* UnoInterfaceProxy::Invoke(srrm::IMessage
* callmsg
)
425 sc::IDictionary
* props
= callmsg
->Properties
;
426 srrm::LogicalCallContext
* context
=
427 static_cast<srrm::LogicalCallContext
*>(
428 props
->get_Item(m_CallContextString
));
429 srrm::IMethodCallMessage
* mcm
=
430 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
432 //Find out which UNO interface is being called
433 System::String
* sTypeName
= static_cast<System::String
*>(
434 props
->get_Item(m_typeNameString
));
435 sTypeName
= sTypeName
->Substring(0, sTypeName
->IndexOf(','));
437 // Special Handling for System.Object methods
438 if(sTypeName
->IndexOf(m_system_Object_String
) != -1)
440 return invokeObject(props
, context
, mcm
);
443 System::Type
* typeBeingCalled
= loadCliType(sTypeName
);
444 UnoInterfaceInfo
* info
= findInfo( typeBeingCalled
);
445 OSL_ASSERT( 0 != info
);
447 // ToDo do without string conversion, a OUString is not needed here
448 // get the type description of the call
449 OUString
usMethodName(mapCliString(static_cast<System::String
*>(
450 props
->get_Item(m_methodNameString
))));
451 typelib_TypeDescriptionReference
** ppAllMembers
=
452 info
->m_typeDesc
->ppAllMembers
;
453 sal_Int32 numberMembers
= info
->m_typeDesc
->nAllMembers
;
454 for ( sal_Int32 nPos
= numberMembers
; nPos
--; )
456 typelib_TypeDescriptionReference
* member_type
= ppAllMembers
[nPos
];
458 // check usMethodName against fully qualified usTypeName
459 // of member_type; usTypeName is of the form
460 // <name> "::" <usMethodName> *(":@" <idx> "," <idx> ":" <name>)
461 OUString
const & usTypeName
=
462 OUString::unacquired( & member_type
->pTypeName
);
464 #if OSL_DEBUG_LEVEL >= 2
465 System::String
* pTypeName
;
466 pTypeName
= mapUnoString(usTypeName
.pData
);
468 sal_Int32 offset
= usTypeName
.indexOf( ':' ) + 2;
470 offset
>= 2 && offset
< usTypeName
.getLength()
471 && usTypeName
[offset
- 1] == ':' );
472 sal_Int32 remainder
= usTypeName
.getLength() - offset
;
474 if (typelib_TypeClass_INTERFACE_METHOD
== member_type
->eTypeClass
)
476 if ((usMethodName
.getLength() == remainder
477 || (usMethodName
.getLength() < remainder
478 && usTypeName
[offset
+ usMethodName
.getLength()] == ':'))
479 && usTypeName
.match(usMethodName
, offset
))
481 TypeDescr
member_td( member_type
);
482 typelib_InterfaceMethodTypeDescription
* method_td
=
483 (typelib_InterfaceMethodTypeDescription
*)
486 System::Object
* args
[] = static_cast<System::Object
*[]>(
487 props
->get_Item(m_ArgsString
));
488 System::Type
* argTypes
[] = static_cast<System::Type
*[]>(
489 props
->get_Item(m_methodSignatureString
));
490 System::Object
* pExc
= NULL
;
491 System::Object
* cli_ret
= m_bridge
->call_uno(
492 info
->m_unoI
, member_td
.get(),
493 method_td
->pReturnTypeRef
, method_td
->nParams
,
494 method_td
->pParams
, args
, argTypes
, &pExc
);
495 return constructReturnMessage(cli_ret
, args
, method_td
,
502 OSL_ASSERT( typelib_TypeClass_INTERFACE_ATTRIBUTE
==
503 member_type
->eTypeClass
);
504 if (usMethodName
.getLength() > 4
505 && (usMethodName
.getLength() - 4 == remainder
506 || (usMethodName
.getLength() - 4 < remainder
508 offset
+ (usMethodName
.getLength() - 4)] == ':'))
509 && usMethodName
[1] == 'e' && usMethodName
[2] == 't'
510 && rtl_ustr_compare_WithLength(
511 usTypeName
.getStr() + offset
,
512 usMethodName
.getLength() - 4,
513 usMethodName
.getStr() + 4,
514 usMethodName
.getLength() - 4) == 0)
516 if ('g' == usMethodName
[0])
518 TypeDescr
member_td( member_type
);
519 typelib_InterfaceAttributeTypeDescription
* attribute_td
=
520 (typelib_InterfaceAttributeTypeDescription
*)
523 System::Object
* pExc
= NULL
;
524 System::Object
* cli_ret
= m_bridge
->call_uno(
525 info
->m_unoI
, member_td
.get(),
526 attribute_td
->pAttributeTypeRef
,
529 return constructReturnMessage(cli_ret
, NULL
, NULL
,
532 else if ('s' == usMethodName
[0])
534 TypeDescr
member_td( member_type
);
535 typelib_InterfaceAttributeTypeDescription
* attribute_td
=
536 (typelib_InterfaceAttributeTypeDescription
*)
538 if (! attribute_td
->bReadOnly
)
540 typelib_MethodParameter param
;
541 param
.pTypeRef
= attribute_td
->pAttributeTypeRef
;
542 param
.bIn
= sal_True
;
543 param
.bOut
= sal_False
;
545 System::Object
* args
[] =
546 static_cast<System::Object
*[]>(
547 props
->get_Item(m_ArgsString
));
548 System::Object
* pExc
= NULL
;
550 info
->m_unoI
, member_td
.get(),
551 ::getCppuVoidType().getTypeLibType(),
552 1, ¶m
, args
, NULL
, &pExc
);
553 return constructReturnMessage(NULL
, NULL
, NULL
,
558 return constructReturnMessage(NULL
, NULL
, NULL
,
566 // ToDo check if the message of the exception is not crippled
567 // the thing that should not be... no method info found!
568 OUStringBuffer
buf( 64 );
569 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
570 "[cli_uno bridge]calling undeclared function on "
572 buf
.append( *reinterpret_cast< OUString
const * >(
573 & ((typelib_TypeDescription
*)info
->m_typeDesc
)->pTypeName
));
574 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
575 buf
.append( usMethodName
);
576 throw BridgeRuntimeError( buf
.makeStringAndClear() );
578 catch (BridgeRuntimeError
& err
)
580 srrm::IMethodCallMessage
* mcm
=
581 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
582 return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
583 mapUnoString(err
.m_message
.pData
), NULL
), mcm
);
585 catch (System::Exception
* e
)
587 st::StringBuilder
* sb
= new st::StringBuilder(512);
588 sb
->Append(new System::String(
589 S
"An unexpected CLI exception occurred in "
590 S
"UnoInterfaceProxy::Invoke. Original"
592 sb
->Append(e
->get_Message());
593 sb
->Append((__wchar_t
) '\n');
594 sb
->Append(e
->get_StackTrace());
595 srrm::IMethodCallMessage
* mcm
=
596 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
597 return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
598 sb
->ToString(), NULL
), mcm
);
602 System::String
* msg
= new System::String(
603 S
"An unexpected native C++ exception occurred in "
604 S
"UnoInterfaceProxy::Invoke.");
605 srrm::IMethodCallMessage
* mcm
=
606 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
607 return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
612 /** If the argument args is NULL then this function is called for an attribute
613 method (either setXXX or getXXX).
614 For attributes the argument mtd is also NULL.
616 srrm::IMessage
* UnoInterfaceProxy::constructReturnMessage(
617 System::Object
* cliReturn
,
618 System::Object
* args
[],
619 typelib_InterfaceMethodTypeDescription
* mtd
,
620 srrm::IMessage
* msg
, System::Object
* exc
)
622 srrm::IMessage
* retVal
= NULL
;
623 srrm::IMethodCallMessage
* mcm
= static_cast<srrm::IMethodCallMessage
*>(msg
);
626 retVal
= new srrm::ReturnMessage(
627 dynamic_cast<System::Exception
*>(exc
), mcm
);
631 sc::IDictionary
* props
= msg
->get_Properties();
632 srrm::LogicalCallContext
* context
=
633 static_cast<srrm::LogicalCallContext
*>(
634 props
->get_Item(m_CallContextString
));
638 //build the array of out parameters, allocate max length
639 System::Object
* arOut
[]= new System::Object
*[mtd
->nParams
];
641 for (int i
= 0; i
< mtd
->nParams
; i
++)
643 if (mtd
->pParams
[i
].bOut
)
649 retVal
= new srrm::ReturnMessage(cliReturn
, arOut
, nOut
,
654 // Attribute (getXXX)
655 retVal
= new srrm::ReturnMessage(cliReturn
, NULL
, 0,
662 //################################################################################
663 CliProxy::CliProxy(Bridge
const* bridge
, System::Object
* cliI
,
664 typelib_TypeDescription
const* td
,
665 const rtl::OUString
& usOid
):
669 m_unoType(const_cast<typelib_TypeDescription
*>(td
)),
671 m_oid(mapUnoString(usOid
.pData
)),
672 m_nInheritedInterfaces(0)
675 uno_Interface::acquire
= cli_proxy_acquire
;
676 uno_Interface::release
= cli_proxy_release
;
677 uno_Interface::pDispatcher
= cli_proxy_dispatch
;
679 m_unoType
.makeComplete();
680 m_type
= mapUnoType(m_unoType
.get());
683 #if OSL_DEBUG_LEVEL >= 2
684 sd::Trace::WriteLine(System::String::Format(
685 new System::String(S
"cli uno bridge: Creating proxy for cli object, "
686 S
"id:\n\t{0}\n\t{1}"), m_oid
, m_type
));
691 void CliProxy::makeMethodInfos()
693 #if OSL_DEBUG_LEVEL >= 2
694 System::Object
* cliI
;
700 if (m_type
->get_IsInterface() == false)
702 sr::MethodInfo
* arThisMethods
[] = m_type
->GetMethods();
703 //get the inherited interfaces
704 System::Type
* arInheritedIfaces
[] = m_type
->GetInterfaces();
705 m_nInheritedInterfaces
= arInheritedIfaces
->get_Length();
706 //array containing the number of methods for the interface and its
707 //inherited interfaces
708 m_arInterfaceMethodCount
= new int __gc
[m_nInheritedInterfaces
+ 1];
709 //determine the number of all interface methods, including the inherited
711 int numMethods
= arThisMethods
->get_Length();
712 for (int i
= 0; i
< m_nInheritedInterfaces
; i
++)
714 numMethods
+= arInheritedIfaces
[i
]->GetMethods()->get_Length();
716 //array containing MethodInfos of the cli object
717 m_arMethodInfos
= new sr::MethodInfo
*[numMethods
];
718 //array containing MethodInfos of the interface
719 m_arInterfaceMethodInfos
= new sr::MethodInfo
*[numMethods
];
720 //array containing the mapping of Uno interface pos to pos in
722 m_arUnoPosToCliPos
= new System::Int32
[numMethods
];
723 // initialize with -1
724 for (int i
= 0; i
< numMethods
; i
++)
725 m_arUnoPosToCliPos
[i
] = -1;
727 #if OSL_DEBUG_LEVEL >= 2
728 sr::MethodInfo
* arMethodInfosDbg
[];
729 sr::MethodInfo
* arInterfaceMethodInfosDbg
[];
730 System::Int32 arInterfaceMethodCountDbg
[];
731 arMethodInfosDbg
= m_arMethodInfos
;
732 arInterfaceMethodInfosDbg
= m_arInterfaceMethodInfos
;
733 arInterfaceMethodCountDbg
= m_arInterfaceMethodCount
;
737 //fill m_arMethodInfos with the mappings
738 // !!! InterfaceMapping.TargetMethods should be MethodInfo*[] according
740 // but it is Type*[] instead. Bug in the framework?
741 System::Type
* objType
= m_cliI
->GetType();
745 // now get the methods from the inherited interface
746 //arInheritedIfaces[0] is the direct base interface
747 //arInheritedIfaces[n] is the furthest inherited interface
748 //Start with the base interface
749 int nArLength
= arInheritedIfaces
->get_Length();
750 for (;nArLength
> 0; nArLength
--)
752 sr::InterfaceMapping mapInherited
= objType
->GetInterfaceMap(
753 arInheritedIfaces
[nArLength
- 1]);
754 int numMethods
= mapInherited
.TargetMethods
->get_Length();
755 m_arInterfaceMethodCount
[nArLength
- 1] = numMethods
;
756 for (int i
= 0; i
< numMethods
; i
++, index
++)
758 m_arMethodInfos
[index
] = __try_cast
<sr::MethodInfo
*>(
759 mapInherited
.TargetMethods
[i
]);
761 m_arInterfaceMethodInfos
[index
] = __try_cast
<sr::MethodInfo
*>(
762 mapInherited
.InterfaceMethods
[i
]);
765 //At last come the methods of the furthest derived interface
766 sr::InterfaceMapping map
= objType
->GetInterfaceMap(m_type
);
767 nArLength
= map
.TargetMethods
->get_Length();
768 m_arInterfaceMethodCount
[m_nInheritedInterfaces
] = nArLength
;
769 for (int i
= 0; i
< nArLength
; i
++,index
++)
771 m_arMethodInfos
[index
]= __try_cast
<sr::MethodInfo
*>(
772 map
.TargetMethods
[i
]);
773 m_arInterfaceMethodInfos
[index
]= __try_cast
<sr::MethodInfo
*>(
774 map
.InterfaceMethods
[i
]);
777 catch (System::InvalidCastException
* )
779 OUStringBuffer
buf( 128 );
780 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
781 "[cli_uno bridge] preparing proxy for "
782 "cli interface: ") );
783 buf
.append(mapCliString(m_type
->ToString() ));
784 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(" \nfailed!"));
785 throw BridgeRuntimeError( buf
.makeStringAndClear() );
789 sr::MethodInfo
* CliProxy::getMethodInfo(int nUnoFunctionPos
,
790 const rtl::OUString
& usMethodName
, MethodKind methodKind
)
792 sr::MethodInfo
* ret
= NULL
;
793 #if OSL_DEBUG_LEVEL >= 2
794 System::String
* sMethodNameDbg
;
795 sr::MethodInfo
* arMethodInfosDbg
[];
796 sr::MethodInfo
* arInterfaceMethodInfosDbg
[];
797 System::Int32 arInterfaceMethodCountDbg
[];
798 System::Int32 arUnoPosToCliPosDbg
[];
799 sMethodNameDbg
= mapUnoString(usMethodName
.pData
);
800 arMethodInfosDbg
= m_arMethodInfos
;
801 arInterfaceMethodInfosDbg
= m_arInterfaceMethodInfos
;
802 arInterfaceMethodCountDbg
= m_arInterfaceMethodCount
;
803 arUnoPosToCliPosDbg
= m_arUnoPosToCliPos
;
805 //deduct 3 for XInterface methods
806 nUnoFunctionPos
-= 3;
807 System::Threading::Monitor::Enter(m_arUnoPosToCliPos
);
810 int cliPos
= m_arUnoPosToCliPos
[nUnoFunctionPos
];
812 return m_arMethodInfos
[cliPos
];
814 //create the method function name
815 System::String
* sMethodName
= mapUnoString(usMethodName
.pData
);
821 sMethodName
= System::String::Concat(
822 const_cast<System::String
*>(Constants::sAttributeSet
),
826 sMethodName
= System::String::Concat(
827 const_cast<System::String
*>(Constants::sAttributeGet
),
833 //Find the cli interface method that corresponds to the Uno method
834 // System::String* sMethodName= mapUnoString(usMethodName.pData);
835 int indexCliMethod
= -1;
836 //If the cli interfaces and their methods are in the same order
837 //as they were declared (inheritance chain and within the interface)
838 //then nUnoFunctionPos should lead to the correct method. However,
839 //the documentation does not say that this ordering is given.
840 if (sMethodName
->Equals(m_arInterfaceMethodInfos
[nUnoFunctionPos
]->Name
))
841 indexCliMethod
= nUnoFunctionPos
;
844 int cMethods
= m_arInterfaceMethodInfos
->get_Length();
845 for (int i
= 0; i
< cMethods
; i
++)
847 System::String
* cliMethod
= m_arInterfaceMethodInfos
[i
]->Name
;
848 if (cliMethod
->Equals(sMethodName
))
855 if (indexCliMethod
== -1)
857 OUStringBuffer
buf(256);
858 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
859 "[cli_uno bridge] CliProxy::getMethodInfo():"
860 "cli object does not implement interface method: "));
861 buf
.append(usMethodName
);
862 throw BridgeRuntimeError(buf
.makeStringAndClear());
865 m_arUnoPosToCliPos
[nUnoFunctionPos
] = indexCliMethod
;
866 ret
= m_arMethodInfos
[indexCliMethod
];
870 System::Threading::Monitor::Exit(m_arUnoPosToCliPos
);
876 CliProxy::~CliProxy()
878 #if OSL_DEBUG_LEVEL >= 2
879 sd::Trace::WriteLine(System::String::Format(
881 S
"cli uno bridge: Destroying proxy for cli object, "
882 S
"id:\n\t{0}\n\t{1}\n"),
885 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
, mapUnoType(m_unoType
.get()));
889 uno_Interface
* CliProxy::create(Bridge
const * bridge
,
890 System::Object
* cliI
,
891 typelib_TypeDescription
const* pTD
,
892 const rtl::OUString
& ousOid
)
894 uno_Interface
* proxy
= static_cast<uno_Interface
*>(
895 new CliProxy(bridge
, cliI
, pTD
, ousOid
));
897 //register proxy with target environment (uno)
898 (*bridge
->m_uno_env
->registerProxyInterface
)(
900 reinterpret_cast<void**>(&proxy
),
902 ousOid
.pData
, (typelib_InterfaceTypeDescription
*) pTD
);
903 //register original interface
904 CliEnvHolder::g_cli_env
->registerInterface(cliI
, mapUnoString(ousOid
.pData
),
912 void SAL_CALL
CliProxy::uno_DispatchMethod(
913 struct _uno_Interface
*,
914 const struct _typelib_TypeDescription
*,
920 inline void CliProxy::acquire() const
922 if (1 == osl_incrementInterlockedCount( &m_ref
))
924 // rebirth of proxy zombie
925 void * that
= const_cast< CliProxy
* >( this );
926 // register at uno env
927 (*m_bridge
->m_uno_env
->registerProxyInterface
)(
928 m_bridge
->m_uno_env
, &that
,
929 cli_proxy_free
, m_usOid
.pData
,
930 (typelib_InterfaceTypeDescription
*)m_unoType
.get() );
931 #if OSL_DEBUG_LEVEL >= 2
932 OSL_ASSERT( this == (void const * const)that
);
936 //---------------------------------------------------------------------------
937 inline void CliProxy::release() const
939 if (0 == osl_decrementInterlockedCount( &m_ref
))
941 // revoke from uno env on last release,
942 // The proxy can be resurrected if acquire is called before the uno
943 // environment calls cli_proxy_free. cli_proxy_free will
944 //delete the proxy. The environment does not acquire a registered
946 (*m_bridge
->m_uno_env
->revokeInterface
)(
947 m_bridge
->m_uno_env
, const_cast< CliProxy
* >( this ) );
956 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
*, void * proxy
)
959 cli_uno::CliProxy
* cliProxy
= reinterpret_cast<
960 cli_uno::CliProxy
* >( proxy
);
966 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
969 CliProxy
const * cliProxy
= static_cast< CliProxy
const * >( pUnoI
);
972 //-----------------------------------------------------------------------------
974 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
977 CliProxy
* cliProxy
= static_cast< CliProxy
* >( pUnoI
);
981 //------------------------------------------------------------------------------
984 void SAL_CALL
cli_proxy_dispatch(
985 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
986 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
989 CliProxy
* proxy
= static_cast< CliProxy
* >( pUnoI
);
992 Bridge
const* bridge
= proxy
->m_bridge
;
994 switch (member_td
->eTypeClass
)
996 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
999 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
1000 member_td
)->nPosition
;
1001 typelib_InterfaceTypeDescription
* iface_td
=
1002 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
1004 member_pos
< iface_td
->nAllMembers
,
1005 "### member pos out of range!" );
1006 sal_Int32 function_pos
=
1007 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
1009 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
1010 "### illegal function index!" );
1012 if (uno_ret
) // is getter method
1014 OUString
const& usAttrName
= *(rtl_uString
**)&
1015 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1017 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
,
1018 usAttrName
, CliProxy::MK_GET
);
1022 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1023 ->pAttributeTypeRef
,
1025 uno_ret
, 0, uno_exc
);
1027 else // is setter method
1029 OUString
const& usAttrName
= *(rtl_uString
**) &
1030 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1032 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
+ 1,
1033 usAttrName
, CliProxy::MK_SET
);
1034 typelib_MethodParameter param
;
1036 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1037 ->pAttributeTypeRef
;
1038 param
.bIn
= sal_True
;
1039 param
.bOut
= sal_False
;
1043 // set follows get method
1045 0 /* indicates void return */, ¶m
, 1,
1046 0, uno_args
, uno_exc
);
1050 case typelib_TypeClass_INTERFACE_METHOD
:
1052 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
1053 member_td
)->nPosition
;
1054 typelib_InterfaceTypeDescription
* iface_td
=
1055 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
1057 member_pos
< iface_td
->nAllMembers
,
1058 "### member pos out of range!" );
1059 sal_Int32 function_pos
=
1060 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
1062 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
1063 "### illegal function index!" );
1065 switch (function_pos
)
1067 case 0: // queryInterface()
1069 TypeDescr
demanded_td(
1070 *reinterpret_cast<typelib_TypeDescriptionReference
**>(
1072 if (typelib_TypeClass_INTERFACE
1073 != demanded_td
.get()->eTypeClass
)
1075 throw BridgeRuntimeError(
1076 OUSTR("queryInterface() call demands an INTERFACE type!"));
1079 uno_Interface
* pInterface
= 0;
1080 (*bridge
->m_uno_env
->getRegisteredInterface
)(
1082 (void **)&pInterface
, proxy
->m_usOid
.pData
,
1083 (typelib_InterfaceTypeDescription
*)demanded_td
.get() );
1085 if (0 == pInterface
)
1087 System::Type
* mgdDemandedType
=
1088 mapUnoType(demanded_td
.get());
1089 if (mgdDemandedType
->IsInstanceOfType( proxy
->m_cliI
))
1091 #if OSL_DEBUG_LEVEL > 0
1094 CliEnvHolder::g_cli_env
->getObjectIdentifier(
1096 OSL_ENSURE(usOid
.equals( proxy
->m_usOid
),
1097 "### different oids!");
1099 uno_Interface
* pUnoI
= bridge
->map_cli2uno(
1100 proxy
->m_cliI
, demanded_td
.get() );
1102 (uno_Any
*)uno_ret
, &pUnoI
, demanded_td
.get(), 0 );
1103 (*pUnoI
->release
)( pUnoI
);
1105 else // object does not support demanded interface
1107 uno_any_construct( (uno_Any
*)uno_ret
, 0, 0, 0 );
1109 // no excetpion occured
1115 reinterpret_cast< uno_Any
* >( uno_ret
),
1116 &pInterface
, demanded_td
.get(), 0 );
1117 (*pInterface
->release
)( pInterface
);
1122 case 1: // acquire this proxy
1123 cli_proxy_acquire(proxy
);
1126 case 2: // release this proxy
1127 cli_proxy_release(proxy
);
1130 default: // arbitrary method call
1132 typelib_InterfaceMethodTypeDescription
* method_td
=
1133 (typelib_InterfaceMethodTypeDescription
*)member_td
;
1134 OUString
const& usMethodName
= *(rtl_uString
**) &
1135 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1138 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
,
1139 usMethodName
, CliProxy::MK_METHOD
);
1143 method_td
->pReturnTypeRef
, method_td
->pParams
,
1145 uno_ret
, uno_args
, uno_exc
);
1153 throw BridgeRuntimeError(
1154 OUSTR("illegal member type description!") );
1158 catch (BridgeRuntimeError
& err
)
1160 // binary identical struct
1161 ::com::sun::star::uno::RuntimeException
exc(
1162 OUSTR("[cli_uno bridge error] ") + err
.m_message
,
1163 ::com::sun::star::uno::Reference
<
1164 ::com::sun::star::uno::XInterface
>() );
1165 ::com::sun::star::uno::Type
const & exc_type
= ::getCppuType( & exc
);
1166 uno_type_any_construct( *uno_exc
, &exc
, exc_type
.getTypeLibType(), 0);
1167 #if OSL_DEBUG_LEVEL >= 1
1168 OString
cstr_msg(OUStringToOString(exc
.Message
,
1169 RTL_TEXTENCODING_ASCII_US
) );
1170 OSL_ENSURE(0, cstr_msg
.getStr());