1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "typelib/typedescription.h"
30 #include "rtl/ustrbuf.hxx"
31 #include "com/sun/star/uno/RuntimeException.hpp"
32 #include "osl/mutex.hxx"
33 #include "cli_proxy.h"
35 #include "cli_bridge.h"
39 #using <cli_uretypes.dll>
41 namespace sr
= System::Reflection
;
42 namespace st
= System::Text
;
43 namespace sc
= System::Collections
;
44 namespace srrm
= System::Runtime::Remoting::Messaging
;
45 namespace srr
= System::Runtime::Remoting
;
46 namespace srrp
= System::Runtime::Remoting::Proxies
;
47 namespace sd
= System::Diagnostics
;
48 namespace css
= com::sun::star
;
49 namespace ucss
= unoidl::com::sun::star
;
51 using namespace cli_uno
;
53 using ::rtl::OUString
;
54 using ::rtl::OUStringToOString
;
56 using ::rtl::OUStringBuffer
;
59 //------------------------------------------------------------------------------
60 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
* env
, void * proxy
)
62 //------------------------------------------------------------------------------
63 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
65 //------------------------------------------------------------------------------
66 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
68 //------------------------------------------------------------------------------
69 void SAL_CALL
cli_proxy_dispatch(
70 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
71 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
80 UnoInterfaceInfo::UnoInterfaceInfo(Bridge
const * bridge
, uno_Interface
* unoI
,
81 typelib_InterfaceTypeDescription
* td
):
88 m_type
= mapUnoType(reinterpret_cast<typelib_TypeDescription
*>(td
));
89 m_unoI
->acquire(m_unoI
);
90 typelib_typedescription_acquire(&m_typeDesc
->aBase
);
91 if ( ! m_typeDesc
->aBase
.bComplete
)
93 typelib_TypeDescription
* _pt
= &m_typeDesc
->aBase
;
94 sal_Bool bComplete
= ::typelib_typedescription_complete( & _pt
);
97 OUStringBuffer
buf( 128 );
98 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(
99 "cannot make type complete: ") );
100 buf
.append( *reinterpret_cast< OUString
const * >(
101 & m_typeDesc
->aBase
.pTypeName
));
102 throw BridgeRuntimeError(buf
.makeStringAndClear());
106 UnoInterfaceInfo::~UnoInterfaceInfo()
108 //accessing unmanaged objects is ok.
109 m_bridge
->m_uno_env
->revokeInterface(
110 m_bridge
->m_uno_env
, m_unoI
);
113 m_unoI
->release(m_unoI
);
114 typelib_typedescription_release(
115 reinterpret_cast<typelib_TypeDescription
*>(m_typeDesc
));
118 UnoInterfaceProxy::UnoInterfaceProxy(
120 uno_Interface
* pUnoI
,
121 typelib_InterfaceTypeDescription
* pTD
,
122 const OUString
& oid
)
123 :RealProxy(__typeof(MarshalByRefObject
)),
125 m_oid(mapUnoString(oid
.pData
)),
126 m_sTypeName(m_system_Object_String
)
129 // create the list that holds all UnoInterfaceInfos
130 m_listIfaces
= new ArrayList(10);
132 m_listAdditionalProxies
= new ArrayList();
133 m_nlistAdditionalProxies
= 0;
134 //put the information of the first UNO interface into the arraylist
135 #if OSL_DEBUG_LEVEL >= 2
139 addUnoInterface(pUnoI
, pTD
);
143 UnoInterfaceProxy::~UnoInterfaceProxy()
145 #if OSL_DEBUG_LEVEL >= 2
146 sd::Trace::WriteLine(System::String::Format(
147 new System::String(S
"cli uno bridge: Destroying proxy "
148 S
"for UNO object, OID: \n\t{0} \n\twith uno interfaces: "),
151 sd::Trace::WriteLine( mapUnoString(_sInterfaces
));
152 rtl_uString_release(_sInterfaces
);
154 //m_bridge is unmanaged, therefore we can access it in this finalizer
155 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
);
160 System::Object
* UnoInterfaceProxy::create(
162 uno_Interface
* pUnoI
,
163 typelib_InterfaceTypeDescription
* pTD
,
166 UnoInterfaceProxy
* proxyHandler
=
167 new UnoInterfaceProxy(bridge
, pUnoI
, pTD
, oid
);
168 System::Object
* proxy
= proxyHandler
->GetTransparentProxy();
169 CliEnvHolder::g_cli_env
->registerInterface(proxy
, mapUnoString(oid
.pData
));
174 void UnoInterfaceProxy::addUnoInterface(uno_Interface
* pUnoI
,
175 typelib_InterfaceTypeDescription
* pTd
)
177 sc::IEnumerator
* enumInfos
= m_listIfaces
->GetEnumerator();
178 System::Threading::Monitor::Enter(this);
181 while (enumInfos
->MoveNext())
183 UnoInterfaceInfo
* info
= static_cast<UnoInterfaceInfo
*>(
185 #if OSL_DEBUG_LEVEL > 1
189 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
) );
191 reinterpret_cast<typelib_TypeDescription
*>(pTd
) );
193 if (typelib_typedescription_equals(
194 reinterpret_cast<typelib_TypeDescription
*>(info
->m_typeDesc
),
195 reinterpret_cast<typelib_TypeDescription
*>(pTd
)))
200 OUString
oid(mapCliString(m_oid
));
201 (*m_bridge
->m_uno_env
->registerInterface
)(
202 m_bridge
->m_uno_env
, reinterpret_cast< void ** >( &pUnoI
),
204 //This proxy does not contain the uno_Interface. Add it.
205 m_listIfaces
->Add(new UnoInterfaceInfo(m_bridge
, pUnoI
, pTd
));
206 m_numUnoIfaces
= m_listIfaces
->Count
;
207 #if OSL_DEBUG_LEVEL >= 2
208 System::String
* sInterfaceName
= static_cast<UnoInterfaceInfo
*>(
209 m_listIfaces
->get_Item(m_numUnoIfaces
- 1))->m_type
->FullName
;
210 sd::Trace::WriteLine(System::String::Format(
211 new System::String(S
"cli uno bridge: Creating proxy for uno object, "
212 S
"id:\n\t{0}\n\t{1}"), m_oid
, sInterfaceName
));
213 // add to the string that contains all interface names
215 OUStringBuffer
buf(512);
216 buf
.appendAscii("\t");
217 buf
.append( OUString::valueOf((sal_Int32
)_numInterfaces
));
218 buf
.appendAscii(". ");
219 buf
.append(mapCliString(sInterfaceName
));
220 buf
.appendAscii("\n");
221 OUString _sNewInterface
= buf
.makeStringAndClear();
222 rtl_uString
* __pin
* pp_sInterfaces
= & _sInterfaces
;
223 rtl_uString_newConcat( pp_sInterfaces
, * pp_sInterfaces
,
224 _sNewInterface
.pData
);
228 System::Threading::Monitor::Exit(this);
234 bool UnoInterfaceProxy::CanCastTo(System::Type
* fromType
,
237 if (fromType
== __typeof(System::Object
)) // trivial case
240 System::Threading::Monitor::Enter(this);
243 if (0 != findInfo( fromType
)) // proxy supports demanded interface
246 //query an uno interface for the required type
248 // we use the first interface in the list (m_listIfaces) to make
249 // the queryInterface call
250 UnoInterfaceInfo
* info
=
251 static_cast<UnoInterfaceInfo
*>(m_listIfaces
->get_Item(0));
252 css::uno::TypeDescription
membertd(
253 reinterpret_cast<typelib_InterfaceTypeDescription
*>(
254 info
->m_typeDesc
)->ppAllMembers
[0]);
255 System::Object
*args
[] = new System::Object
*[1];
258 __box
uno::Any
* pAny
;
259 System::Object
* pException
= NULL
;
261 pAny
= static_cast<__box
uno::Any
*>(
265 ((typelib_InterfaceMethodTypeDescription
*)
266 membertd
.get())->pReturnTypeRef
,
268 ((typelib_InterfaceMethodTypeDescription
*)
269 membertd
.get())->pParams
,
270 args
, NULL
, &pException
) );
272 // handle regular exception from target
276 mapCliString( pException
->ToString()),
277 RTL_TEXTENCODING_UTF8
).getStr() );
279 if (pAny
->Type
!= __typeof (void)) // has value?
281 if (0 != findInfo( fromType
))
283 // proxy now supports demanded interface
287 // via aggregation: it is possible that queryInterface() returns
288 // and interface with a different oid.
289 // That way, this type is supported for the CLI
290 // interpreter (CanCastTo() returns true)
291 ::System::Object
* obj
= pAny
->Value
;
292 OSL_ASSERT( srr::RemotingServices::IsTransparentProxy( obj
) );
293 if (srr::RemotingServices::IsTransparentProxy( obj
))
295 UnoInterfaceProxy
* proxy
=
296 static_cast< UnoInterfaceProxy
* >(
297 srr::RemotingServices::GetRealProxy( obj
) );
298 OSL_ASSERT( 0 != proxy
->findInfo( fromType
) );
299 m_listAdditionalProxies
->Add( proxy
);
300 m_nlistAdditionalProxies
= m_listAdditionalProxies
->Count
;
301 OSL_ASSERT( 0 != findInfo( fromType
) );
306 catch (BridgeRuntimeError
& e
)
308 (void) e
; // avoid warning
311 e
.m_message
, RTL_TEXTENCODING_UTF8
).getStr() );
313 catch (System::Exception
* e
)
315 System::String
* msg
= new System::String(
316 S
"An unexpected CLI exception occurred in "
317 S
"UnoInterfaceProxy::CanCastTo(). Original"
319 msg
= System::String::Concat(msg
, e
->get_Message());
322 mapCliString(msg
), RTL_TEXTENCODING_UTF8
).getStr() );
327 "An unexpected native C++ exception occurred in "
328 "UnoInterfaceProxy::CanCastTo()" );
332 System::Threading::Monitor::Exit(this);
337 srrm::IMessage
* UnoInterfaceProxy::invokeObject(
338 sc::IDictionary
* props
,
339 srrm::LogicalCallContext
* context
,
340 srrm::IMethodCallMessage
* mcm
)
342 System::Object
* retMethod
= 0;
343 System::String
* sMethod
= static_cast<System::String
*>
344 (props
->get_Item(m_methodNameString
));
345 System::Object
* args
[] = static_cast<System::Object
*[]>(
346 props
->get_Item(m_ArgsString
));
347 if (m_Equals_String
->Equals(sMethod
))
350 OSL_ASSERT(args
->get_Length() == 1);
351 srrp::RealProxy
* rProxy
= srr::RemotingServices::GetRealProxy(args
[0]);
355 UnoInterfaceProxy
* unoProxy
=
356 dynamic_cast<UnoInterfaceProxy
*>(rProxy
);
359 bool b
= m_oid
->Equals(unoProxy
->getOid());
360 retMethod
= __box(b
);
366 //no proxy or not our proxy, therefore Equals must be false
367 retMethod
= __box(false);
370 else if (m_GetHashCode_String
->Equals(sMethod
))
372 // Object.GetHashCode
373 int nHash
= m_oid
->GetHashCode();
374 retMethod
= __box(nHash
);
376 else if (m_GetType_String
->Equals(sMethod
))
379 retMethod
= __typeof(System::Object
);
381 else if (m_ToString_String
->Equals(sMethod
))
384 st::StringBuilder
* sb
= new st::StringBuilder(256);
385 // sb->AppendFormat(S"Uno object proxy. Implemented interface: {0}"
386 // S". OID: {1}", m_type->ToString(), m_oid);
387 sb
->AppendFormat(S
"Uno object proxy. OID: {0}", m_oid
);
388 retMethod
= sb
->ToString();
392 //Either Object has new functions or a protected method was called
393 //which should not be possible
396 srrm::IMessage
* retVal
= new srrm::ReturnMessage(
397 retMethod
, new System::Object
*[0], 0, context
, mcm
);
401 UnoInterfaceInfo
* UnoInterfaceProxy::findInfo( ::System::Type
* type
)
403 for (int i
= 0; i
< m_numUnoIfaces
; i
++)
405 UnoInterfaceInfo
* tmpInfo
= static_cast<UnoInterfaceInfo
*>(
406 m_listIfaces
->get_Item(i
));
407 if (type
->IsAssignableFrom(tmpInfo
->m_type
))
410 for ( int i
= 0; i
< m_nlistAdditionalProxies
; ++i
)
412 UnoInterfaceProxy
* proxy
=
413 static_cast< UnoInterfaceProxy
* >(
414 m_listAdditionalProxies
->get_Item( i
) );
415 UnoInterfaceInfo
* info
= proxy
->findInfo( type
);
422 srrm::IMessage
* UnoInterfaceProxy::Invoke(srrm::IMessage
* callmsg
)
426 sc::IDictionary
* props
= callmsg
->Properties
;
427 srrm::LogicalCallContext
* context
=
428 static_cast<srrm::LogicalCallContext
*>(
429 props
->get_Item(m_CallContextString
));
430 srrm::IMethodCallMessage
* mcm
=
431 static_cast<srrm::IMethodCallMessage
*>(callmsg
);
433 //Find out which UNO interface is being called
434 System::String
* sTypeName
= static_cast<System::String
*>(
435 props
->get_Item(m_typeNameString
));
436 sTypeName
= sTypeName
->Substring(0, sTypeName
->IndexOf(','));
438 // Special Handling for System.Object methods
439 if(sTypeName
->IndexOf(m_system_Object_String
) != -1)
441 return invokeObject(props
, context
, mcm
);
444 System::Type
* typeBeingCalled
= loadCliType(sTypeName
);
445 UnoInterfaceInfo
* info
= findInfo( typeBeingCalled
);
446 OSL_ASSERT( 0 != info
);
448 // ToDo do without string conversion, a OUString is not needed here
449 // get the type description of the call
450 OUString
usMethodName(mapCliString(static_cast<System::String
*>(
451 props
->get_Item(m_methodNameString
))));
452 typelib_TypeDescriptionReference
** ppAllMembers
=
453 info
->m_typeDesc
->ppAllMembers
;
454 sal_Int32 numberMembers
= info
->m_typeDesc
->nAllMembers
;
455 for ( sal_Int32 nPos
= numberMembers
; nPos
--; )
457 typelib_TypeDescriptionReference
* member_type
= ppAllMembers
[nPos
];
459 // check usMethodName against fully qualified usTypeName
460 // of member_type; usTypeName is of the form
461 // <name> "::" <usMethodName> *(":@" <idx> "," <idx> ":" <name>)
462 OUString
const & usTypeName
=
463 OUString::unacquired( & member_type
->pTypeName
);
465 #if OSL_DEBUG_LEVEL >= 2
466 System::String
* pTypeName
;
467 pTypeName
= mapUnoString(usTypeName
.pData
);
469 sal_Int32 offset
= usTypeName
.indexOf( ':' ) + 2;
471 offset
>= 2 && offset
< usTypeName
.getLength()
472 && usTypeName
[offset
- 1] == ':' );
473 sal_Int32 remainder
= usTypeName
.getLength() - offset
;
475 if (typelib_TypeClass_INTERFACE_METHOD
== member_type
->eTypeClass
)
477 if ((usMethodName
.getLength() == remainder
478 || (usMethodName
.getLength() < remainder
479 && usTypeName
[offset
+ usMethodName
.getLength()] == ':'))
480 && usTypeName
.match(usMethodName
, offset
))
482 TypeDescr
member_td( member_type
);
483 typelib_InterfaceMethodTypeDescription
* method_td
=
484 (typelib_InterfaceMethodTypeDescription
*)
487 System::Object
* args
[] = static_cast<System::Object
*[]>(
488 props
->get_Item(m_ArgsString
));
489 System::Type
* argTypes
[] = static_cast<System::Type
*[]>(
490 props
->get_Item(m_methodSignatureString
));
491 System::Object
* pExc
= NULL
;
492 System::Object
* cli_ret
= m_bridge
->call_uno(
493 info
->m_unoI
, member_td
.get(),
494 method_td
->pReturnTypeRef
, method_td
->nParams
,
495 method_td
->pParams
, args
, argTypes
, &pExc
);
496 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());
864 m_arUnoPosToCliPos
[nUnoFunctionPos
] = indexCliMethod
;
865 ret
= m_arMethodInfos
[indexCliMethod
];
869 System::Threading::Monitor::Exit(m_arUnoPosToCliPos
);
875 CliProxy::~CliProxy()
877 #if OSL_DEBUG_LEVEL >= 2
878 sd::Trace::WriteLine(System::String::Format(
880 S
"cli uno bridge: Destroying proxy for cli object, "
881 S
"id:\n\t{0}\n\t{1}\n"),
884 CliEnvHolder::g_cli_env
->revokeInterface(m_oid
, mapUnoType(m_unoType
.get()));
888 uno_Interface
* CliProxy::create(Bridge
const * bridge
,
889 System::Object
* cliI
,
890 typelib_TypeDescription
const* pTD
,
891 const rtl::OUString
& ousOid
)
893 uno_Interface
* proxy
= static_cast<uno_Interface
*>(
894 new CliProxy(bridge
, cliI
, pTD
, ousOid
));
896 //register proxy with target environment (uno)
897 (*bridge
->m_uno_env
->registerProxyInterface
)(
899 reinterpret_cast<void**>(&proxy
),
901 ousOid
.pData
, (typelib_InterfaceTypeDescription
*) pTD
);
902 //register original interface
903 CliEnvHolder::g_cli_env
->registerInterface(cliI
, mapUnoString(ousOid
.pData
),
911 void SAL_CALL
CliProxy::uno_DispatchMethod(
912 struct _uno_Interface
*,
913 const struct _typelib_TypeDescription
*,
919 inline void CliProxy::acquire() const
921 if (1 == osl_incrementInterlockedCount( &m_ref
))
923 // rebirth of proxy zombie
924 void * that
= const_cast< CliProxy
* >( this );
925 // register at uno env
926 (*m_bridge
->m_uno_env
->registerProxyInterface
)(
927 m_bridge
->m_uno_env
, &that
,
928 cli_proxy_free
, m_usOid
.pData
,
929 (typelib_InterfaceTypeDescription
*)m_unoType
.get() );
930 #if OSL_DEBUG_LEVEL >= 2
931 OSL_ASSERT( this == (void const * const)that
);
935 //---------------------------------------------------------------------------
936 inline void CliProxy::release() const
938 if (0 == osl_decrementInterlockedCount( &m_ref
))
940 // revoke from uno env on last release,
941 // The proxy can be resurrected if acquire is called before the uno
942 // environment calls cli_proxy_free. cli_proxy_free will
943 //delete the proxy. The environment does not acquire a registered
945 (*m_bridge
->m_uno_env
->revokeInterface
)(
946 m_bridge
->m_uno_env
, const_cast< CliProxy
* >( this ) );
955 void SAL_CALL
cli_proxy_free( uno_ExtEnvironment
*, void * proxy
)
958 cli_uno::CliProxy
* cliProxy
= reinterpret_cast<
959 cli_uno::CliProxy
* >( proxy
);
965 void SAL_CALL
cli_proxy_acquire( uno_Interface
* pUnoI
)
968 CliProxy
const * cliProxy
= static_cast< CliProxy
const * >( pUnoI
);
971 //-----------------------------------------------------------------------------
973 void SAL_CALL
cli_proxy_release( uno_Interface
* pUnoI
)
976 CliProxy
* cliProxy
= static_cast< CliProxy
* >( pUnoI
);
980 //------------------------------------------------------------------------------
983 void SAL_CALL
cli_proxy_dispatch(
984 uno_Interface
* pUnoI
, typelib_TypeDescription
const * member_td
,
985 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
)
988 CliProxy
* proxy
= static_cast< CliProxy
* >( pUnoI
);
991 Bridge
const* bridge
= proxy
->m_bridge
;
993 switch (member_td
->eTypeClass
)
995 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
998 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
999 member_td
)->nPosition
;
1000 typelib_InterfaceTypeDescription
* iface_td
=
1001 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
1003 member_pos
< iface_td
->nAllMembers
,
1004 "### member pos out of range!" );
1005 sal_Int32 function_pos
=
1006 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
1008 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
1009 "### illegal function index!" );
1011 if (uno_ret
) // is getter method
1013 OUString
const& usAttrName
= *(rtl_uString
**)&
1014 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1016 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
,
1017 usAttrName
, CliProxy::MK_GET
);
1021 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1022 ->pAttributeTypeRef
,
1024 uno_ret
, 0, uno_exc
);
1026 else // is setter method
1028 OUString
const& usAttrName
= *(rtl_uString
**) &
1029 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1031 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
+ 1,
1032 usAttrName
, CliProxy::MK_SET
);
1033 typelib_MethodParameter param
;
1035 ((typelib_InterfaceAttributeTypeDescription
*)member_td
)
1036 ->pAttributeTypeRef
;
1037 param
.bIn
= sal_True
;
1038 param
.bOut
= sal_False
;
1042 // set follows get method
1044 0 /* indicates void return */, ¶m
, 1,
1045 0, uno_args
, uno_exc
);
1049 case typelib_TypeClass_INTERFACE_METHOD
:
1051 sal_Int32 member_pos
= ((typelib_InterfaceMemberTypeDescription
*)
1052 member_td
)->nPosition
;
1053 typelib_InterfaceTypeDescription
* iface_td
=
1054 (typelib_InterfaceTypeDescription
*)proxy
->m_unoType
.get();
1056 member_pos
< iface_td
->nAllMembers
,
1057 "### member pos out of range!" );
1058 sal_Int32 function_pos
=
1059 iface_td
->pMapMemberIndexToFunctionIndex
[ member_pos
];
1061 function_pos
< iface_td
->nMapFunctionIndexToMemberIndex
,
1062 "### illegal function index!" );
1064 switch (function_pos
)
1066 case 0: // queryInterface()
1068 TypeDescr
demanded_td(
1069 *reinterpret_cast<typelib_TypeDescriptionReference
**>(
1071 if (typelib_TypeClass_INTERFACE
1072 != demanded_td
.get()->eTypeClass
)
1074 throw BridgeRuntimeError(
1075 OUSTR("queryInterface() call demands an INTERFACE type!"));
1078 uno_Interface
* pInterface
= 0;
1079 (*bridge
->m_uno_env
->getRegisteredInterface
)(
1081 (void **)&pInterface
, proxy
->m_usOid
.pData
,
1082 (typelib_InterfaceTypeDescription
*)demanded_td
.get() );
1084 if (0 == pInterface
)
1086 System::Type
* mgdDemandedType
=
1087 mapUnoType(demanded_td
.get());
1088 if (mgdDemandedType
->IsInstanceOfType( proxy
->m_cliI
))
1090 #if OSL_DEBUG_LEVEL > 0
1093 CliEnvHolder::g_cli_env
->getObjectIdentifier(
1095 OSL_ENSURE(usOid
.equals( proxy
->m_usOid
),
1096 "### different oids!");
1098 uno_Interface
* pUnoI
= bridge
->map_cli2uno(
1099 proxy
->m_cliI
, demanded_td
.get() );
1101 (uno_Any
*)uno_ret
, &pUnoI
, demanded_td
.get(), 0 );
1102 (*pUnoI
->release
)( pUnoI
);
1104 else // object does not support demanded interface
1106 uno_any_construct( (uno_Any
*)uno_ret
, 0, 0, 0 );
1108 // no excetpion occurred
1114 reinterpret_cast< uno_Any
* >( uno_ret
),
1115 &pInterface
, demanded_td
.get(), 0 );
1116 (*pInterface
->release
)( pInterface
);
1121 case 1: // acquire this proxy
1122 cli_proxy_acquire(proxy
);
1125 case 2: // release this proxy
1126 cli_proxy_release(proxy
);
1129 default: // arbitrary method call
1131 typelib_InterfaceMethodTypeDescription
* method_td
=
1132 (typelib_InterfaceMethodTypeDescription
*)member_td
;
1133 OUString
const& usMethodName
= *(rtl_uString
**) &
1134 ((typelib_InterfaceMemberTypeDescription
*) member_td
)
1137 sr::MethodInfo
* info
= proxy
->getMethodInfo(function_pos
,
1138 usMethodName
, CliProxy::MK_METHOD
);
1142 method_td
->pReturnTypeRef
, method_td
->pParams
,
1144 uno_ret
, uno_args
, uno_exc
);
1152 throw BridgeRuntimeError(
1153 OUSTR("illegal member type description!") );
1157 catch (BridgeRuntimeError
& err
)
1159 // binary identical struct
1160 ::com::sun::star::uno::RuntimeException
exc(
1161 OUSTR("[cli_uno bridge error] ") + err
.m_message
,
1162 ::com::sun::star::uno::Reference
<
1163 ::com::sun::star::uno::XInterface
>() );
1164 ::com::sun::star::uno::Type
const & exc_type
= ::getCppuType( & exc
);
1165 uno_type_any_construct( *uno_exc
, &exc
, exc_type
.getTypeLibType(), 0);
1166 #if OSL_DEBUG_LEVEL >= 1
1167 OString
cstr_msg(OUStringToOString(exc
.Message
,
1168 RTL_TEXTENCODING_ASCII_US
) );
1169 OSL_FAIL(cstr_msg
.getStr());
1178 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */