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 .
20 #include "typelib/typedescription.h"
21 #include "rtl/ustrbuf.hxx"
22 #include "com/sun/star/uno/RuntimeException.hpp"
23 #include "osl/mutex.hxx"
24 #include "cli_proxy.h"
26 #include "cli_bridge.h"
29 #using <cli_uretypes.dll>
31 namespace sr
= System::Reflection
;
32 namespace st
= System::Text
;
33 namespace sc
= System::Collections
;
34 namespace srrm
= System::Runtime::Remoting::Messaging
;
35 namespace srr
= System::Runtime::Remoting
;
36 namespace srrp
= System::Runtime::Remoting::Proxies
;
37 namespace sd
= System::Diagnostics
;
38 namespace ucss
= unoidl::com::sun::star
;
40 using namespace cli_uno
;
44 //------------------------------------------------------------------------------
45 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
* env
, void * proxy
)
47 //------------------------------------------------------------------------------
48 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
50 //------------------------------------------------------------------------------
51 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
53 //------------------------------------------------------------------------------
54 void SAL_CALL
cli_proxy_dispatch(
55 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
56 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
65 UnoInterfaceInfo::UnoInterfaceInfo(Bridge
const * bridge
, uno_Interface
* unoI
,
66 typelib_InterfaceTypeDescription
* td
):
73 m_type
= mapUnoType(reinterpret_cast<typelib_TypeDescription
*>(td
));
74 m_unoI
->acquire(m_unoI
);
75 typelib_typedescription_acquire(&m_typeDesc
->aBase
);
76 if ( ! m_typeDesc
->aBase
.bComplete
)
78 typelib_TypeDescription
* _pt
= &m_typeDesc
->aBase
;
79 sal_Bool bComplete
= ::typelib_typedescription_complete( & _pt
);
82 OUStringBuffer
buf( 128 );
83 buf
.append( "cannot make type complete: " );
84 buf
.append( *reinterpret_cast< OUString
const * >(
85 & m_typeDesc
->aBase
.pTypeName
));
86 throw BridgeRuntimeError(buf
.makeStringAndClear());
90 UnoInterfaceInfo::~UnoInterfaceInfo()
92 //accessing unmanaged objects is ok.
93 m_bridge
->m_uno_env
->revokeInterface(
94 m_bridge
->m_uno_env
, m_unoI
);
97 m_unoI
->release(m_unoI
);
98 typelib_typedescription_release(
99 reinterpret_cast<typelib_TypeDescription
*>(m_typeDesc
));
102 UnoInterfaceProxy::UnoInterfaceProxy(
104 uno_Interface
* pUnoI
,
105 typelib_InterfaceTypeDescription
* pTD
,
106 const OUString
& oid
)
107 :RealProxy(MarshalByRefObject::typeid),
109 m_oid(mapUnoString(oid
.pData
)),
110 m_sTypeName(m_system_Object_String
)
113 // create the list that holds all UnoInterfaceInfos
114 m_listIfaces
= gcnew
ArrayList(10);
116 m_listAdditionalProxies
= gcnew
ArrayList();
117 m_nlistAdditionalProxies
= 0;
118 //put the information of the first UNO interface into the arraylist
119 #if OSL_DEBUG_LEVEL >= 2
123 addUnoInterface(pUnoI
, pTD
);
127 UnoInterfaceProxy::~UnoInterfaceProxy()
129 #if OSL_DEBUG_LEVEL >= 2
130 sd::Trace::WriteLine(System::String::Format(
131 new System::String(S
"cli uno bridge: Destroying proxy "
132 S
"for UNO object, OID: \n\t{0} \n\twith uno interfaces: "),
135 sd::Trace::WriteLine( mapUnoString(_sInterfaces
));
136 rtl_uString_release(_sInterfaces
);
138 //m_bridge is unmanaged, therefore we can access it in this finalizer
139 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
);
144 System::Object
^ UnoInterfaceProxy::create(
146 uno_Interface
* pUnoI
,
147 typelib_InterfaceTypeDescription
* pTD
,
150 UnoInterfaceProxy
^ proxyHandler
=
151 gcnew
UnoInterfaceProxy(bridge
, pUnoI
, pTD
, oid
);
152 System::Object
^ proxy
= proxyHandler
->GetTransparentProxy();
153 CliEnvHolder::g_cli_env
->registerInterface(proxy
, mapUnoString(oid
.pData
));
158 void UnoInterfaceProxy::addUnoInterface(uno_Interface
* pUnoI
,
159 typelib_InterfaceTypeDescription
* pTd
)
161 sc::IEnumerator
^ enumInfos
= m_listIfaces
->GetEnumerator();
162 System::Threading::Monitor::Enter(this);
165 while (enumInfos
->MoveNext())
167 UnoInterfaceInfo
^ info
= static_cast<UnoInterfaceInfo
^>(
169 #if OSL_DEBUG_LEVEL > 1
173 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
) );
175 reinterpret_cast<typelib_TypeDescription
*>(pTd
) );
177 if (typelib_typedescription_equals(
178 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
),
179 reinterpret_cast<typelib_TypeDescription
*>(pTd
)))
184 OUString
oid(mapCliString(m_oid
));
185 (*m_bridge
->m_uno_env
->registerInterface
)(
186 m_bridge
->m_uno_env
, reinterpret_cast< void ** >( &pUnoI
),
188 //This proxy does not contain the uno_Interface. Add it.
189 m_listIfaces
->Add(gcnew
UnoInterfaceInfo(m_bridge
, pUnoI
, pTd
));
190 m_numUnoIfaces
= m_listIfaces
->Count
;
191 #if OSL_DEBUG_LEVEL >= 2
192 System::String
* sInterfaceName
= static_cast<UnoInterfaceInfo
*>(
193 m_listIfaces
->get_Item(m_numUnoIfaces
- 1))->m_type
->FullName
;
194 sd::Trace::WriteLine(System::String::Format(
195 new System::String(S
"cli uno bridge: Creating proxy for uno object, "
196 S
"id:\n\t{0}\n\t{1}"), m_oid
, sInterfaceName
));
197 // add to the string that contains all interface names
199 OUStringBuffer
buf(512);
201 buf
.append( OUString::valueOf((sal_Int32
)_numInterfaces
));
203 buf
.append(mapCliString(sInterfaceName
));
205 OUString _sNewInterface
= buf
.makeStringAndClear();
206 rtl_uString
* __pin
* pp_sInterfaces
= & _sInterfaces
;
207 rtl_uString_newConcat( pp_sInterfaces
, * pp_sInterfaces
,
208 _sNewInterface
.pData
);
212 System::Threading::Monitor::Exit(this);
218 bool UnoInterfaceProxy::CanCastTo(System::Type
^ fromType
,
221 if (fromType
== System::Object::typeid) // trivial case
224 System::Threading::Monitor::Enter(this);
227 if (nullptr != findInfo( fromType
)) // proxy supports demanded interface
230 //query an uno interface for the required type
232 // we use the first interface in the list (m_listIfaces) to make
233 // the queryInterface call
234 UnoInterfaceInfo
^ info
=
235 static_cast<UnoInterfaceInfo
^>(m_listIfaces
[0]);
236 css::uno::TypeDescription
membertd(
237 reinterpret_cast<typelib_InterfaceTypeDescription
*>(
238 info
->m_typeDesc
)->ppAllMembers
[0]);
239 array
<System::Object
^>^ args
= gcnew array
<System::Object
^>(1);
243 System::Object
^ pException
= nullptr;
245 pAny
= static_cast<uno::Any
^>(
249 ((typelib_InterfaceMethodTypeDescription
*)
250 membertd
.get())->pReturnTypeRef
,
252 ((typelib_InterfaceMethodTypeDescription
*)
253 membertd
.get())->pParams
,
254 args
, nullptr, &pException
) );
256 // handle regular exception from target
258 nullptr == pException
,
260 mapCliString( pException
->ToString()),
261 RTL_TEXTENCODING_UTF8
).getStr() );
263 if (pAny
->Type
!= void::typeid) // has value?
265 if (nullptr != findInfo( fromType
))
267 // proxy now supports demanded interface
271 // via aggregation: it is possible that queryInterface() returns
272 // and interface with a different oid.
273 // That way, this type is supported for the CLI
274 // interpreter (CanCastTo() returns true)
275 ::System::Object
^ obj
= pAny
->Value
;
276 OSL_ASSERT( srr::RemotingServices::IsTransparentProxy( obj
) );
277 if (srr::RemotingServices::IsTransparentProxy( obj
))
279 UnoInterfaceProxy
^ proxy
=
280 static_cast< UnoInterfaceProxy
^ >(
281 srr::RemotingServices::GetRealProxy( obj
) );
282 OSL_ASSERT( nullptr != proxy
->findInfo( fromType
) );
283 m_listAdditionalProxies
->Add( proxy
);
284 m_nlistAdditionalProxies
= m_listAdditionalProxies
->Count
;
285 OSL_ASSERT( nullptr != findInfo( fromType
) );
290 catch (BridgeRuntimeError
& e
)
292 (void) e
; // avoid warning
295 e
.m_message
, RTL_TEXTENCODING_UTF8
).getStr() );
297 catch (System::Exception
^ e
)
299 System::String
^ msg
= gcnew
System::String(
300 "An unexpected CLI exception occurred in "
301 "UnoInterfaceProxy::CanCastTo(). Original"
303 msg
= System::String::Concat(msg
, e
->Message
);
306 mapCliString(msg
), RTL_TEXTENCODING_UTF8
).getStr() );
311 "An unexpected native C++ exception occurred in "
312 "UnoInterfaceProxy::CanCastTo()" );
316 System::Threading::Monitor::Exit(this);
321 srrm::IMessage
^ UnoInterfaceProxy::invokeObject(
322 sc::IDictionary
^ props
,
323 srrm::LogicalCallContext
^ context
,
324 srrm::IMethodCallMessage
^ mcm
)
326 System::Object
^ retMethod
= nullptr;
327 System::String
^ sMethod
= static_cast<System::String
^>
328 (props
[m_methodNameString
]);
329 array
<System::Object
^>^ args
= static_cast<array
<System::Object
^>^>(
330 props
[m_ArgsString
]);
331 if (m_Equals_String
->Equals(sMethod
))
334 OSL_ASSERT(args
->Length
== 1);
335 srrp::RealProxy
^ rProxy
= srr::RemotingServices::GetRealProxy(args
[0]);
339 UnoInterfaceProxy
^ unoProxy
=
340 dynamic_cast<UnoInterfaceProxy
^>(rProxy
);
343 bool b
= m_oid
->Equals(unoProxy
->getOid());
350 //no proxy or not our proxy, therefore Equals must be false
354 else if (m_GetHashCode_String
->Equals(sMethod
))
356 // Object.GetHashCode
357 int nHash
= m_oid
->GetHashCode();
360 else if (m_GetType_String
->Equals(sMethod
))
363 retMethod
= System::Object::typeid;
365 else if (m_ToString_String
->Equals(sMethod
))
368 st::StringBuilder
^ sb
= gcnew
st::StringBuilder(256);
369 // sb->AppendFormat(S"Uno object proxy. Implemented interface: {0}"
370 // S". OID: {1}", m_type->ToString(), m_oid);
371 sb
->AppendFormat("Uno object proxy. OID: {0}", m_oid
);
372 retMethod
= sb
->ToString();
376 //Either Object has new functions or a protected method was called
377 //which should not be possible
380 srrm::IMessage
^ retVal
= gcnew
srrm::ReturnMessage(
381 retMethod
, gcnew array
<System::Object
^>(0), 0, context
, mcm
);
385 UnoInterfaceInfo
^ UnoInterfaceProxy::findInfo( ::System::Type
^ type
)
387 for (int i
= 0; i
< m_numUnoIfaces
; i
++)
389 UnoInterfaceInfo
^ tmpInfo
= static_cast<UnoInterfaceInfo
^>(
391 if (type
->IsAssignableFrom(tmpInfo
->m_type
))
394 for ( int i
= 0; i
< m_nlistAdditionalProxies
; ++i
)
396 UnoInterfaceProxy
^ proxy
=
397 static_cast< UnoInterfaceProxy
^ >(
398 m_listAdditionalProxies
[ i
] );
399 UnoInterfaceInfo
^ info
= proxy
->findInfo( type
);
406 srrm::IMessage
^ UnoInterfaceProxy::Invoke(srrm::IMessage
^ callmsg
)
410 sc::IDictionary
^ props
= callmsg
->Properties
;
411 srrm::LogicalCallContext
^ context
=
412 static_cast<srrm::LogicalCallContext
^>(
413 props
[m_CallContextString
]);
414 srrm::IMethodCallMessage
^ mcm
=
415 static_cast<srrm::IMethodCallMessage
^>(callmsg
);
417 //Find out which UNO interface is being called
418 System::String
^ sTypeName
= static_cast<System::String
^>(
419 props
[m_typeNameString
]);
420 sTypeName
= sTypeName
->Substring(0, sTypeName
->IndexOf(','));
422 // Special Handling for System.Object methods
423 if(sTypeName
->IndexOf(m_system_Object_String
) != -1)
425 return invokeObject(props
, context
, mcm
);
428 System::Type
^ typeBeingCalled
= loadCliType(sTypeName
);
429 UnoInterfaceInfo
^ info
= findInfo( typeBeingCalled
);
430 OSL_ASSERT( nullptr != info
);
432 // ToDo do without string conversion, a OUString is not needed here
433 // get the type description of the call
434 OUString
usMethodName(mapCliString(static_cast<System::String
^>(
435 props
[m_methodNameString
])));
436 typelib_TypeDescriptionReference
** ppAllMembers
=
437 info
->m_typeDesc
->ppAllMembers
;
438 sal_Int32 numberMembers
= info
->m_typeDesc
->nAllMembers
;
439 for ( sal_Int32 nPos
= numberMembers
; nPos
--; )
441 typelib_TypeDescriptionReference
* member_type
= ppAllMembers
[nPos
];
443 // check usMethodName against fully qualified usTypeName
444 // of member_type; usTypeName is of the form
445 // <name> "::" <usMethodName> *(":@" <idx> "," <idx> ":" <name>)
446 OUString
const & usTypeName
=
447 OUString::unacquired( & member_type
->pTypeName
);
449 #if OSL_DEBUG_LEVEL >= 2
450 System::String
* pTypeName
;
451 pTypeName
= mapUnoString(usTypeName
.pData
);
453 sal_Int32 offset
= usTypeName
.indexOf( ':' ) + 2;
455 offset
>= 2 && offset
< usTypeName
.getLength()
456 && usTypeName
[offset
- 1] == ':' );
457 sal_Int32 remainder
= usTypeName
.getLength() - offset
;
459 if (typelib_TypeClass_INTERFACE_METHOD
== member_type
->eTypeClass
)
461 if ((usMethodName
.getLength() == remainder
462 || (usMethodName
.getLength() < remainder
463 && usTypeName
[offset
+ usMethodName
.getLength()] == ':'))
464 && usTypeName
.match(usMethodName
, offset
))
466 TypeDescr
member_td( member_type
);
467 typelib_InterfaceMethodTypeDescription
* method_td
=
468 (typelib_InterfaceMethodTypeDescription
*)
471 array
<System::Object
^>^ args
= static_cast<array
<System::Object
^>^>(
472 props
[m_ArgsString
]);
473 array
<System::Type
^>^ argTypes
= static_cast<array
<System::Type
^>^>(
474 props
[m_methodSignatureString
]);
475 System::Object
^ pExc
= nullptr;
476 System::Object
^ cli_ret
= m_bridge
->call_uno(
477 info
->m_unoI
, member_td
.get(),
478 method_td
->pReturnTypeRef
, method_td
->nParams
,
479 method_td
->pParams
, args
, argTypes
, &pExc
);
480 return constructReturnMessage(cli_ret
, args
, method_td
,
486 OSL_ASSERT( typelib_TypeClass_INTERFACE_ATTRIBUTE
==
487 member_type
->eTypeClass
);
488 if (usMethodName
.getLength() > 4
489 && (usMethodName
.getLength() - 4 == remainder
490 || (usMethodName
.getLength() - 4 < remainder
492 offset
+ (usMethodName
.getLength() - 4)] == ':'))
493 && usMethodName
[1] == 'e' && usMethodName
[2] == 't'
494 && rtl_ustr_compare_WithLength(
495 usTypeName
.getStr() + offset
,
496 usMethodName
.getLength() - 4,
497 usMethodName
.getStr() + 4,
498 usMethodName
.getLength() - 4) == 0)
500 if ('g' == usMethodName
[0])
502 TypeDescr
member_td( member_type
);
503 typelib_InterfaceAttributeTypeDescription
* attribute_td
=
504 (typelib_InterfaceAttributeTypeDescription
*)
507 System::Object
^ pExc
= nullptr;
508 System::Object
^ cli_ret
= m_bridge
->call_uno(
509 info
->m_unoI
, member_td
.get(),
510 attribute_td
->pAttributeTypeRef
,
512 nullptr, nullptr, &pExc
);
513 return constructReturnMessage(cli_ret
, nullptr, NULL
,
516 else if ('s' == usMethodName
[0])
518 TypeDescr
member_td( member_type
);
519 typelib_InterfaceAttributeTypeDescription
* attribute_td
=
520 (typelib_InterfaceAttributeTypeDescription
*)
522 if (! attribute_td
->bReadOnly
)
524 typelib_MethodParameter param
;
525 param
.pTypeRef
= attribute_td
->pAttributeTypeRef
;
526 param
.bIn
= sal_True
;
527 param
.bOut
= sal_False
;
529 array
<System::Object
^>^ args
=
530 static_cast<array
<System::Object
^>^>(
531 props
[m_ArgsString
]);
532 System::Object
^ pExc
= nullptr;
534 info
->m_unoI
, member_td
.get(),
535 ::getCppuVoidType().getTypeLibType(),
536 1, ¶m
, args
, nullptr, &pExc
);
537 return constructReturnMessage(nullptr, nullptr, NULL
,
542 return constructReturnMessage(nullptr, nullptr, NULL
,
550 // ToDo check if the message of the exception is not crippled
551 // the thing that should not be... no method info found!
552 OUStringBuffer
buf( 64 );
553 buf
.append( "[cli_uno bridge]calling undeclared function on interface " );
554 buf
.append( *reinterpret_cast< OUString
const * >(
555 & ((typelib_TypeDescription
*)info
->m_typeDesc
)->pTypeName
));
557 buf
.append( usMethodName
);
558 throw BridgeRuntimeError( buf
.makeStringAndClear() );
560 catch (BridgeRuntimeError
& err
)
562 srrm::IMethodCallMessage
^ mcm
=
563 static_cast<srrm::IMethodCallMessage
^>(callmsg
);
564 return gcnew
srrm::ReturnMessage(gcnew
ucss::uno::RuntimeException(
565 mapUnoString(err
.m_message
.pData
), nullptr), mcm
);
567 catch (System::Exception
^ e
)
569 st::StringBuilder
^ sb
= gcnew
st::StringBuilder(512);
570 sb
->Append(gcnew
System::String(
571 "An unexpected CLI exception occurred in "
572 "UnoInterfaceProxy::Invoke. Original"
574 sb
->Append(e
->Message
);
575 sb
->Append((__wchar_t
) '\n');
576 sb
->Append(e
->StackTrace
);
577 srrm::IMethodCallMessage
^ mcm
=
578 static_cast<srrm::IMethodCallMessage
^>(callmsg
);
579 return gcnew
srrm::ReturnMessage(gcnew
ucss::uno::RuntimeException(
580 sb
->ToString(), nullptr), mcm
);
584 System::String
^ msg
= gcnew
System::String(
585 "An unexpected native C++ exception occurred in "
586 "UnoInterfaceProxy::Invoke.");
587 srrm::IMethodCallMessage
^ mcm
=
588 static_cast<srrm::IMethodCallMessage
^>(callmsg
);
589 return gcnew
srrm::ReturnMessage(gcnew
ucss::uno::RuntimeException(
594 /** If the argument args is NULL then this function is called for an attribute
595 method (either setXXX or getXXX).
596 For attributes the argument mtd is also NULL.
598 srrm::IMessage
^ UnoInterfaceProxy::constructReturnMessage(
599 System::Object
^ cliReturn
,
600 array
<System::Object
^>^ args
,
601 typelib_InterfaceMethodTypeDescription
* mtd
,
602 srrm::IMessage
^ msg
, System::Object
^ exc
)
604 srrm::IMessage
^ retVal
= nullptr;
605 srrm::IMethodCallMessage
^ mcm
= static_cast<srrm::IMethodCallMessage
^>(msg
);
608 retVal
= gcnew
srrm::ReturnMessage(
609 dynamic_cast<System::Exception
^>(exc
), mcm
);
613 sc::IDictionary
^ props
= msg
->Properties
;
614 srrm::LogicalCallContext
^ context
=
615 static_cast<srrm::LogicalCallContext
^>(
616 props
[m_CallContextString
]);
620 //build the array of out parameters, allocate max length
621 array
<System::Object
^>^ arOut
= gcnew array
<System::Object
^>(mtd
->nParams
);
623 for (int i
= 0; i
< mtd
->nParams
; i
++)
625 if (mtd
->pParams
[i
].bOut
)
631 retVal
= gcnew
srrm::ReturnMessage(cliReturn
, arOut
, nOut
,
636 // Attribute (getXXX)
637 retVal
= gcnew
srrm::ReturnMessage(cliReturn
, nullptr, 0,
644 //################################################################################
645 CliProxy::CliProxy(Bridge
const* bridge
, System::Object
^ cliI
,
646 typelib_TypeDescription
const* td
,
647 const OUString
& usOid
):
651 m_unoType(const_cast<typelib_TypeDescription
*>(td
)),
653 m_oid(mapUnoString(usOid
.pData
)),
654 m_nInheritedInterfaces(0)
657 uno_Interface::acquire
= cli_proxy_acquire
;
658 uno_Interface::release
= cli_proxy_release
;
659 uno_Interface::pDispatcher
= cli_proxy_dispatch
;
661 m_unoType
.makeComplete();
662 m_type
= mapUnoType(m_unoType
.get());
665 #if OSL_DEBUG_LEVEL >= 2
666 sd::Trace::WriteLine(System::String::Format(
667 new System::String(S
"cli uno bridge: Creating proxy for cli object, "
668 S
"id:\n\t{0}\n\t{1}"), m_oid
, m_type
));
673 void CliProxy::makeMethodInfos()
675 #if OSL_DEBUG_LEVEL >= 2
676 System::Object
* cliI
;
682 if (m_type
->IsInterface
== false)
684 array
<sr::MethodInfo
^>^ arThisMethods
= m_type
->GetMethods();
685 //get the inherited interfaces
686 array
<System::Type
^>^ arInheritedIfaces
= m_type
->GetInterfaces();
687 m_nInheritedInterfaces
= arInheritedIfaces
->Length
;
688 //array containing the number of methods for the interface and its
689 //inherited interfaces
690 m_arInterfaceMethodCount
= gcnew array
<int^>(m_nInheritedInterfaces
+ 1);
691 //determine the number of all interface methods, including the inherited
693 int numMethods
= arThisMethods
->Length
;
694 for (int i
= 0; i
< m_nInheritedInterfaces
; i
++)
696 numMethods
+= arInheritedIfaces
[i
]->GetMethods()->Length
;
698 //array containing MethodInfos of the cli object
699 m_arMethodInfos
= gcnew array
<sr::MethodInfo
^>(numMethods
);
700 //array containing MethodInfos of the interface
701 m_arInterfaceMethodInfos
= gcnew array
<sr::MethodInfo
^>(numMethods
);
702 //array containing the mapping of Uno interface pos to pos in
704 m_arUnoPosToCliPos
= gcnew array
<System::Int32
>(numMethods
);
705 // initialize with -1
706 for (int i
= 0; i
< numMethods
; i
++)
707 m_arUnoPosToCliPos
[i
] = -1;
709 #if OSL_DEBUG_LEVEL >= 2
710 sr::MethodInfo
* arMethodInfosDbg
[];
711 sr::MethodInfo
* arInterfaceMethodInfosDbg
[];
712 System::Int32 arInterfaceMethodCountDbg
[];
713 arMethodInfosDbg
= m_arMethodInfos
;
714 arInterfaceMethodInfosDbg
= m_arInterfaceMethodInfos
;
715 arInterfaceMethodCountDbg
= m_arInterfaceMethodCount
;
719 //fill m_arMethodInfos with the mappings
720 // !!! InterfaceMapping.TargetMethods should be MethodInfo*[] according
722 // but it is Type*[] instead. Bug in the framework?
723 System::Type
^ objType
= m_cliI
->GetType();
727 // now get the methods from the inherited interface
728 //arInheritedIfaces[0] is the direct base interface
729 //arInheritedIfaces[n] is the furthest inherited interface
730 //Start with the base interface
731 int nArLength
= arInheritedIfaces
->Length
;
732 for (;nArLength
> 0; nArLength
--)
734 sr::InterfaceMapping mapInherited
= objType
->GetInterfaceMap(
735 arInheritedIfaces
[nArLength
- 1]);
736 int numMethods
= mapInherited
.TargetMethods
->Length
;
737 m_arInterfaceMethodCount
[nArLength
- 1] = numMethods
;
738 for (int i
= 0; i
< numMethods
; i
++, index
++)
740 m_arMethodInfos
[index
] = safe_cast
<sr::MethodInfo
^>(
741 mapInherited
.TargetMethods
[i
]);
743 m_arInterfaceMethodInfos
[index
] = safe_cast
<sr::MethodInfo
^>(
744 mapInherited
.InterfaceMethods
[i
]);
747 //At last come the methods of the furthest derived interface
748 sr::InterfaceMapping map
= objType
->GetInterfaceMap(m_type
);
749 nArLength
= map
.TargetMethods
->Length
;
750 m_arInterfaceMethodCount
[m_nInheritedInterfaces
] = nArLength
;
751 for (int i
= 0; i
< nArLength
; i
++,index
++)
753 m_arMethodInfos
[index
]= safe_cast
<sr::MethodInfo
^>(
754 map
.TargetMethods
[i
]);
755 m_arInterfaceMethodInfos
[index
]= safe_cast
<sr::MethodInfo
^>(
756 map
.InterfaceMethods
[i
]);
759 catch (System::InvalidCastException
^ )
761 OUStringBuffer
buf( 128 );
762 buf
.append( "[cli_uno bridge] preparing proxy for cli interface: " );
763 buf
.append(mapCliString(m_type
->ToString() ));
764 buf
.append( " \nfailed!" );
765 throw BridgeRuntimeError( buf
.makeStringAndClear() );
769 sr::MethodInfo
^ CliProxy::getMethodInfo(int nUnoFunctionPos
,
770 const OUString
& usMethodName
, MethodKind methodKind
)
772 sr::MethodInfo
^ ret
= nullptr;
773 #if OSL_DEBUG_LEVEL >= 2
774 System::String
* sMethodNameDbg
;
775 sr::MethodInfo
* arMethodInfosDbg
[];
776 sr::MethodInfo
* arInterfaceMethodInfosDbg
[];
777 System::Int32 arInterfaceMethodCountDbg
[];
778 System::Int32 arUnoPosToCliPosDbg
[];
779 sMethodNameDbg
= mapUnoString(usMethodName
.pData
);
780 arMethodInfosDbg
= m_arMethodInfos
;
781 arInterfaceMethodInfosDbg
= m_arInterfaceMethodInfos
;
782 arInterfaceMethodCountDbg
= m_arInterfaceMethodCount
;
783 arUnoPosToCliPosDbg
= m_arUnoPosToCliPos
;
785 //deduct 3 for XInterface methods
786 nUnoFunctionPos
-= 3;
787 System::Threading::Monitor::Enter(m_arUnoPosToCliPos
);
790 int cliPos
= m_arUnoPosToCliPos
[nUnoFunctionPos
];
792 return m_arMethodInfos
[cliPos
];
794 //create the method function name
795 System::String
^ sMethodName
= mapUnoString(usMethodName
.pData
);
801 sMethodName
= System::String::Concat(
802 const_cast<System::String
^>(Constants::sAttributeSet
),
806 sMethodName
= System::String::Concat(
807 const_cast<System::String
^>(Constants::sAttributeGet
),
813 //Find the cli interface method that corresponds to the Uno method
814 // System::String* sMethodName= mapUnoString(usMethodName.pData);
815 int indexCliMethod
= -1;
816 //If the cli interfaces and their methods are in the same order
817 //as they were declared (inheritance chain and within the interface)
818 //then nUnoFunctionPos should lead to the correct method. However,
819 //the documentation does not say that this ordering is given.
820 if (sMethodName
->Equals(m_arInterfaceMethodInfos
[nUnoFunctionPos
]->Name
))
821 indexCliMethod
= nUnoFunctionPos
;
824 int cMethods
= m_arInterfaceMethodInfos
->Length
;
825 for (int i
= 0; i
< cMethods
; i
++)
827 System::String
^ cliMethod
= m_arInterfaceMethodInfos
[i
]->Name
;
828 if (cliMethod
->Equals(sMethodName
))
835 if (indexCliMethod
== -1)
837 OUStringBuffer
buf(256);
838 buf
.append( "[cli_uno bridge] CliProxy::getMethodInfo():"
839 "cli object does not implement interface method: " );
840 buf
.append(usMethodName
);
841 throw BridgeRuntimeError(buf
.makeStringAndClear());
843 m_arUnoPosToCliPos
[nUnoFunctionPos
] = indexCliMethod
;
844 ret
= m_arMethodInfos
[indexCliMethod
];
848 System::Threading::Monitor::Exit(m_arUnoPosToCliPos
);
854 CliProxy::~CliProxy()
856 #if OSL_DEBUG_LEVEL >= 2
857 sd::Trace::WriteLine(System::String::Format(
859 S
"cli uno bridge: Destroying proxy for cli object, "
860 S
"id:\n\t{0}\n\t{1}\n"),
863 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
, mapUnoType(m_unoType
.get()));
867 uno_Interface
* CliProxy::create(Bridge
const * bridge
,
868 System::Object
^ cliI
,
869 typelib_TypeDescription
const* pTD
,
870 const OUString
& ousOid
)
872 uno_Interface
* proxy
= static_cast<uno_Interface
*>(
873 new CliProxy(bridge
, cliI
, pTD
, ousOid
));
875 //register proxy with target environment (uno)
876 (*bridge
->m_uno_env
->registerProxyInterface
)(
878 reinterpret_cast<void**>(&proxy
),
880 ousOid
.pData
, (typelib_InterfaceTypeDescription
*) pTD
);
881 //register original interface
882 CliEnvHolder::g_cli_env
->registerInterface(cliI
, mapUnoString(ousOid
.pData
),
890 void SAL_CALL
CliProxy::uno_DispatchMethod(
891 struct _uno_Interface
*,
892 const struct _typelib_TypeDescription
*,
898 inline void CliProxy::acquire() const
900 if (1 == osl_atomic_increment( &m_ref
))
902 // rebirth of proxy zombie
903 void * that
= const_cast< CliProxy
* >( this );
904 // register at uno env
905 (*m_bridge
->m_uno_env
->registerProxyInterface
)(
906 m_bridge
->m_uno_env
, &that
,
907 cli_proxy_free
, m_usOid
.pData
,
908 (typelib_InterfaceTypeDescription
*)m_unoType
.get() );
909 #if OSL_DEBUG_LEVEL >= 2
910 OSL_ASSERT( this == (void const * const)that
);
914 //---------------------------------------------------------------------------
915 inline void CliProxy::release() const
917 if (0 == osl_atomic_decrement( &m_ref
))
919 // revoke from uno env on last release,
920 // The proxy can be resurrected if acquire is called before the uno
921 // environment calls cli_proxy_free. cli_proxy_free will
922 //delete the proxy. The environment does not acquire a registered
924 (*m_bridge
->m_uno_env
->revokeInterface
)(
925 m_bridge
->m_uno_env
, const_cast< CliProxy
* >( this ) );
934 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
*, void * proxy
)
937 cli_uno::CliProxy
* cliProxy
= reinterpret_cast<
938 cli_uno::CliProxy
* >( proxy
);
944 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
947 CliProxy
const * cliProxy
= static_cast< CliProxy
const * >( pUnoI
);
950 //-----------------------------------------------------------------------------
952 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
955 CliProxy
* cliProxy
= static_cast< CliProxy
* >( pUnoI
);
959 //------------------------------------------------------------------------------
962 void SAL_CALL
cli_proxy_dispatch(
963 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
964 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
967 CliProxy
* proxy
= static_cast< CliProxy
* >( pUnoI
);
970 Bridge
const* bridge
= proxy
->m_bridge
;
972 switch (member_td
->eTypeClass
)
974 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
977 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
978 member_td
)->nPosition
;
979 typelib_InterfaceTypeDescription
* iface_td
=
980 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
982 member_pos
< iface_td
->nAllMembers
,
983 "### member pos out of range!" );
984 sal_Int32 function_pos
=
985 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
987 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
988 "### illegal function index!" );
990 if (uno_ret
) // is getter method
992 OUString
const& usAttrName
= *(rtl_uString
**)&
993 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
995 sr::MethodInfo
^ info
= proxy
->getMethodInfo(function_pos
,
996 usAttrName
, CliProxy::MK_GET
);
1000 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1001 ->pAttributeTypeRef
,
1003 uno_ret
, 0, uno_exc
);
1005 else // is setter method
1007 OUString
const& usAttrName
= *(rtl_uString
**) &
1008 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1010 sr::MethodInfo
^ info
= proxy
->getMethodInfo(function_pos
+ 1,
1011 usAttrName
, CliProxy::MK_SET
);
1012 typelib_MethodParameter param
;
1014 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1015 ->pAttributeTypeRef
;
1016 param
.bIn
= sal_True
;
1017 param
.bOut
= sal_False
;
1021 // set follows get method
1023 0 /* indicates void return */, ¶m
, 1,
1024 0, uno_args
, uno_exc
);
1028 case typelib_TypeClass_INTERFACE_METHOD
:
1030 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
1031 member_td
)->nPosition
;
1032 typelib_InterfaceTypeDescription
* iface_td
=
1033 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
1035 member_pos
< iface_td
->nAllMembers
,
1036 "### member pos out of range!" );
1037 sal_Int32 function_pos
=
1038 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
1040 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
1041 "### illegal function index!" );
1043 switch (function_pos
)
1045 case 0: // queryInterface()
1047 TypeDescr
demanded_td(
1048 *reinterpret_cast<typelib_TypeDescriptionReference
**>(
1050 if (typelib_TypeClass_INTERFACE
1051 != demanded_td
.get()->eTypeClass
)
1053 throw BridgeRuntimeError(
1054 "queryInterface() call demands an INTERFACE type!");
1057 uno_Interface
* pInterface
= 0;
1058 (*bridge
->m_uno_env
->getRegisteredInterface
)(
1060 (void **)&pInterface
, proxy
->m_usOid
.pData
,
1061 (typelib_InterfaceTypeDescription
*)demanded_td
.get() );
1063 if (0 == pInterface
)
1065 System::Type
^ mgdDemandedType
=
1066 mapUnoType(demanded_td
.get());
1067 if (mgdDemandedType
->IsInstanceOfType( proxy
->m_cliI
))
1069 #if OSL_DEBUG_LEVEL > 0
1072 CliEnvHolder::g_cli_env
->getObjectIdentifier(
1074 OSL_ENSURE(usOid
.equals( proxy
->m_usOid
),
1075 "### different oids!");
1077 uno_Interface
* pUnoI
= bridge
->map_cli2uno(
1078 proxy
->m_cliI
, demanded_td
.get() );
1080 (uno_Any
*)uno_ret
, &pUnoI
, demanded_td
.get(), 0 );
1081 (*pUnoI
->release
)( pUnoI
);
1083 else // object does not support demanded interface
1085 uno_any_construct( (uno_Any
*)uno_ret
, 0, 0, 0 );
1087 // no excetpion occurred
1093 reinterpret_cast< uno_Any
* >( uno_ret
),
1094 &pInterface
, demanded_td
.get(), 0 );
1095 (*pInterface
->release
)( pInterface
);
1100 case 1: // acquire this proxy
1101 cli_proxy_acquire(proxy
);
1104 case 2: // release this proxy
1105 cli_proxy_release(proxy
);
1108 default: // arbitrary method call
1110 typelib_InterfaceMethodTypeDescription
* method_td
=
1111 (typelib_InterfaceMethodTypeDescription
*)member_td
;
1112 OUString
const& usMethodName
= *(rtl_uString
**) &
1113 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1116 sr::MethodInfo
^ info
= proxy
->getMethodInfo(function_pos
,
1117 usMethodName
, CliProxy::MK_METHOD
);
1121 method_td
->pReturnTypeRef
, method_td
->pParams
,
1123 uno_ret
, uno_args
, uno_exc
);
1131 throw BridgeRuntimeError(
1132 "illegal member type description!" );
1136 catch (BridgeRuntimeError
& err
)
1138 // binary identical struct
1139 ::com::sun::star::uno::RuntimeException
exc(
1140 "[cli_uno bridge error] " + err
.m_message
,
1141 ::com::sun::star::uno::Reference
<
1142 ::com::sun::star::uno::XInterface
>() );
1143 ::com::sun::star::uno::Type
const & exc_type
= ::getCppuType( & exc
);
1144 uno_type_any_construct( *uno_exc
, &exc
, exc_type
.getTypeLibType(), 0);
1145 #if OSL_DEBUG_LEVEL >= 1
1146 OString
cstr_msg(OUStringToOString(exc
.Message
,
1147 RTL_TEXTENCODING_ASCII_US
) );
1148 OSL_FAIL(cstr_msg
.getStr());
1157 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */