diff options
Diffstat (limited to 'cli_ure/source/climaker')
-rw-r--r-- | cli_ure/source/climaker/climaker.exe.config | 10 | ||||
-rw-r--r-- | cli_ure/source/climaker/climaker_app.cxx | 749 | ||||
-rw-r--r-- | cli_ure/source/climaker/climaker_emit.cxx | 2323 | ||||
-rw-r--r-- | cli_ure/source/climaker/climaker_share.h | 268 | ||||
-rw-r--r-- | cli_ure/source/climaker/makefile.mk | 137 |
5 files changed, 3487 insertions, 0 deletions
diff --git a/cli_ure/source/climaker/climaker.exe.config b/cli_ure/source/climaker/climaker.exe.config new file mode 100644 index 000000000000..5ff03513900c --- /dev/null +++ b/cli_ure/source/climaker/climaker.exe.config @@ -0,0 +1,10 @@ +<?xml version="1.0"?>
+<configuration>
+ <runtime>
+ <gcConcurrent enabled="true" />
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <publisherPolicy apply="no" />
+ <probing privatePath="" />
+ </assemblyBinding>
+ </runtime>
+</configuration>
\ No newline at end of file diff --git a/cli_ure/source/climaker/climaker_app.cxx b/cli_ure/source/climaker/climaker_app.cxx new file mode 100644 index 000000000000..9c257d079682 --- /dev/null +++ b/cli_ure/source/climaker/climaker_app.cxx @@ -0,0 +1,749 @@ +/************************************************************************* + * + * 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 <stdio.h> +#include <vector> +#include <memory> + +#include "climaker_share.h" + +#include "sal/main.h" +#include "osl/process.h" +#include "osl/file.hxx" +#include "osl/thread.h" +#include "rtl/ustrbuf.hxx" +#include "cppuhelper/shlib.hxx" +#include "cppuhelper/bootstrap.hxx" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XSet.hpp" +#include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp" +#include "com/sun/star/registry/XSimpleRegistry.hpp" + +using namespace ::std; +using namespace ::System::Reflection; + + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace climaker +{ + +//------------------------------------------------------------------------------ +static char const s_usingText [] = +"\n" +"using: climaker <switches> [registry-file-1 registry-file-2 ...]\n" +"\n" +"switches:\n" +" -O, --out <output-file> output assembly file;\n" +" defaults to cli_unotypes.dll if more than one\n" +" registry-file is given, else <registry-file>.dll\n" +" -T, --types types to be generated (if none is given,\n" +" <type1[;type2;...]> then all types of given registries are emitted\n" +" -X, --extra <rdb-file> additional rdb to saturate referenced types in\n" +" given registry file(s); these types will not be\n" +" emitted into the output assembly file\n" +" -r, --reference reference metadata from assembly file\n" +" <assembly-file>\n" +" -k, --keyfile keyfile needed for strong name\n" +" --assembly-version <version> sets assembly version\n" +" --assembly-description <text> sets assembly description text\n" +" --assembly-product <text> sets assembly product name\n" +" --assembly-company <text> sets assembly company\n" +" --assembly-copyright <text> sets assembly copyright\n" +" --assembly-trademark <text> sets assembly trademark\n" +" -v, --verbose verbose output to stdout\n" +" -h, --help this message\n" +"\n" +"example: climaker --out cli_mytypes.dll \\\n" +" --reference cli_uretypes.dll \\\n" +" --extra types.rdb \\\n" +" mytypes.rdb\n" +"\n"; + +struct OptionInfo +{ + char const * m_name; + sal_uInt32 m_name_length; + sal_Unicode m_short_option; + bool m_has_argument; +}; + +bool g_verbose = false; + +//------------------------------------------------------------------------------ +static const OptionInfo s_option_infos [] = { + { RTL_CONSTASCII_STRINGPARAM("out"), 'O', true }, + { RTL_CONSTASCII_STRINGPARAM("types"), 'T', true }, + { RTL_CONSTASCII_STRINGPARAM("extra"), 'X', true }, + { RTL_CONSTASCII_STRINGPARAM("reference"), 'r', true }, + { RTL_CONSTASCII_STRINGPARAM("keyfile"), 'k', true }, + { RTL_CONSTASCII_STRINGPARAM("delaySign"), 'd', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-version"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-description"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-product"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-company"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-copyright"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("assembly-trademark"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false }, + { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false } +}; + +//============================================================================== +static OptionInfo const * get_option_info( + OUString const & opt, sal_Unicode copt = '\0' ) +{ + for ( sal_Int32 pos = 0; + pos < (sizeof (s_option_infos) / sizeof (OptionInfo)); + ++pos ) + { + OptionInfo const & option_info = s_option_infos[ pos ]; + + if (opt.getLength() > 0) + { + if (opt.equalsAsciiL( + option_info.m_name, option_info.m_name_length ) && + (copt == '\0' || copt == option_info.m_short_option)) + { + return &option_info; + } + } + else + { + OSL_ASSERT( copt != '\0' ); + if (copt == option_info.m_short_option) + { + return &option_info; + } + } + } + OSL_ENSURE( + 0, OUStringToOString( opt, osl_getThreadTextEncoding() ).getStr() ); + return 0; +} + +//============================================================================== +static bool is_option( + OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + OSL_ASSERT( option_info != 0 ); + if (osl_getCommandArgCount() <= *pIndex) + return false; + + OUString arg; + osl_getCommandArg( *pIndex, &arg.pData ); + sal_Int32 len = arg.getLength(); + + if (len < 2 || arg[ 0 ] != '-') + return false; + + if (len == 2 && arg[ 1 ] == option_info->m_short_option) + { + ++(*pIndex); +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( + __FILE__": identified option \'%c\'", option_info->m_short_option ); +#endif + return true; + } + if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare( + arg.pData->buffer + 2, option_info->m_name ) == 0) + { + ++(*pIndex); +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( __FILE__": identified option \'%s\'", option_info->m_name ); +#endif + return true; + } + return false; +} + +//============================================================================== +static inline bool read_option( + bool * flag, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + bool ret = is_option( option_info, pIndex ); + if (ret) + *flag = true; + return ret; +} + +//============================================================================== +static bool read_argument( + OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + if (is_option( option_info, pIndex )) + { + if (*pIndex < osl_getCommandArgCount()) + { + osl_getCommandArg( *pIndex, &pValue->pData ); + ++(*pIndex); +#if OSL_DEBUG_LEVEL > 1 + OString cstr_val( + OUStringToOString( *pValue, osl_getThreadTextEncoding() ) ); + OSL_TRACE( __FILE__": argument value: %s\n", cstr_val.getStr() ); +#endif + return true; + } + --(*pIndex); + } + return false; +} + +//============================================================================== +static OUString const & path_get_working_dir() +{ + static OUString s_workingDir; + if (! s_workingDir.getLength()) + osl_getProcessWorkingDir( &s_workingDir.pData ); + return s_workingDir; +} + +//============================================================================== +static OUString path_make_absolute_file_url( OUString const & path ) +{ + OUString file_url; + oslFileError rc = osl_getFileURLFromSystemPath( + path.pData, &file_url.pData ); + if (osl_File_E_None == rc) + { + OUString abs; + rc = osl_getAbsoluteFileURL( + path_get_working_dir().pData, file_url.pData, &abs.pData ); + if (osl_File_E_None == rc) + { + return abs; + } + else + { + throw RuntimeException( + OUSTR("cannot make absolute: ") + file_url, + Reference< XInterface >() ); + } + } + else + { + throw RuntimeException( + OUSTR("cannot get file url from system path: ") + path, + Reference< XInterface >() ); + } +} + +//============================================================================== +Reference< registry::XSimpleRegistry > open_registries( + vector< OUString > const & registries, + Reference< XComponentContext > xContext ) +{ + if (registries.empty()) + { + throw RuntimeException( + OUSTR("no registries given!"), + Reference< XInterface >() ); + } + + Reference< registry::XSimpleRegistry > xSimReg; + for ( size_t nPos = registries.size(); nPos--; ) + { + Reference< registry::XSimpleRegistry > xReg( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ), + UNO_QUERY_THROW ); + xReg->open( registries[ nPos ], sal_True, sal_False ); + if (! xReg->isValid()) + { + throw RuntimeException( + OUSTR("invalid registry: ") + registries[ nPos ], + Reference< XInterface >() ); + } + + if (xSimReg.is()) // nest? + { + Reference< registry::XSimpleRegistry > xNested( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.NestedRegistry"), xContext ), + UNO_QUERY_THROW ); + Reference< lang::XInitialization > xInit( + xNested, UNO_QUERY_THROW ); + Sequence< Any > args( 2 ); + args[ 0 ] <<= xReg; + args[ 1 ] <<= xSimReg; + xInit->initialize( args ); + xSimReg = xNested; + } + else + { + xSimReg = xReg; + } + } + + return xSimReg; +} + +} + +using namespace ::climaker; + +//############################################################################## +SAL_IMPLEMENT_MAIN() +{ + sal_uInt32 nCount = osl_getCommandArgCount(); + if (0 == nCount) + { + printf( s_usingText ); + return 0; + } + + int ret = 0; + Reference< XComponentContext > xContext; + + try + { + OptionInfo const * info_help = + get_option_info( OUSTR("help") ); + OptionInfo const * info_verbose = + get_option_info( OUSTR("verbose") ); + OptionInfo const * info_out = + get_option_info( OUSTR("out") ); + OptionInfo const * info_types = + get_option_info( OUSTR("types") ); + OptionInfo const * info_reference = + get_option_info( OUSTR("reference") ); + OptionInfo const * info_extra = + get_option_info( OUSTR("extra") ); + OptionInfo const * info_keyfile = + get_option_info( OUSTR("keyfile") ); + OptionInfo const * info_delaySign = + get_option_info( OUSTR("delaySign") ); + OptionInfo const * info_version = + get_option_info( OUSTR("assembly-version") ); + OptionInfo const * info_product = + get_option_info( OUSTR("assembly-product") ); + OptionInfo const * info_description = + get_option_info( OUSTR("assembly-description") ); + OptionInfo const * info_company = + get_option_info( OUSTR("assembly-company") ); + OptionInfo const * info_copyright = + get_option_info( OUSTR("assembly-copyright") ); + OptionInfo const * info_trademark = + get_option_info( OUSTR("assembly-trademark") ); + + OUString output; + vector< OUString > mandatory_registries; + vector< OUString > extra_registries; + vector< OUString > extra_assemblies; + vector< OUString > explicit_types; + OUString version, product, description, company, copyright, trademark, + keyfile, delaySign; + + OUString cmd_arg; + for ( sal_uInt32 nPos = 0; nPos < nCount; ) + { + // options + if (is_option( info_help, &nPos )) + { + printf( s_usingText ); + return 0; + } + else if (read_argument( &cmd_arg, info_types, &nPos )) + { + sal_Int32 index = 0; + do + { + explicit_types.push_back( + cmd_arg.getToken( 0, ';', index ) ); + } + while (index >= 0); + } + else if (read_argument( &cmd_arg, info_extra, &nPos )) + { + extra_registries.push_back( + path_make_absolute_file_url( cmd_arg ) ); + } + else if (read_argument( &cmd_arg, info_reference, &nPos )) + { + extra_assemblies.push_back( + path_make_absolute_file_url( cmd_arg ) ); + } + else if (!read_option( &g_verbose, info_verbose, &nPos ) && + !read_argument( &output, info_out, &nPos ) && + !read_argument( &version, info_version, &nPos ) && + !read_argument( &description, info_description, &nPos ) && + !read_argument( &product, info_product, &nPos ) && + !read_argument( &company, info_company, &nPos ) && + !read_argument( ©right, info_copyright, &nPos ) && + !read_argument( &trademark, info_trademark, &nPos ) && + !read_argument( &keyfile, info_keyfile, &nPos ) && + !read_argument( &delaySign, info_delaySign, &nPos )) + { + if ( osl_getCommandArg( nPos, &cmd_arg.pData ) != + osl_Process_E_None ) + { + OSL_ASSERT( false ); + } + ++nPos; + cmd_arg = cmd_arg.trim(); + if (cmd_arg.getLength() > 0) + { + if (cmd_arg[ 0 ] == '-') // is option + { + OptionInfo const * option_info = 0; + if (cmd_arg.getLength() > 2 && + cmd_arg[ 1 ] == '-') + { + // long option + option_info = get_option_info( + cmd_arg.copy( 2 ), '\0' ); + } + else if (cmd_arg.getLength() == 2 && + cmd_arg[ 1 ] != '-') + { + // short option + option_info = get_option_info( + OUString(), cmd_arg[ 1 ] ); + } + if (option_info == 0) + { + OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("unknown option ") ); + buf.append( cmd_arg ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "! Use climaker --help " + "to print all options.") ); + throw RuntimeException( + buf.makeStringAndClear(), + Reference< XInterface >() ); + } + else + { + OSL_ENSURE( 0, "unhandled valid option?!" ); + if (option_info->m_has_argument) + ++nPos; + } + } + else + { + mandatory_registries.push_back( + path_make_absolute_file_url( cmd_arg ) ); + } + } + } + } + + // bootstrap uno + xContext = ::cppu::bootstrap_InitialComponentContext( + Reference< registry::XSimpleRegistry >() ); + Reference< container::XHierarchicalNameAccess > xTDmgr( + xContext->getValueByName( + OUSTR("/singletons/com.sun.star.reflection." + "theTypeDescriptionManager") ), + UNO_QUERY_THROW ); + + // get rdb tdprovider factory + Reference< lang::XSingleComponentFactory > xTDprov_factory( + ::cppu::loadSharedLibComponentFactory( + OUSTR("bootstrap.uno" SAL_DLLEXTENSION), OUString(), + OUSTR("com.sun.star.comp.stoc.RegistryTypeDescriptionProvider"), + Reference< lang::XMultiServiceFactory >( + xContext->getServiceManager(), UNO_QUERY ), + Reference< registry::XRegistryKey >() ), UNO_QUERY ); + if (! xTDprov_factory.is()) + { + throw RuntimeException( + OUSTR("cannot get registry typedescription provider: " + "bootstrap.uno" SAL_DLLEXTENSION "!"), + Reference< XInterface >() ); + } + + // create registry td provider for mandatory registry files + Any arg( makeAny( open_registries( mandatory_registries, xContext ) ) ); + Reference< XInterface > xTD_provider( + xTDprov_factory->createInstanceWithArgumentsAndContext( + Sequence< Any >( &arg, 1 ), xContext ) ); + // insert provider to tdmgr + Reference< container::XSet > xSet( xTDmgr, UNO_QUERY_THROW ); + Any provider( makeAny( xTD_provider ) ); + xSet->insert( provider ); + OSL_ASSERT( xSet->has( provider ) ); + if (! extra_registries.empty()) + { + arg = makeAny( open_registries( extra_registries, xContext ) ); + provider = makeAny( + xTDprov_factory->createInstanceWithArgumentsAndContext( + Sequence< Any >( &arg, 1 ), xContext ) ); + xSet->insert( provider ); + OSL_ASSERT( xSet->has( provider ) ); + } + + if (0 == output.getLength()) // no output file specified + { + // if only one rdb has been given, then take rdb name + if (1 == mandatory_registries.size()) + { + output = mandatory_registries[ 0 ]; + output = output.copy( output.lastIndexOf( '/' ) +1 ); + sal_Int32 dot = output.lastIndexOf( '.' ); + if (dot > 0) + output = output.copy( 0, dot ); + } + else + { + output = OUSTR("cli_unotypes"); + } + } + output = path_make_absolute_file_url( output ); + sal_Int32 slash = output.lastIndexOf( '/' ); + OUString sys_output_dir; + if (FileBase::E_None != FileBase::getSystemPathFromFileURL( + output.copy( 0, slash ), sys_output_dir )) + { + throw RuntimeException( + OUSTR("cannot get system path from file url ") + + output.copy( 0, slash ), + Reference< XInterface >() ); + } + OUString filename( output.copy( slash +1 ) ); + sal_Int32 dot = filename.lastIndexOf( '.' ); + OUString name( filename ); + if (dot < 0) // has no extension + filename += OUSTR(".dll"); + else + name = name.copy( 0, dot ); + ::System::String * output_dir = ustring_to_String( sys_output_dir ); + ::System::String * output_file = ustring_to_String( filename ); + + //Get the key pair for making a strong name + StrongNameKeyPair* kp = NULL; + if (keyfile.getLength() > 0) + { + ::System::String * sKeyFile = ustring_to_String(keyfile); + try { + System::IO::FileStream* fs = new System::IO::FileStream( + sKeyFile, System::IO::FileMode::Open); + kp = new StrongNameKeyPair(fs); + fs->Close(); + } + catch (System::IO::FileNotFoundException * ) + { + throw Exception(OUSTR("Could not find the keyfile. Verify the --keyfile argument!"), 0); + } + } + else + { + if (g_verbose) + { + ::System::Console::Write( + S"> no key file specified. Cannot create strong name!\n"); + } + } + // setup assembly info: xxx todo set more? e.g. avoid strong versioning + AssemblyName * assembly_name = new AssemblyName(); + assembly_name->set_CodeBase( output_dir ); + assembly_name->set_Name( name ); + if (kp != NULL) + assembly_name->set_KeyPair(kp); + + if (version.getLength() != 0) + { + assembly_name->set_Version( + new ::System::Version( ustring_to_String( version ) ) ); + } + + // app domain + ::System::AppDomain * current_appdomain = + ::System::AppDomain::get_CurrentDomain(); + // target assembly + Emit::AssemblyBuilder * assembly_builder = + current_appdomain->DefineDynamicAssembly( + assembly_name, Emit::AssemblyBuilderAccess::Save, output_dir ); + if (product.getLength() != 0) + { + ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ]; + ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ]; + params[ 0 ] = __typeof (::System::String); + args[ 0 ] = ustring_to_String( product ); + assembly_builder->SetCustomAttribute( + new Emit::CustomAttributeBuilder( + __typeof (AssemblyProductAttribute)->GetConstructor( + params ), args ) ); + } + if (description.getLength() != 0) + { + ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ]; + ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ]; + params[ 0 ] = __typeof (::System::String); + args[ 0 ] = ustring_to_String( description ); + assembly_builder->SetCustomAttribute( + new Emit::CustomAttributeBuilder( + __typeof (AssemblyDescriptionAttribute)->GetConstructor( + params ), args ) ); + } + if (company.getLength() != 0) + { + ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ]; + ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ]; + params[ 0 ] = __typeof (::System::String); + args[ 0 ] = ustring_to_String( company ); + assembly_builder->SetCustomAttribute( + new Emit::CustomAttributeBuilder( + __typeof (AssemblyCompanyAttribute)->GetConstructor( + params ), args ) ); + } + if (copyright.getLength() != 0) + { + ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ]; + ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ]; + params[ 0 ] = __typeof (::System::String); + args[ 0 ] = ustring_to_String( copyright ); + assembly_builder->SetCustomAttribute( + new Emit::CustomAttributeBuilder( + __typeof (AssemblyCopyrightAttribute)->GetConstructor( + params ), args ) ); + } + if (trademark.getLength() != 0) + { + ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ]; + ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ]; + params[ 0 ] = __typeof (::System::String); + args[ 0 ] = ustring_to_String( trademark ); + assembly_builder->SetCustomAttribute( + new Emit::CustomAttributeBuilder( + __typeof (AssemblyTrademarkAttribute)->GetConstructor( + params ), args ) ); + } + + // load extra assemblies + Assembly * assemblies __gc [] = + new Assembly * __gc [ extra_assemblies.size() ]; + for ( size_t pos = 0; pos < extra_assemblies.size(); ++pos ) + { + assemblies[ pos ] = Assembly::LoadFrom( + ustring_to_String( extra_assemblies[ pos ] ) ); + } + + // type emitter + TypeEmitter * type_emitter = new TypeEmitter( + assembly_builder->DefineDynamicModule( output_file ), assemblies ); + // add handler resolving assembly's types + ::System::ResolveEventHandler * type_resolver = + new ::System::ResolveEventHandler( + type_emitter, &TypeEmitter::type_resolve ); + current_appdomain->add_TypeResolve( type_resolver ); + + // and emit types to it + if (explicit_types.empty()) + { + Reference< reflection::XTypeDescriptionEnumeration > xTD_enum( + Reference< reflection::XTypeDescriptionEnumerationAccess >( + xTD_provider, UNO_QUERY_THROW ) + ->createTypeDescriptionEnumeration( + OUString() /* all IDL modules */, + Sequence< TypeClass >() /* all classes of types */, + reflection::TypeDescriptionSearchDepth_INFINITE ) ); + while (xTD_enum->hasMoreElements()) + { + type_emitter->get_type( xTD_enum->nextTypeDescription() ); + } + } + else + { + Reference< container::XHierarchicalNameAccess > xHNA( + xTD_provider, UNO_QUERY_THROW ); + for ( size_t nPos = explicit_types.size(); nPos--; ) + { + type_emitter->get_type( + Reference< reflection::XTypeDescription >( + xHNA->getByHierarchicalName( explicit_types[ nPos ] ), + UNO_QUERY_THROW ) ); + } + } + type_emitter->Dispose(); + + if (g_verbose) + { + ::System::Console::Write( + S"> saving assembly {0}{1}{2}...", + output_dir, + new ::System::String( + ::System::IO::Path::DirectorySeparatorChar, 1 ), + output_file ); + } + assembly_builder->Save( output_file ); + if (g_verbose) + { + ::System::Console::WriteLine( S"ok." ); + } + current_appdomain->remove_TypeResolve( type_resolver ); + } + catch (Exception & exc) + { + OString msg( + OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) ); + fprintf( + stderr, "\n> error: %s\n> dying abnormally...\n", msg.getStr() ); + ret = 1; + } + catch (::System::Exception * exc) + { + OString msg( OUStringToOString( + String_to_ustring( exc->ToString() ), + osl_getThreadTextEncoding() ) ); + fprintf( + stderr, + "\n> error: .NET exception occured: %s\n> dying abnormally...", + msg.getStr() ); + ret = 1; + } + + try + { + Reference< lang::XComponent > xComp( xContext, UNO_QUERY ); + if (xComp.is()) + xComp->dispose(); + } + catch (Exception & exc) + { + OString msg( + OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) ); + fprintf( + stderr, + "\n> error disposing component context: %s\n" + "> dying abnormally...\n", + msg.getStr() ); + ret = 1; + } + + return ret; +} diff --git a/cli_ure/source/climaker/climaker_emit.cxx b/cli_ure/source/climaker/climaker_emit.cxx new file mode 100644 index 000000000000..24a10ce2ddbb --- /dev/null +++ b/cli_ure/source/climaker/climaker_emit.cxx @@ -0,0 +1,2323 @@ +/************************************************************************* + * + * 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 "climaker_share.h" + +#include "rtl/string.hxx" +#include "rtl/ustrbuf.hxx" +#include "com/sun/star/reflection/XIndirectTypeDescription.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" +#include <vector> + +using namespace ::System::Reflection; + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace climaker +{ +System::String* mapUnoPolymorphicName(System::String* unoName); +//------------------------------------------------------------------------------ +static inline ::System::String * to_cts_name( + OUString const & uno_name ) +{ + OUStringBuffer buf( 7 + uno_name.getLength() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("unoidl.") ); + buf.append( uno_name ); + return ustring_to_String( buf.makeStringAndClear() ); +} + +//------------------------------------------------------------------------------ +static inline ::System::Object * to_cli_constant( Any const & value ) +{ + switch (value.getValueTypeClass()) + { + case TypeClass_CHAR: + return __box + ((::System::Char) *reinterpret_cast< sal_Unicode const * >( + value.getValue() )); + case TypeClass_BOOLEAN: + return __box + ((::System::Boolean) + sal_False != *reinterpret_cast< sal_Bool const * >( + value.getValue() )); + case TypeClass_BYTE: + return __box + ((::System::Byte) *reinterpret_cast< sal_Int8 const * >( + value.getValue() )); + case TypeClass_SHORT: + return __box + ((::System::Int16) *reinterpret_cast< sal_Int16 const * >( + value.getValue() )); + case TypeClass_UNSIGNED_SHORT: + return __box + ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >( + value.getValue() )); + case TypeClass_LONG: + return __box + ((::System::Int32) *reinterpret_cast< sal_Int32 const * >( + value.getValue() )); + case TypeClass_UNSIGNED_LONG: + return __box + ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >( + value.getValue() )); + case TypeClass_HYPER: + return __box + ((::System::Int64) *reinterpret_cast< sal_Int64 const * >( + value.getValue() )); + case TypeClass_UNSIGNED_HYPER: + return __box + ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >( + value.getValue() )); + case TypeClass_FLOAT: + return __box + ((::System::Single) *reinterpret_cast< float const * >( + value.getValue() )); + case TypeClass_DOUBLE: + return __box + ((::System::Double) *reinterpret_cast< double const * >( + value.getValue() )); + default: + throw RuntimeException( + OUSTR("unexpected constant type ") + + value.getValueType().getTypeName(), + Reference< XInterface >() ); + } +} + +//------------------------------------------------------------------------------ +static inline void emit_ldarg( Emit::ILGenerator * code, ::System::Int32 index ) +{ + switch (index) + { + case 0: + code->Emit( Emit::OpCodes::Ldarg_0 ); + break; + case 1: + code->Emit( Emit::OpCodes::Ldarg_1 ); + break; + case 2: + code->Emit( Emit::OpCodes::Ldarg_2 ); + break; + case 3: + code->Emit( Emit::OpCodes::Ldarg_3 ); + break; + default: + if (index < 0x100) + code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index ); + else if (index < 0x8000) + code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index ); + else + code->Emit( Emit::OpCodes::Ldarg, index ); + break; + } +} + +void polymorphicStructNameToStructName(::System::String ** sPolyName) +{ + if ((*sPolyName)->EndsWith(S">") == false) + return; + + int index = (*sPolyName)->IndexOf('<'); + OSL_ASSERT(index != -1); + *sPolyName = (*sPolyName)->Substring(0, index); +} + + +System::String* mapUnoTypeName(System::String * typeName) +{ + ::System::Text::StringBuilder* buf= new System::Text::StringBuilder(); + ::System::String * sUnoName = ::System::String::Copy(typeName); + //determine if the type is a sequence and its dimensions + int dims= 0; + if (typeName->StartsWith(S"["))//if (usUnoName[0] == '[') + { + int index= 1; + while (true) + { + if (typeName->get_Chars(index++) == ']')//if (usUnoName[index++] == ']') + dims++; + if (typeName->get_Chars(index++) != '[')//usUnoName[index++] != '[') + break; + } + sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1); + } + if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoBool))) + buf->Append(const_cast<System::String*>(Constants::sBoolean)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoChar))) + buf->Append(const_cast<System::String*>(Constants::sChar)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoByte))) + buf->Append(const_cast<System::String*>(Constants::sByte)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoShort))) + buf->Append(const_cast<System::String*>(Constants::sInt16)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoUShort))) + buf->Append(const_cast<System::String*>(Constants::sUInt16)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoLong))) + buf->Append(const_cast<System::String*>(Constants::sInt32)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoULong))) + buf->Append(const_cast<System::String*>(Constants::sUInt32)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoHyper))) + buf->Append(const_cast<System::String*>(Constants::sInt64)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoUHyper))) + buf->Append(const_cast<System::String*>(Constants::sUInt64)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoFloat))) + buf->Append(const_cast<System::String*>(Constants::sSingle)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoDouble))) + buf->Append(const_cast<System::String*>(Constants::sDouble)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoString))) + buf->Append(const_cast<System::String*>(Constants::sString)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoVoid))) + buf->Append(const_cast<System::String*>(Constants::sVoid)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoType))) + buf->Append(const_cast<System::String*>(Constants::sType)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoXInterface))) + buf->Append(const_cast<System::String*>(Constants::sObject)); + else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoAny))) + { + buf->Append(const_cast<System::String*>(Constants::sAny)); + } + else + { + //put "unoidl." at the beginning + buf->Append(const_cast<System::String*>(Constants::sUnoidl)); + buf->Append(mapUnoPolymorphicName(sUnoName)); + } + // 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. + + Strings can be as complicated as this + test.MyStruct<char,test.MyStruct<long, []string>> + */ +System::String* mapUnoPolymorphicName(System::String* unoName) +{ + int index = unoName->IndexOf('<'); + if (index == -1) + return unoName; + + System::Text::StringBuilder * builder = + new System::Text::StringBuilder(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; + builder->Append(mapUnoTypeName(sParam)); + } + 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(); +} + + + +//______________________________________________________________________________ +Assembly * TypeEmitter::type_resolve( + ::System::Object *, ::System::ResolveEventArgs * args ) +{ + ::System::String * cts_name = args->get_Name(); + ::System::Type * ret_type = m_module_builder->GetType( + cts_name, false /* no exc */ ); + if (0 == ret_type) + { + iface_entry * entry = dynamic_cast< iface_entry * >( + m_incomplete_ifaces->get_Item( cts_name ) ); + if (0 != entry) + ret_type = entry->m_type_builder; + } + if (0 == ret_type) + { + sal_Int32 len = m_extra_assemblies->get_Length(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + ret_type = m_extra_assemblies[ pos ]->GetType( + cts_name, false /* no exc */ ); + if (0 != ret_type) + { + if (g_verbose) + { + ::System::Console::WriteLine( + "> resolving type {0} from {1}.", + cts_name, ret_type->get_Assembly()->get_FullName() ); + } + break; + } + } + } + if (0 != ret_type) + return ret_type->get_Assembly(); + return 0; +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + ::System::String * cts_name, bool throw_exc ) +{ + ::System::Type * ret_type = m_module_builder->GetType( cts_name, false ); + //We get the type from the ModuleBuilder even if the type is not complete + //but have been defined. + //if (ret_type == 0) + //{ + // iface_entry * entry = dynamic_cast< iface_entry * >( + // m_incomplete_ifaces->get_Item( cts_name ) ); + // if (0 != entry) + // ret_type = entry->m_type_builder; + //} + //try the cli_basetypes assembly + if (ret_type == 0) + { + ::System::Text::StringBuilder * builder = new ::System::Text::StringBuilder(cts_name); + builder->Append(S",cli_basetypes"); + ret_type = ::System::Type::GetType(builder->ToString()); + } + + if (ret_type == 0) + { + try + { + // may call on type_resolve() + return ::System::Type::GetType( cts_name, throw_exc ); + } + catch (::System::Exception* exc) + { + //If the type is not found one may have forgotten to specify assemblies with + //additional types + ::System::Text::StringBuilder * sb = new ::System::Text::StringBuilder(); + sb->Append(new ::System::String(S"\nThe type ")); + sb->Append(cts_name); + sb->Append(new ::System::String(S" \n could not be found. Did you forget to " \ + S"specify an additional assembly with the --reference option?\n")); + if (throw_exc) + throw new ::System::Exception(sb->ToString(), exc); + } + } + else + { + return ret_type; + } +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type_Exception() +{ + if (0 == m_type_Exception) + { + m_type_Exception = get_type( + S"unoidl.com.sun.star.uno.Exception", false /* no exc */ ); + if (0 == m_type_Exception) + { + // define hardcoded type unoidl.com.sun.star.uno.Exception + Emit::TypeBuilder * type_builder = + m_module_builder->DefineType( + S"unoidl.com.sun.star.uno.Exception", + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass), + __typeof (::System::Exception) ); + Emit::FieldBuilder * field_Context = type_builder->DefineField( + S"Context", __typeof (::System::Object), + FieldAttributes::Public ); + // default .ctor + type_builder->DefineDefaultConstructor( c_ctor_method_attr ); + // .ctor + ::System::Type * param_types[] = + new ::System::Type *[ 2 ]; + param_types[ 0 ] = __typeof (::System::String); + param_types[ 1 ] = __typeof (::System::Object); + Emit::ConstructorBuilder * ctor_builder = + type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, + param_types ); + ctor_builder->DefineParameter( + 1, ParameterAttributes::In, S"Message" ); + ctor_builder->DefineParameter( + 2, ParameterAttributes::In, S"Context" ); + Emit::ILGenerator * code = ctor_builder->GetILGenerator(); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldarg_1 ); + param_types = new ::System::Type * [ 1 ]; + param_types[ 0 ] = __typeof (::System::String); + code->Emit( + Emit::OpCodes::Call, + __typeof (::System::Exception) + ->GetConstructor( param_types ) ); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldarg_2 ); + code->Emit( Emit::OpCodes::Stfld, field_Context ); + code->Emit( Emit::OpCodes::Ret ); + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting exception type " + "unoidl.com.sun.star.uno.Exception" ); + } + m_type_Exception = type_builder->CreateType(); + } + } + return m_type_Exception; +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type_RuntimeException() +{ + if (0 == m_type_RuntimeException) + { + m_type_RuntimeException = get_type( + S"unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ ); + if (0 == m_type_RuntimeException) + { + // define hardcoded type unoidl.com.sun.star.uno.RuntimeException + ::System::Type * type_Exception = get_type_Exception(); + Emit::TypeBuilder * type_builder = + m_module_builder->DefineType( + S"unoidl.com.sun.star.uno.RuntimeException", + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass), + type_Exception ); + // default .ctor + type_builder->DefineDefaultConstructor( c_ctor_method_attr ); + // .ctor + ::System::Type * param_types [] = + new ::System::Type * [ 2 ]; + param_types[ 0 ] = __typeof (::System::String); + param_types[ 1 ] = __typeof (::System::Object); + Emit::ConstructorBuilder * ctor_builder = + type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, + param_types ); + ctor_builder->DefineParameter( + 1, ParameterAttributes::In, S"Message" ); + ctor_builder->DefineParameter( + 2, ParameterAttributes::In, S"Context" ); + Emit::ILGenerator * code = ctor_builder->GetILGenerator(); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldarg_1 ); + code->Emit( Emit::OpCodes::Ldarg_2 ); + code->Emit( + Emit::OpCodes::Call, + type_Exception->GetConstructor( param_types ) ); + code->Emit( Emit::OpCodes::Ret ); + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting exception type " + "unoidl.com.sun.star.uno.RuntimeException" ); + } + m_type_RuntimeException = type_builder->CreateType(); + } + } + return m_type_RuntimeException; +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + Reference< reflection::XConstantTypeDescription > const & xType ) +{ + ::System::String * cts_name = to_cts_name( xType->getName() ); + ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); + if (0 == ret_type) + { + Reference< reflection::XConstantTypeDescription > xConstant( + xType, UNO_QUERY_THROW ); + ::System::Object * constant = + to_cli_constant( xConstant->getConstantValue() ); + Emit::TypeBuilder * type_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass) ); + + Emit::FieldBuilder * field_builder = type_builder->DefineField( + cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ), + constant->GetType(), + (FieldAttributes) (FieldAttributes::Public | + FieldAttributes::Static | + FieldAttributes::Literal) ); + field_builder->SetConstant( constant ); + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting constant type {0}", cts_name ); + } + ret_type = type_builder->CreateType(); + } + return ret_type; +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + Reference< reflection::XConstantsTypeDescription > const & xType ) +{ + ::System::String * cts_name = to_cts_name( xType->getName() ); + ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); + if (0 == ret_type) + { + Emit::TypeBuilder * type_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass) ); + + Sequence< Reference< + reflection::XConstantTypeDescription > > seq_constants( + xType->getConstants() ); + Reference< reflection::XConstantTypeDescription > const * constants = + seq_constants.getConstArray(); + sal_Int32 constants_length = seq_constants.getLength(); + for ( sal_Int32 constants_pos = 0; + constants_pos < constants_length; ++constants_pos ) + { + Reference< + reflection::XConstantTypeDescription > const & xConstant = + constants[ constants_pos ]; + ::System::Object * constant = + to_cli_constant( xConstant->getConstantValue() ); + ::System::String * uno_name = + ustring_to_String( xConstant->getName() ); + Emit::FieldBuilder * field_builder = type_builder->DefineField( + uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ), + constant->GetType(), + (FieldAttributes) (FieldAttributes::Public | + FieldAttributes::Static | + FieldAttributes::Literal) ); + field_builder->SetConstant( constant ); + } + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting constants group type {0}", cts_name ); + } + ret_type = type_builder->CreateType(); + } + return ret_type; +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + Reference< reflection::XEnumTypeDescription > const & xType ) +{ + ::System::String * cts_name = to_cts_name( xType->getName() ); + ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); + if (0 == ret_type) + { +// Emit::EnumBuilder * enum_builder = +// m_module_builder->DefineEnum( +// cts_name, +// (TypeAttributes) (TypeAttributes::Public | +// // TypeAttributes::Sealed | +// TypeAttributes::AnsiClass), +// __typeof (::System::Int32) ); + // workaround enum builder bug + Emit::TypeBuilder * enum_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed), + __typeof (::System::Enum) ); + enum_builder->DefineField( + S"value__", __typeof (::System::Int32), + (FieldAttributes) (FieldAttributes::Private | + FieldAttributes::SpecialName | + FieldAttributes::RTSpecialName) ); + Sequence< OUString > seq_enum_names( xType->getEnumNames() ); + Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() ); + sal_Int32 enum_length = seq_enum_names.getLength(); + OSL_ASSERT( enum_length == seq_enum_values.getLength() ); + OUString const * enum_names = seq_enum_names.getConstArray(); + sal_Int32 const * enum_values = seq_enum_values.getConstArray(); + for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos ) + { +// enum_builder->DefineLiteral( +// ustring_to_String( enum_names[ enum_pos ] ), +// __box ((::System::Int32) enum_values[ enum_pos ]) ); + Emit::FieldBuilder * field_builder = + enum_builder->DefineField( + ustring_to_String( enum_names[ enum_pos ] ), + enum_builder, + (FieldAttributes) (FieldAttributes::Public | + FieldAttributes::Static | + FieldAttributes::Literal) ); + field_builder->SetConstant( + __box ((::System::Int32) enum_values[ enum_pos ]) ); + } + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting enum type {0}", cts_name ); + } + ret_type = enum_builder->CreateType(); + } + return ret_type; +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + Reference< reflection::XCompoundTypeDescription > const & xType ) +{ + OUString uno_name( xType->getName() ); + if (TypeClass_EXCEPTION == xType->getTypeClass()) + { + if (uno_name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.uno.Exception") )) + { + return get_type_Exception(); + } + if (uno_name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.uno.RuntimeException") )) + { + return get_type_RuntimeException(); + } + } + ::System::String * cts_name = to_cts_name( uno_name ); + // if the struct is an instantiated polymorpic struct then we create the simple struct name + // For example: + // void func ([in] PolyStruct<boolean> arg); + //PolyStruct<boolean> will be converted to PolyStruct + polymorphicStructNameToStructName( & cts_name); + + ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); + if (0 == ret_type) + { + Reference< reflection::XCompoundTypeDescription > xBaseType( + xType->getBaseType(), UNO_QUERY ); + ::System::Type * base_type = (xBaseType.is() + ? get_type( xBaseType ) + : __typeof (::System::Object)); + Emit::TypeBuilder * type_builder = + m_module_builder->DefineType( + cts_name, + (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass), + base_type ); + + + // insert to be completed + struct_entry * entry = new struct_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + entry->m_base_type = base_type; + m_incomplete_structs->Add( cts_name, entry ); + + // type is incomplete + ret_type = type_builder; + } + + //In case of an instantiated polymorphic struct we want to return a + //uno.PolymorphicType (inherits Type) rather then Type. This is neaded for constructing + //the service code. We can only do that if the struct is completed. + if (m_generated_structs->get_Item(cts_name)) + { + Reference< reflection::XStructTypeDescription> xStructTypeDesc( + xType, UNO_QUERY); + + if (xStructTypeDesc.is()) + { + Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments(); + sal_Int32 numTypes = seqTypeArgs.getLength(); + if (numTypes > 0) + { + //it is an instantiated polymorphic struct + ::System::String * sCliName = mapUnoTypeName(ustring_to_String(xType->getName())); + ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName); + } + } + } + return ret_type; +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + Reference< reflection::XInterfaceTypeDescription2 > const & xType ) +{ + OUString uno_name( xType->getName() ); + if (uno_name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )) + { + return __typeof (::System::Object); + } + + ::System::String * cts_name = to_cts_name( xType->getName() ); + ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); + if (0 == ret_type) + { + Emit::TypeBuilder * type_builder; + + TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Interface | + TypeAttributes::Abstract | + TypeAttributes::AnsiClass); + + std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes; + Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes = + xType->getBaseTypes(); + if (seqBaseTypes.getLength() > 0) + { + for (int i = 0; i < seqBaseTypes.getLength(); i++) + { + Reference<reflection::XInterfaceTypeDescription2> xIfaceTd = + resolveInterfaceTypedef(seqBaseTypes[i]); + + if (xIfaceTd->getName().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) == sal_False) + { + vecBaseTypes.push_back(xIfaceTd); + } + } + + ::System::Type * base_interfaces [] = + new ::System::Type * [ vecBaseTypes.size() ]; + + typedef std::vector<Reference<reflection::XInterfaceTypeDescription2> >::const_iterator it; + int index = 0; + for (it i = vecBaseTypes.begin(); i != vecBaseTypes.end(); i++, index++) + base_interfaces[ index ] = get_type( *i ); + type_builder = m_module_builder->DefineType( + cts_name, attr, 0, base_interfaces ); + } + else + { + ::System::Console::WriteLine( + "warning: IDL interface {0} is not derived from " + "com.sun.star.uno.XInterface!", + ustring_to_String( uno_name ) ); + + type_builder = m_module_builder->DefineType( cts_name, attr ); + } + + // insert to be completed + iface_entry * entry = new iface_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + m_incomplete_ifaces->Add( cts_name, entry ); + + // type is incomplete + ret_type = type_builder; + } + return ret_type; +} + + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + Reference< reflection::XServiceTypeDescription2 > const & xType ) +{ + if (xType->isSingleInterfaceBased() == sal_False) + return NULL; + + System::String * cts_name = to_cts_name( xType->getName() ); + System::Type * ret_type = get_type( cts_name, false /* no exc */ ); + if (ret_type != NULL) + return ret_type; + + TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass); + + Emit::TypeBuilder * type_builder = m_module_builder->DefineType( + cts_name, attr); + + // insert to be completed + service_entry * entry = new service_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + m_incomplete_services->Add(cts_name,entry ); + + return type_builder; +} + +::System::Type * TypeEmitter::get_type( + Reference<reflection::XSingletonTypeDescription2 > const & xType ) +{ + if (xType->isInterfaceBased() == sal_False) + return NULL; + + ::System::String* cts_name = to_cts_name( xType->getName() ); + ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); + if (ret_type != NULL) + return ret_type; + + TypeAttributes attr = static_cast<TypeAttributes>( + TypeAttributes::Public | + TypeAttributes::Sealed | + TypeAttributes::BeforeFieldInit | + TypeAttributes::AnsiClass); + + Emit::TypeBuilder * type_builder = m_module_builder->DefineType( + cts_name, attr); + + // insert to be completed + singleton_entry * entry = new singleton_entry(); + xType->acquire(); + entry->m_xType = xType.get(); + entry->m_type_builder = type_builder; + m_incomplete_singletons->Add(cts_name,entry ); + + return type_builder; + +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::complete_iface_type( iface_entry * entry ) +{ + Emit::TypeBuilder * type_builder = entry->m_type_builder; + reflection::XInterfaceTypeDescription2 * xType = entry->m_xType; + + Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() ); + if (seqBaseTypes.getLength() > 0) + { + for (int i = 0; i < seqBaseTypes.getLength(); i++) + { + //make sure we get the interface rather then a typedef + Reference<reflection::XInterfaceTypeDescription2> aBaseType = + resolveInterfaceTypedef( seqBaseTypes[i]); + + if (aBaseType->getName().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) == sal_False) + { + ::System::String * basetype_name = to_cts_name( aBaseType->getName() ); + iface_entry * base_entry = dynamic_cast< iface_entry * >( + m_incomplete_ifaces->get_Item( basetype_name ) ); + if (0 != base_entry) + { + // complete uncompleted base type first + complete_iface_type( base_entry ); + } + } + } + } + + Sequence< + Reference< reflection::XInterfaceMemberTypeDescription > > seq_members( + xType->getMembers() ); + Reference< reflection::XInterfaceMemberTypeDescription > const * members = + seq_members.getConstArray(); + sal_Int32 members_length = seq_members.getLength(); + for ( sal_Int32 members_pos = 0; + members_pos < members_length; ++members_pos ) + { + Reference< + reflection::XInterfaceMemberTypeDescription > const & xMember = + members[ members_pos ]; + Sequence< Reference< reflection::XTypeDescription > > seq_exceptions; + Emit::MethodBuilder * method_builder; + + const MethodAttributes c_method_attr = (MethodAttributes) + (MethodAttributes::Public | + MethodAttributes::Abstract | + MethodAttributes::Virtual | + MethodAttributes::NewSlot | + MethodAttributes::HideBySig); +//#if defined(_MSC_VER) && (_MSC_VER < 1400) +// MethodAttributes::Instance); +//#else +// Instance); +//#endif + + if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass()) + { + Reference< reflection::XInterfaceMethodTypeDescription > xMethod( + xMember, UNO_QUERY_THROW ); + + Sequence< + Reference< reflection::XMethodParameter > > seq_parameters( + xMethod->getParameters() ); + sal_Int32 params_length = seq_parameters.getLength(); + ::System::Type * param_types [] = + new ::System::Type * [ params_length ]; + Reference< reflection::XMethodParameter > const * parameters = + seq_parameters.getConstArray(); + // first determine all types + //Make the first param type as return type + sal_Int32 params_pos = 0; + for ( ; params_pos < params_length; ++params_pos ) + { + Reference< reflection::XMethodParameter > const & xParam = + parameters[ params_pos ]; + ::System::Type * param_type = get_type( xParam->getType() ); + ::System::String * param_type_name = param_type->get_FullName(); + if (xParam->isOut()) + { + param_type = get_type( + ::System::String::Concat( + param_type_name, S"&" ), true ); + } + param_types[ xParam->getPosition() ] = param_type; + } + + + // create method +// if (tb) +// method_builder = type_builder->DefineMethod( +// ustring_to_String( xMethod->getMemberName() ), +// c_method_attr, tb, +// param_types ); +// else + method_builder = type_builder->DefineMethod( + ustring_to_String( xMethod->getMemberName() ), + c_method_attr, get_type( xMethod->getReturnType() ), + param_types ); + // then define parameter infos + params_pos = 0; + for ( ; params_pos < params_length; ++params_pos ) + { + Reference< reflection::XMethodParameter > const & xParam = + parameters[ params_pos ]; + long param_flags = 0; + if (xParam->isIn()) + param_flags |= ParameterAttributes::In; + if (xParam->isOut()) + param_flags |= ParameterAttributes::Out; + OSL_ASSERT( 0 != param_flags ); + method_builder->DefineParameter( + xParam->getPosition() +1 /* starts with 1 */, + (ParameterAttributes) param_flags, + ustring_to_String( xParam->getName() ) ); + } + //Apply attribute TypeParametersAttribute to return value if it + //is a parameterized Type. Currently only structs can have parameters. + Reference<reflection::XStructTypeDescription> xReturnStruct( + xMethod->getReturnType(), UNO_QUERY); + + if (xReturnStruct.is()) + { + Sequence<Reference<reflection::XTypeDescription> > seq_type_args = + xReturnStruct->getTypeArguments(); + if (seq_type_args.getLength() != 0) + { + //get th ctor of the attribute + ::System::Type * arCtor[] = {::System::Type::GetType(S"System.Type[]")}; + //Get the arguments for the attribute's ctor + Reference<reflection::XTypeDescription> const * arXTypeArgs = + seq_type_args.getConstArray(); + int numTypes = seq_type_args.getLength(); + ::System::Type * arCtsTypes[] = new ::System::Type*[numTypes]; + for (int i = 0; i < numTypes; i++) + arCtsTypes[i] = get_type(arXTypeArgs[i]); + ::System::Object * arArgs[] = {arCtsTypes}; + + Emit::CustomAttributeBuilder * attrBuilder = + new Emit::CustomAttributeBuilder( + __typeof(::uno::TypeArgumentsAttribute) + ->GetConstructor( arCtor), + arArgs); + + method_builder->SetCustomAttribute(attrBuilder); + } + } + + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder* attrBuilder = + get_iface_method_exception_attribute(xMethod); + if (attrBuilder != NULL) + method_builder->SetCustomAttribute(attrBuilder); + + // oneway attribute + if (xMethod->isOneway()) + { + ::System::Type * arCtorOneway[] = new ::System::Type*[0]; + ::System::Object * arArgs[] = new ::System::Object*[0]; + Emit::CustomAttributeBuilder * attrBuilder = + new Emit::CustomAttributeBuilder( + __typeof(::uno::OnewayAttribute)->GetConstructor( arCtorOneway), + arArgs); + method_builder->SetCustomAttribute(attrBuilder); + } + } + else // attribute + { + OSL_ASSERT( + TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() ); + Reference< + reflection::XInterfaceAttributeTypeDescription2 > xAttribute( + xMember, UNO_QUERY_THROW ); + + const MethodAttributes c_property_method_attr = (MethodAttributes) + (c_method_attr | MethodAttributes::SpecialName); + + ::System::Type * attribute_type = get_type( xAttribute->getType() ); + ::System::Type * parameters [] = + new ::System::Type * [ 0 ]; + + Emit::PropertyBuilder * property_builder = + type_builder->DefineProperty( + ustring_to_String( xAttribute->getMemberName() ), + PropertyAttributes::None, + attribute_type, parameters ); + + //set BoundAttribute, if necessary + if (xAttribute->isBound()) + { + ConstructorInfo * ctorBoundAttr = + __typeof(::uno::BoundAttribute)->GetConstructor( + new System::Type*[0]); + Emit::CustomAttributeBuilder * attrBuilderBound = + new Emit::CustomAttributeBuilder( + ctorBoundAttr, new ::System::Object*[0]); + property_builder->SetCustomAttribute(attrBuilderBound); + } + + // getter + Emit::MethodBuilder * method_builder = + type_builder->DefineMethod( + ustring_to_String( OUSTR("get_") + + xAttribute->getMemberName() ), + c_property_method_attr, attribute_type, parameters ); + + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder* attrBuilder = + get_exception_attribute(xAttribute->getGetExceptions()); + if (attrBuilder != NULL) + method_builder->SetCustomAttribute(attrBuilder); + + property_builder->SetGetMethod( method_builder ); + + if (! xAttribute->isReadOnly()) + { + // setter + parameters = new ::System::Type * [ 1 ]; + parameters[ 0 ] = attribute_type; + method_builder = + type_builder->DefineMethod( + ustring_to_String( OUSTR("set_") + + xAttribute->getMemberName() ), + c_property_method_attr, 0, parameters ); + // define parameter info + method_builder->DefineParameter( + 1 /* starts with 1 */, ParameterAttributes::In, S"value" ); + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder* attrBuilder = + get_exception_attribute(xAttribute->getSetExceptions()); + if (attrBuilder != NULL) + method_builder->SetCustomAttribute(attrBuilder); + + property_builder->SetSetMethod( method_builder ); + } + } + } + + // remove from incomplete types map + ::System::String * cts_name = type_builder->get_FullName(); + m_incomplete_ifaces->Remove( cts_name ); + xType->release(); + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting interface type {0}", cts_name ); + } + return type_builder->CreateType(); +} + +::System::Type * TypeEmitter::complete_struct_type( struct_entry * entry ) +{ + OSL_ASSERT(entry); + ::System::String * cts_name = entry->m_type_builder->get_FullName(); + + //Polymorphic struct, define uno.TypeParametersAttribute + //A polymorphic struct cannot have a basetype. + //When we create the template of the struct then we have no exact types + //and the name does not contain a parameter list + Sequence< OUString > seq_type_parameters; + Reference< reflection::XStructTypeDescription> xStructTypeDesc( + entry->m_xType, UNO_QUERY); + if (xStructTypeDesc.is()) + { + seq_type_parameters = xStructTypeDesc->getTypeParameters(); + int numTypes = 0; + if ((numTypes = seq_type_parameters.getLength()) > 0) + { + ::System::Object * aArg[] = new ::System::Object*[numTypes]; + for (int i = 0; i < numTypes; i++) + aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]); + ::System::Object * args[] = {aArg}; + + ::System::Type * arTypesCtor[] = + {::System::Type::GetType(S"System.String[]")}; + Emit::CustomAttributeBuilder * attrBuilder = + new Emit::CustomAttributeBuilder( + __typeof(::uno::TypeParametersAttribute)->GetConstructor(arTypesCtor), + args); + entry->m_type_builder->SetCustomAttribute(attrBuilder); + } + } + + // optional: lookup base type whether generated entry of this session + struct_entry * base_type_entry = 0; + if (0 != entry->m_base_type) + { + //ToDo maybe get from incomplete structs + base_type_entry = + dynamic_cast< struct_entry * >( + m_generated_structs->get_Item( + entry->m_base_type->get_FullName() ) ); + } + + // members + Sequence< Reference< reflection::XTypeDescription > > seq_members( + entry->m_xType->getMemberTypes() ); + Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() ); + sal_Int32 members_length = seq_members.getLength(); + OSL_ASSERT( seq_member_names.getLength() == members_length ); + //check if we have a XTypeDescription for every member. If not then the user may + //have forgotten to specify additional rdbs with the --extra option. + Reference< reflection::XTypeDescription > const * pseq_members = + seq_members.getConstArray(); + OUString const * pseq_member_names = + seq_member_names.getConstArray(); + for (int i = 0; i < members_length; i++) + { + const OUString sType(entry->m_xType->getName()); + const OUString sMemberName(pseq_member_names[i]); + if ( ! pseq_members[i].is()) + throw RuntimeException(OUSTR("Missing type description . Check if you need to " \ + "specify additional RDBs with the --extra option. Type missing for: ") + sType + + OUSTR("::") + sMemberName,0); + } + + sal_Int32 all_members_length = 0; + sal_Int32 member_pos; + sal_Int32 type_param_pos = 0; + + // collect base types; wrong order + ::System::Collections::ArrayList * base_types_list = + new ::System::Collections::ArrayList( 3 /* initial capacity */ ); + for (::System::Type * base_type_pos = entry->m_base_type; + ! base_type_pos->Equals( __typeof (::System::Object) ); + base_type_pos = base_type_pos->get_BaseType() ) + { + base_types_list->Add( base_type_pos ); + if (base_type_pos->Equals( __typeof (::System::Exception) )) + { + // special Message member + all_members_length += 1; + break; // don't include System.Exception base classes + } + else + { + //ensure the base type is complete. Otherwise GetFields won't work + get_complete_struct(base_type_pos->get_FullName()); + all_members_length += + base_type_pos->GetFields( + (BindingFlags) (BindingFlags::Instance | + BindingFlags::Public | + BindingFlags::DeclaredOnly) ) + ->get_Length(); + } + } + + // create all_members arrays; right order + ::System::String * all_member_names[] = + new ::System::String * [all_members_length + members_length ]; + ::System::Type * all_param_types[] = + new ::System::Type * [all_members_length + members_length ]; + member_pos = 0; + for ( sal_Int32 pos = base_types_list->get_Count(); pos--; ) + { + ::System::Type * base_type = __try_cast< ::System::Type * >( + base_types_list->get_Item( pos ) ); + if (base_type->Equals( __typeof (::System::Exception) )) + { + all_member_names[ member_pos ] = S"Message"; + all_param_types[ member_pos ] = __typeof (::System::String); + ++member_pos; + } + else + { + ::System::String * base_type_name = base_type->get_FullName(); + + //ToDo m_generated_structs? + struct_entry * entry = + dynamic_cast< struct_entry * >( + m_generated_structs->get_Item( base_type_name ) ); + if (0 == entry) + { + // complete type + FieldInfo * fields [] = + base_type->GetFields( + (BindingFlags) (BindingFlags::Instance | + BindingFlags::Public | + BindingFlags::DeclaredOnly) ); + sal_Int32 len = fields->get_Length(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + FieldInfo * field = fields[ pos ]; + all_member_names[ member_pos ] = field->get_Name(); + all_param_types[ member_pos ] = field->get_FieldType(); + ++member_pos; + } + } + else // generated during this session: + // members may be incomplete ifaces + { + sal_Int32 len = entry->m_member_names->get_Length(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + all_member_names[ member_pos ] = + entry->m_member_names[ pos ]; + all_param_types[ member_pos ] = + entry->m_param_types[ pos ]; + ++member_pos; + } + } + } + } + OSL_ASSERT( all_members_length == member_pos ); + + // build up entry +// struct_entry * entry = new struct_entry(); + entry->m_member_names = new ::System::String * [ members_length ]; + entry->m_param_types = new ::System::Type * [ members_length ]; + + // add members + Emit::FieldBuilder * members[] = new Emit::FieldBuilder * [ members_length ]; + //Reference< reflection::XTypeDescription > const * pseq_members = + // seq_members.getConstArray(); + //OUString const * pseq_member_names = + // seq_member_names.getConstArray(); + + int curParamIndex = 0; //count the fields which have parameterized types + for ( member_pos = 0; member_pos < members_length; ++member_pos ) + { + ::System::String * field_name = + ustring_to_String( pseq_member_names[ member_pos ] ); + ::System::Type * field_type; + //Special handling of struct parameter types + bool bParameterizedType = false; + if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN) + { + bParameterizedType = true; + if (type_param_pos < seq_type_parameters.getLength()) + { + field_type = __typeof(::System::Object); + type_param_pos++; + } + else + { + throw RuntimeException( + OUSTR("unexpected member type in ") + entry->m_xType->getName(), + Reference< XInterface >() ); + } + } + else + { + field_type = + get_type( pseq_members[ member_pos ] ); + } + members[ member_pos ] = + entry->m_type_builder->DefineField( + field_name, field_type, FieldAttributes::Public ); + + //parameterized type (polymorphic struct) ? + if (bParameterizedType && xStructTypeDesc.is()) + { + //get the name + OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex); + ::System::String* sTypeName = ustring_to_String( + seq_type_parameters.getConstArray()[curParamIndex++]); + ::System::Object * args[] = {sTypeName}; + //set ParameterizedTypeAttribute + ::System::Type * arCtorTypes[] = {__typeof(::System::String)}; + + Emit::CustomAttributeBuilder * attrBuilder = + new Emit::CustomAttributeBuilder( + __typeof(::uno::ParameterizedTypeAttribute) + ->GetConstructor(arCtorTypes), + args); + + members[member_pos]->SetCustomAttribute(attrBuilder); + } + // add to all_members + all_member_names[ all_members_length + member_pos ] = field_name; + all_param_types[ all_members_length + member_pos ] = field_type; + // add to entry + entry->m_member_names[ member_pos ] = field_name; + entry->m_param_types[ member_pos ] = field_type; + } + all_members_length += members_length; + + // default .ctor + Emit::ConstructorBuilder * ctor_builder = + entry->m_type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, + new ::System::Type * [ 0 ] ); + Emit::ILGenerator * code = ctor_builder->GetILGenerator(); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( + Emit::OpCodes::Call, + 0 == base_type_entry + ? entry->m_base_type->GetConstructor( new ::System::Type * [ 0 ] ) + : base_type_entry->m_default_ctor ); + // default initialize members + for ( member_pos = 0; member_pos < members_length; ++member_pos ) + { + FieldInfo * field = members[ member_pos ]; + ::System::Type * field_type = field->get_FieldType(); + // ::System::Type * new_field_type = m_module_builder->GetType(field_type->FullName, false); + // default initialize: + // string, type, enum, sequence, struct, exception, any + if (field_type->Equals( __typeof (::System::String) )) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldstr, S"" ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + else if (field_type->Equals( __typeof (::System::Type) )) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( + Emit::OpCodes::Ldtoken, __typeof (::System::Void) ); + code->Emit( + Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + else if (field_type->get_IsArray()) + { + //Find the value type. In case of sequence<sequence< ... > > find the actual value type + ::System::Type * value = field_type; + while ((value = value->GetElementType())->get_IsArray()); + //If the value type is a struct then make sure it is fully created. + get_complete_struct(value->get_FullName()); + + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldc_I4_0 ); + code->Emit( + Emit::OpCodes::Newarr, field_type->GetElementType() ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + else if (field_type->get_IsValueType()) + { + if (field_type->get_FullName()->Equals( S"uno.Any" )) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( Emit::OpCodes::Ldsfld, __typeof(::uno::Any)->GetField(S"VOID")); + code->Emit( Emit::OpCodes::Stfld, field ); + } + } + else if (field_type->get_IsClass()) + { + /* may be XInterface */ + if (! field_type->Equals( __typeof (::System::Object) )) + { + // struct, exception + //make sure the struct is already complete. + get_complete_struct(field_type->get_FullName()); + code->Emit( Emit::OpCodes::Ldarg_0 ); + code->Emit( + Emit::OpCodes::Newobj, + //GetConstructor requies that the member types of the object which is to be constructed are already known. + field_type->GetConstructor( + new ::System::Type * [ 0 ] ) ); + code->Emit( Emit::OpCodes::Stfld, field ); + } + } + } + code->Emit( Emit::OpCodes::Ret ); + entry->m_default_ctor = ctor_builder; + + // parameterized .ctor including all base members + ctor_builder = entry->m_type_builder->DefineConstructor( + c_ctor_method_attr, CallingConventions::Standard, all_param_types ); + for ( member_pos = 0; member_pos < all_members_length; ++member_pos ) + { + ctor_builder->DefineParameter( + member_pos +1 /* starts with 1 */, ParameterAttributes::In, + all_member_names[ member_pos ] ); + } + code = ctor_builder->GetILGenerator(); + // call base .ctor + code->Emit( Emit::OpCodes::Ldarg_0 ); // push this + sal_Int32 base_members_length = all_members_length - members_length; + ::System::Type * param_types [] = + new ::System::Type * [ base_members_length ]; + for ( member_pos = 0; member_pos < base_members_length; ++member_pos ) + { + emit_ldarg( code, member_pos +1 ); + param_types[ member_pos ] = all_param_types[ member_pos ]; + } + code->Emit( + Emit::OpCodes::Call, + 0 == base_type_entry + ? entry->m_base_type->GetConstructor( param_types ) + : base_type_entry->m_ctor ); + // initialize members + for ( member_pos = 0; member_pos < members_length; ++member_pos ) + { + code->Emit( Emit::OpCodes::Ldarg_0 ); // push this + emit_ldarg( code, member_pos + base_members_length +1 ); + code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] ); + } + code->Emit( Emit::OpCodes::Ret ); + entry->m_ctor = ctor_builder; + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting {0} type {1}", + TypeClass_STRUCT == entry->m_xType->getTypeClass() + ? S"struct" + : S"exception", + cts_name); + } + // new entry + m_generated_structs->Add(cts_name, entry ); + ::System::Type * ret_type = entry->m_type_builder->CreateType(); + + // remove from incomplete types map + m_incomplete_structs->Remove( cts_name ); + entry->m_xType->release(); + + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting struct type {0}", cts_name); + } + return ret_type; +} + +//Examples of generated code +// public static XWeak constructor1(XComponentContext ctx) +// { +// XMultiComponentFactory factory = ctx.getServiceManager(); +// if (factory == null) +// throw new com.sun.star.uno.DeploymentException("bla", null); +// return (XWeak) factory.createInstanceWithContext("service_specifier", ctx); +// } +// public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c) +// { +// XMultiComponentFactory factory = ctx.getServiceManager(); +// if (factory == null) +// throw new com.sun.star.uno.DeploymentException("bla", null); +// Any[] arAny = new Any[3]; +// arAny[0] = new Any(typeof(int), a); +// arAny[1] = new Any(typeof(int), b); +// arAny[2] = new Any(c.Type, c.Value); +// return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx); +// } +// Notice that a any parameter is NOT wrapped by another any. Instead the new any is created with the type and value +// of the parameter. + +// public static XWeak constructor3(XComponentContext ctx, params Any[] c) +// { +// XMultiComponentFactory factory = ctx.getServiceManager(); +// if (factory == null) +// throw new com.sun.star.uno.DeploymentException("bla", null); +// return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx); +// } +::System::Type * TypeEmitter::complete_service_type(service_entry * entry) +{ + Emit::TypeBuilder * type_builder = entry->m_type_builder; + reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType; + + //Create the private default constructor + Emit::ConstructorBuilder* ctor_builder = + type_builder->DefineConstructor( + (MethodAttributes) (MethodAttributes::Private | + MethodAttributes::HideBySig | + MethodAttributes::SpecialName | + MethodAttributes::RTSpecialName), + CallingConventions::Standard, NULL); + + Emit::ILGenerator* ilGen = ctor_builder->GetILGenerator(); + ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this + ilGen->Emit( + Emit::OpCodes::Call, + type_builder->BaseType->GetConstructor(new ::System::Type*[0])); + ilGen->Emit( Emit::OpCodes::Ret ); + + + //Create the service constructors. + //obtain the interface which makes up this service, it is the return + //type of the constructor functions + Reference<reflection::XInterfaceTypeDescription2> xIfaceType( + xServiceType->getInterface(), UNO_QUERY); + if (xIfaceType.is () == sal_False) + xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface()); + System::Type * retType = get_type(xIfaceType); + + //Create the ConstructorInfo for a DeploymentException + ::System::Type * typeDeploymentExc = + get_type(S"unoidl.com.sun.star.uno.DeploymentException", true); + + ::System::Type * arTypeCtor[] = {__typeof(::System::String), + __typeof(::System::Object)}; + ::System::Reflection::ConstructorInfo * ctorDeploymentException = + typeDeploymentExc->GetConstructor(arTypeCtor); + + Sequence<Reference<reflection::XServiceConstructorDescription> > seqCtors = + xServiceType->getConstructors(); + + ::System::Type * type_uno_exception = get_type(S"unoidl.com.sun.star.uno.Exception", true); + + for (int i = seqCtors.getLength() - 1; i >= 0; i--) + { + bool bParameterArray = false; + ::System::Type * typeAny = __typeof(::uno::Any); + const Reference<reflection::XServiceConstructorDescription> & ctorDes = + seqCtors[i]; + //obtain the parameter types + Sequence<Reference<reflection::XParameter> > seqParams = + ctorDes->getParameters(); + Reference<reflection::XParameter> const * arXParams = seqParams.getConstArray(); + sal_Int32 cParams = seqParams.getLength(); + ::System::Type * arTypeParameters[] = new ::System::Type* [cParams + 1]; + arTypeParameters[0] = get_type(S"unoidl.com.sun.star.uno.XComponentContext", true); + for (int iparam = 0; iparam != cParams; iparam++) + { + if (arXParams[iparam]->isRestParameter()) + arTypeParameters[iparam + 1] = __typeof(::uno::Any[]); + else + arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType()); + } + //The array arTypeParameters can contain: + //System.Type and uno.PolymorphicType. + //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem. + //The exception will read something like no on information for parameter # d + //Maybe we need no override another Type method in PolymorphicType ... + //Until we have figured this out, we will create another array of System.Type which + //we pass on to DefineMethod. + ::System::Type * arParamTypes[] = new ::System::Type * [cParams + 1]; +// arParamTypes[0] = get_type(S"unoidl.com.sun.star.uno.XComponentContext", true); + for (int i = 0; i < cParams + 1; i++) + { + ::uno::PolymorphicType * pT = dynamic_cast< ::uno::PolymorphicType * >(arTypeParameters[i]); + if (pT) + arParamTypes[i] = pT->OriginalType; + else + arParamTypes[i] = arTypeParameters[i]; + } + //define method + System::String * ctorName; + if (ctorDes->isDefaultConstructor()) + ctorName = new ::System::String(S"create"); + else + ctorName = ustring_to_String(ctorDes->getName()); + Emit::MethodBuilder* method_builder = type_builder->DefineMethod( + ctorName, + static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig | + MethodAttributes::Static), + retType, +// arTypeParameters); + arParamTypes); + + //define UNO exception attribute (exceptions)-------------------------------------- + Emit::CustomAttributeBuilder* attrBuilder = get_service_exception_attribute(ctorDes); + if (attrBuilder != NULL) + method_builder->SetCustomAttribute(attrBuilder); + + //------------------------------------------------------------- + //define parameter attributes (paramarray), names etc. + //The first parameter is the XComponentContext, which cannot be obtained + //from reflection. + //The context is not part of the idl description + method_builder->DefineParameter( + 1, ParameterAttributes::In, S"the_context"); + + Emit::ParameterBuilder * arParameterBuilder[] = + new Emit::ParameterBuilder * [cParams]; + for (int iparam = 0; iparam != cParams; iparam++) + { + Reference<reflection::XParameter> const & aParam = arXParams[iparam]; + ::System::String * sParamName = ustring_to_String(aParam->getName()); + + arParameterBuilder[iparam] = method_builder->DefineParameter( + iparam + 2, ParameterAttributes::In, sParamName); + + if (aParam->isRestParameter()) + { + bParameterArray = true; + //set the ParameterArrayAttribute + ::System::Reflection::ConstructorInfo* ctor_info = + __typeof(System::ParamArrayAttribute)->GetConstructor( + new ::System::Type*[0]); + Emit::CustomAttributeBuilder * attr_builder = + new Emit::CustomAttributeBuilder(ctor_info, new ::System::Object*[0]); + arParameterBuilder[iparam]->SetCustomAttribute(attr_builder); + break; + } + } + + Emit::ILGenerator * ilGen = method_builder->GetILGenerator(); + + //Define locals --------------------------------- + //XMultiComponentFactory + Emit::LocalBuilder* local_factory = + ilGen->DeclareLocal( + get_type(S"unoidl.com.sun.star.lang.XMultiComponentFactory", true)); + + //The return type + Emit::LocalBuilder* local_return_val = + ilGen->DeclareLocal(retType); + + //Obtain the XMultiComponentFactory and throw an exception if we do not get one + ilGen->Emit(Emit::OpCodes::Ldarg_0); + + ::System::Reflection::MethodInfo * methodGetServiceManager = get_type( + S"unoidl.com.sun.star.uno.XComponentContext", true) + ->GetMethod(S"getServiceManager"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager); + ilGen->Emit(Emit::OpCodes::Stloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + Emit::Label label1 = ilGen->DefineLabel(); + ilGen->Emit(Emit::OpCodes::Brtrue, label1); + //The string for the exception + ::System::Text::StringBuilder * strbuilder = new ::System::Text::StringBuilder(256); + strbuilder->Append(S"The service "); + strbuilder->Append(to_cts_name(xServiceType->getName())); + strbuilder->Append(S" could not be created. The context failed to supply the service manager."); + + ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); + ilGen->Emit(Emit::OpCodes::Throw); + ilGen->MarkLabel(label1); + + //We create a try/ catch around the createInstanceWithContext, etc. functions + //There are 3 cases + //1. function do not specify exceptions. Then RuntimeExceptions are retrhown and other + // exceptions produce a DeploymentException. + //2. function specify Exception. Then all exceptions fly through + //3. function specifies exceptions but no Exception. Then these are rethrown + // and other exceptions, except RuntimeException, produce a deployment exception. + //In case there are no parameters we call + //XMultiComponentFactory.createInstanceWithContext + + ::System::Collections::ArrayList * arExceptionTypes = + get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions()); + if (arExceptionTypes->Contains( + type_uno_exception) == false) + { + ilGen->BeginExceptionBlock(); + } + if (cParams == 0) + { + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + + ::System::Reflection::MethodInfo * methodCreate = + local_factory->get_LocalType()->GetMethod(S"createInstanceWithContext"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); + } + else if(bParameterArray) + { + //Service constructor with parameter array + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); + ilGen->Emit(Emit::OpCodes::Ldarg_1); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ::System::Reflection::MethodInfo * methodCreate = + local_factory->get_LocalType()->GetMethod(S"createInstanceWithArgumentsAndContext"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); + } + else + { + // Any param1, Any param2, etc. + // For each parameter,except the component context, and parameter array + // and Any is created. + Emit::LocalBuilder * arLocalAny[] = new Emit::LocalBuilder* [cParams]; + + for (int iParam = 0; iParam < cParams; iParam ++) + { + arLocalAny[iParam] = ilGen->DeclareLocal(typeAny); + } + + //Any[]. This array is filled with the created Anys which contain the parameters + //and the values contained in the parameter array + Emit::LocalBuilder * local_anyParams = + ilGen->DeclareLocal(__typeof(::uno::Any[])); + + //Create the Any for every argument, except for the parameter array + //arLocalAny contains the LocalBuilder for all these parameters. + //we call the ctor Any(Type, Object) + //If the parameter is an Any then the Any is created with Any(param.Type, param.Value); + ::System::Type * arTypesCtorAny[] = {__typeof(::System::Type), + __typeof(::System::Object)}; + ::System::Reflection::ConstructorInfo * ctorAny = + typeAny->GetConstructor( arTypesCtorAny); + ::System::Reflection::MethodInfo * methodAnyGetType = + typeAny->GetProperty(S"Type")->GetGetMethod(); + ::System::Reflection::MethodInfo * methodAnyGetValue = + typeAny->GetProperty(S"Value")->GetGetMethod(); + for (int i = 0; i < arLocalAny->Length; i ++) + { + //check if the parameter is a polymorphic struct + ::uno::PolymorphicType *polyType = dynamic_cast< ::uno::PolymorphicType* >(arTypeParameters[i+1]); + //arTypeParameters[i+1] = polyType->OriginalType; + if (polyType) + { + //It is a polymorphic struct + //Load the uninitialized local Any on which we will call the ctor + ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); + // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName) + // Prepare the first parameter + ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->get_OriginalType()); + ::System::Type * arTypeParams[] = {__typeof(::System::RuntimeTypeHandle)}; + ilGen->Emit(Emit::OpCodes::Call, + __typeof(::System::Type)->GetMethod( + S"GetTypeFromHandle", arTypeParams)); + // Prepare the second parameter + ilGen->Emit(Emit::OpCodes::Ldstr, polyType->get_PolymorphicName()); + // Make the actual call + ::System::Type * arTypeParam_GetType[] = { + __typeof(::System::Type), __typeof(::System::String) }; + ilGen->Emit(Emit::OpCodes::Call, + __typeof(::uno::PolymorphicType)->GetMethod(new System::String(S"GetType"), + arTypeParam_GetType)); + + //Stack is: localAny, PolymorphicType + //Call Any::Any(Type, Object) + //Prepare the second parameter for the any ctor + ilGen->Emit(Emit::OpCodes::Ldarg, i + 1); + // if the parameter is a value type then we need to box it, because + // the Any ctor takes an Object + if (arTypeParameters[i+1]->IsValueType) + ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]); + ilGen->Emit(Emit::OpCodes::Call, ctorAny); + } + else if (arTypeParameters[i+1] == typeAny) + { + //Create the call new Any(param.Type,param,Value) + //Stack must be Any,Type,Value + //First load the Any which is to be constructed + ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); + //Load the Type, which is obtained by calling param.Type + ilGen->Emit(Emit::OpCodes::Ldarga, i + 1); + ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType); + //Load the Value, which is obtained by calling param.Value + ilGen->Emit(Emit::OpCodes::Ldarga, i + 1); + ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue); + //Call the Any ctor. + ilGen->Emit(Emit::OpCodes::Call, ctorAny); + } + else + { + ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); + ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]); + + ::System::Type * arTypeParams[] = {__typeof(::System::RuntimeTypeHandle)}; + ilGen->Emit(Emit::OpCodes::Call, + __typeof(::System::Type)->GetMethod( + S"GetTypeFromHandle", arTypeParams)); + ilGen->Emit(Emit::OpCodes::Ldarg, i + 1); + // if the parameter is a value type then we need to box it, because + // the Any ctor takes an Object + if (arTypeParameters[i+1]->IsValueType) + ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]); + ilGen->Emit(Emit::OpCodes::Call, ctorAny); + } + } + + //Create the Any[] that is passed to the + //createInstanceWithContext[AndArguments] function + ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length); + ilGen->Emit(Emit::OpCodes::Newarr, typeAny); + ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams); + + //Assign all anys created from the parameters + //array to the Any[] + for (int i = 0; i < arLocalAny->Length; i++) + { + ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams); + ilGen->Emit(Emit::OpCodes::Ldc_I4, i); + ilGen->Emit(Emit::OpCodes::Ldelema, typeAny); + ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]); + ilGen->Emit(Emit::OpCodes::Stobj, typeAny); + } + // call createInstanceWithContextAndArguments + ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); + ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); + ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ::System::Reflection::MethodInfo * methodCreate = + local_factory->get_LocalType()->GetMethod(S"createInstanceWithArgumentsAndContext"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); + } + //cast the object returned by the functions createInstanceWithContext or + //createInstanceWithArgumentsAndContext to the interface type + ilGen->Emit(Emit::OpCodes::Castclass, retType); + ilGen->Emit(Emit::OpCodes::Stloc, local_return_val); + + //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext + if (arExceptionTypes->Contains(type_uno_exception) == false) + { + // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;} + ilGen->BeginCatchBlock(get_type(S"unoidl.com.sun.star.uno.RuntimeException", true)); + ilGen->Emit(Emit::OpCodes::Pop); + ilGen->Emit(Emit::OpCodes::Rethrow); + + //catch and rethrow all other defined Exceptions + for (int i = 0; i < arExceptionTypes->Count; i++) + { + ::System::Type * excType = __try_cast< ::System::Type* >( + arExceptionTypes->get_Item(i)); + if (excType->IsInstanceOfType( + get_type(S"unoidl.com.sun.star.uno.RuntimeException", true))) + {// we have a catch for RuntimeException already defined + continue; + } + + //catch Exception and rethrow + ilGen->BeginCatchBlock(excType); + ilGen->Emit(Emit::OpCodes::Pop); + ilGen->Emit(Emit::OpCodes::Rethrow); + } + //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...} + ilGen->BeginCatchBlock(type_uno_exception); + + //Define the local variabe that keeps the exception + Emit::LocalBuilder * local_exception = ilGen->DeclareLocal( + type_uno_exception); + + //Store the exception + ilGen->Emit(Emit::OpCodes::Stloc, local_exception); + + //prepare the construction of the exception + strbuilder = new ::System::Text::StringBuilder(256); + strbuilder->Append(S"The context (com.sun.star.uno.XComponentContext) failed to supply the service "); + strbuilder->Append(to_cts_name(xServiceType->getName())); + strbuilder->Append(S": "); + + ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); + + //add to the string the Exception.Message + ilGen->Emit(Emit::OpCodes::Ldloc, local_exception); + ilGen->Emit(Emit::OpCodes::Callvirt, + type_uno_exception->GetProperty(S"Message")->GetGetMethod()); + ::System::Type * arConcatParams [] = {__typeof(System::String), + __typeof(System::String)}; + ilGen->Emit(Emit::OpCodes::Call, + __typeof(System::String)->GetMethod(S"Concat", arConcatParams)); + //load contex argument + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); + ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc); + + ilGen->EndExceptionBlock(); + } + + + //Check if the service instance was create and throw a exception if not. + Emit::Label label_service_created = ilGen->DefineLabel(); + ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val); + ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created); + + strbuilder = new ::System::Text::StringBuilder(256); + strbuilder->Append(S"The context (com.sun.star.uno.XComponentContext) failed to supply the service "); + strbuilder->Append(to_cts_name(xServiceType->getName())); + strbuilder->Append(S"."); + ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); + ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc); + + ilGen->MarkLabel(label_service_created); + ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val); + ilGen->Emit(Emit::OpCodes::Ret); + + } + // remove from incomplete types map + ::System::String * cts_name = type_builder->get_FullName(); + m_incomplete_services->Remove( cts_name ); + xServiceType->release(); + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting service type {0}", cts_name ); + } + return type_builder->CreateType(); +} + + +Emit::CustomAttributeBuilder* TypeEmitter::get_service_exception_attribute( + const Reference<reflection::XServiceConstructorDescription> & ctorDes ) +{ + return get_exception_attribute(ctorDes->getExceptions()); +} + +Emit::CustomAttributeBuilder* TypeEmitter::get_iface_method_exception_attribute( + const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod ) +{ + + const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions(); + int len = seqTD.getLength(); + Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len); + Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray(); + for (int i = 0; i < len; i++) + arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW); + return get_exception_attribute(seqCTD); +} + +Emit::CustomAttributeBuilder* TypeEmitter::get_exception_attribute( + + const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd ) +{ + Emit::CustomAttributeBuilder * attr_builder = NULL; + + Reference< reflection::XCompoundTypeDescription > const * exceptions = + seq_exceptionsTd.getConstArray(); + + ::System::Type * arTypesCtor[] = {::System::Type::GetType(S"System.Type[]")}; + ConstructorInfo * ctor_ExceptionAttribute = + __typeof(::uno::ExceptionAttribute)->GetConstructor(arTypesCtor); + + sal_Int32 exc_length = seq_exceptionsTd.getLength(); + if (exc_length != 0) // opt + { + ::System::Type * exception_types [] = + new ::System::Type * [ exc_length ]; + for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos ) + { + Reference< reflection::XCompoundTypeDescription > const & xExc = + exceptions[ exc_pos ]; + exception_types[ exc_pos ] = get_type( xExc ); + } + ::System::Object * args [] = {exception_types}; + attr_builder = new Emit::CustomAttributeBuilder( + ctor_ExceptionAttribute, args ); + } + return attr_builder; +} + + +::System::Type * TypeEmitter::complete_singleton_type(singleton_entry * entry) +{ + Emit::TypeBuilder * type_builder = entry->m_type_builder; + reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType; + ::System::String* sSingletonName = to_cts_name(xSingletonType->getName()); + + //Create the private default constructor + Emit::ConstructorBuilder* ctor_builder = + type_builder->DefineConstructor( + static_cast<MethodAttributes>(MethodAttributes::Private | + MethodAttributes::HideBySig | + MethodAttributes::SpecialName | + MethodAttributes::RTSpecialName), + CallingConventions::Standard, NULL); + + Emit::ILGenerator* ilGen = ctor_builder->GetILGenerator(); + ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this + ilGen->Emit( + Emit::OpCodes::Call, + type_builder->BaseType->GetConstructor(new ::System::Type*[0])); + ilGen->Emit( Emit::OpCodes::Ret ); + + + //obtain the interface which makes up this service, it is the return + //type of the constructor functions + Reference<reflection::XInterfaceTypeDescription2> xIfaceType( + xSingletonType->getInterface(), UNO_QUERY); + if (xIfaceType.is () == sal_False) + xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface()); + System::Type * retType = get_type(xIfaceType); + + //define method + ::System::Type * arTypeParameters[] = {get_type(S"unoidl.com.sun.star.uno.XComponentContext", true)}; + Emit::MethodBuilder* method_builder = type_builder->DefineMethod( + new System::String(S"get"), + static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig | + MethodAttributes::Static), + retType, + arTypeParameters); + + +// method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes)); + + //The first parameter is the XComponentContext, which cannot be obtained + //from reflection. + //The context is not part of the idl description + method_builder->DefineParameter(1, ParameterAttributes::In, S"the_context"); + + + ilGen = method_builder->GetILGenerator(); + //Define locals --------------------------------- + // Any, returned by XComponentContext.getValueByName + Emit::LocalBuilder* local_any = + ilGen->DeclareLocal(__typeof(::uno::Any)); + + //Call XContext::getValueByName + ilGen->Emit(Emit::OpCodes::Ldarg_0); + // build the singleton name : /singleton/unoidl.com.sun.star.XXX + ::System::Text::StringBuilder* sBuilder = + new ::System::Text::StringBuilder(S"/singletons/"); + sBuilder->Append(sSingletonName); + ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString()); + + ::System::Reflection::MethodInfo * methodGetValueByName = + get_type(S"unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod(S"getValueByName"); + ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName); + ilGen->Emit(Emit::OpCodes::Stloc_0); + + //Contains the returned Any a value? + ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any); + ::System::Reflection::MethodInfo * methodHasValue = + __typeof(::uno::Any)->GetMethod(S"hasValue"); + ilGen->Emit(Emit::OpCodes::Call, methodHasValue); + + //If not, then throw an DeploymentException + Emit::Label label_singleton_exists = ilGen->DefineLabel(); + ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists); + sBuilder = new ::System::Text::StringBuilder( + S"Component context fails to supply singleton "); + sBuilder->Append(sSingletonName); + sBuilder->Append(S" of type "); + sBuilder->Append(retType->FullName); + sBuilder->Append(S"."); + ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString()); + ilGen->Emit(Emit::OpCodes::Ldarg_0); + ::System::Type * arTypesCtorDeploymentException[] = { + __typeof(::System::String), __typeof(::System::Object)}; + ilGen->Emit(Emit::OpCodes::Newobj, + get_type(S"unoidl.com.sun.star.uno.DeploymentException",true) + ->GetConstructor(arTypesCtorDeploymentException)); + ilGen->Emit(Emit::OpCodes::Throw); + ilGen->MarkLabel(label_singleton_exists); + + //Cast the singleton contained in the Any to the expected interface and return it. + ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any); + ilGen->Emit(Emit::OpCodes::Call, __typeof(::uno::Any)->GetProperty(S"Value")->GetGetMethod()); + ilGen->Emit(Emit::OpCodes::Castclass, retType); + ilGen->Emit(Emit::OpCodes::Ret); + + // remove from incomplete types map + ::System::String * cts_name = type_builder->get_FullName(); + m_incomplete_singletons->Remove( cts_name ); + xSingletonType->release(); + if (g_verbose) + { + ::System::Console::WriteLine( + "> emitting singleton type {0}", cts_name ); + } + return type_builder->CreateType(); +} + + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_type( + Reference< reflection::XTypeDescription > const & xType ) +{ + switch (xType->getTypeClass()) + { + case TypeClass_VOID: + return __typeof (::System::Void); + case TypeClass_CHAR: + return __typeof (::System::Char); + case TypeClass_BOOLEAN: + return __typeof (::System::Boolean); + case TypeClass_BYTE: + return __typeof (::System::Byte); + case TypeClass_SHORT: + return __typeof (::System::Int16); + case TypeClass_UNSIGNED_SHORT: + return __typeof (::System::UInt16); + case TypeClass_LONG: + return __typeof (::System::Int32); + case TypeClass_UNSIGNED_LONG: + return __typeof (::System::UInt32); + case TypeClass_HYPER: + return __typeof (::System::Int64); + case TypeClass_UNSIGNED_HYPER: + return __typeof (::System::UInt64); + case TypeClass_FLOAT: + return __typeof (::System::Single); + case TypeClass_DOUBLE: + return __typeof (::System::Double); + case TypeClass_STRING: + return __typeof (::System::String); + case TypeClass_TYPE: + return __typeof (::System::Type); + case TypeClass_ANY: + return __typeof(::uno::Any); + case TypeClass_ENUM: + return get_type( Reference< reflection::XEnumTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_TYPEDEF: + // unwind typedefs + return get_type( + Reference< reflection::XIndirectTypeDescription >( + xType, UNO_QUERY_THROW )->getReferencedType() ); + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + return get_type( + Reference< reflection::XCompoundTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_SEQUENCE: + { + ::System::Type * element_type = get_type( + Reference< reflection::XIndirectTypeDescription >( + xType, UNO_QUERY_THROW )->getReferencedType() ); + ::System::Type * retType = get_type( + ::System::String::Concat( + element_type->get_FullName(), S"[]" ), true ); + + ::uno::PolymorphicType * pt = dynamic_cast< ::uno::PolymorphicType * >(element_type); + if (pt) + { + ::System::String * sName = ::System::String::Concat(pt->PolymorphicName, S"[]"); + retType = ::uno::PolymorphicType::GetType(retType, sName); + } + return retType; + } + case TypeClass_INTERFACE: + return get_type( + Reference< reflection::XInterfaceTypeDescription2 >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_CONSTANT: + return get_type( + Reference< reflection::XConstantTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_CONSTANTS: + return get_type( + Reference< reflection::XConstantsTypeDescription >( + xType, UNO_QUERY_THROW ) ); + case TypeClass_SERVICE: + return get_type( + Reference< reflection::XServiceTypeDescription2 >( + xType, UNO_QUERY_THROW) ); + case TypeClass_SINGLETON: + return get_type( + Reference< reflection::XSingletonTypeDescription2 >( + xType, UNO_QUERY_THROW) ); + case TypeClass_MODULE: + // ignore these + return 0; + default: + throw RuntimeException( + OUSTR("unexpected type ") + xType->getName(), + Reference< XInterface >() ); + } +} + +//______________________________________________________________________________ +::System::Type * TypeEmitter::get_complete_struct( ::System::String * sName) +{ + struct_entry * pStruct = __try_cast< struct_entry *>( + m_incomplete_structs->get_Item(sName)); + if (pStruct) + { + complete_struct_type(pStruct); + } + //get_type will asked the module builder for the type or otherwise all known assemblies. + return get_type(sName, true); +} +void TypeEmitter::Dispose() +{ + while (true) + { + ::System::Collections::IDictionaryEnumerator * enumerator = + m_incomplete_ifaces->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_iface_type( + __try_cast< iface_entry * >( enumerator->get_Value() ) ); + } + + while (true) + { + ::System::Collections::IDictionaryEnumerator * enumerator = + m_incomplete_structs->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_struct_type( + __try_cast< struct_entry * >( enumerator->get_Value() ) ); + } + + + while (true) + { + ::System::Collections::IDictionaryEnumerator * enumerator = + m_incomplete_services->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_service_type( + __try_cast< service_entry * >( enumerator->get_Value() ) ); + } + + while (true) + { + ::System::Collections::IDictionaryEnumerator * enumerator = + m_incomplete_singletons->GetEnumerator(); + if (! enumerator->MoveNext()) + break; + complete_singleton_type( + __try_cast< singleton_entry * >( enumerator->get_Value() ) ); + } +} +//______________________________________________________________________________ +TypeEmitter::TypeEmitter( + ::System::Reflection::Emit::ModuleBuilder * module_builder, + ::System::Reflection::Assembly * extra_assemblies [] ) + : m_module_builder( module_builder ), + m_extra_assemblies( extra_assemblies ), + m_method_info_Type_GetTypeFromHandle( 0 ), + m_type_Exception( 0 ), + m_type_RuntimeException( 0 ), + m_incomplete_ifaces( new ::System::Collections::Hashtable() ), + m_incomplete_structs( new ::System::Collections::Hashtable() ), + m_incomplete_services(new ::System::Collections::Hashtable() ), + m_incomplete_singletons(new ::System::Collections::Hashtable() ), + m_generated_structs( new ::System::Collections::Hashtable() ) +{ + ::System::Type * param_types[] = new ::System::Type * [ 1 ]; + param_types[ 0 ] = __typeof (::System::RuntimeTypeHandle); + m_method_info_Type_GetTypeFromHandle = + __typeof (::System::Type) + ->GetMethod( "GetTypeFromHandle", param_types ); +} + +::System::Collections::ArrayList * TypeEmitter::get_service_ctor_method_exceptions_reduced( + const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd) +{ + if (seqExceptionsTd.getLength() == 0) + return new ::System::Collections::ArrayList(); + + ::System::Collections::ArrayList * arTypes = new ::System::Collections::ArrayList(); + for (int i = 0; i < seqExceptionsTd.getLength(); i++) + arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true)); + + int start = 0; + while (true) + { + bool bRemove = false; + for (int i = start; i < arTypes->Count; i++) + { + ::System::Type * t = __try_cast< ::System::Type* >(arTypes->get_Item(i)); + for (int j = 0; j < arTypes->Count; j++) + { + if (t->IsSubclassOf(__try_cast< ::System::Type* >(arTypes->get_Item(j)))) + { + arTypes->RemoveAt(i); + bRemove = true; + break; + } + } + if (bRemove) + break; + start++; + } + + if (bRemove == false) + break; + } + return arTypes; +} + + +css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > +resolveInterfaceTypedef( + const css::uno::Reference<css::reflection::XTypeDescription>& type) +{ + Reference<reflection::XInterfaceTypeDescription2> + xIfaceTd(type, UNO_QUERY); + + if (xIfaceTd.is()) + return xIfaceTd; + + Reference<reflection::XIndirectTypeDescription> xIndTd( + type, UNO_QUERY); + if (xIndTd.is() == sal_False) + throw css::uno::Exception( + OUSTR("resolveInterfaceTypedef was called with an invalid argument"), 0); + + return resolveInterfaceTypedef(xIndTd->getReferencedType()); +} + + +} diff --git a/cli_ure/source/climaker/climaker_share.h b/cli_ure/source/climaker/climaker_share.h new file mode 100644 index 000000000000..c663f007015b --- /dev/null +++ b/cli_ure/source/climaker/climaker_share.h @@ -0,0 +1,268 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#using <mscorlib.dll> +#using <cli_basetypes.dll> + +#include <vcclr.h> + +#include "osl/diagnose.h" +#include "com/sun/star/reflection/XConstantTypeDescription.hpp" +#include "com/sun/star/reflection/XConstantsTypeDescription.hpp" +#include "com/sun/star/reflection/XEnumTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XCompoundTypeDescription.hpp" +#include "com/sun/star/reflection/XServiceTypeDescription2.hpp" +#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +namespace css = ::com::sun::star; + +namespace climaker +{ + +//------------------------------------------------------------------------------ +extern bool g_verbose; + +__gc struct Constants +{ + static const ::System::String * sUnoVoid = S"void"; + static const ::System::String * sUnoType = S"type"; + static const ::System::String * sUnoAny = S"any"; + static const ::System::String * sUnoBool = S"boolean"; + static const ::System::String * sUnoByte = S"byte"; + static const ::System::String * sUnoChar = S"char"; + static const ::System::String * sUnoShort = S"short"; + static const ::System::String * sUnoUShort = S"unsigned short"; + static const ::System::String * sUnoLong = S"long"; + static const ::System::String * sUnoULong = S"unsigned long"; + static const ::System::String * sUnoHyper = S"hyper"; + static const ::System::String * sUnoUHyper = S"unsigned hyper"; + static const ::System::String * sUnoString = S"string"; + static const ::System::String * sUnoFloat = S"float"; + static const ::System::String * sUnoDouble = S"double"; + static const ::System::String * sUnoXInterface = S"com.sun.star.uno.XInterface"; + static const ::System::String * sBrackets = S"[]"; + + static const System::String* sObject = S"System.Object"; + static const System::String* sType = S"System.Type"; + static const System::String* sUnoidl = S"unoidl."; + static const System::String* sVoid = S"System.Void"; + static const System::String* sAny = S"uno.Any"; + static const System::String* sBoolean = S"System.Boolean"; + static const System::String* sChar = S"System.Char"; + static const System::String* sByte = S"System.Byte"; + static const System::String* sInt16 = S"System.Int16"; + static const System::String* sUInt16 = S"System.UInt16"; + static const System::String* sInt32 = S"System.Int32"; + static const System::String* sUInt32 = S"System.UInt32"; + static const System::String* sInt64 = S"System.Int64"; + static const System::String* sUInt64 = S"System.UInt64"; + static const System::String* sString = S"System.String"; + static const System::String* sSingle = S"System.Single"; + static const System::String* sDouble = S"System.Double"; + static const System::String* sComma = new System::String(S","); + +}; + +//------------------------------------------------------------------------------ +inline ::System::String * ustring_to_String( ::rtl::OUString const & ustr ) +{ + return new ::System::String( ustr.getStr(), 0, ustr.getLength() ); +} + +//------------------------------------------------------------------------------ +inline ::rtl::OUString String_to_ustring( ::System::String * str ) +{ + OSL_ASSERT( sizeof (wchar_t) == sizeof (sal_Unicode) ); + wchar_t const __pin * chars = PtrToStringChars( str ); + return ::rtl::OUString( chars, str->get_Length() ); +} + +/* If the argument type is a typedef for an interface then the interface + type description is returned, otherwise an exeption is thrown. +*/ +css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > +resolveInterfaceTypedef(const css::uno::Reference<css::reflection::XTypeDescription>& type); + +const ::System::Reflection::MethodAttributes c_ctor_method_attr = +(::System::Reflection::MethodAttributes) + (::System::Reflection::MethodAttributes::Public | + ::System::Reflection::MethodAttributes::HideBySig | + ::System::Reflection::MethodAttributes::SpecialName | + ::System::Reflection::MethodAttributes::RTSpecialName + /* | xxx todo: ??? compiler does not know Instance ??? + ::System::Reflection::MethodAttributes::Instance*/); + +//============================================================================== +__gc class TypeEmitter : public ::System::IDisposable +{ + ::System::Reflection::Emit::ModuleBuilder * m_module_builder; + ::System::Reflection::Assembly * m_extra_assemblies __gc []; + + ::System::Reflection::MethodInfo * m_method_info_Type_GetTypeFromHandle; + + ::System::Type * m_type_Exception; + ::System::Type * get_type_Exception(); + ::System::Type * m_type_RuntimeException; + ::System::Type * get_type_RuntimeException(); + + ::System::Reflection::Emit::CustomAttributeBuilder* get_service_exception_attribute( + const css::uno::Reference<css::reflection::XServiceConstructorDescription> & ctorDesc); + ::System::Reflection::Emit::CustomAttributeBuilder* get_iface_method_exception_attribute( + const css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription >& xMethod ); + ::System::Reflection::Emit::CustomAttributeBuilder* get_exception_attribute( + const css::uno::Sequence<css::uno::Reference< + css::reflection::XCompoundTypeDescription > >& seq_exceptionsTd ); +/* Creates ::System::Type object for UNO exceptions. The UNO exceptions are + obtained by + com::sun::star::reflection::XServiceConstructorDescription::getExceptions + In a first step the respective CLI types are created. Then it is examined + if a Type represents a super class of another class. If so the Type of the + derived class is discarded. For example there are a uno RuntimeException and + a DeploymentException which inherits RuntimeException. Then only the cli Type + of the RuntimeException is returned. + The purpose of this function is to provide exceptions for which catch blocks + are generated in the service constructor code. + + It is always an instance of an ArrayList returned, even if the sequence argument + does not contain elements. + */ + ::System::Collections::ArrayList * get_service_ctor_method_exceptions_reduced( + const css::uno::Sequence< + css::uno::Reference<css::reflection::XCompoundTypeDescription> > & seqExceptionsTd); + + + __gc class iface_entry + { + public: + css::reflection::XInterfaceTypeDescription2 * m_xType; + ::System::Reflection::Emit::TypeBuilder * m_type_builder; + }; + ::System::Collections::Hashtable * m_incomplete_ifaces; + ::System::Type * complete_iface_type( iface_entry * entry ); + + __gc class struct_entry + { + public: + css::reflection::XCompoundTypeDescription * m_xType; + ::System::Reflection::Emit::TypeBuilder * m_type_builder; + ::System::Type * m_base_type; + + ::System::String * m_member_names __gc []; + ::System::Type * m_param_types __gc []; + ::System::Reflection::ConstructorInfo * m_default_ctor; + ::System::Reflection::ConstructorInfo * m_ctor; + }; + ::System::Collections::Hashtable * m_incomplete_structs; + ::System::Type * complete_struct_type( struct_entry * entry ); + + /* returns the type for the name. If it is a struct then it may + complete the struct if not already done. This also refers to its + base types. + + @param sName + the full name of the type. + @return the type object for sName. Not necessarily a struct. + */ + ::System::Type * get_complete_struct( ::System::String * sName); + + __gc class service_entry + { + public: + ::System::Reflection::Emit::TypeBuilder * m_type_builder; + css::reflection::XServiceTypeDescription2 * m_xType; + }; + ::System::Collections::Hashtable * m_incomplete_services; + ::System::Type * complete_service_type(service_entry * entry); + + __gc class singleton_entry + { + public: + ::System::Reflection::Emit::TypeBuilder * m_type_builder; + css::reflection::XSingletonTypeDescription2 * m_xType; + }; + + + ::System::Collections::Hashtable * m_incomplete_singletons; + ::System::Type * complete_singleton_type(singleton_entry * entry); + + + ::System::Collections::Hashtable * m_generated_structs; + + ::System::Type * get_type( + ::System::String * cli_name, bool throw_exc ); + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XConstantTypeDescription > const & xType ); + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XConstantsTypeDescription > const & xType ); + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XEnumTypeDescription > const & xType ); + /* returns the type for a struct or exception. In case of a polymorphic struct it may + return a ::uno::PolymorphicType (cli_basetypes.dll) only if the struct is already + complete. + */ + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XCompoundTypeDescription > const & xType ); + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XInterfaceTypeDescription2 > const & xType ); + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XSingletonTypeDescription2 > const & xType ); + + /* + May return NULL if the service description is an obsolete. See + description of + com.sun.star.reflection.XServiceTypeDescription2.isSingleInterfaceBased + */ + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XServiceTypeDescription2 > const & xType ); +public: + TypeEmitter( + ::System::Reflection::Emit::ModuleBuilder * module_builder, + ::System::Reflection::Assembly * assemblies __gc [] ); + // must be called to finish up uncompleted types + void Dispose(); + + ::System::Reflection::Assembly * type_resolve( + ::System::Object * sender, ::System::ResolveEventArgs * args ); + + ::System::Type * get_type( + css::uno::Reference< + css::reflection::XTypeDescription > const & xType ); +}; + +} diff --git a/cli_ure/source/climaker/makefile.mk b/cli_ure/source/climaker/makefile.mk new file mode 100644 index 000000000000..b001a1545fae --- /dev/null +++ b/cli_ure/source/climaker/makefile.mk @@ -0,0 +1,137 @@ +#************************************************************************* +# +# 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 = climaker +TARGETTYPE = CUI +LIBTARGET = NO +ENABLE_EXCEPTIONS = TRUE + +# disable caching to avoid stale objects +# on version changes +CCACHE_DISABLE=TRUE +.EXPORT : CCACHE_DISABLE + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +.IF "$(BUILD_FOR_CLI)" != "" + +NO_OFFUH=TRUE +CPPUMAKERFLAGS = + +UNOTYPES = \ + com.sun.star.uno.TypeClass \ + com.sun.star.uno.XAggregation \ + com.sun.star.uno.XWeak \ + com.sun.star.uno.XComponentContext \ + com.sun.star.lang.XTypeProvider \ + com.sun.star.lang.XInitialization \ + com.sun.star.lang.XComponent \ + com.sun.star.lang.XMultiComponentFactory \ + com.sun.star.lang.XMultiServiceFactory \ + com.sun.star.lang.XSingleComponentFactory \ + com.sun.star.container.XSet \ + com.sun.star.container.XHierarchicalNameAccess \ + com.sun.star.loader.XImplementationLoader \ + com.sun.star.registry.XSimpleRegistry \ + com.sun.star.registry.XRegistryKey \ + com.sun.star.reflection.XTypeDescriptionEnumerationAccess \ + com.sun.star.reflection.XConstantTypeDescription \ + com.sun.star.reflection.XConstantsTypeDescription \ + com.sun.star.reflection.XIndirectTypeDescription \ + com.sun.star.reflection.XEnumTypeDescription \ + com.sun.star.reflection.XInterfaceTypeDescription2 \ + com.sun.star.reflection.XInterfaceMethodTypeDescription \ + com.sun.star.reflection.XInterfaceAttributeTypeDescription2 \ + com.sun.star.reflection.XCompoundTypeDescription \ + com.sun.star.reflection.XServiceTypeDescription2 \ + com.sun.star.reflection.XSingletonTypeDescription2 \ + com.sun.star.reflection.XStructTypeDescription + +CFLAGSCXX +=-AI$(BIN) + + +# 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 "$(COMEX)"=="10" +CFLAGSCXX += -clr:noAssembly -wd4339 +.ELSE +CFLAGSCXX += -clr:oldSyntax -LN -wd4339 -wd4715 +.ENDIF + +OBJFILES = \ + $(OBJ)$/climaker_app.obj \ + $(OBJ)$/climaker_emit.obj + +APP1TARGET = $(TARGET) +APP1OBJS = $(OBJFILES) + + +APP1STDLIBS = \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + mscoree.lib + +.IF "$(CCNUMVER)" >= "001399999999" +APP1STDLIBS += \ + msvcmrt.lib +.ENDIF + +.ENDIF + + + +.INCLUDE : $(PRJ)$/util$/target.pmk +.INCLUDE : target.mk + +CLIMAKER_CONFIG = $(BIN)$/climaker.exe.config + +ALLTAR: \ + $(CLIMAKER_CONFIG) + + + +#Create the config file that is used with the policy assembly +$(CLIMAKER_CONFIG): climaker.exe.config + $(COPY) $< $@ + chmod +x $@ + + +.IF "$(BUILD_FOR_CLI)" != "" + +$(OBJFILES): $(BIN)$/cli_basetypes.dll + + +.ENDIF + + + + |