summaryrefslogtreecommitdiff
path: root/cli_ure/source/uno_bridge
diff options
context:
space:
mode:
Diffstat (limited to 'cli_ure/source/uno_bridge')
-rw-r--r--cli_ure/source/uno_bridge/README.txt20
-rw-r--r--cli_ure/source/uno_bridge/bridge_exports.map8
-rw-r--r--cli_ure/source/uno_bridge/cli_base.h180
-rw-r--r--cli_ure/source/uno_bridge/cli_bridge.cxx369
-rw-r--r--cli_ure/source/uno_bridge/cli_bridge.h120
-rw-r--r--cli_ure/source/uno_bridge/cli_data.cxx2011
-rw-r--r--cli_ure/source/uno_bridge/cli_environment.cxx173
-rw-r--r--cli_ure/source/uno_bridge/cli_environment.h114
-rw-r--r--cli_ure/source/uno_bridge/cli_proxy.cxx1178
-rw-r--r--cli_ure/source/uno_bridge/cli_proxy.h299
-rw-r--r--cli_ure/source/uno_bridge/cli_uno.cxx290
-rw-r--r--cli_ure/source/uno_bridge/makefile.mk95
12 files changed, 4857 insertions, 0 deletions
diff --git a/cli_ure/source/uno_bridge/README.txt b/cli_ure/source/uno_bridge/README.txt
new file mode 100644
index 000000000000..39b3ce3648fe
--- /dev/null
+++ b/cli_ure/source/uno_bridge/README.txt
@@ -0,0 +1,20 @@
+Because of the LoaderLock bug in .NET Framework 1.0 and 1.1 the cli_uno.dll is linked
+with the /NOENTRY switch, which prevent that the C-runtime is initialized when loading
+the dll.
+
+Also I removed all static c++ objects which need construction by the CRT,
+exception handling seems to need an initialised CRT. Therefore
+I added CRT initialization code in uno_initEnvironment (cli_bridge.cxx)
+However there is no deinitialization done because bridge libraries remain
+in memory until the process dies. There is actually no good place where
+this had to be called. If we would do that we would have to implement that
+the bridge can be disposed.
+
+
+Sell also:
+
+http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vcconmixeddllloadingproblem.asp
+http://support.microsoft.com/?id=814472
+http://www.ddj.com/dept/windows/184416689
+http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx
+http://msdn2.microsoft.com/en-US/library/ms172219.aspx \ No newline at end of file
diff --git a/cli_ure/source/uno_bridge/bridge_exports.map b/cli_ure/source/uno_bridge/bridge_exports.map
new file mode 100644
index 000000000000..df39965a2b51
--- /dev/null
+++ b/cli_ure/source/uno_bridge/bridge_exports.map
@@ -0,0 +1,8 @@
+UDK_3_0_0 {
+ global:
+ component_canUnload;
+ uno_initEnvironment;
+ uno_ext_getMapping;
+ local:
+ *;
+};
diff --git a/cli_ure/source/uno_bridge/cli_base.h b/cli_ure/source/uno_bridge/cli_base.h
new file mode 100644
index 000000000000..0ff3f40f9762
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_base.h
@@ -0,0 +1,180 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_CLI_BASE_H
+#define INCLUDED_CLI_BASE_H
+
+#pragma unmanaged
+// Workaround: osl/mutex.h contains only a forward declaration of _oslMutexImpls.
+// When using the inline class in Mutex in osl/mutex.hxx, the loader needs to find
+// a declaration for the struct. If not found a TypeLoadException is being thrown.
+struct _oslMutexImpl
+{
+};
+#pragma managed
+#include <memory>
+#include "rtl/ustring.hxx"
+#include "typelib/typedescription.hxx"
+
+#using <mscorlib.dll>
+#using <system.dll>
+
+#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
+
+namespace cli_uno
+{
+System::Type* loadCliType(System::String * typeName);
+System::Type* mapUnoType(typelib_TypeDescription const * pTD);
+System::Type* mapUnoType(typelib_TypeDescriptionReference const * pTD);
+typelib_TypeDescriptionReference* mapCliType(System::Type* cliType);
+rtl::OUString mapCliString(System::String const * data);
+System::String* mapUnoString(rtl_uString const * data);
+System::String* mapUnoTypeName(rtl_uString const * typeName);
+
+__gc struct Constants
+{
+ static const System::String* sXInterfaceName= new System::String(
+ S"unoidl.com.sun.star.uno.XInterface");
+ static const System::String* sObject= new System::String(S"System.Object");
+ static const System::String* sType= new System::String(S"System.Type");
+ static const System::String* sUnoidl= new System::String(S"unoidl.");
+ static const System::String* sVoid= new System::String(S"System.Void");
+ static const System::String* sAny= new System::String(S"uno.Any");
+ static const System::String* sArArray= new System::String(S"System.Array[]");
+ static const System::String* sBoolean= new System::String(S"System.Boolean");
+ static const System::String* sChar= new System::String(S"System.Char");
+ static const System::String* sByte= new System::String(S"System.Byte");
+ static const System::String* sInt16= new System::String(S"System.Int16");
+ static const System::String* sUInt16= new System::String(S"System.UInt16");
+ static const System::String* sInt32= new System::String(S"System.Int32");
+ static const System::String* sUInt32= new System::String(S"System.UInt32");
+ static const System::String* sInt64= new System::String(S"System.Int64");
+ static const System::String* sUInt64= new System::String(S"System.UInt64");
+ static const System::String* sString= new System::String(S"System.String");
+ static const System::String* sSingle= new System::String(S"System.Single");
+ static const System::String* sDouble= new System::String(S"System.Double");
+ static const System::String* sArBoolean= new System::String(S"System.Boolean[]");
+ static const System::String* sArChar= new System::String(S"System.Char[]");
+ static const System::String* sArByte= new System::String(S"System.Byte[]");
+ static const System::String* sArInt16= new System::String(S"System.Int16[]");
+ static const System::String* sArUInt16= new System::String(S"System.UInt16[]");
+ static const System::String* sArInt32= new System::String(S"System.Int32[]");
+ static const System::String* sArUInt32= new System::String(S"System.UInt32[]");
+ static const System::String* sArInt64= new System::String(S"System.Int64[]");
+ static const System::String* sArUInt64= new System::String(S"System.UInt64[]");
+ static const System::String* sArString= new System::String(S"System.String[]");
+ static const System::String* sArSingle= new System::String(S"System.Single[]");
+ static const System::String* sArDouble= new System::String(S"System.Double[]");
+ static const System::String* sArType= new System::String(S"System.Type[]");
+ static const System::String* sArObject= new System::String(S"System.Object[]");
+ static const System::String* sBrackets= new System::String(S"[]");
+ static const System::String* sAttributeSet= new System::String(S"set_");
+ static const System::String* sAttributeGet= new System::String(S"get_");
+
+ static const System::String* usXInterface = S"com.sun.star.uno.XInterface";
+ static const System::String* usVoid = S"void";
+ static const System::String* usType = S"type";
+ static const System::String* usAny = S"any";
+ static const System::String* usBrackets = S"[]";
+ static const System::String* usBool = S"boolean";
+ static const System::String* usByte = S"byte";
+ static const System::String* usChar = S"char";
+ static const System::String* usShort = S"short";
+ static const System::String* usUShort = S"unsigned short";
+ static const System::String* usLong = S"long";
+ static const System::String* usULong = S"unsigned long";
+ static const System::String* usHyper = S"hyper";
+ static const System::String* usUHyper = S"unsigned hyper";
+ static const System::String* usString = S"string";
+ static const System::String* usFloat = S"float";
+ static const System::String* usDouble = S"double";
+};
+
+struct BridgeRuntimeError
+{
+ ::rtl::OUString m_message;
+
+ inline BridgeRuntimeError( ::rtl::OUString const & message )
+ : m_message( message )
+ {}
+};
+
+//==================================================================================================
+struct rtl_mem
+{
+ inline static void * operator new ( size_t nSize )
+ { return rtl_allocateMemory( nSize ); }
+ inline static void operator delete ( void * mem )
+ { if (mem) rtl_freeMemory( mem ); }
+ inline static void * operator new ( size_t, void * mem )
+ { return mem; }
+ inline static void operator delete ( void *, void * )
+ {}
+
+ static inline ::std::auto_ptr< rtl_mem > allocate( ::std::size_t bytes );
+};
+//--------------------------------------------------------------------------------------------------
+inline ::std::auto_ptr< rtl_mem > rtl_mem::allocate( ::std::size_t bytes )
+{
+ void * p = rtl_allocateMemory( bytes );
+ if (0 == p)
+ throw BridgeRuntimeError(OUSTR("out of memory!") );
+ return ::std::auto_ptr< rtl_mem >( (rtl_mem *)p );
+}
+
+//==================================================================================================
+class TypeDescr
+{
+ typelib_TypeDescription * m_td;
+
+ TypeDescr( TypeDescr & ); // not impl
+ void operator = ( TypeDescr ); // not impl
+
+public:
+ inline explicit TypeDescr( typelib_TypeDescriptionReference * td_ref );
+ inline ~TypeDescr() SAL_THROW( () )
+ { TYPELIB_DANGER_RELEASE( m_td ); }
+
+ inline typelib_TypeDescription * get() const
+ { return m_td; }
+};
+
+inline TypeDescr::TypeDescr( typelib_TypeDescriptionReference * td_ref )
+ : m_td( 0 )
+{
+ TYPELIB_DANGER_GET( &m_td, td_ref );
+ if (0 == m_td)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("cannot get comprehensive type description for ") +
+ *reinterpret_cast< ::rtl::OUString const * >( &td_ref->pTypeName ) );
+ }
+}
+
+
+} //end namespace cli_uno
+ #endif
diff --git a/cli_ure/source/uno_bridge/cli_bridge.cxx b/cli_ure/source/uno_bridge/cli_bridge.cxx
new file mode 100644
index 000000000000..ab78b2f9d95b
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_bridge.cxx
@@ -0,0 +1,369 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <vcclr.h>
+//ToDo: remove when build with .NET 2
+#pragma warning(push, 1)
+#include <windows.h>
+#include "uno/environment.hxx"
+#pragma warning(pop)
+#include "rtl/unload.h"
+#include "uno/lbnames.h"
+#include "uno/mapping.hxx"
+#include "typelib/typedescription.hxx"
+#include "rtl/ustring.hxx"
+
+#include "cli_bridge.h"
+#include "cli_proxy.h"
+namespace srr= System::Runtime::Remoting;
+namespace srrp= System::Runtime::Remoting::Proxies;
+#using <mscorlib.dll>
+#if defined(_MSC_VER) && (_MSC_VER < 1400)
+#include <_vcclrit.h>
+#endif
+
+namespace cssu= com::sun::star::uno;
+
+
+namespace sri= System::Runtime::InteropServices;
+using namespace rtl;
+
+namespace cli_uno
+{
+
+extern "C"
+{
+void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ that->m_bridge->acquire();
+}
+//--------------------------------------------------------------------------------------------------
+void SAL_CALL Mapping_release( uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ that->m_bridge->release();
+}
+
+
+//--------------------------------------------------------------------------------------------------
+void SAL_CALL Mapping_cli2uno(
+ uno_Mapping * mapping, void ** ppOut,
+ void * pIn, typelib_InterfaceTypeDescription * td )
+ SAL_THROW_EXTERN_C()
+{
+ uno_Interface ** ppUnoI = (uno_Interface **)ppOut;
+ intptr_t cliI = (intptr_t)pIn;
+
+ OSL_ENSURE( ppUnoI && td, "### null ptr!" );
+
+ if (0 != *ppUnoI)
+ {
+ uno_Interface * pUnoI = *(uno_Interface **)ppUnoI;
+ (*pUnoI->release)( pUnoI );
+ *ppUnoI = 0;
+ }
+ try
+ {
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ Bridge * bridge = that->m_bridge;
+
+ if (0 != cliI)
+ {
+ System::Object* cliObj= sri::GCHandle::op_Explicit(cliI).Target;
+ (*ppOut)= bridge->map_cli2uno(cliObj, (typelib_TypeDescription*) td);
+ }
+ }
+ catch (BridgeRuntimeError & err)
+ {
+#if OSL_DEBUG_LEVEL >= 1
+ OString cstr_msg(
+ OUStringToOString(
+ OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) );
+ OSL_ENSURE( 0, cstr_msg.getStr() );
+#else
+ (void) err; // unused
+#endif
+ }
+}
+//--------------------------------------------------------------------------------------------------
+void SAL_CALL Mapping_uno2cli(
+ uno_Mapping * mapping, void ** ppOut,
+ void * pIn, typelib_InterfaceTypeDescription * td )
+ SAL_THROW_EXTERN_C()
+{
+ try
+ {
+ OSL_ENSURE( td && ppOut, "### null ptr!" );
+ OSL_ENSURE( (sizeof(System::Char) == sizeof(sal_Unicode))
+ && (sizeof(System::Boolean) == sizeof(sal_Bool))
+ && (sizeof(System::SByte) == sizeof(sal_Int8))
+ && (sizeof(System::Int16) == sizeof(sal_Int16))
+ && (sizeof(System::UInt16) == sizeof(sal_uInt16))
+ && (sizeof(System::Int32) == sizeof(sal_Int32))
+ && (sizeof(System::UInt32) == sizeof(sal_uInt32))
+ && (sizeof(System::Int64) == sizeof(sal_Int64))
+ && (sizeof(System::UInt64) == sizeof(sal_uInt64))
+ && (sizeof(System::Single) == sizeof(float))
+ && (sizeof(System::Double) == sizeof(double)),
+ "[cli_uno bridge] incompatible .NET data types");
+ intptr_t * ppDNetI = (intptr_t *)ppOut;
+ uno_Interface * pUnoI = (uno_Interface *)pIn;
+
+ Mapping const * that = static_cast< Mapping const * >( mapping );
+ Bridge * bridge = that->m_bridge;
+
+ if (0 != *ppDNetI)
+ {
+ sri::GCHandle::op_Explicit(ppDNetI).Free();
+ }
+
+ if (0 != pUnoI)
+ {
+ System::Object* cliI= bridge->map_uno2cli(pUnoI, td);
+ intptr_t ptr= NULL;
+ if(cliI)
+ {
+ ptr= sri::GCHandle::op_Explicit(sri::GCHandle::Alloc(cliI))
+#ifdef _WIN32
+ .ToInt32();
+#else /* defined(_WIN64) */ .ToInt64();
+#endif
+ }
+ (*ppOut)= reinterpret_cast<void*>(ptr);
+ }
+ }
+ catch (BridgeRuntimeError & err)
+ {
+#if OSL_DEBUG_LEVEL >= 1
+ rtl::OString cstr_msg(
+ rtl::OUStringToOString(
+ OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) );
+ OSL_ENSURE( 0, cstr_msg.getStr() );
+#else
+ (void) err; // unused
+#endif
+ }
+}
+
+//__________________________________________________________________________________________________
+void SAL_CALL Bridge_free( uno_Mapping * mapping )
+ SAL_THROW_EXTERN_C()
+{
+ Mapping * that = static_cast< Mapping * >( mapping );
+ delete that->m_bridge;
+}
+
+} //extern C
+} //namespace
+
+namespace cli_uno
+{
+
+//__________________________________________________________________________________________________
+/** ToDo
+ I doubt that the the case that the ref count raises from 0 to 1
+ can occur. uno_ext_getMapping returns an acquired mapping. Every time
+ that function is called then a new mapping is created. Following the
+ rules of ref counted objects, then if the ref count is null noone has
+ a reference to the object anymore. Hence noone can call acquire. If someone
+ calls acquire then they must have kept an unacquired pointer which is
+ illegal.
+ */
+void Bridge::acquire() const SAL_THROW( () )
+{
+ if (1 == osl_incrementInterlockedCount( &m_ref ))
+ {
+ if (m_registered_cli2uno)
+ {
+ uno_Mapping * mapping = const_cast<Mapping*>(&m_cli2uno);
+ uno_registerMapping(
+ & const_cast<uno_Mapping*>(mapping), Bridge_free, m_uno_cli_env, (uno_Environment *)m_uno_env, 0 );
+ }
+ else
+ {
+ uno_Mapping * mapping = const_cast<Mapping*>(&m_uno2cli);
+ uno_registerMapping(
+ &mapping, Bridge_free, (uno_Environment *)m_uno_env, m_uno_cli_env, 0 );
+ }
+ }
+}
+//__________________________________________________________________________________________________
+void Bridge::release() const SAL_THROW( () )
+{
+ if (! osl_decrementInterlockedCount( &m_ref ))
+ {
+ uno_revokeMapping(
+ m_registered_cli2uno
+ ? const_cast<Mapping*>(&m_cli2uno)
+ : const_cast<Mapping*>(&m_uno2cli) );
+ }
+}
+//__________________________________________________________________________________________________
+Bridge::Bridge(
+ uno_Environment * uno_cli_env, uno_ExtEnvironment * uno_env,
+ bool registered_cli2uno )
+ : m_ref( 1 ),
+ m_uno_env( uno_env ),
+ m_uno_cli_env( uno_cli_env ),
+ m_registered_cli2uno( registered_cli2uno )
+{
+ OSL_ASSERT( 0 != m_uno_cli_env && 0 != m_uno_env );
+ (*((uno_Environment *)m_uno_env)->acquire)( (uno_Environment *)m_uno_env );
+ (*m_uno_cli_env->acquire)( m_uno_cli_env );
+
+ // cli2uno
+ m_cli2uno.acquire = Mapping_acquire;
+ m_cli2uno.release = Mapping_release;
+ m_cli2uno.mapInterface = Mapping_cli2uno;
+ m_cli2uno.m_bridge = this;
+ // uno2cli
+ m_uno2cli.acquire = Mapping_acquire;
+ m_uno2cli.release = Mapping_release;
+ m_uno2cli.mapInterface = Mapping_uno2cli;
+ m_uno2cli.m_bridge = this;
+
+}
+
+//__________________________________________________________________________________________________
+Bridge::~Bridge() SAL_THROW( () )
+{
+ //System::GC::Collect();
+ (*m_uno_cli_env->release)( m_uno_cli_env );
+ (*((uno_Environment *)m_uno_env)->release)( (uno_Environment *)m_uno_env );
+}
+
+
+
+} //namespace cli_uno
+
+extern "C"
+{
+
+namespace cli_uno
+{
+//--------------------------------------------------------------------------------------------------
+void SAL_CALL cli_env_disposing( uno_Environment * uno_cli_env )
+ SAL_THROW_EXTERN_C()
+{
+ uno_cli_env->pContext = 0;
+}
+
+//##################################################################################################
+void SAL_CALL uno_initEnvironment( uno_Environment * uno_cli_env )
+ SAL_THROW_EXTERN_C()
+{
+ //ToDo: remove when compiled with .NET 2
+#if defined(_MSC_VER) && (_MSC_VER < 1400)
+ __crt_dll_initialize();
+#endif
+
+ uno_cli_env->environmentDisposing= cli_env_disposing;
+ uno_cli_env->pExtEnv = 0;
+ //Set the console to print Trace messages
+#if OSL_DEBUG_LEVEL >= 1
+ System::Diagnostics::Trace::get_Listeners()->
+ Add( new System::Diagnostics::TextWriterTraceListener(System::Console::get_Out()));
+#endif
+ OSL_ASSERT( 0 == uno_cli_env->pContext );
+
+ // We let the Cli_environment leak, since there is no good point where we could destruct it.
+ //dispose is not used because we would have then also synchronize the calls to proxies. If the
+ //Cli_environment is disposed, we must prevent all calls, otherwise we may crash at points
+ //where g_cli_env is accessed.
+ //When we compile the bridge with .NET 2 then we can again hold g_cli_env as a static gcroot
+ //member in a unmanaged class, such as Bridge.
+ CliEnvHolder::g_cli_env = new Cli_environment();
+}
+//##################################################################################################
+void SAL_CALL uno_ext_getMapping(
+ uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
+ if (*ppMapping)
+ {
+ (*(*ppMapping)->release)( *ppMapping );
+ *ppMapping = 0;
+ }
+
+
+ OUString const & from_env_typename = *reinterpret_cast< OUString const * >(
+ &pFrom->pTypeName );
+ OUString const & to_env_typename = *reinterpret_cast< OUString const * >(
+ &pTo->pTypeName );
+
+ uno_Mapping * mapping = 0;
+
+ try
+ {
+ if (from_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_CLI) ) &&
+ to_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
+ {
+ Bridge * bridge = new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1
+ mapping = &bridge->m_cli2uno;
+ uno_registerMapping(
+ &mapping, Bridge_free, pFrom, (uno_Environment *)pTo->pExtEnv, 0 );
+ }
+ else if (from_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ) &&
+ to_env_typename.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_CLI) ))
+ {
+ Bridge * bridge = new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1
+ mapping = &bridge->m_uno2cli;
+ uno_registerMapping(
+ &mapping, Bridge_free, (uno_Environment *)pFrom->pExtEnv, pTo, 0 );
+ }
+ }
+ catch (BridgeRuntimeError & err)
+ {
+#if OSL_DEBUG_LEVEL >= 1
+ OString cstr_msg(
+ OUStringToOString(
+ OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) );
+ OSL_ENSURE( 0, cstr_msg.getStr() );
+#else
+ (void) err; // unused
+#endif
+ }
+ *ppMapping = mapping;
+}
+
+
+//##################################################################################################
+sal_Bool SAL_CALL component_canUnload( TimeValue * )
+ SAL_THROW_EXTERN_C()
+{
+ return true;
+}
+
+}
+}
diff --git a/cli_ure/source/uno_bridge/cli_bridge.h b/cli_ure/source/uno_bridge/cli_bridge.h
new file mode 100644
index 000000000000..1bc3a926519e
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_bridge.h
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_CLI_BRIDGE_H
+#define INCLUDED_CLI_BRIDGE_H
+#include <vcclr.h>
+#include "osl/interlck.h"
+#include "uno/mapping.h"
+#include "uno/environment.h"
+#include "uno/dispatcher.h"
+#include "cli_base.h"
+#include "cli_environment.h"
+#using <mscorlib.dll>
+//#using <cli_uretypes.dll>
+#using <cli_basetypes.dll>
+#using <system.dll>
+
+namespace sr = System::Reflection;
+
+namespace cli_uno
+{
+
+
+//==== holds environments and mappings =============================================================
+struct Bridge;
+struct Mapping : public uno_Mapping
+{
+ Bridge* m_bridge;
+};
+
+// The environment will be created in uno_initEnvironment. See also the remarks there
+//Managed cli environment for cli objects an UNO proxies (which are cli
+//objects. The uno_Environment is not used for cli objects.
+__gc struct CliEnvHolder {
+static Cli_environment * g_cli_env = NULL;
+};
+
+//==================================================================================================
+/** An instance of Bridge represents exactly one mapping therefore either
+ m_cli2uno or m_uno2cli is valid.
+*/
+struct Bridge
+{
+ mutable oslInterlockedCount m_ref;
+ uno_ExtEnvironment * m_uno_env;
+ uno_Environment * m_uno_cli_env;
+
+ Mapping m_cli2uno;
+ Mapping m_uno2cli;
+ bool m_registered_cli2uno;
+
+ ~Bridge() SAL_THROW( () );
+ Bridge( uno_Environment * java_env, uno_ExtEnvironment * uno_env, bool registered_java2uno );
+
+ void acquire() const;
+ void release() const;
+
+ void map_to_uno(
+ void * uno_data, System::Object* cli_data,
+ typelib_TypeDescriptionReference * type,
+ bool assign) const;
+
+ /**
+ @param info
+ the type of the converted data. It may be a byref type.
+ */
+ void map_to_cli(
+ System::Object* *cli_data, void const * uno_data,
+ typelib_TypeDescriptionReference * type, System::Type* info /* maybe 0 */,
+ bool bDontCreateObj) const;
+
+ System::Object* map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription* pTD) const;
+
+ System::Object* Bridge::call_uno(uno_Interface * pUnoI,
+ typelib_TypeDescription* member_td,
+ typelib_TypeDescriptionReference * return_type,
+ sal_Int32 nParams, typelib_MethodParameter const * pParams,
+ System::Object * args[], System::Type* argTypes[],
+ System::Object** pException) const;
+
+
+ void call_cli(
+ System::Object* cliI, sr::MethodInfo* method,
+ typelib_TypeDescriptionReference * return_type,
+ typelib_MethodParameter * params, int nParams,
+ void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const;
+
+ uno_Interface * map_cli2uno(
+ System::Object* cliI, typelib_TypeDescription* pTD) const;
+
+};
+
+} //namespace cli_uno
+
+
+#endif
diff --git a/cli_ure/source/uno_bridge/cli_data.cxx b/cli_ure/source/uno_bridge/cli_data.cxx
new file mode 100644
index 000000000000..99f4bda82563
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_data.cxx
@@ -0,0 +1,2011 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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"
+
+#pragma warning(push, 1)
+#include "windows.h"
+#pragma warning(pop)
+
+#include <memory>
+
+
+#include "rtl/ustring.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "uno/sequence2.h"
+#include "typelib/typedescription.hxx"
+#include "cli_proxy.h"
+#include "cli_base.h"
+#include "cli_bridge.h"
+
+#using <cli_uretypes.dll>
+
+
+#undef VOID
+
+namespace css = com::sun::star;
+
+namespace sri = System::Runtime::InteropServices;
+namespace sr = System::Reflection;
+namespace st = System::Text;
+namespace ucss = unoidl::com::sun::star;
+
+using namespace rtl;
+using namespace std;
+
+
+namespace cli_uno
+{
+System::String* mapUnoPolymorphicName(System::String* unoName);
+OUString mapCliTypeName(System::String* typeName);
+System::String* mapCliPolymorphicName(System::String* unoName);
+System::String* mapPolymorphicName(System::String* unoName, bool bCliToUno);
+
+inline auto_ptr< rtl_mem > seq_allocate( sal_Int32 nElements, sal_Int32 nSize )
+{
+ auto_ptr< rtl_mem > seq(
+ rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) );
+ uno_Sequence * p = (uno_Sequence *)seq.get();
+ p->nRefCount = 1;
+ p->nElements = nElements;
+ return seq;
+}
+
+
+System::Object* Bridge::map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription *pTD) const
+{
+ System::Object* retVal= NULL;
+// get oid
+ rtl_uString * pOid = 0;
+ (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI );
+ OSL_ASSERT( 0 != pOid );
+ OUString oid(pOid, SAL_NO_ACQUIRE);
+
+ //see if the interface was already mapped
+ System::Type* ifaceType= mapUnoType(reinterpret_cast<typelib_TypeDescription*>(pTD));
+ System::String* sOid= mapUnoString(oid.pData);
+
+ System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env );
+ try
+ {
+ retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType);
+ if (retVal)
+ {
+ // There is already an registered object. It can either be a proxy
+ // for the UNO object or a real cli object. In the first case we
+ // tell the proxy that it shall also represent the current UNO
+ // interface. If it already does that, then it does nothing
+ if (srr::RemotingServices::IsTransparentProxy(retVal))
+ {
+ UnoInterfaceProxy* p = static_cast<UnoInterfaceProxy*>(
+ srr::RemotingServices::GetRealProxy(retVal));
+ p->addUnoInterface(pUnoI, pTD);
+ }
+ }
+ else
+ {
+ retVal = UnoInterfaceProxy::create(
+ (Bridge *) this, pUnoI, pTD, oid );
+ }
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env );
+ }
+
+ return retVal;
+}
+
+uno_Interface* Bridge::map_cli2uno(System::Object* cliObj, typelib_TypeDescription *pTD) const
+{
+ uno_Interface* retIface = NULL;
+ // get oid from dot net environment
+ System::String* ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj);
+ OUString ousOid = mapCliString(ds_oid);
+ // look if interface is already mapped
+ m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
+ (typelib_InterfaceTypeDescription*) pTD);
+ if ( ! retIface)
+ {
+ System::Threading::Monitor::Enter(__typeof(Cli_environment));
+ try
+ {
+ m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
+ (typelib_InterfaceTypeDescription*) pTD);
+ if ( ! retIface)
+ {
+ retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid);
+ }
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit(__typeof(Cli_environment));
+ }
+ }
+ return retIface;
+}
+
+inline System::Type* loadCliType(rtl_uString * unoName)
+{
+ return loadCliType(mapUnoTypeName(unoName));
+}
+
+System::Type* loadCliType(System::String * unoName)
+{
+ System::Type* retVal= NULL;
+ try
+ {
+ //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted<System.Char>
+ //then we remove the type list, otherwise the type could not be loaded.
+ bool bIsPolymorphic = false;
+
+ System::String * loadName = unoName;
+ int index = unoName->IndexOf('<');
+ if (index != -1)
+ {
+ loadName = unoName->Substring(0, index);
+ bIsPolymorphic = true;
+ }
+ System::AppDomain* currentDomain = System::AppDomain::CurrentDomain;
+ sr::Assembly* assems[] = currentDomain->GetAssemblies();
+ for (int i = 0; i < assems->Length; i++)
+ {
+ retVal = assems[i]->GetType(loadName, false);
+ if (retVal)
+ break;
+ }
+
+ if (retVal == NULL)
+ {
+ System::String * msg = new System::String(S"A type could not be loaded: ");
+ msg = System::String::Concat(msg, loadName);
+ throw BridgeRuntimeError(mapCliString(msg));
+ }
+
+ if (bIsPolymorphic)
+ {
+ retVal = uno::PolymorphicType::GetType(retVal, unoName);
+ }
+ }
+ catch( System::Exception * e)
+ {
+ rtl::OUString ouMessage(mapCliString(e->get_Message()));
+ throw BridgeRuntimeError(ouMessage);
+ }
+ return retVal;
+}
+
+
+System::Type* mapUnoType(typelib_TypeDescription const * pTD)
+{
+ return mapUnoType(pTD->pWeakRef);
+}
+
+System::Type* mapUnoType(typelib_TypeDescriptionReference const * pTD)
+{
+ System::Type * retVal = 0;
+ switch (pTD->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ retVal= __typeof(void); break;
+ case typelib_TypeClass_CHAR:
+ retVal= __typeof(System::Char); break;
+ case typelib_TypeClass_BOOLEAN:
+ retVal= __typeof(System::Boolean); break;
+ case typelib_TypeClass_BYTE:
+ retVal= __typeof(System::Byte); break;
+ case typelib_TypeClass_SHORT:
+ retVal= __typeof(System::Int16); break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ retVal= __typeof(System::UInt16); break;
+ case typelib_TypeClass_LONG:
+ retVal= __typeof(System::Int32); break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ retVal= __typeof(System::UInt32); break;
+ case typelib_TypeClass_HYPER:
+ retVal= __typeof(System::Int64); break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ retVal= __typeof(System::UInt64); break;
+ case typelib_TypeClass_FLOAT:
+ retVal= __typeof(System::Single); break;
+ case typelib_TypeClass_DOUBLE:
+ retVal= __typeof(System::Double); break;
+ case typelib_TypeClass_STRING:
+ retVal= __typeof(System::String); break;
+ case typelib_TypeClass_TYPE:
+ retVal= __typeof(System::Type); break;
+ case typelib_TypeClass_ANY:
+ retVal= __typeof(uno::Any); break;
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ retVal= loadCliType(pTD->pTypeName); break;
+ case typelib_TypeClass_INTERFACE:
+ {
+ //special handling for XInterface, since it does not exist in cli.
+ rtl::OUString usXInterface(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XInterface"));
+ if (usXInterface.equals(pTD->pTypeName))
+ retVal= __typeof(System::Object);
+ else
+ retVal= loadCliType(pTD->pTypeName);
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ css::uno::TypeDescription seqType(
+ const_cast<typelib_TypeDescriptionReference*>(pTD));
+ typelib_TypeDescriptionReference* pElementTDRef=
+ reinterpret_cast<typelib_IndirectTypeDescription*>(seqType.get())->pType;
+ switch (pElementTDRef->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArChar)); break;
+ case typelib_TypeClass_BOOLEAN:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArBoolean));
+ break;
+ case typelib_TypeClass_BYTE:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArByte));
+ break;
+ case typelib_TypeClass_SHORT:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArInt16));
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArUInt16));
+ break;
+ case typelib_TypeClass_LONG:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArInt32));
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArUInt32));
+ break;
+ case typelib_TypeClass_HYPER:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArInt64));
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArUInt64));
+ break;
+ case typelib_TypeClass_FLOAT:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArSingle));
+ break;
+ case typelib_TypeClass_DOUBLE:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArDouble));
+ break;
+ case typelib_TypeClass_STRING:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArString));
+ break;
+ case typelib_TypeClass_TYPE:
+ retVal= System::Type::GetType(const_cast<System::String*>(Constants::sArType));
+ break;
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_INTERFACE:
+ case typelib_TypeClass_SEQUENCE:
+ {
+ retVal= loadCliType(pTD->pTypeName);
+ break;
+ }
+ default:
+ //All cases should be handled by the case statements above
+ OSL_ASSERT(0);
+ break;
+ }
+ break;
+ }
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ return retVal;
+}
+
+/** Returns an acquired td.
+ */
+typelib_TypeDescriptionReference* mapCliType(System::Type* cliType)
+{
+ typelib_TypeDescriptionReference* retVal= NULL;
+ if (cliType == NULL)
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_VOID );
+ typelib_typedescriptionreference_acquire( retVal );
+ return retVal;
+ }
+ //check for Enum first,
+ //because otherwise case System::TypeCode::Int32 applies
+ if (cliType->get_IsEnum())
+ {
+ OUString usTypeName= mapCliTypeName(cliType->get_FullName());
+ css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName);
+ retVal= unoType.getTypeLibType();
+ typelib_typedescriptionreference_acquire(retVal);
+ }
+ else
+ {
+ switch (System::Type::GetTypeCode(cliType))
+ {
+ case System::TypeCode::Boolean:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_BOOLEAN );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Char:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_CHAR );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Byte:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_BYTE );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int16:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_SHORT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int32:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_LONG );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int64:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_HYPER );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt16:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_SHORT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt32:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_LONG );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt64:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_HYPER );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Single:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_FLOAT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Double:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_DOUBLE );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::String:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_STRING );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ default:
+ break;
+ }
+ }
+ if (retVal == NULL)
+ {
+ System::String* cliTypeName= cliType->get_FullName();
+ // Void
+ if (const_cast<System::String*>(Constants::sVoid)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_VOID );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ // Type
+ else if (const_cast<System::String*>(Constants::sType)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_TYPE );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ // Any
+ else if (const_cast<System::String*>(Constants::sAny)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_ANY );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ //struct, interfaces, sequences
+ else
+ {
+ OUString usTypeName;
+ uno::PolymorphicType * poly = dynamic_cast<uno::PolymorphicType*>(cliType);
+ if (poly != NULL)
+ usTypeName = mapCliTypeName( poly->PolymorphicName);
+ else
+ usTypeName = mapCliTypeName(cliTypeName);
+ typelib_TypeDescription* td = NULL;
+ typelib_typedescription_getByName(&td, usTypeName.pData);
+ if (td)
+ {
+ retVal = td->pWeakRef;
+ typelib_typedescriptionreference_acquire(retVal);
+ typelib_typedescription_release(td);
+ }
+ }
+ }
+ if (retVal == NULL)
+ {
+ OUStringBuffer buf( 128 );
+ buf.appendAscii(
+ RTL_CONSTASCII_STRINGPARAM("[cli_uno bridge] mapCliType():"
+ "could not map type: ") );
+ buf.append(mapCliString(cliType->get_FullName()));
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ return retVal;
+}
+
+/**
+ Otherwise a leading "unoidl." is removed.
+ */
+System::String* mapUnoTypeName(rtl_uString const * typeName)
+{
+ OUString usUnoName( const_cast< rtl_uString * >( typeName ) );
+ st::StringBuilder* buf= new st::StringBuilder();
+ //determine if the type is a sequence and its dimensions
+ int dims= 0;
+ if (usUnoName[0] == '[')
+ {
+ sal_Int32 index= 1;
+ while (true)
+ {
+ if (usUnoName[index++] == ']')
+ dims++;
+ if (usUnoName[index++] != '[')
+ break;
+ }
+ usUnoName = usUnoName.copy(index - 1);
+ }
+ System::String * sUnoName = mapUnoString(usUnoName.pData);
+ if (sUnoName->Equals(const_cast<System::String*>(Constants::usBool)))
+ buf->Append(const_cast<System::String*>(Constants::sBoolean));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usChar)))
+ buf->Append(const_cast<System::String*>(Constants::sChar));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usByte)))
+ buf->Append(const_cast<System::String*>(Constants::sByte));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usShort)))
+ buf->Append(const_cast<System::String*>(Constants::sInt16));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usUShort)))
+ buf->Append(const_cast<System::String*>(Constants::sUInt16));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usLong)))
+ buf->Append(const_cast<System::String*>(Constants::sInt32));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usULong)))
+ buf->Append(const_cast<System::String*>(Constants::sUInt32));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usHyper)))
+ buf->Append(const_cast<System::String*>(Constants::sInt64));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usUHyper)))
+ buf->Append(const_cast<System::String*>(Constants::sUInt64));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usFloat)))
+ buf->Append(const_cast<System::String*>(Constants::sSingle));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usDouble)))
+ buf->Append(const_cast<System::String*>(Constants::sDouble));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usString)))
+ buf->Append(const_cast<System::String*>(Constants::sString));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usVoid)))
+ buf->Append(const_cast<System::String*>(Constants::sVoid));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usType)))
+ buf->Append(const_cast<System::String*>(Constants::sType));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usXInterface)))
+ buf->Append(const_cast<System::String*>(Constants::sObject));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::usAny)))
+ {
+ buf->Append(const_cast<System::String*>(Constants::sAny));
+ }
+ else
+ {
+ //put "unoidl." at the beginning
+ buf->Append(const_cast<System::String*>(Constants::sUnoidl));
+ //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct
+ System::String * sName = mapUnoPolymorphicName(sUnoName);
+ buf->Append(sName);
+ }
+ // apend []
+ for (;dims--;)
+ buf->Append(const_cast<System::String*>(Constants::sBrackets));
+
+ return buf->ToString();
+}
+
+
+
+
+/** For example, there is a uno type
+ com.sun.star.Foo<char, long>.
+ The values in the type list
+ are uno types and are replaced by cli types, such as System.Char,
+ System.Int32, etc.
+ The präfix unoidl is not added.
+ */
+inline System::String* mapUnoPolymorphicName(System::String* unoName)
+{
+ return mapPolymorphicName(unoName, false);
+}
+/** For example, there is a type name such as
+ com.sun.star.Foo<System.Char, System.Int32>.
+ The values in the type list
+ are CLI types and are replaced by uno types, such as char,
+ long, etc.
+ The präfix unoidl remains.
+ */
+inline System::String* mapCliPolymorphicName(System::String* unoName)
+{
+ return mapPolymorphicName(unoName, true);
+}
+
+System::String* mapPolymorphicName(System::String* unoName, bool bCliToUno)
+{
+ int index = unoName->IndexOf('<');
+ if (index == -1)
+ return unoName;
+
+ System::Text::StringBuilder * builder = new System::Text::StringBuilder(256);
+ builder->Append(unoName->Substring(0, index +1 ));
+
+ //Find the first occurrence of ','
+ //If the parameter is a polymorphic struct then we neede to ignore everything
+ //between the brackets because it can also contain commas
+ //get the type list within < and >
+ int endIndex = unoName->Length - 1;
+ index++;
+ int cur = index;
+ int countParams = 0;
+ while (cur <= endIndex)
+ {
+ System::Char c = unoName->Chars[cur];
+ if (c == ',' || c == '>')
+ {
+ //insert a comma if needed
+ if (countParams != 0)
+ builder->Append(S",");
+ countParams++;
+ System::String * sParam = unoName->Substring(index, cur - index);
+ //skip the comma
+ cur++;
+ //the the index to the beginning of the next param
+ index = cur;
+ if (bCliToUno)
+ {
+ builder->Append(mapCliTypeName(sParam));
+ }
+ else
+ {
+ OUString s = mapCliString(sParam);
+ builder->Append(mapUnoTypeName(s.pData));
+ }
+ }
+ else if (c == '<')
+ {
+ cur++;
+ //continue until the matching '>'
+ int numNested = 0;
+ for (;;cur++)
+ {
+ System::Char curChar = unoName->Chars[cur];
+ if (curChar == '<')
+ {
+ numNested ++;
+ }
+ else if (curChar == '>')
+ {
+ if (numNested > 0)
+ numNested--;
+ else
+ break;
+ }
+ }
+ }
+ cur++;
+ }
+
+ builder->Append((System::Char) '>');
+ return builder->ToString();
+}
+
+OUString mapCliTypeName(System::String* typeName)
+{
+ int dims= 0;
+ // Array? determine the "rank" (number of "[]")
+ // move from the rightmost end to the left, for example
+ // unoidl.PolymorphicStruct<System.Char[]>[]
+ // has only a "dimension" of 1
+ int cur = typeName->Length - 1;
+ bool bRightBracket = false;
+ while (cur >= 0)
+ {
+ System::Char c = typeName->Chars[cur];
+ if (c == ']')
+ {
+ bRightBracket = true;
+ }
+ else if (c == '[')
+ {
+ if (!bRightBracket)
+ throw BridgeRuntimeError(
+ OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") +
+ mapCliString(typeName));
+ bRightBracket = false;
+ dims ++;
+ }
+ else
+ {
+ if (bRightBracket)
+ throw BridgeRuntimeError(
+ OUSTR("Typename is wrong. No matching brackets for sequence. Name is: ") +
+ mapCliString(typeName));
+ break;
+ }
+ cur--;
+ }
+
+ if (bRightBracket || cur < 0)
+ throw BridgeRuntimeError(
+ OUSTR("Typename is wrong. ") +
+ mapCliString(typeName));
+
+ typeName = typeName->Substring(0, cur + 1);
+
+ System::Text::StringBuilder * buf = new System::Text::StringBuilder(512);
+
+ //Put the "[]" at the beginning of the uno type name
+ for (;dims--;)
+ buf->Append(const_cast<System::String*>(Constants::usBrackets));
+
+ if (typeName->Equals(const_cast<System::String*>(Constants::sBoolean)))
+ buf->Append(const_cast<System::String*>(Constants::usBool));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sChar)))
+ buf->Append(const_cast<System::String*>(Constants::usChar));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sByte)))
+ buf->Append(const_cast<System::String*>(Constants::usByte));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sInt16)))
+ buf->Append(const_cast<System::String*>(Constants::usShort));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sUInt16)))
+ buf->Append(const_cast<System::String*>(Constants::usUShort));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sInt32)))
+ buf->Append(const_cast<System::String*>(Constants::usLong));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sUInt32)))
+ buf->Append(const_cast<System::String*>(Constants::usULong));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sInt64)))
+ buf->Append(const_cast<System::String*>(Constants::usHyper));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sUInt64)))
+ buf->Append(const_cast<System::String*>(Constants::usUHyper));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sSingle)))
+ buf->Append(const_cast<System::String*>(Constants::usFloat));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sDouble)))
+ buf->Append(const_cast<System::String*>(Constants::usDouble));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sString)))
+ buf->Append(const_cast<System::String*>(Constants::usString));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sVoid)))
+ buf->Append(const_cast<System::String*>(Constants::usVoid));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sType)))
+ buf->Append(const_cast<System::String*>(Constants::usType));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sObject)))
+ buf->Append(const_cast<System::String*>(Constants::usXInterface));
+ else if (typeName->Equals(const_cast<System::String*>(Constants::sAny)))
+ buf->Append(const_cast<System::String*>(Constants::usAny));
+ else
+ {
+ System::String * sName = mapCliPolymorphicName(typeName);
+ int i= sName->IndexOf(L'.');
+ buf->Append(sName->Substring(i + 1));
+ }
+ return mapCliString(buf->ToString());
+}
+/** Maps uno types to dot net types.
+ * If uno_data is null then the type description is converted to System::Type
+ */
+inline System::String* mapUnoString( rtl_uString const * data)
+{
+ OSL_ASSERT(data);
+ return new System::String((__wchar_t*) data->buffer, 0, data->length);
+}
+
+OUString mapCliString(System::String const * data)
+{
+
+ if (data != NULL)
+ {
+ OSL_ASSERT(sizeof(wchar_t) == sizeof(sal_Unicode));
+ wchar_t const __pin * pdata= PtrToStringChars(data);
+ return OUString(pdata, const_cast<System::String*>(data)->get_Length());
+ }
+ else
+ {
+ return OUString();
+ }
+}
+
+// ToDo convert cli types to expected types, e.g a long to a short where the uno type
+// is a sal_Int16. This could be necessary if a scripting language (typeless) is used
+// @param assign the uno_data has to be destructed (in/out args)
+void Bridge::map_to_uno(void * uno_data, System::Object* cli_data,
+ typelib_TypeDescriptionReference * type,
+ bool assign) const
+{
+ try{
+ switch (type->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ break;
+ case typelib_TypeClass_CHAR:
+ {
+ System::Char aChar= *__try_cast<System::Char*>(cli_data);
+ *(sal_Unicode*) uno_data= aChar;
+ break;
+ }
+ case typelib_TypeClass_BOOLEAN:
+ {
+ System::Boolean aBool= *__try_cast<System::Boolean*>(cli_data);
+ *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False;
+ break;
+ }
+ case typelib_TypeClass_BYTE:
+ {
+ System::Byte aByte= *__try_cast<System::Byte*>(cli_data);
+ *(sal_Int8*) uno_data= aByte;
+ break;
+ }
+ case typelib_TypeClass_SHORT:
+ {
+ System::Int16 aShort= *__try_cast<System::Int16*>(cli_data);
+ *(sal_Int16*) uno_data= aShort;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ {
+ System::UInt16 aUShort= *__try_cast<System::UInt16*>(cli_data);
+ *(sal_uInt16*) uno_data= aUShort;
+ break;
+ }
+ case typelib_TypeClass_LONG:
+ {
+ System::Int32 aLong= *__try_cast<System::Int32*>(cli_data);
+ *(sal_Int32*) uno_data= aLong;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ {
+ System::UInt32 aULong= *__try_cast<System::UInt32*>(cli_data);
+ *(sal_uInt32*) uno_data= aULong;
+ break;
+ }
+ case typelib_TypeClass_HYPER:
+ {
+ System::Int64 aHyper= *__try_cast<System::Int64*>(cli_data);
+ *(sal_Int64*) uno_data= aHyper;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ {
+ System::UInt64 aLong= *__try_cast<System::UInt64*>(cli_data);
+ *(sal_uInt64*) uno_data= aLong;
+ break;
+ }
+ case typelib_TypeClass_FLOAT:
+ {
+ System::Single aFloat= *__try_cast<System::Single*>(cli_data);
+ *(float*) uno_data= aFloat;
+ break;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ System::Double aDouble= *__try_cast<System::Double*>(cli_data);
+ *(double*) uno_data= aDouble;
+ break;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ if (assign && *(rtl_uString**) uno_data)
+ rtl_uString_release(*(rtl_uString**) uno_data);
+
+ *(rtl_uString **)uno_data = 0;
+ if (cli_data == NULL)
+ {
+ rtl_uString_new((rtl_uString**) uno_data);
+ }
+ else
+ {
+ System::String *s= __try_cast<System::String*>(cli_data);
+ wchar_t const __pin * pdata= PtrToStringChars(s);
+ rtl_uString_newFromStr_WithLength( (rtl_uString**) uno_data,
+ pdata, s->get_Length() );
+ }
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ typelib_TypeDescriptionReference* td= mapCliType(__try_cast<System::Type*>(
+ cli_data));
+ if (assign)
+ {
+ typelib_typedescriptionreference_release(
+ *(typelib_TypeDescriptionReference **)uno_data );
+ }
+ *(typelib_TypeDescriptionReference **)uno_data = td;
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any * pAny = (uno_Any *)uno_data;
+ if (cli_data == NULL) // null-ref or uninitialized any maps to empty any
+ {
+ if (assign)
+ uno_any_destruct( pAny, 0 );
+ uno_any_construct( pAny, 0, 0, 0 );
+ break;
+ }
+ uno::Any aAny= *__try_cast<uno::Any*>(cli_data);
+ css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE);
+
+ if (assign)
+ uno_any_destruct( pAny, 0 );
+
+ try
+ {
+ switch (value_td.getTypeClass())
+ {
+ case typelib_TypeClass_VOID:
+ pAny->pData = &pAny->pReserved;
+ break;
+ case typelib_TypeClass_CHAR:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Unicode*) &pAny->pReserved = *__try_cast<System::Char*>(aAny.Value);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Bool *) &pAny->pReserved = *__try_cast<System::Boolean*>(aAny.Value);
+ break;
+ case typelib_TypeClass_BYTE:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int8*) &pAny->pReserved = *__try_cast<System::Byte*>(aAny.Value);
+ break;
+ case typelib_TypeClass_SHORT:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int16*) &pAny->pReserved = *__try_cast<System::Int16*>(aAny.Value);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt16*) &pAny->pReserved = *__try_cast<System::UInt16*>(aAny.Value);
+ break;
+ case typelib_TypeClass_LONG:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int32*) &pAny->pReserved = *__try_cast<System::Int32*>(aAny.Value);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt32*) &pAny->pReserved = *__try_cast<System::UInt32*>(aAny.Value);
+ break;
+ case typelib_TypeClass_HYPER:
+ if (sizeof (sal_Int64) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int64*) &pAny->pReserved = *__try_cast<System::Int64*>(aAny.Value);
+ }
+ else
+ {
+ auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) );
+ *(sal_Int64 *) mem.get()= *__try_cast<System::Int64*>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (sizeof (sal_uInt64) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt64*) &pAny->pReserved = *__try_cast<System::UInt64*>(aAny.Value);
+ }
+ else
+ {
+ auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) );
+ *(sal_uInt64 *) mem.get()= *__try_cast<System::UInt64*>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (sizeof (float) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(float*) &pAny->pReserved = *__try_cast<System::Single*>(aAny.Value);
+ }
+ else
+ {
+ auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) );
+ *(float*) mem.get() = *__try_cast<System::Single*>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (sizeof (double) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(double*) &pAny->pReserved= *__try_cast<System::Double*>(aAny.Value);
+ }
+ else
+ {
+ auto_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) );
+ *(double*) mem.get()= *__try_cast<System::Double*>(aAny.Value);
+ pAny->pData= mem.release();
+ }
+ break;
+ case typelib_TypeClass_STRING: // anies often contain strings; copy string directly
+ {
+ pAny->pData= &pAny->pReserved;
+ OUString _s = mapCliString(static_cast<System::String*>(aAny.Value));
+ pAny->pReserved= _s.pData;
+ rtl_uString_acquire(_s.pData);
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ENUM: //ToDo copy enum direct
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_INTERFACE:
+ pAny->pData = &pAny->pReserved;
+ pAny->pReserved = 0;
+ map_to_uno(
+ &pAny->pReserved, aAny.Value, value_td.getTypeLibType(),
+ false /* no assign */);
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ css::uno::Type anyType(value_td);
+ typelib_TypeDescription* td= NULL;
+ anyType.getDescription(&td);
+ auto_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize));
+ typelib_typedescription_release(td);
+ map_to_uno(
+ mem.get(), aAny.Value, value_td.getTypeLibType(),
+ false /* no assign */);
+ pAny->pData = mem.release();
+ break;
+ }
+ default:
+ {
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
+ buf.append(value_td.getTypeName());
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported value type of any!") );
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ }
+ }
+ catch(System::InvalidCastException* )
+ {
+// ToDo check this
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ OUStringBuffer buf( 256 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():Any") );
+ buf.append(value_td.getTypeName());
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("]The Any type "));
+ buf.append(value_td.getTypeName());
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" does not correspont "
+ "to its value type: ") );
+ if(aAny.Value != NULL)
+ {
+ css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE);
+ buf.append(td.getTypeName());
+ }
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ catch (BridgeRuntimeError& )
+ {
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw;
+ }
+ catch (...)
+ {
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw;
+ }
+
+ pAny->pType = value_td.getTypeLibType();
+ typelib_typedescriptionreference_acquire(pAny->pType);
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ // InvalidCastException is caught at the end of this method
+ System::Int32 aEnum= System::Convert::ToInt32((cli_data));
+ *(sal_Int32*) uno_data = aEnum;
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ css::uno::TypeDescription td(type);
+ typelib_CompoundTypeDescription * comp_td =
+ (typelib_CompoundTypeDescription*) td.get();
+
+ typelib_StructTypeDescription * struct_td = NULL;
+ if (type->eTypeClass == typelib_TypeClass_STRUCT)
+ struct_td = (typelib_StructTypeDescription*) td.get();
+
+ if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
+ ::typelib_typedescription_complete(
+ (typelib_TypeDescription**) & comp_td );
+
+ sal_Int32 nMembers = comp_td->nMembers;
+ boolean bException= false;
+ System::Type* cliType = NULL;
+ if (cli_data)
+ cliType = cli_data->GetType();
+
+ if (0 != comp_td->pBaseTypeDescription)
+ {
+ map_to_uno(
+ uno_data, cli_data,
+ ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef,
+ assign);
+ }
+ sal_Int32 nPos = 0;
+ try
+ {
+ typelib_TypeDescriptionReference * member_type= NULL;
+
+ rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception"));
+ for (; nPos < nMembers; ++nPos)
+ {
+ member_type= comp_td->ppTypeRefs[nPos];
+#if OSL_DEBUG_LEVEL >= 2
+ System::String* __s;
+ sr::FieldInfo* arFields[];
+ __s = mapUnoString(comp_td->ppMemberNames[nPos]);
+ arFields = cliType != NULL ? cliType->GetFields() : NULL;
+#endif
+ System::Object* val= NULL;
+ if (cli_data != NULL)
+ {
+ sr::FieldInfo* aField= cliType->GetField(
+ mapUnoString(comp_td->ppMemberNames[nPos]));
+ // special case for Exception.Message property
+ // The com.sun.star.uno.Exception.Message field is mapped to the
+ // System.Exception property. Type.GetField("Message") returns null
+ if ( ! aField && usUnoException.equals(td.get()->pTypeName))
+ {// get Exception.Message property
+ rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message"));
+ if (usMessageMember.equals(comp_td->ppMemberNames[nPos]))
+ {
+ sr::PropertyInfo* pi= cliType->GetProperty(
+ mapUnoString(comp_td->ppMemberNames[nPos]));
+ val= pi->GetValue(cli_data, NULL);
+ }
+ else
+ {
+ OUStringBuffer buf(512);
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno(): Member: "));
+ buf.append(comp_td->ppMemberNames[nPos]);
+ throw BridgeRuntimeError(buf.makeStringAndClear());
+ }
+ }
+ else
+ {
+ val= aField->GetValue(cli_data);
+ }
+ }
+ void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ];
+ //When using polymorphic structs then the parameterized members can be null.
+ //Then we set a default value.
+ bool bDefault = ((struct_td != NULL
+ && struct_td->pParameterizedTypes != NULL
+ && struct_td->pParameterizedTypes[nPos] == sal_True
+ && val == NULL)
+ || cli_data == NULL) ? true : false;
+ switch (member_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ if (bDefault)
+ *(sal_Unicode*) p = 0;
+ else
+ *(sal_Unicode*) p = *__try_cast<System::Char*>(val);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ if (bDefault)
+ *(sal_Bool*) p = sal_False;
+ else
+ *(sal_Bool*) p = *__try_cast<System::Boolean*>(val);
+ break;
+ case typelib_TypeClass_BYTE:
+ if (bDefault)
+ *(sal_Int8*) p = 0;
+ else
+ *(sal_Int8*) p = *__try_cast<System::Byte*>(val);
+ break;
+ case typelib_TypeClass_SHORT:
+ if (bDefault)
+ *(sal_Int16*) p = 0;
+ else
+ *(sal_Int16*) p = *__try_cast<System::Int16*>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ if (bDefault)
+ *(sal_uInt16*) p = 0;
+ else
+ *(sal_uInt16*) p = *__try_cast<System::UInt16*>(val);
+ break;
+ case typelib_TypeClass_LONG:
+ if (bDefault)
+ *(sal_Int32*) p = 0;
+ else
+ *(sal_Int32*) p = *__try_cast<System::Int32*>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ if (bDefault)
+ *(sal_uInt32*) p = 0;
+ else
+ *(sal_uInt32*) p = *__try_cast<System::UInt32*>(val);
+ break;
+ case typelib_TypeClass_HYPER:
+ if (bDefault)
+ *(sal_Int64*) p = 0;
+ else
+ *(sal_Int64*) p = *__try_cast<System::Int64*>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (bDefault)
+ *(sal_uInt64*) p = 0;
+ else
+ *(sal_uInt64*) p= *__try_cast<System::UInt64*>(val);
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (bDefault)
+ *(float*) p = 0.;
+ else
+ *(float*) p = *__try_cast<System::Single*>(val);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (bDefault)
+ *(double*) p = 0.;
+ else
+ *(double*) p = *__try_cast<System::Double*>(val);
+ break;
+ default:
+ { // ToDo enum, should be converted here
+ map_to_uno(p, val, member_type, assign);
+ break;
+ }
+ }
+ }
+ }
+ catch (BridgeRuntimeError& e)
+ {
+ bException= true;
+ OUStringBuffer buf(512);
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("[map_to_uno():"));
+ if (cliType)
+ {
+ buf.append(mapCliString(cliType->get_FullName()));
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("."));
+ buf.append(comp_td->ppMemberNames[nPos]);
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" "));
+ }
+ buf.append(e.m_message);
+ throw BridgeRuntimeError(buf.makeStringAndClear());
+ }
+ catch (System::InvalidCastException* )
+ {
+ bException= true;
+ OUStringBuffer buf( 256 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
+ if (cliType)
+ {
+ buf.append(mapCliString(cliType->get_FullName()));
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("."));
+ buf.append(comp_td->ppMemberNames[nPos]);
+ }
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] Value has not the required type."));
+ throw BridgeRuntimeError(buf.makeStringAndClear());
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ bException= true;
+ throw;
+ }
+ __finally
+ {
+ if (bException && !assign) // if assign then caller cleans up
+ {
+ // cleanup the members which we have converted so far
+ for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup )
+ {
+ uno_type_destructData(
+ uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 );
+ }
+ if (0 != comp_td->pBaseTypeDescription)
+ {
+ uno_destructData(
+ uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 );
+ }
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ TypeDescr td( type );
+ typelib_TypeDescriptionReference * element_type =
+ ((typelib_IndirectTypeDescription *)td.get())->pType;
+
+ auto_ptr< rtl_mem > seq;
+
+ System::Array* ar = NULL;
+ if (cli_data != NULL)
+ {
+ ar = __try_cast<System::Array*>(cli_data);
+ sal_Int32 nElements = ar->GetLength(0);
+
+ try
+ {
+ switch (element_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ seq = seq_allocate(nElements, sizeof (sal_Unicode));
+ sri::Marshal::Copy(__try_cast<System::Char[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ seq = seq_allocate(nElements, sizeof (sal_Bool));
+ sri::Marshal::Copy(__try_cast<System::Boolean[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_BYTE:
+ seq = seq_allocate( nElements, sizeof (sal_Int8) );
+ sri::Marshal::Copy(__try_cast<System::Byte[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_SHORT:
+ seq = seq_allocate(nElements, sizeof (sal_Int16));
+ sri::Marshal::Copy(__try_cast<System::Int16[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ seq = seq_allocate( nElements, sizeof (sal_uInt16) );
+ sri::Marshal::Copy(static_cast<System::Int16[]>(
+ __try_cast<System::UInt16[]>(cli_data)), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_LONG:
+ seq = seq_allocate(nElements, sizeof (sal_Int32));
+ sri::Marshal::Copy(__try_cast<System::Int32[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ seq = seq_allocate( nElements, sizeof (sal_uInt32) );
+ sri::Marshal::Copy(static_cast<System::Int32[]>(
+ __try_cast<System::UInt32[]>(cli_data)), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_HYPER:
+ seq = seq_allocate(nElements, sizeof (sal_Int64));
+ sri::Marshal::Copy(__try_cast<System::Int64[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ seq = seq_allocate(nElements, sizeof (sal_uInt64));
+ sri::Marshal::Copy(static_cast<System::Int64[]>(
+ __try_cast<System::UInt64[]>(cli_data)), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_FLOAT:
+ seq = seq_allocate(nElements, sizeof (float));
+ sri::Marshal::Copy(__try_cast<System::Single[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ seq = seq_allocate(nElements, sizeof (double));
+ sri::Marshal::Copy(__try_cast<System::Double[]>(cli_data), 0,
+ & ((uno_Sequence*) seq.get())->elements, nElements);
+ break;
+ case typelib_TypeClass_STRING:
+ {
+ seq = seq_allocate(nElements, sizeof (rtl_uString*));
+ System::String* arStr[]= __try_cast<System::String*[]>(cli_data);
+ for (int i= 0; i < nElements; i++)
+ {
+ wchar_t const __pin * pdata= PtrToStringChars(arStr[i]);
+ rtl_uString** pStr= & ((rtl_uString**) &
+ ((uno_Sequence*) seq.get())->elements)[i];
+ *pStr= NULL;
+ rtl_uString_newFromStr_WithLength( pStr, pdata,
+ arStr[i]->get_Length());
+ }
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ seq = seq_allocate(nElements, sizeof (sal_Int32));
+ for (int i= 0; i < nElements; i++)
+ {
+ ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]=
+ System::Convert::ToInt32(ar->GetValue(i));
+ }
+ break;
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_INTERFACE:
+ {
+ TypeDescr element_td( element_type );
+ seq = seq_allocate( nElements, element_td.get()->nSize );
+
+ for (sal_Int32 nPos = 0; nPos < nElements; ++nPos)
+ {
+ try
+ {
+ void * p= ((uno_Sequence *) seq.get())->elements +
+ (nPos * element_td.get()->nSize);
+ System::Object* elemData= dynamic_cast<System::Array*>(cli_data)->GetValue(nPos);
+ map_to_uno(
+ p, elemData, element_td.get()->pWeakRef,
+ false /* no assign */);
+ }
+ catch (...)
+ {
+ // cleanup
+ for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos )
+ {
+ void * p =
+ ((uno_Sequence *)seq.get())->elements +
+ (nCleanPos * element_td.get()->nSize);
+ uno_destructData( p, element_td.get(), 0 );
+ }
+ throw;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
+ buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported sequence element type: ") );
+ buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) );
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ }
+ }
+ catch (BridgeRuntimeError& e)
+ {
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
+ buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ));
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] conversion failed\n "));
+ buf.append(e.m_message);
+ throw BridgeRuntimeError(buf.makeStringAndClear());
+ }
+ catch (System::InvalidCastException* )
+ {
+ // Ok, checked
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
+ buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName) );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert sequence element type: ") );
+ buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) );
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ throw;
+ }
+ __finally
+ {
+ if (assign)
+ uno_destructData( uno_data, td.get(), 0 );
+ }
+ }
+ else
+ {
+ seq = seq_allocate(0, sizeof (sal_Int32));
+ }
+ *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release();
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ if (assign)
+ {
+ uno_Interface * p = *(uno_Interface **)uno_data;
+ if (0 != p)
+ (*p->release)( p );
+ }
+ if (0 == cli_data) // null-ref
+ {
+ *(uno_Interface **)uno_data = 0;
+ }
+ else
+ {
+ TypeDescr td( type );
+ uno_Interface * pUnoI = map_cli2uno(cli_data, td.get());
+ *(uno_Interface **)uno_data = pUnoI;
+ }
+ break;
+ }
+ default:
+ {
+ //ToDo check
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
+ buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") );
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ }
+ }
+ // BridgeRuntimeError are allowed to be thrown
+ catch (System::InvalidCastException* )
+ {
+ //ToDo check
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_uno():") );
+ buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] could not convert type!") );
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ catch (System::NullReferenceException * e)
+ {
+ OUStringBuffer buf(512);
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
+ "[map_to_uno()] Illegal null reference passed!\n"));
+ buf.append(mapCliString(e->get_StackTrace()));
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ catch (BridgeRuntimeError& )
+ {
+ throw;
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ throw;
+ }
+
+}
+
+/**
+ @param info
+ The expected target type. Currently info is provdided when this method is called
+ to convert the in/out and out parameters of a call from cli to uno. Then info
+ is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion.
+ @param bDontCreateObj
+ false - a new object is created which holds the mapped uno value and is assigned to
+ cli_data.
+ true - cli_data already contains the newly constructed object. This is the case if
+ a struct is converted then on the first call to map_to_cli the new object is created.
+ If the struct inherits another struct then this function is called recursivly while the
+ newly created object is passed in cli_data.
+ */
+void Bridge::map_to_cli(
+ System::Object* *cli_data, void const * uno_data,
+ typelib_TypeDescriptionReference * type, System::Type* info,
+ bool bDontCreateObj) const
+{
+ switch (type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ *cli_data= __box(*(__wchar_t const*)uno_data);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ *cli_data = __box((*(bool const*)uno_data) == sal_True ? true : false);
+ break;
+ case typelib_TypeClass_BYTE:
+ *cli_data = __box(*(unsigned char const*) uno_data);
+ break;
+ case typelib_TypeClass_SHORT:
+ *cli_data= __box(*(short const*) uno_data);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *cli_data= __box(*(unsigned short const*) uno_data);
+ break;
+ case typelib_TypeClass_LONG:
+ *cli_data= __box(*(int const*) uno_data);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *cli_data= __box(*(unsigned int const*) uno_data);
+ break;
+ case typelib_TypeClass_HYPER:
+ *cli_data= __box(*(__int64 const*) uno_data);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *cli_data= __box(*(unsigned __int64 const*) uno_data);
+ break;
+ case typelib_TypeClass_FLOAT:
+ *cli_data= __box(*(float const*) uno_data);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ *cli_data= __box(*(double const*) uno_data);
+ break;
+ case typelib_TypeClass_STRING:
+ {
+ rtl_uString const* sVal= NULL;
+ sVal= *(rtl_uString* const*) uno_data;
+ *cli_data= new System::String((__wchar_t*) sVal->buffer,0, sVal->length);
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data );
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any const * pAny = (uno_Any const *)uno_data;
+ if (typelib_TypeClass_VOID != pAny->pType->eTypeClass)
+ {
+ System::Object* objCli= NULL;
+ map_to_cli(
+ &objCli, pAny->pData, pAny->pType, 0,
+ false);
+
+ uno::Any anyVal(mapUnoType(pAny->pType), objCli);
+ *cli_data= __box(anyVal);
+ }
+ else
+ { // void any
+ *cli_data= __box(uno::Any::VOID);
+ }
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ if (info != NULL)
+ {
+ OSL_ASSERT(info->get_IsByRef());
+ info= info->GetElementType();
+ *cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data);
+ }
+ else
+ *cli_data= System::Enum::ToObject(
+ mapUnoType(type), *(System::Int32*) uno_data);
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ TypeDescr td( type );
+ typelib_CompoundTypeDescription * comp_td =
+ (typelib_CompoundTypeDescription *) td.get();
+ if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
+ ::typelib_typedescription_complete(
+ (typelib_TypeDescription**) & comp_td );
+
+
+ //create the type
+ System::Type* cliType= loadCliType(td.get()->pTypeName);
+ //detect if we recursivly convert inherited structures
+ //If this point is reached because of a recursive call during convering a
+ //struct then we must not create a new object rather we use the one in
+ // cli_data argument.
+ System::Object* cliObj;
+ if (bDontCreateObj)
+ cliObj = *cli_data; // recursive call
+ else
+ {
+ //Special handling for Exception conversion. We must call constructor System::Exception
+ //to pass the message string
+ if (__typeof(ucss::uno::Exception)->IsAssignableFrom(cliType))
+ {
+ //We need to get the Message field. Therefore we must obtain the offset from
+ //the typedescription. The base interface of all exceptions is
+ //com::sun::star::uno::Exception which contains the message
+ typelib_CompoundTypeDescription* pCTD = comp_td;
+ while (pCTD->pBaseTypeDescription)
+ pCTD = pCTD->pBaseTypeDescription;
+ int nPos = -1;
+
+ rtl::OUString usMessageMember(RTL_CONSTASCII_USTRINGPARAM("Message"));
+ for (int i = 0; i < pCTD->nMembers; i ++)
+ {
+#if OSL_DEBUG_LEVEL >= 2
+ System::String* sMember;
+ sMember = mapUnoString(pCTD->ppMemberNames[i]);
+#endif
+ if (usMessageMember.equals(pCTD->ppMemberNames[i]))
+ {
+ nPos = i;
+ break;
+ }
+ }
+ OSL_ASSERT (nPos != -1);
+ int offset = pCTD->pMemberOffsets[nPos];
+ //Whith the offset within the exception we can get the message string
+ System::String* sMessage = mapUnoString(*(rtl_uString**)
+ ((char*) uno_data + offset));
+ //We need to find a constructor for the exception that takes the message string
+ //We assume that the first argument is the message string
+ sr::ConstructorInfo* arCtorInfo[] = cliType->GetConstructors();
+ sr::ConstructorInfo* ctorInfo = NULL;
+ int numCtors = arCtorInfo->get_Length();
+ //Constructor must at least have 2 params for the base
+ //unoidl.com.sun.star.uno.Exception (String, Object);
+ sr::ParameterInfo * arParamInfo[];
+ for (int i = 0; i < numCtors; i++)
+ {
+ arParamInfo = arCtorInfo[i]->GetParameters();
+ if (arParamInfo->get_Length() < 2)
+ continue;
+ ctorInfo = arCtorInfo[i];
+ break;
+ }
+ OSL_ASSERT(arParamInfo[0]->get_ParameterType()->Equals(__typeof(System::String))
+ && arParamInfo[1]->get_ParameterType()->Equals(__typeof(System::Object))
+ && arParamInfo[0]->get_Position() == 0
+ && arParamInfo[1]->get_Position() == 1);
+ //Prepare parameters for constructor
+ int numArgs = arParamInfo->get_Length();
+ System::Object * args[] = new System::Object*[numArgs];
+ //only initialize the first argument with the message
+ args[0] = sMessage;
+ cliObj = ctorInfo->Invoke(args);
+ }
+ else
+ cliObj = System::Activator::CreateInstance(cliType);
+ }
+ sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets;
+
+ if (comp_td->pBaseTypeDescription)
+ {
+ //convert inherited struct
+ //cliObj is passed inout (args in_param, out_param are true), hence the passed
+ // cliObj is used by the callee instead of a newly created struct
+ map_to_cli(
+ &cliObj, uno_data,
+ ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, 0,
+ true);
+ }
+ rtl::OUString usUnoException(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception"));
+ for (sal_Int32 nPos = comp_td->nMembers; nPos--; )
+ {
+ typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ];
+ System::String* sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]);
+ sr::FieldInfo* aField= cliType->GetField(sMemberName);
+ // special case for Exception.Message. The field has already been
+ // set while constructing cli object
+ if ( ! aField && usUnoException.equals(td.get()->pTypeName))
+ {
+ continue;
+ }
+ void const * p = (char const *)uno_data + pMemberOffsets[ nPos ];
+ switch (member_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ aField->SetValue(cliObj, __box(*(System::Char*) p));
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ aField->SetValue(cliObj, __box(*(System::Boolean*) p));
+ break;
+ case typelib_TypeClass_BYTE:
+ aField->SetValue(cliObj, __box(*(System::Byte*) p));
+ break;
+ case typelib_TypeClass_SHORT:
+ aField->SetValue(cliObj, __box(*(System::Int16*) p));
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ aField->SetValue(cliObj, __box(*(System::UInt16*) p));
+ break;
+ case typelib_TypeClass_LONG:
+ aField->SetValue(cliObj, __box(*(System::Int32*) p));
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ aField->SetValue(cliObj, __box(*(System::UInt32*) p));
+ break;
+ case typelib_TypeClass_HYPER:
+ aField->SetValue(cliObj, __box(*(System::Int64*) p));
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ aField->SetValue(cliObj, __box(*(System::UInt64*) p));
+ break;
+ case typelib_TypeClass_FLOAT:
+ aField->SetValue(cliObj, __box(*(System::Single*) p));
+ break;
+ case typelib_TypeClass_DOUBLE:
+ aField->SetValue(cliObj, __box(*(System::Double*) p));
+ break;
+ default:
+ {
+ System::Object* cli_val;
+ map_to_cli(
+ &cli_val, p, member_type, 0,
+ false);
+ aField->SetValue(cliObj, cli_val);
+ break;
+ }
+ }
+ }
+ *cli_data= cliObj;
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ sal_Int32 nElements;
+ uno_Sequence const * seq = 0;
+ seq = *(uno_Sequence * const *)uno_data;
+ nElements = seq->nElements;
+
+ TypeDescr td( type );
+ typelib_TypeDescriptionReference * element_type =
+ ((typelib_IndirectTypeDescription *)td.get())->pType;
+
+ switch (element_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ {
+ System::Char arChar[]= new System::Char[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arChar, 0, nElements);
+ *cli_data= arChar;
+ break;
+ }
+ case typelib_TypeClass_BOOLEAN:
+ {
+ System::Boolean arBool[]= new System::Boolean[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arBool, 0, nElements);
+ *cli_data= arBool;
+ break;
+ }
+ case typelib_TypeClass_BYTE:
+ {
+ System::Byte arByte[]= new System::Byte[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arByte, 0, nElements);
+ *cli_data= arByte;
+ break;
+ }
+ case typelib_TypeClass_SHORT:
+ {
+ System::Int16 arShort[]= new System::Int16[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arShort, 0, nElements);
+ *cli_data= arShort;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ {
+ System::UInt16 arUInt16[]= new System::UInt16[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, static_cast<System::Int16[]>(arUInt16),
+ 0, nElements);
+ *cli_data= arUInt16;
+ break;
+ }
+ case typelib_TypeClass_LONG:
+ {
+ System::Int32 arInt32[]= new System::Int32[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arInt32, 0, nElements);
+ *cli_data= arInt32;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ {
+ System::UInt32 arUInt32[]= new System::UInt32[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, static_cast<System::Int32[]>(arUInt32),
+ 0, nElements);
+ *cli_data= arUInt32;
+ break;
+ }
+ case typelib_TypeClass_HYPER:
+ {
+ System::Int64 arInt64[]= new System::Int64[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arInt64, 0, nElements);
+ *cli_data= arInt64;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ {
+ System::UInt64 arUInt64[]= new System::UInt64[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arUInt64, 0, nElements);
+ *cli_data= arUInt64;
+ break;
+ }
+ case typelib_TypeClass_FLOAT:
+ {
+ System::Single arSingle[]= new System::Single[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arSingle, 0, nElements);
+ *cli_data= arSingle;
+ break;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ System::Double arDouble[]= new System::Double[nElements];
+ sri::Marshal::Copy( (void*) &seq->elements, arDouble, 0, nElements);
+ *cli_data= arDouble;
+ break;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ System::String* arString[]= new System::String*[nElements];
+ for (int i= 0; i < nElements; i++)
+ {
+ rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i];
+ arString[i]= new System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length);
+ }
+ *cli_data= arString;
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ System::Type* arType[]= new System::Type*[nElements];
+ for (int i= 0; i < nElements; i++)
+ {
+ arType[i]=
+ mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]);
+ }
+ *cli_data= arType;
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno::Any arCli[]= new uno::Any[nElements];
+ uno_Any const * p = (uno_Any const *)seq->elements;
+ for (sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object* cli_obj = NULL;
+ map_to_cli(
+ &cli_obj, &p[ nPos ], element_type, 0, false);
+ arCli[nPos]= *__try_cast<__box uno::Any*>(cli_obj);
+ }
+ *cli_data= arCli;
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ //get the Enum type
+ System::Type* enumType= NULL;
+ if (info != NULL)
+ {
+ //info is EnumType[]&, remove &
+ OSL_ASSERT(info->IsByRef);
+ enumType = info->GetElementType();
+ //enumType is EnumType[], remove []
+ enumType = enumType->GetElementType();
+ }
+ else
+ enumType= mapUnoType(element_type);
+
+ System::Array* arEnum = System::Array::CreateInstance(
+ enumType, nElements);
+ for (int i= 0; i < nElements; i++)
+ {
+ arEnum->SetValue(System::Enum::ToObject(enumType,
+ ((sal_Int32*) seq->elements)[i]), i);
+ }
+ *cli_data = arEnum;
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ TypeDescr element_td( element_type );
+ System::Array* ar= System::Array::CreateInstance(
+ mapUnoType(element_type),nElements);
+ if (0 < nElements)
+ {
+ // ToDo check this
+ char * p = (char *) &seq->elements;
+ sal_Int32 nSize = element_td.get()->nSize;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object* val;
+ map_to_cli(
+ &val, p + (nSize * nPos), element_type, 0, false);
+ ar->SetValue(val, nPos);
+ }
+ }
+ *cli_data = ar;
+ break;
+ }
+// ToDo, verify
+ case typelib_TypeClass_SEQUENCE:
+ {
+ System::Array *ar= System::Array::CreateInstance(
+ mapUnoType(element_type), nElements);
+ if (0 < nElements)
+ {
+ TypeDescr element_td( element_type );
+ uno_Sequence ** elements = (uno_Sequence**) seq->elements;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object* val;
+ map_to_cli(
+ &val, &elements[nPos], element_type, 0, false);
+ ar->SetValue(val, nPos);
+ }
+ }
+ *cli_data = ar;
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ TypeDescr element_td( element_type );
+ System::Type * ifaceType= mapUnoType(element_type);
+ System::Array* ar= System::Array::CreateInstance(ifaceType, nElements);
+
+ char * p = (char *)seq->elements;
+ sal_Int32 nSize = element_td.get()->nSize;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object* val;
+ map_to_cli(
+ &val, p + (nSize * nPos), element_type, NULL, false);
+
+ ar->SetValue(val, nPos);
+ }
+ *cli_data= ar;
+ break;
+ }
+ default:
+ {
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") );
+ buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported element type: ") );
+ buf.append( *reinterpret_cast< OUString const * >( &element_type->pTypeName ) );
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ uno_Interface * pUnoI = *(uno_Interface * const *)uno_data;
+ if (0 != pUnoI)
+ {
+ TypeDescr td( type );
+ *cli_data= map_uno2cli( pUnoI, reinterpret_cast<
+ typelib_InterfaceTypeDescription*>(td.get())) ;
+ }
+ else
+ *cli_data= NULL;
+ break;
+ }
+ default:
+ {
+ //ToDo check this exception. The String is probably crippled
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[map_to_cli():") );
+ buf.append( *reinterpret_cast< OUString const * >( &type->pTypeName ) );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] unsupported type!") );
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+ }
+}
+}
diff --git a/cli_ure/source/uno_bridge/cli_environment.cxx b/cli_ure/source/uno_bridge/cli_environment.cxx
new file mode 100644
index 000000000000..cfa0f8e57817
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_environment.cxx
@@ -0,0 +1,173 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 "Cli_environment.h"
+
+#using <mscorlib.dll>
+#using <cli_ure.dll>
+#using <system.dll>
+#include "osl/diagnose.h"
+#include "cli_proxy.h"
+
+using namespace System::Runtime::Remoting;
+using namespace System::Runtime::Remoting::Proxies;
+using namespace System::Collections;
+using namespace System::Text;
+using namespace System::Diagnostics;
+using namespace System::Threading;
+
+namespace cli_uno
+{
+
+inline System::String* Cli_environment::createKey(System::String* oid, System::Type* t)
+{
+ return System::String::Concat(oid, t->get_FullName());
+}
+
+
+inline Cli_environment::Cli_environment()
+{
+#if OSL_DEBUG_LEVEL >= 2
+ _numRegisteredObjects = 0;
+#endif
+}
+
+Cli_environment::~Cli_environment()
+{
+ OSL_ENSURE(_numRegisteredObjects == 0,
+ "cli uno bridge: CLI environment contains unrevoked objects");
+}
+
+
+System::Object* Cli_environment::registerInterface(
+ System::Object* obj, System::String* oid)
+{
+#if OSL_DEBUG_LEVEL >= 1
+ //obj must be a transparent proxy
+ OSL_ASSERT(RemotingServices::IsTransparentProxy(obj));
+ _numRegisteredObjects ++;
+#endif
+ OSL_ASSERT( ! m_objects->ContainsKey(oid));
+ m_objects->Add(oid, new WeakReference(obj));
+ return obj;
+}
+System::Object* Cli_environment::registerInterface (
+ System::Object* obj, System::String* oid, System::Type* type)
+{
+#if OSL_DEBUG_LEVEL >= 1
+ //obj must be a real cli object
+ OSL_ASSERT( ! RemotingServices::IsTransparentProxy(obj));
+ _numRegisteredObjects ++;
+#endif
+ System::String* key = createKey(oid, type);
+ //see synchronization in map_uno2cli in cli_data.cxx
+ OSL_ASSERT( ! m_objects->ContainsKey(key));
+ m_objects->Add(key, new WeakReference(obj));
+ return obj;
+}
+
+void Cli_environment::revokeInterface(System::String* oid, System::Type* type)
+{
+ System::String* key = type != NULL ? createKey(oid, type) : oid;
+#if OSL_DEBUG_LEVEL >= 1
+ _numRegisteredObjects --;
+#endif
+#if OSL_DEBUG_LEVEL >= 2
+ int i = 1;
+ if (m_objects->ContainsKey(key) == false)
+ {
+ Trace::WriteLine("cli uno bridge: try to revoke unregistered interface");
+ Trace::WriteLine(oid);
+ i = 0;
+ }
+ Trace::WriteLine(System::String::Format(
+ new System::String(S"cli uno bridge: {0} remaining registered interfaces"),
+ __box(m_objects->get_Count() - 1)));
+#endif
+ m_objects->Remove(key);
+}
+
+inline void Cli_environment::revokeInterface(System::String* oid)
+{
+ return revokeInterface(oid, NULL);
+}
+
+System::Object* Cli_environment::getRegisteredInterface(System::String* oid,
+ System::Type* type)
+{
+ //try if it is a UNO interface
+ System::Object* ret = NULL;
+ ret = m_objects->get_Item(oid);
+ if (! ret)
+ {
+ //try if if it is a proxy for a cli object
+ oid = createKey(oid, type);
+ ret = m_objects->get_Item( oid );
+ }
+ if (ret != 0)
+ {
+ System::WeakReference* weakIface =
+ static_cast< System::WeakReference * >( ret );
+ ret = weakIface->Target;
+ }
+ if (ret == 0)
+ m_objects->Remove( oid );
+ return ret;
+}
+
+System::String* Cli_environment::getObjectIdentifier(System::Object* obj)
+{
+ System::String* oId= 0;
+ RealProxy* aProxy= RemotingServices::GetRealProxy(obj);
+ if (aProxy)
+ {
+ UnoInterfaceProxy* proxyImpl= dynamic_cast<UnoInterfaceProxy*>(aProxy);
+ if (proxyImpl)
+ oId= proxyImpl->getOid();
+ }
+
+ if (oId == 0)
+ {
+ StringBuilder * buf= new StringBuilder(256);
+ bool bFirst = false;
+ System::Threading::Monitor::Enter(__typeof(Cli_environment));
+ try {
+ buf->Append(m_IDGen->GetId(obj, & bFirst));
+ } __finally
+ {
+ System::Threading::Monitor::Exit(__typeof(Cli_environment));
+ }
+
+ buf->Append(sOidPart);
+ oId= buf->ToString();
+ }
+ return oId;
+}
+} //namespace cli_uno
diff --git a/cli_ure/source/uno_bridge/cli_environment.h b/cli_ure/source/uno_bridge/cli_environment.h
new file mode 100644
index 000000000000..486d5c169807
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_environment.h
@@ -0,0 +1,114 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_CLI_ENVIRONMENT_H
+#define INCLUDED_CLI_ENVIRONMENT_H
+
+#include "cli_base.h"
+#using <mscorlib.dll>
+
+using namespace System;
+using namespace System::Collections;
+using namespace System::Runtime::Serialization;
+
+namespace cli_uno
+{
+
+public __gc class Cli_environment
+{
+ static System::String* sOidPart;
+ static Hashtable* m_objects;
+ static System::Runtime::Serialization::ObjectIDGenerator* m_IDGen;
+ inline static System::String* createKey(System::String* oid, System::Type* t);
+
+#if OSL_DEBUG_LEVEL >= 1
+ int _numRegisteredObjects;
+#endif
+
+public:
+
+ static Cli_environment()
+ {
+ m_objects = Hashtable::Synchronized(new Hashtable());
+ m_IDGen = new System::Runtime::Serialization::ObjectIDGenerator();
+ System::Text::StringBuilder* buffer = new System::Text::StringBuilder(256);
+ Guid gd = Guid::NewGuid();
+ buffer->Append(S";cli[0];");
+ buffer->Append(gd.ToString());
+ sOidPart = buffer->ToString();
+ }
+
+ inline Cli_environment();
+
+ ~Cli_environment();
+
+ /**
+ Registers an UNO object as being mapped by this bridge. The resulting
+ cli object is represents all interfaces of the UNO object. Therefore the
+ object can be registered only with its OID; a type is not necessary.
+ */
+ Object* registerInterface(Object* obj, System::String* oid);
+ /**
+ Registers a CLI object as being mapped by this bridge. The resulting
+ object represents exactly one UNO interface.
+ */
+ Object* registerInterface(Object* obj, System::String* oid, System::Type* type);
+
+ /**
+ By revoking an interface it is declared that the respective interface has
+ not been mapped. The proxy implementations call revoke interface in their
+ destructors.
+ */
+ inline void revokeInterface(System::String* oid);
+
+ void revokeInterface(System::String* oid, System::Type* type);
+ /**
+ * Retrieves an interface identified by its object id and type from this
+ * environment.
+ *
+ * @param oid object id of interface to be retrieved
+ * @param type the type description of the interface to be retrieved
+ * @see com.sun.star.uno.IEnvironment#getRegisteredInterface
+ */
+ Object* getRegisteredInterface(System::String* oid, System::Type* type);
+
+ /**
+ * Generates a worldwide unique object identifier (oid) for the given object. It is
+ * guaranteed, that subsequent calls to the method with the same object
+ * will give the same id.
+ * <p>
+ * @return the generated oid.
+ * @param object the object for which a Oid should be generated.
+ */
+ static System::String* getObjectIdentifier(Object* obj);
+
+};
+
+} //namespace cli_uno
+
+
+#endif
diff --git a/cli_ure/source/uno_bridge/cli_proxy.cxx b/cli_ure/source/uno_bridge/cli_proxy.cxx
new file mode 100644
index 000000000000..0fd662a24fe9
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_proxy.cxx
@@ -0,0 +1,1178 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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, &param, 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 */, &param, 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
+ }
+}
+
+
+
+
+
diff --git a/cli_ure/source/uno_bridge/cli_proxy.h b/cli_ure/source/uno_bridge/cli_proxy.h
new file mode 100644
index 000000000000..2441bebf1365
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_proxy.h
@@ -0,0 +1,299 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_CLI_PROXY_H
+#define INCLUDED_CLI_PROXY_H
+
+#pragma warning(push, 1)
+#include "uno/environment.hxx"
+#pragma warning(pop)
+#include "uno/mapping.hxx"
+#include "uno/dispatcher.h"
+#include "cli_bridge.h"
+#include "cli_environment.h"
+
+#using <mscorlib.dll>
+#using <cli_ure.dll>
+
+namespace srrp = System::Runtime::Remoting::Proxies;
+namespace srrm = System::Runtime::Remoting::Messaging;
+namespace srr = System::Runtime::Remoting;
+namespace sr = System::Reflection;
+namespace sc = System::Collections;
+using namespace uno;
+
+namespace cli_uno
+{
+
+public __gc class UnoInterfaceInfo
+{
+public:
+ UnoInterfaceInfo(Bridge const * bridge, uno_Interface* unoI,
+ typelib_InterfaceTypeDescription* td);
+ ~UnoInterfaceInfo();
+ uno_Interface * m_unoI; // wrapped interface
+ System::Type * m_type;
+ typelib_InterfaceTypeDescription* m_typeDesc;
+
+ Bridge const* m_bridge;
+};
+
+public __gc class UnoInterfaceProxy: public srrp::RealProxy,
+ public srr::IRemotingTypeInfo
+{
+ /** used for IRemotingTypeInfo.TypeName
+ */
+ System::String* m_sTypeName;
+ /** The list is filled with UnoInterfaceInfo objects. The list can only
+ grow and elements are never changed. If an element was added it
+ must not be changed!
+ */
+ sc::ArrayList* m_listIfaces;
+ /** The number of UNO interfaces this proxy represents. It corresponds
+ to the the number of elements in m_listIfaces.
+ */
+ int m_numUnoIfaces;
+ /** The list is filled with additional UnoInterfaceProxy object due
+ to aggregation via bridges. Though the latter is strongly
+ discouraged, this has to be supported.
+ */
+ sc::ArrayList* m_listAdditionalProxies;
+ int m_nlistAdditionalProxies;
+
+ UnoInterfaceInfo * findInfo( ::System::Type * type );
+
+ Bridge const* m_bridge;
+ System::String* m_oid;
+
+#if OSL_DEBUG_LEVEL >= 2
+ /** The string contains all names of UNO interfaces which are
+ represented by this proxy. It is used to print out the interfaces
+ when this proxy dies. In the destructor it is not allowed to
+ access m_listIfaces or any other managed object.
+ */
+ rtl_uString * _sInterfaces;
+// /** Count of interfaces. Used in conjunction with _sInterfaces.
+// */
+ int _numInterfaces;
+#endif
+
+public:
+
+ /** Creates a proxy and registers it on the dot NET side.
+ */
+ static System::Object* create(Bridge * bridge,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription* pTd,
+ const rtl::OUString& oid);
+
+ /** RealProxy::Invoke */
+ srrm::IMessage* Invoke(srrm::IMessage* msg);
+
+ /** Must be called from within a synchronized section.
+ Add only the interface if it is not already contained.
+ This method is called from the constructor and as a result
+ of IRemotingTypeInfo::CanCastTo
+ */
+ void addUnoInterface(uno_Interface* pUnoI,
+ typelib_InterfaceTypeDescription* pTd);
+ ~UnoInterfaceProxy();
+
+ /**
+ */
+ inline System::String * getOid()
+ { return m_oid; }
+
+ //IRemotingTypeInfo ----------------------------------------------
+ bool CanCastTo(System::Type* fromType, System::Object* o);
+
+ __property System::String* get_TypeName()
+ {
+ return m_sTypeName;
+ }
+ __property void set_TypeName(System::String* name)
+ {
+ m_sTypeName = name;
+ }
+
+
+private:
+ UnoInterfaceProxy(
+ Bridge * bridge,
+ uno_Interface * pUnoI,
+ typelib_InterfaceTypeDescription* pTD,
+ const rtl::OUString& oid );
+
+ static srrm::IMessage* constructReturnMessage(System::Object* retVal,
+ System::Object* outArgs[],
+ typelib_InterfaceMethodTypeDescription* mtd,
+ srrm::IMessage* msg, System::Object* exc);
+
+ static System::String* m_methodNameString =
+ new System::String("__MethodName");
+ static System::String* m_typeNameString = new System::String("__TypeName");
+ static System::String* m_ArgsString = new System::String("__Args");
+ static System::String* m_CallContextString =
+ new System::String("__CallContext");
+ static System::String* m_system_Object_String =
+ new System::String("System.Object");
+ static System::String* m_methodSignatureString =
+ new System::String("__MethodSignature");
+ static System::String* m_Equals_String = new System::String("Equals");
+ static System::String* m_GetHashCode_String =
+ new System::String("GetHashCode");
+ static System::String* m_GetType_String = new System::String("GetType");
+ static System::String* m_ToString_String = new System::String("ToString");
+
+protected:
+ srrm::IMessage* invokeObject(sc::IDictionary* properties,
+ srrm::LogicalCallContext* context,
+ srrm::IMethodCallMessage* mcm);
+};
+
+
+//Cannot make this __gc because a managed type cannot derive from unmanaged type
+struct CliProxy: public uno_Interface
+{
+ mutable oslInterlockedCount m_ref;
+ const Bridge* m_bridge;
+ const gcroot<System::Object*> m_cliI;
+ gcroot<System::Type*> m_type;
+ const com::sun::star::uno::TypeDescription m_unoType;
+ const gcroot<System::String*> m_oid;
+ const rtl::OUString m_usOid;
+
+ enum MethodKind {MK_METHOD = 0, MK_SET, MK_GET};
+ /** The array contains MethodInfos of the cli object. Each one reflects an
+ implemented interface method of the interface for which this proxy was
+ created. The MethodInfos are from the object's method and not from the
+ interface type. That is, they can be used to invoke the methods. The
+ order of the MethodInfo objects corresponds to the order of the
+ interface methods (see member m_type). Position 0 contains the
+ MethodInfo of the first method of the interface which represents the
+ root of the inheritance chain. The last MethodInfo represents the last
+ method of the furthest derived interface.
+
+ The array is completely initialized in the constructor of this object.
+
+ When the uno_DispatchMethod is called for this proxy then it receives
+ a typelib_TypeDescription of the member which is either an attribute
+ (setter or getter) or method. After determining the position of the
+ method within the UNO interface one can use the position to obtain the
+ MethodInfo of the corresponding cli method. To obtain the index for the
+ m_arMethodInfos array the function position has to be decreased by 3.
+ This is becaus, the cli interface does not contain the XInterface
+ methods.
+ */
+ gcroot<sr::MethodInfo*[]> m_arMethodInfos;
+
+ /** This array is similar to m_arMethodInfos but it contains the MethodInfo
+ objects of the interface (not the object). When a call is made from uno
+ to cli then the uno method name is compared to the cli method name. The
+ cli method name can be obtained from the MethodInfo object in this
+ array. The name of the actual implemented method may not be the same as
+ the interface method.
+ */
+ gcroot<sr::MethodInfo*[]> m_arInterfaceMethodInfos;
+
+ /** Maps the position of the method in the UNO interface to the position of
+ the corresponding MethodInfo in m_arMethodInfos. The Uno position must
+ not include the XInterface methods. For example,
+ pos 0 = XInterface::queryInterface
+ pos 1 = XInterface::acquire
+ pos 2 = XInterface::release
+
+ That is the real Uno position has to be deducted by 3. Then
+ arUnoPosToCliPos[pos] contains the index for m_arMethodInfos.
+
+ */
+ gcroot<System::Int32[]> m_arUnoPosToCliPos;
+
+ /** Count of inherited interfaces of the cli interface.
+ */
+ int m_nInheritedInterfaces;
+ /** Contains the number of methods of each interface.
+ */
+ gcroot<System::Int32[]> m_arInterfaceMethodCount;
+
+ CliProxy( Bridge const* bridge, System::Object* cliI,
+ typelib_TypeDescription const* pTD,
+ const rtl::OUString& usOid);
+ ~CliProxy();
+
+ static uno_Interface* create(Bridge const * bridge,
+ System::Object* cliI,
+ typelib_TypeDescription const * TD,
+ rtl::OUString const & usOid );
+
+ /** Prepares an array (m_arMethoInfos) containing MethodInfo object of the
+ interface and all inherited interfaces. At index null is the first
+ method of the base interface and at the last position is the last method
+ of the furthest derived interface.
+ If a UNO call is received then one can determine the position of the
+ method (or getter or setter for an attribute) from the passed type
+ information. The position minus 3 (there is no XInterface in the cli
+ mapping) corresponds to the index of the cli interface method in the
+ array.
+ */
+ void makeMethodInfos();
+
+ /**Obtains a MethodInfo which can be used to invoke the cli object.
+ Internally it maps nUnoFunctionPos to an index that is used to get the
+ corresponding MethodInfo object from m_arMethoInfos. The mapping table
+ is dynamically initialized. If the cli interface has no base interface
+ or exactly one then the mapping table is initialized in one go at the
+ first call. In all ensuing calls the MethodInfo object is immediately
+ retrieved through the mapping table.
+
+ If the interface has more then one interface in its inheritance chain,
+ that is Type.GetInterfaces return more then one Type, then the mapping
+ table is partially initiallized. On the first call the mappings for the
+ methods of the belonging interface are created.
+
+ The implementation assumes that the order of interface methods as
+ provided by InterfaceMapping.InterfaceMethods corresponds to the order
+ of methods in the interface declaration.
+
+ @param nUnoFunctionPos
+ Position of the method in the uno interface.
+ */
+ sr::MethodInfo* getMethodInfo(int nUnoFunctionPos,
+ const rtl::OUString & usMethodName,
+ MethodKind mk);
+
+ void SAL_CALL uno_DispatchMethod(
+ struct _uno_Interface * pUnoI,
+ const struct _typelib_TypeDescription * pMemberType,
+ void * pReturn,
+ void * pArgs[],
+ uno_Any ** ppException );
+
+ inline void acquire() const;
+ inline void release() const;
+};
+}
+#endif
diff --git a/cli_ure/source/uno_bridge/cli_uno.cxx b/cli_ure/source/uno_bridge/cli_uno.cxx
new file mode 100644
index 000000000000..34fdbe0c66ef
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_uno.cxx
@@ -0,0 +1,290 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <sal/alloca.h>
+#include "rtl/ustrbuf.hxx"
+#include "cli_base.h"
+#include "cli_bridge.h"
+
+namespace sr=System::Reflection;
+namespace css=com::sun::star;
+using namespace rtl;
+
+namespace cli_uno
+{
+
+union largest
+{
+ sal_Int64 n;
+ double d;
+ void * p;
+ uno_Any a;
+};
+
+System::Object* Bridge::call_uno(uno_Interface * pUnoI,
+ typelib_TypeDescription* member_td,
+ typelib_TypeDescriptionReference * return_type,
+ sal_Int32 nParams, typelib_MethodParameter const * pParams,
+ System::Object * args[], System::Type* argTypes[],
+ System::Object** ppExc) const
+{
+ // return mem
+ sal_Int32 return_size = sizeof (largest);
+ if ((0 != return_type) &&
+ (typelib_TypeClass_STRUCT == return_type->eTypeClass ||
+ typelib_TypeClass_EXCEPTION == return_type->eTypeClass))
+ {
+ TypeDescr return_td( return_type );
+ if (return_td.get()->nSize > sizeof (largest))
+ return_size = return_td.get()->nSize;
+ }
+ //Prepare memory that contains all converted arguments and return valuse
+ //The memory block contains first pointers to the arguments which are in the same block
+ // For example, 2 arguments, 1 ret.
+ //
+ // | Pointer
+ // | Pointer
+ // | Return value
+ // | Arg 1
+ // | Arg 2
+ //
+ // If an argument is larger then union largest, such as some structures, then the pointer
+ // points to an extra block of memory. The same goes for a big return value.
+
+ char * mem = (char *)alloca(
+ (nParams * sizeof (void *)) + return_size + (nParams * sizeof (largest)) );
+ //array of pointers to args
+ void ** uno_args = (void **)mem;
+ //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int )
+ void * uno_ret= NULL;
+ if ( !(member_td->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE && nParams == 1))
+ uno_ret = (mem + (nParams * sizeof (void *)));
+ largest * uno_args_mem = (largest *)(mem + (nParams * sizeof (void *)) + return_size);
+
+ OSL_ASSERT( (0 == nParams) || (nParams == args->get_Length()) );
+ for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = pParams[ nPos ];
+ typelib_TypeDescriptionReference * type = param.pTypeRef;
+
+ uno_args[ nPos ] = &uno_args_mem[ nPos ];
+ if (typelib_TypeClass_STRUCT == type->eTypeClass ||
+ typelib_TypeClass_EXCEPTION == type->eTypeClass)
+ {
+ TypeDescr td( type );
+ if (td.get()->nSize > sizeof (largest))
+ uno_args[ nPos ] = alloca( td.get()->nSize );
+ }
+
+ if (param.bIn)
+ {
+ try
+ {
+ // in, in/out params
+ map_to_uno(
+ uno_args[ nPos ],args[nPos] , type, false /* no assign */);
+ }
+ catch (...)
+ {
+ // cleanup uno in args
+ for (sal_Int32 n = 0; n < nPos; ++n)
+ {
+ typelib_MethodParameter const & param = pParams[n];
+ if (param.bIn)
+ {
+ uno_type_destructData(uno_args[n], param.pTypeRef, 0);
+ }
+ }
+ throw;
+ }
+ }
+ }
+ uno_Any uno_exc_holder;
+ uno_Any * uno_exc = &uno_exc_holder;
+ // call binary uno
+
+ (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc );
+
+ if (0 == uno_exc)
+ {
+ // convert out args; destruct uno args
+ for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = pParams[ nPos ];
+ typelib_TypeDescriptionReference * type = param.pTypeRef;
+ if (param.bOut)
+ {
+ try
+ {
+ map_to_cli(
+ &args[nPos], uno_args[nPos], param.pTypeRef,
+ argTypes != NULL ? argTypes[nPos] : NULL, false );
+ }
+ catch (...)
+ {
+ // cleanup further uno args
+ for ( sal_Int32 n = nPos; n < nParams; ++n )
+ {
+ uno_type_destructData( uno_args[n], pParams[n].pTypeRef, 0 );
+ }
+ // cleanup uno return value
+ uno_type_destructData( uno_ret, return_type, 0 );
+ throw;
+ }
+ }
+ //cleanup args
+ if (typelib_TypeClass_DOUBLE < type->eTypeClass &&
+ typelib_TypeClass_ENUM != type->eTypeClass) // opt
+ {
+ uno_type_destructData(uno_args[nPos], type, 0);
+ }
+ }
+
+ if ((0 != return_type) &&
+ (typelib_TypeClass_VOID != return_type->eTypeClass))
+ {
+ // convert uno return value
+ try
+ {
+ System::Object* cli_ret;
+ map_to_cli(
+ &cli_ret, uno_ret, return_type, 0, false);
+ uno_type_destructData(uno_ret, return_type, 0);
+ return cli_ret;
+ }
+ catch (...)
+ {
+ uno_type_destructData(uno_ret, return_type, 0);
+ throw;
+ }
+ }
+ return 0; // void return
+ }
+ else // exception occured
+ {
+ // destruct uno in args
+ for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = pParams[ nPos ];
+ if (param.bIn)
+ {
+ uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 );
+ }
+ }
+ map_to_cli(ppExc, uno_exc_holder.pData,
+ uno_exc_holder.pType, NULL, false);
+ return 0;
+ }
+}
+
+void Bridge::call_cli(
+ System::Object* cliI,
+ sr::MethodInfo* method,
+ typelib_TypeDescriptionReference * return_type,
+ typelib_MethodParameter * params, int nParams,
+ void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const
+{
+ System::Object *args[]= new System::Object*[nParams];
+ for (int nPos= 0; nPos < nParams; nPos++)
+ {
+ typelib_MethodParameter const & param= params[nPos];
+ if (param.bIn)
+ {
+ map_to_cli( &args[nPos],
+ uno_args[nPos], param.pTypeRef, 0, false);
+ }
+ }
+ System::Object* retInvoke= NULL;
+ try
+ {
+ retInvoke= method->Invoke(cliI, args);
+ }
+ catch (sr::TargetInvocationException* e)
+ {
+ System::Exception* exc= e->get_InnerException();
+ css::uno::TypeDescription td(mapCliType(exc->GetType()));
+ // memory for exception
+ std::auto_ptr< rtl_mem > memExc(rtl_mem::allocate(td.get()->nSize));
+ map_to_uno(memExc.get(), exc, td.get()->pWeakRef, false);
+ (*uno_exc)->pType= td.get()->pWeakRef;
+ (*uno_exc)->pData= memExc.release();
+ return;
+ }
+ catch (System::Exception* e)
+ {
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
+ "Unexspected exception during invocation of cli object. "
+ "Original message is: \n") );
+ buf.append(mapCliString(e->get_Message()));
+ throw BridgeRuntimeError( buf.makeStringAndClear() );
+ }
+
+ //convert out, in/out params
+ for (int nPos = 0; nPos < nParams; ++nPos )
+ {
+ typelib_MethodParameter const & param = params[ nPos ];
+
+ if (param.bOut)
+ {
+ try
+ {
+ map_to_uno(
+ uno_args[ nPos ], args[ nPos ], param.pTypeRef,
+ sal_True == param.bIn /* assign if inout */);
+ // out array
+ }
+ catch (...)
+ {
+ // cleanup uno pure out
+ for ( sal_Int32 n = 0; n < nPos; ++n )
+ {
+ typelib_MethodParameter const & param = params[ n ];
+ if (! param.bIn)
+ uno_type_destructData( uno_args[ n ], param.pTypeRef, 0 );
+ }
+ throw;
+ }
+ }
+ }
+ // return value
+ if (0 != return_type)
+ {
+ map_to_uno(
+ uno_ret, retInvoke, return_type, false /* no assign */);
+ }
+ // no exception occured
+ *uno_exc = 0;
+}
+
+
+
+
+}
diff --git a/cli_ure/source/uno_bridge/makefile.mk b/cli_ure/source/uno_bridge/makefile.mk
new file mode 100644
index 000000000000..b7682aed4b1b
--- /dev/null
+++ b/cli_ure/source/uno_bridge/makefile.mk
@@ -0,0 +1,95 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# 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.
+#
+#*************************************************************************
+
+PRJ = ..$/..
+PRJNAME = cli_ure
+
+TARGET = cli_uno
+NO_BSYMBOLIC = TRUE
+ENABLE_EXCEPTIONS = TRUE
+USE_DEFFILE = TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+
+.IF "$(COM)" == "MSC"
+# When compiling for CLR, disable "warning C4339: use of undefined type detected
+# in CLR meta-data - use of this type may lead to a runtime exception":
+.IF "$(CCNUMVER)" <= "001399999999"
+CFLAGSCXX += -clr -AI $(DLLDEST) -AI $(SOLARBINDIR) -wd4339
+.ELSE
+CFLAGSCXX += -clr:oldSyntax -AI $(DLLDEST) -AI $(SOLARBINDIR) -wd4339
+.ENDIF
+
+.IF "$(debug)" != ""
+CFLAGS += -Ob0
+.ENDIF
+
+
+
+.IF "$(CCNUMVER)" <= "001399999999"
+#see Microsoft Knowledge Base Article - 814472
+LINKFLAGS += -NOENTRY -NODEFAULTLIB:nochkclr.obj -INCLUDE:__DllMainCRTStartup@12
+.ENDIF
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/cli_environment.obj \
+ $(SLO)$/cli_bridge.obj \
+ $(SLO)$/cli_data.obj \
+ $(SLO)$/cli_proxy.obj \
+ $(SLO)$/cli_uno.obj
+
+SHL1OBJS = $(SLOFILES)
+
+SHL1TARGET = $(TARGET)
+
+SHL1STDLIBS = \
+ $(CPPULIB) \
+ $(SALLIB) \
+ mscoree.lib
+
+.IF "$(CCNUMVER)" >= "001399999999"
+SHL1STDLIBS += \
+ msvcmrt.lib
+.ENDIF
+
+SHL1VERSIONMAP = bridge_exports.map
+
+SHL1IMPLIB = i$(TARGET)
+SHL1LIBS = $(SLB)$/$(TARGET).lib
+SHL1DEF = $(MISC)$/$(SHL1TARGET).def
+DEF1NAME = $(SHL1TARGET)
+
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk