/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the 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 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(Constants::sUnoBool))) buf->Append(const_cast(Constants::sBoolean)); else if (sUnoName->Equals(const_cast(Constants::sUnoChar))) buf->Append(const_cast(Constants::sChar)); else if (sUnoName->Equals(const_cast(Constants::sUnoByte))) buf->Append(const_cast(Constants::sByte)); else if (sUnoName->Equals(const_cast(Constants::sUnoShort))) buf->Append(const_cast(Constants::sInt16)); else if (sUnoName->Equals(const_cast(Constants::sUnoUShort))) buf->Append(const_cast(Constants::sUInt16)); else if (sUnoName->Equals(const_cast(Constants::sUnoLong))) buf->Append(const_cast(Constants::sInt32)); else if (sUnoName->Equals(const_cast(Constants::sUnoULong))) buf->Append(const_cast(Constants::sUInt32)); else if (sUnoName->Equals(const_cast(Constants::sUnoHyper))) buf->Append(const_cast(Constants::sInt64)); else if (sUnoName->Equals(const_cast(Constants::sUnoUHyper))) buf->Append(const_cast(Constants::sUInt64)); else if (sUnoName->Equals(const_cast(Constants::sUnoFloat))) buf->Append(const_cast(Constants::sSingle)); else if (sUnoName->Equals(const_cast(Constants::sUnoDouble))) buf->Append(const_cast(Constants::sDouble)); else if (sUnoName->Equals(const_cast(Constants::sUnoString))) buf->Append(const_cast(Constants::sString)); else if (sUnoName->Equals(const_cast(Constants::sUnoVoid))) buf->Append(const_cast(Constants::sVoid)); else if (sUnoName->Equals(const_cast(Constants::sUnoType))) buf->Append(const_cast(Constants::sType)); else if (sUnoName->Equals(const_cast(Constants::sUnoXInterface))) buf->Append(const_cast(Constants::sObject)); else if (sUnoName->Equals(const_cast(Constants::sUnoAny))) { buf->Append(const_cast(Constants::sAny)); } else { //put "unoidl." at the beginning buf->Append(const_cast(Constants::sUnoidl)); buf->Append(mapUnoPolymorphicName(sUnoName)); } // apend [] for (;dims--;) buf->Append(const_cast(Constants::sBrackets)); return buf->ToString(); } /** For example, there is a uno type com.sun.star.Foo. 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> */ 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 arg); //PolyStruct 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 > vecBaseTypes; Sequence > seqBaseTypes = xType->getBaseTypes(); if (seqBaseTypes.getLength() > 0) { for (int i = 0; i < seqBaseTypes.getLength(); i++) { Reference 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 >::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 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::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 > 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 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 xReturnStruct( xMethod->getReturnType(), UNO_QUERY); if (xReturnStruct.is()) { Sequence > 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 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 > 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 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 > 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 & ctorDes = seqCtors[i]; //obtain the parameter types Sequence > seqParams = ctorDes->getParameters(); Reference 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::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 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 & ctorDes ) { return get_exception_attribute(ctorDes->getExceptions()); } Emit::CustomAttributeBuilder* TypeEmitter::get_iface_method_exception_attribute( const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod ) { const Sequence > seqTD = xMethod->getExceptions(); int len = seqTD.getLength(); Sequence > seqCTD(len); Reference * arCTD = seqCTD.getArray(); for (int i = 0; i < len; i++) arCTD[i] = Reference(seqTD[i], UNO_QUERY_THROW); return get_exception_attribute(seqCTD); } Emit::CustomAttributeBuilder* TypeEmitter::get_exception_attribute( const Sequence >& 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::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 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::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 > & 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& type) { Reference xIfaceTd(type, UNO_QUERY); if (xIfaceTd.is()) return xIfaceTd; Reference 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()); } }