edf64c5d88
2008/06/18 14:25:01 jl 1.3.4.1: #i88078# cli_ure moved to URE, therefore it can only build ure types, tests moved to testtools
1183 lines
44 KiB
C++
1183 lines
44 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: cli_proxy.cxx,v $
|
|
* $Revision: 1.4 $
|
|
* $RCSfile: cli_proxy.cxx,v $
|
|
* $Revision: 1.4 $
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_cli_ure.hxx"
|
|
#include "typelib/typedescription.h"
|
|
#include "rtl/ustrbuf.hxx"
|
|
#include "com/sun/star/uno/RuntimeException.hpp"
|
|
#include "osl/mutex.hxx"
|
|
#include "cli_proxy.h"
|
|
#include "cli_base.h"
|
|
#include "cli_bridge.h"
|
|
|
|
#using <mscorlib.dll>
|
|
#using <cli_ure.dll>
|
|
#using <cli_uretypes.dll>
|
|
|
|
namespace sr = System::Reflection;
|
|
namespace st = System::Text;
|
|
namespace sre = System::Reflection::Emit;
|
|
namespace sc = System::Collections;
|
|
namespace srrm = System::Runtime::Remoting::Messaging;
|
|
namespace srr = System::Runtime::Remoting;
|
|
namespace srrp = System::Runtime::Remoting::Proxies;
|
|
namespace sri = System::Runtime::InteropServices;
|
|
namespace sd = System::Diagnostics;
|
|
namespace css = com::sun::star;
|
|
namespace ucss = unoidl::com::sun::star;
|
|
|
|
using namespace cli_uno;
|
|
using namespace rtl;
|
|
extern "C"
|
|
{
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL cli_proxy_free( uno_ExtEnvironment * env, void * proxy )
|
|
SAL_THROW_EXTERN_C();
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
|
|
SAL_THROW_EXTERN_C();
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
|
|
SAL_THROW_EXTERN_C();
|
|
//------------------------------------------------------------------------------
|
|
void SAL_CALL cli_proxy_dispatch(
|
|
uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
|
|
void * uno_ret, void * uno_args[], uno_Any ** uno_exc )
|
|
SAL_THROW_EXTERN_C();
|
|
|
|
|
|
}
|
|
|
|
namespace cli_uno
|
|
{
|
|
|
|
UnoInterfaceInfo::UnoInterfaceInfo(Bridge const * bridge, uno_Interface* unoI,
|
|
typelib_InterfaceTypeDescription* td):
|
|
|
|
m_unoI(unoI),
|
|
m_typeDesc(td),
|
|
m_bridge(bridge)
|
|
{
|
|
m_bridge->acquire();
|
|
m_type = mapUnoType(reinterpret_cast<typelib_TypeDescription*>(td));
|
|
m_unoI->acquire(m_unoI);
|
|
typelib_typedescription_acquire(&m_typeDesc->aBase);
|
|
if ( ! m_typeDesc->aBase.bComplete)
|
|
{
|
|
typelib_TypeDescription* _pt = &m_typeDesc->aBase;
|
|
sal_Bool bComplete = ::typelib_typedescription_complete( & _pt);
|
|
if( ! bComplete)
|
|
{
|
|
OUStringBuffer buf( 128 );
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
|
|
"cannot make type complete: ") );
|
|
buf.append( *reinterpret_cast< OUString const * >(
|
|
& m_typeDesc->aBase.pTypeName));
|
|
throw BridgeRuntimeError(buf.makeStringAndClear());
|
|
}
|
|
}
|
|
}
|
|
UnoInterfaceInfo::~UnoInterfaceInfo()
|
|
{
|
|
//accessing unmanaged objects is ok.
|
|
m_bridge->m_uno_env->revokeInterface(
|
|
m_bridge->m_uno_env, m_unoI );
|
|
m_bridge->release();
|
|
|
|
m_unoI->release(m_unoI);
|
|
typelib_typedescription_release(
|
|
reinterpret_cast<typelib_TypeDescription*>(m_typeDesc));
|
|
}
|
|
|
|
UnoInterfaceProxy::UnoInterfaceProxy(
|
|
Bridge * bridge,
|
|
uno_Interface * pUnoI,
|
|
typelib_InterfaceTypeDescription* pTD,
|
|
const OUString& oid )
|
|
:RealProxy(__typeof(MarshalByRefObject)),
|
|
m_bridge(bridge),
|
|
m_oid(mapUnoString(oid.pData)),
|
|
m_sTypeName(m_system_Object_String)
|
|
{
|
|
m_bridge->acquire();
|
|
// create the list that holds all UnoInterfaceInfos
|
|
m_listIfaces = new ArrayList(10);
|
|
m_numUnoIfaces = 0;
|
|
m_listAdditionalProxies = new ArrayList();
|
|
m_nlistAdditionalProxies = 0;
|
|
//put the information of the first UNO interface into the arraylist
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
_numInterfaces = 0;
|
|
_sInterfaces = NULL;
|
|
#endif
|
|
addUnoInterface(pUnoI, pTD);
|
|
|
|
}
|
|
|
|
UnoInterfaceProxy::~UnoInterfaceProxy()
|
|
{
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
sd::Trace::WriteLine(System::String::Format(
|
|
new System::String(S"cli uno bridge: Destroying proxy "
|
|
S"for UNO object, OID: \n\t{0} \n\twith uno interfaces: "),
|
|
m_oid));
|
|
|
|
sd::Trace::WriteLine( mapUnoString(_sInterfaces));
|
|
rtl_uString_release(_sInterfaces);
|
|
#endif
|
|
//m_bridge is unmanaged, therefore we can access it in this finalizer
|
|
CliEnvHolder::g_cli_env->revokeInterface(m_oid);
|
|
m_bridge->release();
|
|
}
|
|
|
|
|
|
System::Object* UnoInterfaceProxy::create(
|
|
Bridge * bridge,
|
|
uno_Interface * pUnoI,
|
|
typelib_InterfaceTypeDescription* pTD,
|
|
const OUString& oid)
|
|
{
|
|
UnoInterfaceProxy* proxyHandler=
|
|
new UnoInterfaceProxy(bridge, pUnoI, pTD, oid);
|
|
System::Object* proxy= proxyHandler->GetTransparentProxy();
|
|
CliEnvHolder::g_cli_env->registerInterface(proxy, mapUnoString(oid.pData));
|
|
return proxy;
|
|
}
|
|
|
|
|
|
void UnoInterfaceProxy::addUnoInterface(uno_Interface* pUnoI,
|
|
typelib_InterfaceTypeDescription* pTd)
|
|
{
|
|
sc::IEnumerator* enumInfos = m_listIfaces->GetEnumerator();
|
|
System::Threading::Monitor::Enter(this);
|
|
try
|
|
{
|
|
while (enumInfos->MoveNext())
|
|
{
|
|
UnoInterfaceInfo* info = static_cast<UnoInterfaceInfo*>(
|
|
enumInfos->Current);
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
System::Type * t1;
|
|
System::Type * t2;
|
|
t1 = mapUnoType(
|
|
reinterpret_cast<typelib_TypeDescription*>(info->m_typeDesc) );
|
|
t2 = mapUnoType(
|
|
reinterpret_cast<typelib_TypeDescription*>(pTd) );
|
|
#endif
|
|
if (typelib_typedescription_equals(
|
|
reinterpret_cast<typelib_TypeDescription*>(info->m_typeDesc),
|
|
reinterpret_cast<typelib_TypeDescription*>(pTd)))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
OUString oid(mapCliString(m_oid));
|
|
(*m_bridge->m_uno_env->registerInterface)(
|
|
m_bridge->m_uno_env, reinterpret_cast< void ** >( &pUnoI ),
|
|
oid.pData, pTd);
|
|
//This proxy does not contain the uno_Interface. Add it.
|
|
m_listIfaces->Add(new UnoInterfaceInfo(m_bridge, pUnoI, pTd));
|
|
m_numUnoIfaces = m_listIfaces->Count;
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
System::String * sInterfaceName = static_cast<UnoInterfaceInfo*>(
|
|
m_listIfaces->get_Item(m_numUnoIfaces - 1))->m_type->FullName;
|
|
sd::Trace::WriteLine(System::String::Format(
|
|
new System::String(S"cli uno bridge: Creating proxy for uno object, "
|
|
S"id:\n\t{0}\n\t{1}"), m_oid, sInterfaceName));
|
|
// add to the string that contains all interface names
|
|
_numInterfaces ++;
|
|
OUStringBuffer buf(512);
|
|
buf.appendAscii("\t");
|
|
buf.append( OUString::valueOf((sal_Int32)_numInterfaces));
|
|
buf.appendAscii(". ");
|
|
buf.append(mapCliString(sInterfaceName));
|
|
buf.appendAscii("\n");
|
|
OUString _sNewInterface = buf.makeStringAndClear();
|
|
rtl_uString * __pin * pp_sInterfaces = & _sInterfaces;
|
|
rtl_uString_newConcat( pp_sInterfaces, * pp_sInterfaces,
|
|
_sNewInterface.pData);
|
|
#endif
|
|
}
|
|
__finally {
|
|
System::Threading::Monitor::Exit(this);
|
|
}
|
|
}
|
|
|
|
|
|
// IRemotingTypeInfo
|
|
bool UnoInterfaceProxy::CanCastTo(System::Type* fromType,
|
|
System::Object*)
|
|
{
|
|
if (fromType == __typeof(System::Object)) // trivial case
|
|
return true;
|
|
|
|
System::Threading::Monitor::Enter(this);
|
|
try
|
|
{
|
|
if (0 != findInfo( fromType )) // proxy supports demanded interface
|
|
return true;
|
|
|
|
//query an uno interface for the required type
|
|
|
|
// we use the first interface in the list (m_listIfaces) to make
|
|
// the queryInterface call
|
|
UnoInterfaceInfo* info =
|
|
static_cast<UnoInterfaceInfo*>(m_listIfaces->get_Item(0));
|
|
css::uno::TypeDescription membertd(
|
|
reinterpret_cast<typelib_InterfaceTypeDescription*>(
|
|
info->m_typeDesc)->ppAllMembers[0]);
|
|
System::Object *args[] = new System::Object*[1];
|
|
|
|
args[0] = fromType;
|
|
__box uno::Any * pAny;
|
|
System::Object* pException = NULL;
|
|
|
|
pAny= static_cast<__box uno::Any *>(
|
|
m_bridge->call_uno(
|
|
info->m_unoI,
|
|
membertd.get(),
|
|
((typelib_InterfaceMethodTypeDescription*)
|
|
membertd.get())->pReturnTypeRef,
|
|
1,
|
|
((typelib_InterfaceMethodTypeDescription*)
|
|
membertd.get())->pParams,
|
|
args, NULL, &pException) );
|
|
|
|
// handle regular exception from target
|
|
OSL_ENSURE(
|
|
0 == pException,
|
|
OUStringToOString(
|
|
mapCliString( pException->ToString()),
|
|
RTL_TEXTENCODING_UTF8 ).getStr() );
|
|
|
|
if (pAny->Type != __typeof (void)) // has value?
|
|
{
|
|
if (0 != findInfo( fromType ))
|
|
{
|
|
// proxy now supports demanded interface
|
|
return true;
|
|
}
|
|
|
|
// via aggregation: it is possible that queryInterface() returns
|
|
// and interface with a different oid.
|
|
// That way, this type is supported for the CLI
|
|
// interpreter (CanCastTo() returns true)
|
|
::System::Object * obj = pAny->Value;
|
|
OSL_ASSERT( srr::RemotingServices::IsTransparentProxy( obj ) );
|
|
if (srr::RemotingServices::IsTransparentProxy( obj ))
|
|
{
|
|
UnoInterfaceProxy * proxy =
|
|
static_cast< UnoInterfaceProxy * >(
|
|
srr::RemotingServices::GetRealProxy( obj ) );
|
|
OSL_ASSERT( 0 != proxy->findInfo( fromType ) );
|
|
m_listAdditionalProxies->Add( proxy );
|
|
m_nlistAdditionalProxies = m_listAdditionalProxies->Count;
|
|
OSL_ASSERT( 0 != findInfo( fromType ) );
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
catch (BridgeRuntimeError& e)
|
|
{
|
|
(void) e; // avoid warning
|
|
OSL_ENSURE(
|
|
0, OUStringToOString(
|
|
e.m_message, RTL_TEXTENCODING_UTF8 ).getStr() );
|
|
}
|
|
catch (System::Exception* e)
|
|
{
|
|
System::String* msg= new System::String(
|
|
S"An unexpected CLI exception occurred in "
|
|
S"UnoInterfaceProxy::CanCastTo(). Original"
|
|
S"message: \n");
|
|
msg= System::String::Concat(msg, e->get_Message());
|
|
OSL_ENSURE(
|
|
0, OUStringToOString(
|
|
mapCliString(msg), RTL_TEXTENCODING_UTF8 ).getStr() );
|
|
}
|
|
catch (...)
|
|
{
|
|
OSL_ENSURE(
|
|
0, "An unexpected native C++ exception occurred in "
|
|
"UnoInterfaceProxy::CanCastTo()" );
|
|
}
|
|
__finally
|
|
{
|
|
System::Threading::Monitor::Exit(this);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
srrm::IMessage* UnoInterfaceProxy::invokeObject(
|
|
sc::IDictionary* props,
|
|
srrm::LogicalCallContext* context,
|
|
srrm::IMethodCallMessage* mcm)
|
|
{
|
|
System::Object* retMethod = 0;
|
|
System::String* sMethod = static_cast<System::String*>
|
|
(props->get_Item(m_methodNameString));
|
|
System::Object* args[] = static_cast<System::Object*[]>(
|
|
props->get_Item(m_ArgsString));
|
|
if (m_Equals_String->Equals(sMethod))
|
|
{
|
|
// Object.Equals
|
|
OSL_ASSERT(args->get_Length() == 1);
|
|
srrp::RealProxy* rProxy = srr::RemotingServices::GetRealProxy(args[0]);
|
|
bool bDone = false;
|
|
if (rProxy)
|
|
{
|
|
UnoInterfaceProxy* unoProxy =
|
|
dynamic_cast<UnoInterfaceProxy*>(rProxy);
|
|
if (unoProxy)
|
|
{
|
|
bool b = m_oid->Equals(unoProxy->getOid());
|
|
retMethod = __box(b);
|
|
bDone = true;
|
|
}
|
|
}
|
|
if (bDone == false)
|
|
{
|
|
//no proxy or not our proxy, therefore Equals must be false
|
|
retMethod = __box(false);
|
|
}
|
|
}
|
|
else if (m_GetHashCode_String->Equals(sMethod))
|
|
{
|
|
// Object.GetHashCode
|
|
int nHash = m_oid->GetHashCode();
|
|
retMethod = __box(nHash);
|
|
}
|
|
else if (m_GetType_String->Equals(sMethod))
|
|
{
|
|
// Object.GetType
|
|
retMethod = __typeof(System::Object);
|
|
}
|
|
else if (m_ToString_String->Equals(sMethod))
|
|
{
|
|
// Object.ToString
|
|
st::StringBuilder* sb = new st::StringBuilder(256);
|
|
// sb->AppendFormat(S"Uno object proxy. Implemented interface: {0}"
|
|
// S". OID: {1}", m_type->ToString(), m_oid);
|
|
sb->AppendFormat(S"Uno object proxy. OID: {0}", m_oid);
|
|
retMethod = sb->ToString();
|
|
}
|
|
else
|
|
{
|
|
//Either Object has new functions or a protected method was called
|
|
//which should not be possible
|
|
OSL_ASSERT(0);
|
|
}
|
|
srrm::IMessage* retVal= new srrm::ReturnMessage(
|
|
retMethod, new System::Object*[0], 0, context, mcm);
|
|
return retVal;
|
|
}
|
|
|
|
UnoInterfaceInfo * UnoInterfaceProxy::findInfo( ::System::Type * type )
|
|
{
|
|
for (int i = 0; i < m_numUnoIfaces; i++)
|
|
{
|
|
UnoInterfaceInfo* tmpInfo = static_cast<UnoInterfaceInfo*>(
|
|
m_listIfaces->get_Item(i));
|
|
if (type->IsAssignableFrom(tmpInfo->m_type))
|
|
return tmpInfo;
|
|
}
|
|
for ( int i = 0; i < m_nlistAdditionalProxies; ++i )
|
|
{
|
|
UnoInterfaceProxy * proxy =
|
|
static_cast< UnoInterfaceProxy * >(
|
|
m_listAdditionalProxies->get_Item( i ) );
|
|
UnoInterfaceInfo * info = proxy->findInfo( type );
|
|
if (0 != info)
|
|
return info;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
srrm::IMessage* UnoInterfaceProxy::Invoke(srrm::IMessage* callmsg)
|
|
{
|
|
try
|
|
{
|
|
sc::IDictionary* props= callmsg->Properties;
|
|
srrm::LogicalCallContext* context=
|
|
static_cast<srrm::LogicalCallContext*>(
|
|
props->get_Item(m_CallContextString));
|
|
srrm::IMethodCallMessage* mcm=
|
|
static_cast<srrm::IMethodCallMessage*>(callmsg);
|
|
|
|
//Find out which UNO interface is being called
|
|
System::String* sTypeName = static_cast<System::String*>(
|
|
props->get_Item(m_typeNameString));
|
|
sTypeName = sTypeName->Substring(0, sTypeName->IndexOf(','));
|
|
|
|
// Special Handling for System.Object methods
|
|
if(sTypeName->IndexOf(m_system_Object_String) != -1)
|
|
{
|
|
return invokeObject(props, context, mcm);
|
|
}
|
|
|
|
System::Type* typeBeingCalled = loadCliType(sTypeName);
|
|
UnoInterfaceInfo* info = findInfo( typeBeingCalled );
|
|
OSL_ASSERT( 0 != info );
|
|
|
|
// ToDo do without string conversion, a OUString is not needed here
|
|
// get the type description of the call
|
|
OUString usMethodName(mapCliString(static_cast<System::String*>(
|
|
props->get_Item(m_methodNameString))));
|
|
typelib_TypeDescriptionReference ** ppAllMembers =
|
|
info->m_typeDesc->ppAllMembers;
|
|
sal_Int32 numberMembers = info->m_typeDesc->nAllMembers;
|
|
for ( sal_Int32 nPos = numberMembers; nPos--; )
|
|
{
|
|
typelib_TypeDescriptionReference * member_type = ppAllMembers[nPos];
|
|
|
|
// check usMethodName against fully qualified usTypeName
|
|
// of member_type; usTypeName is of the form
|
|
// <name> "::" <usMethodName> *(":@" <idx> "," <idx> ":" <name>)
|
|
OUString const & usTypeName =
|
|
OUString::unacquired( & member_type->pTypeName );
|
|
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
System::String * pTypeName;
|
|
pTypeName = mapUnoString(usTypeName.pData);
|
|
#endif
|
|
sal_Int32 offset = usTypeName.indexOf( ':' ) + 2;
|
|
OSL_ASSERT(
|
|
offset >= 2 && offset < usTypeName.getLength()
|
|
&& usTypeName[offset - 1] == ':' );
|
|
sal_Int32 remainder = usTypeName.getLength() - offset;
|
|
|
|
if (typelib_TypeClass_INTERFACE_METHOD == member_type->eTypeClass)
|
|
{
|
|
if ((usMethodName.getLength() == remainder
|
|
|| (usMethodName.getLength() < remainder
|
|
&& usTypeName[offset + usMethodName.getLength()] == ':'))
|
|
&& usTypeName.match(usMethodName, offset))
|
|
{
|
|
TypeDescr member_td( member_type );
|
|
typelib_InterfaceMethodTypeDescription * method_td =
|
|
(typelib_InterfaceMethodTypeDescription *)
|
|
member_td.get();
|
|
|
|
System::Object* args[] = static_cast<System::Object*[]>(
|
|
props->get_Item(m_ArgsString));
|
|
System::Type* argTypes[] = static_cast<System::Type*[]>(
|
|
props->get_Item(m_methodSignatureString));
|
|
System::Object* pExc = NULL;
|
|
System::Object * cli_ret = m_bridge->call_uno(
|
|
info->m_unoI, member_td.get(),
|
|
method_td->pReturnTypeRef, method_td->nParams,
|
|
method_td->pParams, args, argTypes, &pExc);
|
|
return constructReturnMessage(cli_ret, args, method_td,
|
|
callmsg, pExc);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OSL_ASSERT( typelib_TypeClass_INTERFACE_ATTRIBUTE ==
|
|
member_type->eTypeClass );
|
|
if (usMethodName.getLength() > 4
|
|
&& (usMethodName.getLength() - 4 == remainder
|
|
|| (usMethodName.getLength() - 4 < remainder
|
|
&& usTypeName[
|
|
offset + (usMethodName.getLength() - 4)] == ':'))
|
|
&& usMethodName[1] == 'e' && usMethodName[2] == 't'
|
|
&& rtl_ustr_compare_WithLength(
|
|
usTypeName.getStr() + offset,
|
|
usMethodName.getLength() - 4,
|
|
usMethodName.getStr() + 4,
|
|
usMethodName.getLength() - 4) == 0)
|
|
{
|
|
if ('g' == usMethodName[0])
|
|
{
|
|
TypeDescr member_td( member_type );
|
|
typelib_InterfaceAttributeTypeDescription * attribute_td =
|
|
(typelib_InterfaceAttributeTypeDescription*)
|
|
member_td.get();
|
|
|
|
System::Object* pExc = NULL;
|
|
System::Object* cli_ret= m_bridge->call_uno(
|
|
info->m_unoI, member_td.get(),
|
|
attribute_td->pAttributeTypeRef,
|
|
0, 0,
|
|
NULL, NULL, &pExc);
|
|
return constructReturnMessage(cli_ret, NULL, NULL,
|
|
callmsg, pExc);
|
|
}
|
|
else if ('s' == usMethodName[0])
|
|
{
|
|
TypeDescr member_td( member_type );
|
|
typelib_InterfaceAttributeTypeDescription * attribute_td =
|
|
(typelib_InterfaceAttributeTypeDescription *)
|
|
member_td.get();
|
|
if (! attribute_td->bReadOnly)
|
|
{
|
|
typelib_MethodParameter param;
|
|
param.pTypeRef = attribute_td->pAttributeTypeRef;
|
|
param.bIn = sal_True;
|
|
param.bOut = sal_False;
|
|
|
|
System::Object* args[] =
|
|
static_cast<System::Object*[]>(
|
|
props->get_Item(m_ArgsString));
|
|
System::Object* pExc = NULL;
|
|
m_bridge->call_uno(
|
|
info->m_unoI, member_td.get(),
|
|
::getCppuVoidType().getTypeLibType(),
|
|
1, ¶m, args, NULL, &pExc);
|
|
return constructReturnMessage(NULL, NULL, NULL,
|
|
callmsg, pExc);
|
|
}
|
|
else
|
|
{
|
|
return constructReturnMessage(NULL, NULL, NULL,
|
|
callmsg, NULL);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// ToDo check if the message of the exception is not crippled
|
|
// the thing that should not be... no method info found!
|
|
OUStringBuffer buf( 64 );
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
|
|
"[cli_uno bridge]calling undeclared function on "
|
|
"interface ") );
|
|
buf.append( *reinterpret_cast< OUString const * >(
|
|
& ((typelib_TypeDescription *)info->m_typeDesc)->pTypeName));
|
|
buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
|
|
buf.append( usMethodName );
|
|
throw BridgeRuntimeError( buf.makeStringAndClear() );
|
|
}
|
|
catch (BridgeRuntimeError & err)
|
|
{
|
|
srrm::IMethodCallMessage* mcm =
|
|
static_cast<srrm::IMethodCallMessage*>(callmsg);
|
|
return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
|
|
mapUnoString(err.m_message.pData), NULL), mcm);
|
|
}
|
|
catch (System::Exception* e)
|
|
{
|
|
st::StringBuilder * sb = new st::StringBuilder(512);
|
|
sb->Append(new System::String(
|
|
S"An unexpected CLI exception occurred in "
|
|
S"UnoInterfaceProxy::Invoke. Original"
|
|
S"message: \n"));
|
|
sb->Append(e->get_Message());
|
|
sb->Append((__wchar_t) '\n');
|
|
sb->Append(e->get_StackTrace());
|
|
srrm::IMethodCallMessage* mcm =
|
|
static_cast<srrm::IMethodCallMessage*>(callmsg);
|
|
return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
|
|
sb->ToString(), NULL), mcm);
|
|
}
|
|
catch (...)
|
|
{
|
|
System::String* msg = new System::String(
|
|
S"An unexpected native C++ exception occurred in "
|
|
S"UnoInterfaceProxy::Invoke.");
|
|
srrm::IMethodCallMessage* mcm =
|
|
static_cast<srrm::IMethodCallMessage*>(callmsg);
|
|
return new srrm::ReturnMessage(new ucss::uno::RuntimeException(
|
|
msg, NULL), mcm);
|
|
}
|
|
return NULL;
|
|
}
|
|
/** If the argument args is NULL then this function is called for an attribute
|
|
method (either setXXX or getXXX).
|
|
For attributes the argument mtd is also NULL.
|
|
*/
|
|
srrm::IMessage* UnoInterfaceProxy::constructReturnMessage(
|
|
System::Object* cliReturn,
|
|
System::Object* args[],
|
|
typelib_InterfaceMethodTypeDescription* mtd,
|
|
srrm::IMessage* msg, System::Object* exc)
|
|
{
|
|
srrm::IMessage * retVal= NULL;
|
|
srrm::IMethodCallMessage* mcm = static_cast<srrm::IMethodCallMessage*>(msg);
|
|
if (exc)
|
|
{
|
|
retVal = new srrm::ReturnMessage(
|
|
dynamic_cast<System::Exception*>(exc), mcm);
|
|
}
|
|
else
|
|
{
|
|
sc::IDictionary* props= msg->get_Properties();
|
|
srrm::LogicalCallContext* context=
|
|
static_cast<srrm::LogicalCallContext*>(
|
|
props->get_Item(m_CallContextString));
|
|
if (args != NULL)
|
|
{
|
|
// Method
|
|
//build the array of out parameters, allocate max length
|
|
System::Object* arOut[]= new System::Object*[mtd->nParams];
|
|
int nOut = 0;
|
|
for (int i= 0; i < mtd->nParams; i++)
|
|
{
|
|
if (mtd->pParams[i].bOut)
|
|
{
|
|
arOut[i]= args[i];
|
|
nOut++;
|
|
}
|
|
}
|
|
retVal= new srrm::ReturnMessage(cliReturn, arOut, nOut,
|
|
context, mcm);
|
|
}
|
|
else
|
|
{
|
|
// Attribute (getXXX)
|
|
retVal= new srrm::ReturnMessage(cliReturn, NULL, 0,
|
|
context, mcm);
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
//################################################################################
|
|
CliProxy::CliProxy(Bridge const* bridge, System::Object* cliI,
|
|
typelib_TypeDescription const* td,
|
|
const rtl::OUString& usOid):
|
|
m_ref(1),
|
|
m_bridge(bridge),
|
|
m_cliI(cliI),
|
|
m_unoType(const_cast<typelib_TypeDescription*>(td)),
|
|
m_usOid(usOid),
|
|
m_oid(mapUnoString(usOid.pData)),
|
|
m_nInheritedInterfaces(0)
|
|
{
|
|
m_bridge->acquire();
|
|
uno_Interface::acquire = cli_proxy_acquire;
|
|
uno_Interface::release = cli_proxy_release;
|
|
uno_Interface::pDispatcher = cli_proxy_dispatch;
|
|
|
|
m_unoType.makeComplete();
|
|
m_type= mapUnoType(m_unoType.get());
|
|
|
|
makeMethodInfos();
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
sd::Trace::WriteLine(System::String::Format(
|
|
new System::String(S"cli uno bridge: Creating proxy for cli object, "
|
|
S"id:\n\t{0}\n\t{1}"), m_oid, m_type));
|
|
#endif
|
|
|
|
}
|
|
|
|
void CliProxy::makeMethodInfos()
|
|
{
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
System::Object* cliI;
|
|
System::Type* type;
|
|
cliI = m_cliI;
|
|
type = m_type;
|
|
#endif
|
|
|
|
if (m_type->get_IsInterface() == false)
|
|
return;
|
|
sr::MethodInfo* arThisMethods[] = m_type->GetMethods();
|
|
//get the inherited interfaces
|
|
System::Type* arInheritedIfaces[] = m_type->GetInterfaces();
|
|
m_nInheritedInterfaces = arInheritedIfaces->get_Length();
|
|
//array containing the number of methods for the interface and its
|
|
//inherited interfaces
|
|
m_arInterfaceMethodCount = new int __gc [m_nInheritedInterfaces + 1];
|
|
//determine the number of all interface methods, including the inherited
|
|
//interfaces
|
|
int numMethods = arThisMethods->get_Length();
|
|
for (int i= 0; i < m_nInheritedInterfaces; i++)
|
|
{
|
|
numMethods += arInheritedIfaces[i]->GetMethods()->get_Length();
|
|
}
|
|
//array containing MethodInfos of the cli object
|
|
m_arMethodInfos = new sr::MethodInfo*[numMethods];
|
|
//array containing MethodInfos of the interface
|
|
m_arInterfaceMethodInfos = new sr::MethodInfo*[numMethods];
|
|
//array containing the mapping of Uno interface pos to pos in
|
|
//m_arMethodInfos
|
|
m_arUnoPosToCliPos = new System::Int32[numMethods];
|
|
// initialize with -1
|
|
for (int i = 0; i < numMethods; i++)
|
|
m_arUnoPosToCliPos[i] = -1;
|
|
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
sr::MethodInfo* arMethodInfosDbg[];
|
|
sr::MethodInfo* arInterfaceMethodInfosDbg[];
|
|
System::Int32 arInterfaceMethodCountDbg[];
|
|
arMethodInfosDbg = m_arMethodInfos;
|
|
arInterfaceMethodInfosDbg = m_arInterfaceMethodInfos;
|
|
arInterfaceMethodCountDbg = m_arInterfaceMethodCount;
|
|
#endif
|
|
|
|
|
|
//fill m_arMethodInfos with the mappings
|
|
// !!! InterfaceMapping.TargetMethods should be MethodInfo*[] according
|
|
// to documentation
|
|
// but it is Type*[] instead. Bug in the framework?
|
|
System::Type* objType = m_cliI->GetType();
|
|
try
|
|
{
|
|
int index = 0;
|
|
// now get the methods from the inherited interface
|
|
//arInheritedIfaces[0] is the direct base interface
|
|
//arInheritedIfaces[n] is the furthest inherited interface
|
|
//Start with the base interface
|
|
int nArLength = arInheritedIfaces->get_Length();
|
|
for (;nArLength > 0; nArLength--)
|
|
{
|
|
sr::InterfaceMapping mapInherited = objType->GetInterfaceMap(
|
|
arInheritedIfaces[nArLength - 1]);
|
|
int numMethods = mapInherited.TargetMethods->get_Length();
|
|
m_arInterfaceMethodCount[nArLength - 1] = numMethods;
|
|
for (int i = 0; i < numMethods; i++, index++)
|
|
{
|
|
m_arMethodInfos[index] = __try_cast<sr::MethodInfo*>(
|
|
mapInherited.TargetMethods[i]);
|
|
|
|
m_arInterfaceMethodInfos[index] = __try_cast<sr::MethodInfo*>(
|
|
mapInherited.InterfaceMethods[i]);
|
|
}
|
|
}
|
|
//At last come the methods of the furthest derived interface
|
|
sr::InterfaceMapping map = objType->GetInterfaceMap(m_type);
|
|
nArLength = map.TargetMethods->get_Length();
|
|
m_arInterfaceMethodCount[m_nInheritedInterfaces] = nArLength;
|
|
for (int i = 0; i < nArLength; i++,index++)
|
|
{
|
|
m_arMethodInfos[index]= __try_cast<sr::MethodInfo*>(
|
|
map.TargetMethods[i]);
|
|
m_arInterfaceMethodInfos[index]= __try_cast<sr::MethodInfo*>(
|
|
map.InterfaceMethods[i]);
|
|
}
|
|
}
|
|
catch (System::InvalidCastException* )
|
|
{
|
|
OUStringBuffer buf( 128 );
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
|
|
"[cli_uno bridge] preparing proxy for "
|
|
"cli interface: ") );
|
|
buf.append(mapCliString(m_type->ToString() ));
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" \nfailed!"));
|
|
throw BridgeRuntimeError( buf.makeStringAndClear() );
|
|
}
|
|
}
|
|
|
|
sr::MethodInfo* CliProxy::getMethodInfo(int nUnoFunctionPos,
|
|
const rtl::OUString& usMethodName, MethodKind methodKind)
|
|
{
|
|
sr::MethodInfo* ret = NULL;
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
System::String* sMethodNameDbg;
|
|
sr::MethodInfo* arMethodInfosDbg[];
|
|
sr::MethodInfo* arInterfaceMethodInfosDbg[];
|
|
System::Int32 arInterfaceMethodCountDbg[];
|
|
System::Int32 arUnoPosToCliPosDbg[];
|
|
sMethodNameDbg = mapUnoString(usMethodName.pData);
|
|
arMethodInfosDbg = m_arMethodInfos;
|
|
arInterfaceMethodInfosDbg = m_arInterfaceMethodInfos;
|
|
arInterfaceMethodCountDbg = m_arInterfaceMethodCount;
|
|
arUnoPosToCliPosDbg = m_arUnoPosToCliPos;
|
|
#endif
|
|
//deduct 3 for XInterface methods
|
|
nUnoFunctionPos -= 3;
|
|
System::Threading::Monitor::Enter(m_arUnoPosToCliPos);
|
|
try
|
|
{
|
|
int cliPos = m_arUnoPosToCliPos[nUnoFunctionPos];
|
|
if (cliPos != -1)
|
|
return m_arMethodInfos[cliPos];
|
|
|
|
//create the method function name
|
|
System::String* sMethodName = mapUnoString(usMethodName.pData);
|
|
switch (methodKind)
|
|
{
|
|
case MK_METHOD:
|
|
break;
|
|
case MK_SET:
|
|
sMethodName = System::String::Concat(
|
|
const_cast<System::String*>(Constants::sAttributeSet),
|
|
sMethodName);
|
|
break;
|
|
case MK_GET:
|
|
sMethodName = System::String::Concat(
|
|
const_cast<System::String*>(Constants::sAttributeGet),
|
|
sMethodName);
|
|
break;
|
|
default:
|
|
OSL_ASSERT(0);
|
|
}
|
|
//Find the cli interface method that corresponds to the Uno method
|
|
// System::String* sMethodName= mapUnoString(usMethodName.pData);
|
|
int indexCliMethod = -1;
|
|
//If the cli interfaces and their methods are in the same order
|
|
//as they were declared (inheritance chain and within the interface)
|
|
//then nUnoFunctionPos should lead to the correct method. However,
|
|
//the documentation does not say that this ordering is given.
|
|
if (sMethodName->Equals(m_arInterfaceMethodInfos[nUnoFunctionPos]->Name))
|
|
indexCliMethod = nUnoFunctionPos;
|
|
else
|
|
{
|
|
int cMethods = m_arInterfaceMethodInfos->get_Length();
|
|
for (int i = 0; i < cMethods; i++)
|
|
{
|
|
System::String* cliMethod = m_arInterfaceMethodInfos[i]->Name;
|
|
if (cliMethod->Equals(sMethodName))
|
|
{
|
|
indexCliMethod = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (indexCliMethod == -1)
|
|
{
|
|
OUStringBuffer buf(256);
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
|
|
"[cli_uno bridge] CliProxy::getMethodInfo():"
|
|
"cli object does not implement interface method: "));
|
|
buf.append(usMethodName);
|
|
throw BridgeRuntimeError(buf.makeStringAndClear());
|
|
return 0;
|
|
}
|
|
m_arUnoPosToCliPos[nUnoFunctionPos] = indexCliMethod;
|
|
ret = m_arMethodInfos[indexCliMethod];
|
|
}
|
|
__finally
|
|
{
|
|
System::Threading::Monitor::Exit(m_arUnoPosToCliPos);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
CliProxy::~CliProxy()
|
|
{
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
sd::Trace::WriteLine(System::String::Format(
|
|
new System::String(
|
|
S"cli uno bridge: Destroying proxy for cli object, "
|
|
S"id:\n\t{0}\n\t{1}\n"),
|
|
m_oid, m_type));
|
|
#endif
|
|
CliEnvHolder::g_cli_env->revokeInterface(m_oid, mapUnoType(m_unoType.get()));
|
|
m_bridge->release();
|
|
}
|
|
|
|
uno_Interface* CliProxy::create(Bridge const * bridge,
|
|
System::Object* cliI,
|
|
typelib_TypeDescription const* pTD,
|
|
const rtl::OUString& ousOid)
|
|
{
|
|
uno_Interface* proxy= static_cast<uno_Interface*>(
|
|
new CliProxy(bridge, cliI, pTD, ousOid));
|
|
|
|
//register proxy with target environment (uno)
|
|
(*bridge->m_uno_env->registerProxyInterface)(
|
|
bridge->m_uno_env,
|
|
reinterpret_cast<void**>(&proxy),
|
|
cli_proxy_free,
|
|
ousOid.pData, (typelib_InterfaceTypeDescription*) pTD);
|
|
//register original interface
|
|
CliEnvHolder::g_cli_env->registerInterface(cliI, mapUnoString(ousOid.pData),
|
|
mapUnoType((pTD)));
|
|
|
|
return proxy;
|
|
}
|
|
|
|
|
|
|
|
void SAL_CALL CliProxy::uno_DispatchMethod(
|
|
struct _uno_Interface *,
|
|
const struct _typelib_TypeDescription *,
|
|
void *,
|
|
void **,
|
|
uno_Any ** )
|
|
{
|
|
}
|
|
inline void CliProxy::acquire() const
|
|
{
|
|
if (1 == osl_incrementInterlockedCount( &m_ref ))
|
|
{
|
|
// rebirth of proxy zombie
|
|
void * that = const_cast< CliProxy * >( this );
|
|
// register at uno env
|
|
(*m_bridge->m_uno_env->registerProxyInterface)(
|
|
m_bridge->m_uno_env, &that,
|
|
cli_proxy_free, m_usOid.pData,
|
|
(typelib_InterfaceTypeDescription *)m_unoType.get() );
|
|
#if OSL_DEBUG_LEVEL >= 2
|
|
OSL_ASSERT( this == (void const * const)that );
|
|
#endif
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
inline void CliProxy::release() const
|
|
{
|
|
if (0 == osl_decrementInterlockedCount( &m_ref ))
|
|
{
|
|
// revoke from uno env on last release,
|
|
// The proxy can be resurrected if acquire is called before the uno
|
|
// environment calls cli_proxy_free. cli_proxy_free will
|
|
//delete the proxy. The environment does not acquire a registered
|
|
//proxy.
|
|
(*m_bridge->m_uno_env->revokeInterface)(
|
|
m_bridge->m_uno_env, const_cast< CliProxy * >( this ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C"
|
|
void SAL_CALL cli_proxy_free( uno_ExtEnvironment *, void * proxy )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
cli_uno::CliProxy * cliProxy = reinterpret_cast<
|
|
cli_uno::CliProxy * >( proxy );
|
|
|
|
delete cliProxy;
|
|
}
|
|
|
|
extern "C"
|
|
void SAL_CALL cli_proxy_acquire( uno_Interface * pUnoI )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
CliProxy const * cliProxy = static_cast< CliProxy const * >( pUnoI );
|
|
cliProxy->acquire();
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
extern "C"
|
|
void SAL_CALL cli_proxy_release( uno_Interface * pUnoI )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
CliProxy * cliProxy = static_cast< CliProxy * >( pUnoI );
|
|
cliProxy->release();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
extern "C"
|
|
|
|
void SAL_CALL cli_proxy_dispatch(
|
|
uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
|
|
void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
|
|
SAL_THROW_EXTERN_C()
|
|
{
|
|
CliProxy * proxy = static_cast< CliProxy* >( pUnoI );
|
|
try
|
|
{
|
|
Bridge const* bridge = proxy->m_bridge;
|
|
|
|
switch (member_td->eTypeClass)
|
|
{
|
|
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
|
{
|
|
|
|
sal_Int32 member_pos = ((typelib_InterfaceMemberTypeDescription *)
|
|
member_td)->nPosition;
|
|
typelib_InterfaceTypeDescription * iface_td =
|
|
(typelib_InterfaceTypeDescription *)proxy->m_unoType.get();
|
|
OSL_ENSURE(
|
|
member_pos < iface_td->nAllMembers,
|
|
"### member pos out of range!" );
|
|
sal_Int32 function_pos =
|
|
iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
|
|
OSL_ENSURE(
|
|
function_pos < iface_td->nMapFunctionIndexToMemberIndex,
|
|
"### illegal function index!" );
|
|
|
|
if (uno_ret) // is getter method
|
|
{
|
|
OUString const& usAttrName= *(rtl_uString**)&
|
|
((typelib_InterfaceMemberTypeDescription*) member_td)
|
|
->pMemberName;
|
|
sr::MethodInfo* info = proxy->getMethodInfo(function_pos,
|
|
usAttrName, CliProxy::MK_GET);
|
|
bridge->call_cli(
|
|
proxy->m_cliI,
|
|
info,
|
|
((typelib_InterfaceAttributeTypeDescription *)member_td)
|
|
->pAttributeTypeRef,
|
|
0, 0, // no params
|
|
uno_ret, 0, uno_exc );
|
|
}
|
|
else // is setter method
|
|
{
|
|
OUString const& usAttrName= *(rtl_uString**) &
|
|
((typelib_InterfaceMemberTypeDescription*) member_td)
|
|
->pMemberName;
|
|
sr::MethodInfo* info = proxy->getMethodInfo(function_pos + 1,
|
|
usAttrName, CliProxy::MK_SET);
|
|
typelib_MethodParameter param;
|
|
param.pTypeRef =
|
|
((typelib_InterfaceAttributeTypeDescription *)member_td)
|
|
->pAttributeTypeRef;
|
|
param.bIn = sal_True;
|
|
param.bOut = sal_False;
|
|
|
|
bridge->call_cli(
|
|
proxy->m_cliI,
|
|
// set follows get method
|
|
info,
|
|
0 /* indicates void return */, ¶m, 1,
|
|
0, uno_args, uno_exc );
|
|
}
|
|
break;
|
|
}
|
|
case typelib_TypeClass_INTERFACE_METHOD:
|
|
{
|
|
sal_Int32 member_pos = ((typelib_InterfaceMemberTypeDescription *)
|
|
member_td)->nPosition;
|
|
typelib_InterfaceTypeDescription * iface_td =
|
|
(typelib_InterfaceTypeDescription *)proxy->m_unoType.get();
|
|
OSL_ENSURE(
|
|
member_pos < iface_td->nAllMembers,
|
|
"### member pos out of range!" );
|
|
sal_Int32 function_pos =
|
|
iface_td->pMapMemberIndexToFunctionIndex[ member_pos ];
|
|
OSL_ENSURE(
|
|
function_pos < iface_td->nMapFunctionIndexToMemberIndex,
|
|
"### illegal function index!" );
|
|
|
|
switch (function_pos)
|
|
{
|
|
case 0: // queryInterface()
|
|
{
|
|
TypeDescr demanded_td(
|
|
*reinterpret_cast<typelib_TypeDescriptionReference **>(
|
|
uno_args[0]));
|
|
if (typelib_TypeClass_INTERFACE
|
|
!= demanded_td.get()->eTypeClass)
|
|
{
|
|
throw BridgeRuntimeError(
|
|
OUSTR("queryInterface() call demands an INTERFACE type!"));
|
|
}
|
|
|
|
uno_Interface * pInterface = 0;
|
|
(*bridge->m_uno_env->getRegisteredInterface)(
|
|
bridge->m_uno_env,
|
|
(void **)&pInterface, proxy->m_usOid.pData,
|
|
(typelib_InterfaceTypeDescription *)demanded_td.get() );
|
|
|
|
if (0 == pInterface)
|
|
{
|
|
System::Type* mgdDemandedType =
|
|
mapUnoType(demanded_td.get());
|
|
if (mgdDemandedType->IsInstanceOfType( proxy->m_cliI ))
|
|
{
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
OUString usOid(
|
|
mapCliString(
|
|
CliEnvHolder::g_cli_env->getObjectIdentifier(
|
|
proxy->m_cliI )));
|
|
OSL_ENSURE(usOid.equals( proxy->m_usOid ),
|
|
"### different oids!");
|
|
#endif
|
|
uno_Interface* pUnoI = bridge->map_cli2uno(
|
|
proxy->m_cliI, demanded_td.get() );
|
|
uno_any_construct(
|
|
(uno_Any *)uno_ret, &pUnoI, demanded_td.get(), 0 );
|
|
(*pUnoI->release)( pUnoI );
|
|
}
|
|
else // object does not support demanded interface
|
|
{
|
|
uno_any_construct( (uno_Any *)uno_ret, 0, 0, 0 );
|
|
}
|
|
// no excetpion occured
|
|
*uno_exc = 0;
|
|
}
|
|
else
|
|
{
|
|
uno_any_construct(
|
|
reinterpret_cast< uno_Any * >( uno_ret ),
|
|
&pInterface, demanded_td.get(), 0 );
|
|
(*pInterface->release)( pInterface );
|
|
*uno_exc = 0;
|
|
}
|
|
break;
|
|
}
|
|
case 1: // acquire this proxy
|
|
cli_proxy_acquire(proxy);
|
|
*uno_exc = 0;
|
|
break;
|
|
case 2: // release this proxy
|
|
cli_proxy_release(proxy);
|
|
*uno_exc = 0;
|
|
break;
|
|
default: // arbitrary method call
|
|
{
|
|
typelib_InterfaceMethodTypeDescription * method_td =
|
|
(typelib_InterfaceMethodTypeDescription *)member_td;
|
|
OUString const& usMethodName= *(rtl_uString**) &
|
|
((typelib_InterfaceMemberTypeDescription*) member_td)
|
|
->pMemberName;
|
|
|
|
sr::MethodInfo* info = proxy->getMethodInfo(function_pos,
|
|
usMethodName, CliProxy::MK_METHOD);
|
|
bridge->call_cli(
|
|
proxy->m_cliI,
|
|
info,
|
|
method_td->pReturnTypeRef, method_td->pParams,
|
|
method_td->nParams,
|
|
uno_ret, uno_args, uno_exc);
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
throw BridgeRuntimeError(
|
|
OUSTR("illegal member type description!") );
|
|
}
|
|
}
|
|
}
|
|
catch (BridgeRuntimeError & err)
|
|
{
|
|
// binary identical struct
|
|
::com::sun::star::uno::RuntimeException exc(
|
|
OUSTR("[cli_uno bridge error] ") + err.m_message,
|
|
::com::sun::star::uno::Reference<
|
|
::com::sun::star::uno::XInterface >() );
|
|
::com::sun::star::uno::Type const & exc_type = ::getCppuType( & exc);
|
|
uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0);
|
|
#if OSL_DEBUG_LEVEL >= 1
|
|
OString cstr_msg(OUStringToOString(exc.Message,
|
|
RTL_TEXTENCODING_ASCII_US ) );
|
|
OSL_ENSURE(0, cstr_msg.getStr());
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|