GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_proxy.cxx
blob09bfe60931e8c02a6dd9565d2dac1a4a7628ee12
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
25 #include "cli_base.h"
26 #include "cli_bridge.h"
28 #using <cli_ure.dll>
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;
42 extern "C"
44 //------------------------------------------------------------------------------
45 void SAL_CALL cli_proxy_free( uno_ExtEnvironment * env, void * proxy )
46 SAL_THROW_EXTERN_C();
47 //------------------------------------------------------------------------------
48 void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
49 SAL_THROW_EXTERN_C();
50 //------------------------------------------------------------------------------
51 void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
52 SAL_THROW_EXTERN_C();
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 )
57 SAL_THROW_EXTERN_C();
62 namespace cli_uno
65 UnoInterfaceInfo::UnoInterfaceInfo(Bridge const * bridge, uno_Interface* unoI,
66 typelib_InterfaceTypeDescription* td):
68 m_unoI(unoI),
69 m_typeDesc(td),
70 m_bridge(bridge)
72 m_bridge->acquire();
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);
80 if( ! bComplete)
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 );
95 m_bridge->release();
97 m_unoI->release(m_unoI);
98 typelib_typedescription_release(
99 reinterpret_cast<typelib_TypeDescription*>(m_typeDesc));
102 UnoInterfaceProxy::UnoInterfaceProxy(
103 Bridge * bridge,
104 uno_Interface * pUnoI,
105 typelib_InterfaceTypeDescription* pTD,
106 const OUString& oid )
107 :RealProxy(MarshalByRefObject::typeid),
108 m_bridge(bridge),
109 m_oid(mapUnoString(oid.pData)),
110 m_sTypeName(m_system_Object_String)
112 m_bridge->acquire();
113 // create the list that holds all UnoInterfaceInfos
114 m_listIfaces = gcnew ArrayList(10);
115 m_numUnoIfaces = 0;
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
120 _numInterfaces = 0;
121 _sInterfaces = NULL;
122 #endif
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: "),
133 m_oid));
135 sd::Trace::WriteLine( mapUnoString(_sInterfaces));
136 rtl_uString_release(_sInterfaces);
137 #endif
138 //m_bridge is unmanaged, therefore we can access it in this finalizer
139 CliEnvHolder::g_cli_env->revokeInterface(m_oid);
140 m_bridge->release();
144 System::Object^ UnoInterfaceProxy::create(
145 Bridge * bridge,
146 uno_Interface * pUnoI,
147 typelib_InterfaceTypeDescription* pTD,
148 const OUString& oid)
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));
154 return proxy;
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^>(
168 enumInfos->Current);
169 #if OSL_DEBUG_LEVEL > 1
170 System::Type * t1;
171 System::Type * t2;
172 t1 = mapUnoType(
173 reinterpret_cast<typelib_TypeDescription*>(info->m_typeDesc) );
174 t2 = mapUnoType(
175 reinterpret_cast<typelib_TypeDescription*>(pTd) );
176 #endif
177 if (typelib_typedescription_equals(
178 reinterpret_cast<typelib_TypeDescription*>(info->m_typeDesc),
179 reinterpret_cast<typelib_TypeDescription*>(pTd)))
181 return;
184 OUString oid(mapCliString(m_oid));
185 (*m_bridge->m_uno_env->registerInterface)(
186 m_bridge->m_uno_env, reinterpret_cast< void ** >( &pUnoI ),
187 oid.pData, pTd);
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
198 _numInterfaces ++;
199 OUStringBuffer buf(512);
200 buf.append("\t");
201 buf.append( OUString::valueOf((sal_Int32)_numInterfaces));
202 buf.append(". ");
203 buf.append(mapCliString(sInterfaceName));
204 buf.append("\n");
205 OUString _sNewInterface = buf.makeStringAndClear();
206 rtl_uString * __pin * pp_sInterfaces = & _sInterfaces;
207 rtl_uString_newConcat( pp_sInterfaces, * pp_sInterfaces,
208 _sNewInterface.pData);
209 #endif
211 __finally {
212 System::Threading::Monitor::Exit(this);
217 // IRemotingTypeInfo
218 bool UnoInterfaceProxy::CanCastTo(System::Type^ fromType,
219 System::Object^)
221 if (fromType == System::Object::typeid) // trivial case
222 return true;
224 System::Threading::Monitor::Enter(this);
227 if (nullptr != findInfo( fromType )) // proxy supports demanded interface
228 return true;
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);
241 args[0] = fromType;
242 uno::Any ^ pAny;
243 System::Object^ pException = nullptr;
245 pAny= static_cast<uno::Any ^>(
246 m_bridge->call_uno(
247 info->m_unoI,
248 membertd.get(),
249 ((typelib_InterfaceMethodTypeDescription*)
250 membertd.get())->pReturnTypeRef,
252 ((typelib_InterfaceMethodTypeDescription*)
253 membertd.get())->pParams,
254 args, nullptr, &pException) );
256 // handle regular exception from target
257 OSL_ENSURE(
258 nullptr == pException,
259 OUStringToOString(
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
268 return true;
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 ) );
286 return true;
290 catch (BridgeRuntimeError& e)
292 (void) e; // avoid warning
293 OSL_FAIL(
294 OUStringToOString(
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"
302 "message: \n");
303 msg= System::String::Concat(msg, e->Message);
304 OSL_FAIL(
305 OUStringToOString(
306 mapCliString(msg), RTL_TEXTENCODING_UTF8 ).getStr() );
308 catch (...)
310 OSL_FAIL(
311 "An unexpected native C++ exception occurred in "
312 "UnoInterfaceProxy::CanCastTo()" );
314 __finally
316 System::Threading::Monitor::Exit(this);
318 return false;
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))
333 // Object.Equals
334 OSL_ASSERT(args->Length == 1);
335 srrp::RealProxy^ rProxy = srr::RemotingServices::GetRealProxy(args[0]);
336 bool bDone = false;
337 if (rProxy)
339 UnoInterfaceProxy^ unoProxy =
340 dynamic_cast<UnoInterfaceProxy^>(rProxy);
341 if (unoProxy)
343 bool b = m_oid->Equals(unoProxy->getOid());
344 retMethod = b;
345 bDone = true;
348 if (bDone == false)
350 //no proxy or not our proxy, therefore Equals must be false
351 retMethod = false;
354 else if (m_GetHashCode_String->Equals(sMethod))
356 // Object.GetHashCode
357 int nHash = m_oid->GetHashCode();
358 retMethod = nHash;
360 else if (m_GetType_String->Equals(sMethod))
362 // Object.GetType
363 retMethod = System::Object::typeid;
365 else if (m_ToString_String->Equals(sMethod))
367 // Object.ToString
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();
374 else
376 //Either Object has new functions or a protected method was called
377 //which should not be possible
378 OSL_ASSERT(0);
380 srrm::IMessage^ retVal= gcnew srrm::ReturnMessage(
381 retMethod, gcnew array<System::Object^>(0), 0, context, mcm);
382 return retVal;
385 UnoInterfaceInfo ^ UnoInterfaceProxy::findInfo( ::System::Type ^ type )
387 for (int i = 0; i < m_numUnoIfaces; i++)
389 UnoInterfaceInfo^ tmpInfo = static_cast<UnoInterfaceInfo^>(
390 m_listIfaces[i]);
391 if (type->IsAssignableFrom(tmpInfo->m_type))
392 return tmpInfo;
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 );
400 if (nullptr != info)
401 return info;
403 return nullptr;
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);
452 #endif
453 sal_Int32 offset = usTypeName.indexOf( ':' ) + 2;
454 OSL_ASSERT(
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 *)
469 member_td.get();
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,
481 callmsg, pExc);
484 else
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
491 && usTypeName[
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*)
505 member_td.get();
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,
511 0, 0,
512 nullptr, nullptr, &pExc);
513 return constructReturnMessage(cli_ret, nullptr, NULL,
514 callmsg, pExc);
516 else if ('s' == usMethodName[0])
518 TypeDescr member_td( member_type );
519 typelib_InterfaceAttributeTypeDescription * attribute_td =
520 (typelib_InterfaceAttributeTypeDescription *)
521 member_td.get();
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;
533 m_bridge->call_uno(
534 info->m_unoI, member_td.get(),
535 ::getCppuVoidType().getTypeLibType(),
536 1, &param, args, nullptr, &pExc);
537 return constructReturnMessage(nullptr, nullptr, NULL,
538 callmsg, pExc);
540 else
542 return constructReturnMessage(nullptr, nullptr, NULL,
543 callmsg, nullptr);
546 break;
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));
556 buf.append( ": " );
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"
573 "message: \n"));
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);
582 catch (...)
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(
590 msg, nullptr), mcm);
592 return nullptr;
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);
606 if (exc)
608 retVal = gcnew srrm::ReturnMessage(
609 dynamic_cast<System::Exception^>(exc), mcm);
611 else
613 sc::IDictionary^ props= msg->Properties;
614 srrm::LogicalCallContext^ context=
615 static_cast<srrm::LogicalCallContext^>(
616 props[m_CallContextString]);
617 if (args != nullptr)
619 // Method
620 //build the array of out parameters, allocate max length
621 array<System::Object^>^ arOut= gcnew array<System::Object^>(mtd->nParams);
622 int nOut = 0;
623 for (int i= 0; i < mtd->nParams; i++)
625 if (mtd->pParams[i].bOut)
627 arOut[i]= args[i];
628 nOut++;
631 retVal= gcnew srrm::ReturnMessage(cliReturn, arOut, nOut,
632 context, mcm);
634 else
636 // Attribute (getXXX)
637 retVal= gcnew srrm::ReturnMessage(cliReturn, nullptr, 0,
638 context, mcm);
641 return retVal;
644 //################################################################################
645 CliProxy::CliProxy(Bridge const* bridge, System::Object^ cliI,
646 typelib_TypeDescription const* td,
647 const OUString& usOid):
648 m_ref(1),
649 m_bridge(bridge),
650 m_cliI(cliI),
651 m_unoType(const_cast<typelib_TypeDescription*>(td)),
652 m_usOid(usOid),
653 m_oid(mapUnoString(usOid.pData)),
654 m_nInheritedInterfaces(0)
656 m_bridge->acquire();
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());
664 makeMethodInfos();
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));
669 #endif
673 void CliProxy::makeMethodInfos()
675 #if OSL_DEBUG_LEVEL >= 2
676 System::Object* cliI;
677 System::Type* type;
678 cliI = m_cliI;
679 type = m_type;
680 #endif
682 if (m_type->IsInterface == false)
683 return;
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
692 //interfaces
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
703 //m_arMethodInfos
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;
716 #endif
719 //fill m_arMethodInfos with the mappings
720 // !!! InterfaceMapping.TargetMethods should be MethodInfo*[] according
721 // to documentation
722 // but it is Type*[] instead. Bug in the framework?
723 System::Type^ objType = m_cliI->GetType();
726 int index = 0;
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;
784 #endif
785 //deduct 3 for XInterface methods
786 nUnoFunctionPos -= 3;
787 System::Threading::Monitor::Enter(m_arUnoPosToCliPos);
790 int cliPos = m_arUnoPosToCliPos[nUnoFunctionPos];
791 if (cliPos != -1)
792 return m_arMethodInfos[cliPos];
794 //create the method function name
795 System::String^ sMethodName = mapUnoString(usMethodName.pData);
796 switch (methodKind)
798 case MK_METHOD:
799 break;
800 case MK_SET:
801 sMethodName = System::String::Concat(
802 const_cast<System::String^>(Constants::sAttributeSet),
803 sMethodName);
804 break;
805 case MK_GET:
806 sMethodName = System::String::Concat(
807 const_cast<System::String^>(Constants::sAttributeGet),
808 sMethodName);
809 break;
810 default:
811 OSL_ASSERT(0);
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;
822 else
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))
830 indexCliMethod = i;
831 break;
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];
846 __finally
848 System::Threading::Monitor::Exit(m_arUnoPosToCliPos);
851 return ret;
854 CliProxy::~CliProxy()
856 #if OSL_DEBUG_LEVEL >= 2
857 sd::Trace::WriteLine(System::String::Format(
858 new System::String(
859 S"cli uno bridge: Destroying proxy for cli object, "
860 S"id:\n\t{0}\n\t{1}\n"),
861 m_oid, m_type));
862 #endif
863 CliEnvHolder::g_cli_env->revokeInterface(m_oid, mapUnoType(m_unoType.get()));
864 m_bridge->release();
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)(
877 bridge->m_uno_env,
878 reinterpret_cast<void**>(&proxy),
879 cli_proxy_free,
880 ousOid.pData, (typelib_InterfaceTypeDescription*) pTD);
881 //register original interface
882 CliEnvHolder::g_cli_env->registerInterface(cliI, mapUnoString(ousOid.pData),
883 mapUnoType((pTD)));
885 return proxy;
890 void SAL_CALL CliProxy::uno_DispatchMethod(
891 struct _uno_Interface *,
892 const struct _typelib_TypeDescription *,
893 void *,
894 void **,
895 uno_Any ** )
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 );
911 #endif
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
923 //proxy.
924 (*m_bridge->m_uno_env->revokeInterface)(
925 m_bridge->m_uno_env, const_cast< CliProxy * >( this ) );
933 extern "C"
934 void SAL_CALL cli_proxy_free( uno_ExtEnvironment *, void * proxy )
935 SAL_THROW_EXTERN_C()
937 cli_uno::CliProxy * cliProxy = reinterpret_cast<
938 cli_uno::CliProxy * >( proxy );
940 delete cliProxy;
943 extern "C"
944 void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
945 SAL_THROW_EXTERN_C()
947 CliProxy const * cliProxy = static_cast< CliProxy const * >( pUnoI );
948 cliProxy->acquire();
950 //-----------------------------------------------------------------------------
951 extern "C"
952 void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
953 SAL_THROW_EXTERN_C()
955 CliProxy * cliProxy = static_cast< CliProxy * >( pUnoI );
956 cliProxy->release();
959 //------------------------------------------------------------------------------
960 extern "C"
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 )
965 SAL_THROW_EXTERN_C()
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();
981 OSL_ENSURE(
982 member_pos < iface_td->nAllMembers,
983 "### member pos out of range!" );
984 sal_Int32 function_pos =
985 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
986 OSL_ENSURE(
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)
994 ->pMemberName;
995 sr::MethodInfo^ info = proxy->getMethodInfo(function_pos,
996 usAttrName, CliProxy::MK_GET);
997 bridge->call_cli(
998 proxy->m_cliI,
999 info,
1000 ((typelib_InterfaceAttributeTypeDescription *)member_td)
1001 ->pAttributeTypeRef,
1002 0, 0, // no params
1003 uno_ret, 0, uno_exc );
1005 else // is setter method
1007 OUString const& usAttrName= *(rtl_uString**) &
1008 ((typelib_InterfaceMemberTypeDescription*) member_td)
1009 ->pMemberName;
1010 sr::MethodInfo^ info = proxy->getMethodInfo(function_pos + 1,
1011 usAttrName, CliProxy::MK_SET);
1012 typelib_MethodParameter param;
1013 param.pTypeRef =
1014 ((typelib_InterfaceAttributeTypeDescription *)member_td)
1015 ->pAttributeTypeRef;
1016 param.bIn = sal_True;
1017 param.bOut = sal_False;
1019 bridge->call_cli(
1020 proxy->m_cliI,
1021 // set follows get method
1022 info,
1023 0 /* indicates void return */, &param, 1,
1024 0, uno_args, uno_exc );
1026 break;
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();
1034 OSL_ENSURE(
1035 member_pos < iface_td->nAllMembers,
1036 "### member pos out of range!" );
1037 sal_Int32 function_pos =
1038 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
1039 OSL_ENSURE(
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 **>(
1049 uno_args[0]));
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)(
1059 bridge->m_uno_env,
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
1070 OUString usOid(
1071 mapCliString(
1072 CliEnvHolder::g_cli_env->getObjectIdentifier(
1073 proxy->m_cliI )));
1074 OSL_ENSURE(usOid.equals( proxy->m_usOid ),
1075 "### different oids!");
1076 #endif
1077 uno_Interface* pUnoI = bridge->map_cli2uno(
1078 proxy->m_cliI, demanded_td.get() );
1079 uno_any_construct(
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
1088 *uno_exc = 0;
1090 else
1092 uno_any_construct(
1093 reinterpret_cast< uno_Any * >( uno_ret ),
1094 &pInterface, demanded_td.get(), 0 );
1095 (*pInterface->release)( pInterface );
1096 *uno_exc = 0;
1098 break;
1100 case 1: // acquire this proxy
1101 cli_proxy_acquire(proxy);
1102 *uno_exc = 0;
1103 break;
1104 case 2: // release this proxy
1105 cli_proxy_release(proxy);
1106 *uno_exc = 0;
1107 break;
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)
1114 ->pMemberName;
1116 sr::MethodInfo^ info = proxy->getMethodInfo(function_pos,
1117 usMethodName, CliProxy::MK_METHOD);
1118 bridge->call_cli(
1119 proxy->m_cliI,
1120 info,
1121 method_td->pReturnTypeRef, method_td->pParams,
1122 method_td->nParams,
1123 uno_ret, uno_args, uno_exc);
1124 return;
1127 break;
1129 default:
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());
1149 #endif
1157 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */