diff options
author | Petr Mladek <pmladek@suse.cz> | 2011-08-02 18:37:13 +0200 |
---|---|---|
committer | Petr Mladek <pmladek@suse.cz> | 2013-04-30 12:05:25 +0200 |
commit | 10fb45c7fc8d521db6adae2b4b25eaec137c77fb (patch) | |
tree | 0eb2eb90d0716c9fc58a8f3f6954cd8ee18307aa /cli_ure | |
parent | 5f25dc8a564d01829f3cf9f58ed80cc83ea0eb45 (diff) |
[mono] mono-component-support.diff: add mono support
Conflicts:
cli_ure/prj/build.lst
cli_ure/prj/d.lst
Change-Id: I58285be7b14a4e128d49f00dccc17e0a5fc64248
Diffstat (limited to 'cli_ure')
-rw-r--r-- | cli_ure/Library_mono_loader.mk | 33 | ||||
-rw-r--r-- | cli_ure/source/mono_bridge/bridge.cs | 29 | ||||
-rw-r--r-- | cli_ure/source/mono_loader/mono_loader.cxx | 238 | ||||
-rw-r--r-- | cli_ure/source/mono_loader/mono_loader.xml | 26 | ||||
-rw-r--r-- | cli_ure/source/mono_loader/service.cxx | 72 |
5 files changed, 388 insertions, 10 deletions
diff --git a/cli_ure/Library_mono_loader.mk b/cli_ure/Library_mono_loader.mk new file mode 100644 index 000000000000..719425e0d422 --- /dev/null +++ b/cli_ure/Library_mono_loader.mk @@ -0,0 +1,33 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,mono_loader)) + +$(eval $(call gb_Library_add_cxxflags,mono_loader,\ + $(MONO_CFLAGS) \ +)) + +$(eval $(call gb_Library_use_udk_api,mono_loader)) + +$(eval $(call gb_Library_add_ldflags,mono_loader,\ + $(MONO_LIBS) \ +)) + +$(eval $(call gb_Library_use_libraries,mono_loader,\ + sal \ + cppu \ + cppuhelper \ +)) + +$(eval $(call gb_Library_add_exception_objects,mono_loader,\ + cli_ure/source/mono_loader/service \ + cli_ure/source/mono_loader/mono_loader \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/cli_ure/source/mono_bridge/bridge.cs b/cli_ure/source/mono_bridge/bridge.cs index df2a615f3e98..6fdd78ebfd46 100644 --- a/cli_ure/source/mono_bridge/bridge.cs +++ b/cli_ure/source/mono_bridge/bridge.cs @@ -1646,9 +1646,9 @@ public unsafe class Bridge for (int i = 0; i < nParams; ++i) { - // FIXME it's a TypeDescriptionReference - TypeDescription *type = (TypeDescription *)parameters[i].pTypeRef; - + TypeDescriptionReference *typeref = (TypeDescriptionReference *)parameters[i].pTypeRef; + TypeDescription *type = null; + TypeDescriptionReference.GetDescription(&type, typeref); unoArgPtrs[i] = unoArgs + i; if ((type->eTypeClass == TypeClass.STRUCT || type->eTypeClass == TypeClass.EXCEPTION) && @@ -1663,7 +1663,7 @@ public unsafe class Bridge if (parameters[i].bIn != 0) { // FIXME error handling - MapToUno(unoArgPtrs[i], args[i], type, false /* no assign */); + MapToUno(unoArgPtrs[i], args[i], (TypeDescription*)typeref, false /* no assign */); } } @@ -1795,13 +1795,27 @@ public unsafe class Bridge MapToManaged(ref args[i], unoArgs[i], parameters[i].pTypeRef, null, false); object invocationResult = null; + Exception exc = null; try { invocationResult = method.Invoke(managedI, args); } catch (TargetInvocationException e) { - Exception exc = e.InnerException; + exc = e.InnerException; + } + catch (Exception e) + { + exc = e; + } + if ( exc != null ) + { + if ( !( exc is unoidl.com.sun.star.uno.Exception ) ) + { + // #FIXME put more info in here trace, stack etc. ( when I + // figure out how to do that in mono ) + exc = new unoidl.com.sun.star.uno.RuntimeException( exc.ToString(), null ); + } TypeDescription* td = null; // FIXME leak TypeDescriptionReference.GetDescription(&td, MapManagedType(exc.GetType())); @@ -1811,11 +1825,6 @@ public unsafe class Bridge (*unoExc)->pData = memExc; return; } - catch (Exception e) - { - // FIXME - } - // convert out, in/out params for (int i = 0; i < nParams; ++i) { diff --git a/cli_ure/source/mono_loader/mono_loader.cxx b/cli_ure/source/mono_loader/mono_loader.cxx new file mode 100644 index 000000000000..0651bf3e17bf --- /dev/null +++ b/cli_ure/source/mono_loader/mono_loader.cxx @@ -0,0 +1,238 @@ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include <comphelper/processfactory.hxx> +#include <comphelper/uno3.hxx> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/loader/XImplementationLoader.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <cppuhelper/implbase2.hxx> +#include "uno/mapping.hxx" +#include "osl/file.hxx" +#include "glib/gtypes.h" + +// for debug +#include <comphelper/anytostring.hxx> + +extern "C" { +#include <mono/jit/jit.h> +#include <mono/metadata/object.h> +#include <mono/metadata/environment.h> +#include <mono/metadata/assembly.h> +#include <mono/metadata/debug-helpers.h> +#include <mono/metadata/threads.h> +} + +using namespace ::com::sun::star; +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +//static const char CLIURE_DLL[] = "$URE_LIB_DIR/cli_ure.dll"; +static const char CLIURE_DLL[] = "$URE_INTERNAL_LIB_DIR/cli_ure.dll"; +typedef ::cppu::WeakImplHelper2< loader::XImplementationLoader, lang::XServiceInfo > MonoLoader_BASE; + +namespace mono_loader +{ + ::rtl::OUString SAL_CALL getImplementationName(); + + uno::Reference< uno::XInterface > SAL_CALL create( uno::Reference< uno::XComponentContext > const & xContext ) SAL_THROW( () ); + + uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(); +} + +uno::Reference< loader::XImplementationLoader > +create_object (MonoDomain *domain, MonoImage *image) +{ + MonoClass *klass; + + klass = mono_class_from_name (image, "uno.util", "ManagedCodeLoader"); + if (!klass) { + OSL_TRACE ("Can't find ManagedCodeLoader in assembly %s", mono_image_get_filename (image)); + return NULL; + } + MonoObject* obj = mono_object_new (domain, klass); + /* mono_object_new () only allocates the storage: + * it doesn't run any constructor. Tell the runtime to run + * the default argumentless constructor. + */ + mono_runtime_object_init (obj); + static uno::Reference< loader::XImplementationLoader > xLoader; + // not sure if this is correct ( I'm loosely following 'to_uno' + // method in cli_ure/source/native/native_share.h ) + + loader::XImplementationLoader* pLoader = NULL; + OSL_TRACE("About to call mapInterface for XImplementionLoader returned from Mono"); + // we are storing the object so... I guess we need to tell the gc not + // to bother about this object + //mono_gchandle_new( obj, false ); // where do we release that ? do we even need to do this? + guint32 nHandle = mono_gchandle_new( obj, true ); // where do we release that ? do we even need to do this? + uno::Mapping mapping( OUSTR( UNO_LB_CLI ), OUSTR( CPPU_CURRENT_LANGUAGE_BINDING_NAME ) ); + OSL_ASSERT( mapping.is() ); + if (! mapping.is() ) + return NULL; + + mapping.mapInterface( + reinterpret_cast< void ** >( &pLoader ), + reinterpret_cast< void * >( obj ), ::getCppuType( &xLoader ) ); + mono_gchandle_free ( nHandle ); // copying what cli_ure/source/native/native_share.h does for DotNet + xLoader.set( pLoader, SAL_NO_ACQUIRE /* takeover ownership */ ); + OSL_TRACE("We appear to have got an XImplementationLoader that has a value? %s", xLoader.is() ? "yes" : "no " ); + return xLoader; +} + + +class MonoLoader : public MonoLoader_BASE +{ + class MonoCleanUp + { + public: + MonoCleanUp() { OSL_TRACE("MonoCleanUp created "); } + ~MonoCleanUp() + { + OSL_TRACE("~MonoCleanUp"); + // loader only uses the root domain + mono_jit_cleanup (mono_get_root_domain()); + } + }; + uno::Reference< uno::XComponentContext > mxContext; + uno::Reference< loader::XImplementationLoader > mxLoader; + uno::Reference< util::XMacroExpander > mxExpander; + uno::Reference< loader::XImplementationLoader > getLoader( const char* file) + { + OSL_TRACE("** enter getLoader()"); + // init only once + static MonoDomain* domain = mono_jit_init (file); + // when is a good time to trigger clean up ? + //static MonoCleanUp cleaner; + // hmm appears we need to attach this thread to the domain + mono_thread_attach( domain ); + MonoAssembly *assembly; + + assembly = mono_domain_assembly_open ( domain, file); + OSL_TRACE("** open of assembly %s = 0x%x", file, assembly); + if ( !assembly ) + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to open assembly " ) ) + rtl::OUString::createFromAscii( file ), NULL ); + return create_object (domain, mono_assembly_get_image (assembly)); + } + + +public: + MonoLoader( const uno::Reference< uno::XComponentContext >& rxContext ) : mxContext( rxContext ) + { + if (!(mxContext->getValueByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))) >>= mxExpander) + || !mxExpander.is()) + { + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "component context fails to supply singleton" " com.sun.star.util.theMacroExpander of type" " com.sun.star.util.XMacroExpander")), mxContext); + } + + rtl::OUString dllUrlPath = mxExpander->expandMacros( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CLIURE_DLL ) ) ); + rtl::OUString dllPath; + if ( osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( + dllUrlPath, dllPath )) + { + throw uno::RuntimeException( + OUSTR("cannot get system path from file url ") + + dllPath, + uno::Reference< uno::XInterface >() ); + } + + OSL_TRACE("**** location for dll is %s", rtl::OUStringToOString( dllPath, RTL_TEXTENCODING_UTF8 ).getStr() ); + OSL_TRACE("** MonoLoader::MonoLoader() "); + mxLoader = getLoader( rtl::OUStringToOString( dllPath, RTL_TEXTENCODING_UTF8 ).getStr() ); + if ( mxLoader.is() ) + { + // set the service factory + uno::Sequence< uno::Any > args(1); + args[ 0 ] <<= rxContext->getServiceManager(); + uno::Reference< lang::XInitialization > xInitialize( mxLoader, uno::UNO_QUERY_THROW ); + OSL_TRACE("MonoLoader::MonoLoader() about to call initialise"); + xInitialize->initialize( args ); + } + else + OSL_TRACE("** MonoLoader::MonoLoader(): No Mono loader found "); + + } + ~MonoLoader() + { + OSL_TRACE("** MonoLoader::~MonoLoader() "); + } + // Methods + virtual uno::Reference< uno::XInterface > SAL_CALL activate( const ::rtl::OUString& implementationName, const ::rtl::OUString& implementationLoaderUrl, const ::rtl::OUString& locationUrl, const uno::Reference< registry::XRegistryKey >& xKey ) throw (loader::CannotActivateFactoryException, uno::RuntimeException) + { + // try to instatiate a mono loader and return a reference to it + OSL_TRACE("**** in MonoLoader::activate"); + if ( mxLoader.is() ) + { + OSL_TRACE("*** MonoLoader::activate() about to call activate on 0x%x", mxLoader.get() ); + return mxLoader->activate( implementationName, implementationLoaderUrl, locationUrl, xKey ); + } + return NULL; + } + + virtual ::sal_Bool SAL_CALL writeRegistryInfo( const uno::Reference< registry::XRegistryKey >& xKey, const ::rtl::OUString& implementationLoaderUrl, const ::rtl::OUString& locationUrl ) throw (registry::CannotRegisterImplementationException, uno::RuntimeException) + { + if ( mxLoader.is() ) + return mxLoader->writeRegistryInfo( xKey, implementationLoaderUrl, locationUrl ); + return sal_False; + } + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (uno::RuntimeException){ return mono_loader::getImplementationName(); } + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException) + { + sal_Bool bRes = sal_False; + uno::Sequence< ::rtl::OUString > sServices = mono_loader::getSupportedServiceNames(); + const ::rtl::OUString* pService = sServices.getConstArray(); + const ::rtl::OUString* pEnd = sServices.getConstArray() + sServices.getLength(); + for ( ; pService != pEnd ; ++pService ) + { + if ( (*pService).equals( ServiceName ) ) + { + bRes = sal_True; + break; + } + } + return bRes; + } + virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (uno::RuntimeException){ return mono_loader::getSupportedServiceNames(); } + +}; + +namespace mono_loader +{ + ::rtl::OUString SAL_CALL getImplementationName() + { + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.loader.MonoLoader" ) ); + pImplName = &aImplName; + } + } + return *pImplName; + } + + uno::Reference< uno::XInterface > SAL_CALL create( + uno::Reference< uno::XComponentContext > const & xContext ) + SAL_THROW( () ) + { + OSL_TRACE("** In create for monoloader"); + // mimic java loader if I read it correctly it just has a single entry + // point ( Mono implementation loader should do the same? #TODO maybe ) + // #FIXME use whatever boiler plate static initialisatioon foo that is + // available ( seem to recall there is some helpers for that ) + // static uno::Reference < lang::XTypeProvider > xLoader( new MonoLoader( xContext ) ); + // hmm lets not do it for now because I'm not sure how an exiting/shutting down office/bridge co-operates + // with the mono runtime or if it does at all :/ + uno::Reference < lang::XTypeProvider > xLoader( new MonoLoader( xContext ) ); + return xLoader; + } + + uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + { + const ::rtl::OUString strName( ::mono_loader::getImplementationName() ); + return uno::Sequence< ::rtl::OUString >( &strName, 1 ); + } +} diff --git a/cli_ure/source/mono_loader/mono_loader.xml b/cli_ure/source/mono_loader/mono_loader.xml new file mode 100644 index 000000000000..4c1802795f57 --- /dev/null +++ b/cli_ure/source/mono_loader/mono_loader.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name>mono_loader</module-name> + + <component-description> + <author>Noel Power </author> + <name>Mono Loader</name> + <description>Loader for components located in mono assemblies</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="drafts"/> + <supported-service>org.openoffice.loader.MonoLoader</supported-service> + <type>com.sun.star.uno.XComponentContext</type> + </component-description> + + <project-build-dependency>cppuhelper</project-build-dependency> + <project-build-dependency>cppu</project-build-dependency> + <project-build-dependency>sal</project-build-dependency> + + <runtime-module-dependency>cppuhelper3$(COM)</runtime-module-dependency> + <runtime-module-dependency>cppu3</runtime-module-dependency> + <runtime-module-dependency>sal3</runtime-module-dependency> + +</module-description> diff --git a/cli_ure/source/mono_loader/service.cxx b/cli_ure/source/mono_loader/service.cxx new file mode 100644 index 000000000000..b2f5f0917661 --- /dev/null +++ b/cli_ure/source/mono_loader/service.cxx @@ -0,0 +1,72 @@ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "cppuhelper/implementationentry.hxx" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" + +// ============================================================================= +// component exports +// ============================================================================= +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace mono_loader +{ + // ============================================================================= + // component operations + // ============================================================================= + + uno::Reference< XInterface > SAL_CALL create( + Reference< XComponentContext > const & xContext ) + SAL_THROW( () ); + + // ----------------------------------------------------------------------------- + + ::rtl::OUString SAL_CALL getImplementationName(); + + Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(); + + Reference<XInterface> SAL_CALL create( + Sequence<Any> const &, Reference<XComponentContext> const & ); +} // end mono_loader + + // ============================================================================= + + const ::cppu::ImplementationEntry s_component_entries [] = + { + { + ::mono_loader::create, ::mono_loader::getImplementationName, + ::mono_loader::getSupportedServiceNames, + ::cppu::createSingleComponentFactory, + 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } + }; + +extern "C" +{ + SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) + { + OSL_TRACE("In component_getImplementationEnv"); + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } + + SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo( + lang::XMultiServiceFactory * pServiceManager, registry::XRegistryKey * pRegistryKey ) + { + OSL_TRACE("In component_writeInfo"); + if ( ::cppu::component_writeInfoHelper( + pServiceManager, pRegistryKey, s_component_entries ) ) + return sal_True; + return sal_False; + } + + SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) + { + OSL_TRACE("In component_getFactory"); + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, s_component_entries ); + } +} |