1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cli_ure.hxx" 26 27 #include <stdio.h> 28 #include <vector> 29 #include <memory> 30 31 #include "climaker_share.h" 32 33 #include "sal/main.h" 34 #include "osl/process.h" 35 #include "osl/file.hxx" 36 #include "osl/thread.h" 37 #include "rtl/ustrbuf.hxx" 38 #include "cppuhelper/shlib.hxx" 39 #include "cppuhelper/bootstrap.hxx" 40 #include "com/sun/star/lang/XInitialization.hpp" 41 #include "com/sun/star/lang/XSingleComponentFactory.hpp" 42 #include "com/sun/star/lang/XComponent.hpp" 43 #include "com/sun/star/container/XHierarchicalNameAccess.hpp" 44 #include "com/sun/star/container/XSet.hpp" 45 #include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp" 46 #include "com/sun/star/registry/XSimpleRegistry.hpp" 47 48 using namespace ::std; 49 using namespace ::System::Reflection; 50 51 52 using namespace ::rtl; 53 using namespace ::osl; 54 using namespace ::com::sun::star; 55 using namespace ::com::sun::star::uno; 56 57 namespace climaker 58 { 59 60 //------------------------------------------------------------------------------ 61 static char const s_usingText [] = 62 "\n" 63 "using: climaker <switches> [registry-file-1 registry-file-2 ...]\n" 64 "\n" 65 "switches:\n" 66 " -O, --out <output-file> output assembly file;\n" 67 " defaults to cli_unotypes.dll if more than one\n" 68 " registry-file is given, else <registry-file>.dll\n" 69 " -T, --types types to be generated (if none is given,\n" 70 " <type1[;type2;...]> then all types of given registries are emitted\n" 71 " -X, --extra <rdb-file> additional rdb to saturate referenced types in\n" 72 " given registry file(s); these types will not be\n" 73 " emitted into the output assembly file\n" 74 " -r, --reference reference metadata from assembly file\n" 75 " <assembly-file>\n" 76 " -k, --keyfile keyfile needed for strong name\n" 77 " --assembly-version <version> sets assembly version\n" 78 " --assembly-description <text> sets assembly description text\n" 79 " --assembly-product <text> sets assembly product name\n" 80 " --assembly-company <text> sets assembly company\n" 81 " --assembly-copyright <text> sets assembly copyright\n" 82 " --assembly-trademark <text> sets assembly trademark\n" 83 " -v, --verbose verbose output to stdout\n" 84 " -h, --help this message\n" 85 "\n" 86 "example: climaker --out cli_mytypes.dll \\\n" 87 " --reference cli_uretypes.dll \\\n" 88 " --extra types.rdb \\\n" 89 " mytypes.rdb\n" 90 "\n"; 91 92 struct OptionInfo 93 { 94 char const * m_name; 95 sal_uInt32 m_name_length; 96 sal_Unicode m_short_option; 97 bool m_has_argument; 98 }; 99 100 bool g_verbose = false; 101 102 //------------------------------------------------------------------------------ 103 static const OptionInfo s_option_infos [] = { 104 { RTL_CONSTASCII_STRINGPARAM("out"), 'O', true }, 105 { RTL_CONSTASCII_STRINGPARAM("types"), 'T', true }, 106 { RTL_CONSTASCII_STRINGPARAM("extra"), 'X', true }, 107 { RTL_CONSTASCII_STRINGPARAM("reference"), 'r', true }, 108 { RTL_CONSTASCII_STRINGPARAM("keyfile"), 'k', true }, 109 { RTL_CONSTASCII_STRINGPARAM("delaySign"), 'd', true }, 110 { RTL_CONSTASCII_STRINGPARAM("assembly-version"), '\0', true }, 111 { RTL_CONSTASCII_STRINGPARAM("assembly-description"), '\0', true }, 112 { RTL_CONSTASCII_STRINGPARAM("assembly-product"), '\0', true }, 113 { RTL_CONSTASCII_STRINGPARAM("assembly-company"), '\0', true }, 114 { RTL_CONSTASCII_STRINGPARAM("assembly-copyright"), '\0', true }, 115 { RTL_CONSTASCII_STRINGPARAM("assembly-trademark"), '\0', true }, 116 { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false }, 117 { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false } 118 }; 119 120 //============================================================================== 121 static OptionInfo const * get_option_info( 122 OUString const & opt, sal_Unicode copt = '\0' ) 123 { 124 for ( sal_Int32 pos = 0; 125 pos < (sizeof (s_option_infos) / sizeof (OptionInfo)); 126 ++pos ) 127 { 128 OptionInfo const & option_info = s_option_infos[ pos ]; 129 130 if (opt.getLength() > 0) 131 { 132 if (opt.equalsAsciiL( 133 option_info.m_name, option_info.m_name_length ) && 134 (copt == '\0' || copt == option_info.m_short_option)) 135 { 136 return &option_info; 137 } 138 } 139 else 140 { 141 OSL_ASSERT( copt != '\0' ); 142 if (copt == option_info.m_short_option) 143 { 144 return &option_info; 145 } 146 } 147 } 148 OSL_ENSURE( 149 0, OUStringToOString( opt, osl_getThreadTextEncoding() ).getStr() ); 150 return 0; 151 } 152 153 //============================================================================== 154 static bool is_option( 155 OptionInfo const * option_info, sal_uInt32 * pIndex ) 156 { 157 OSL_ASSERT( option_info != 0 ); 158 if (osl_getCommandArgCount() <= *pIndex) 159 return false; 160 161 OUString arg; 162 osl_getCommandArg( *pIndex, &arg.pData ); 163 sal_Int32 len = arg.getLength(); 164 165 if (len < 2 || arg[ 0 ] != '-') 166 return false; 167 168 if (len == 2 && arg[ 1 ] == option_info->m_short_option) 169 { 170 ++(*pIndex); 171 #if OSL_DEBUG_LEVEL > 1 172 OSL_TRACE( 173 __FILE__": identified option \'%c\'", option_info->m_short_option ); 174 #endif 175 return true; 176 } 177 if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare( 178 arg.pData->buffer + 2, option_info->m_name ) == 0) 179 { 180 ++(*pIndex); 181 #if OSL_DEBUG_LEVEL > 1 182 OSL_TRACE( __FILE__": identified option \'%s\'", option_info->m_name ); 183 #endif 184 return true; 185 } 186 return false; 187 } 188 189 //============================================================================== 190 static inline bool read_option( 191 bool * flag, OptionInfo const * option_info, sal_uInt32 * pIndex ) 192 { 193 bool ret = is_option( option_info, pIndex ); 194 if (ret) 195 *flag = true; 196 return ret; 197 } 198 199 //============================================================================== 200 static bool read_argument( 201 OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex ) 202 { 203 if (is_option( option_info, pIndex )) 204 { 205 if (*pIndex < osl_getCommandArgCount()) 206 { 207 osl_getCommandArg( *pIndex, &pValue->pData ); 208 ++(*pIndex); 209 #if OSL_DEBUG_LEVEL > 1 210 OString cstr_val( 211 OUStringToOString( *pValue, osl_getThreadTextEncoding() ) ); 212 OSL_TRACE( __FILE__": argument value: %s\n", cstr_val.getStr() ); 213 #endif 214 return true; 215 } 216 --(*pIndex); 217 } 218 return false; 219 } 220 221 //============================================================================== 222 static OUString const & path_get_working_dir() 223 { 224 static OUString s_workingDir; 225 if (! s_workingDir.getLength()) 226 osl_getProcessWorkingDir( &s_workingDir.pData ); 227 return s_workingDir; 228 } 229 230 //============================================================================== 231 static OUString path_make_absolute_file_url( OUString const & path ) 232 { 233 OUString file_url; 234 oslFileError rc = osl_getFileURLFromSystemPath( 235 path.pData, &file_url.pData ); 236 if (osl_File_E_None == rc) 237 { 238 OUString abs; 239 rc = osl_getAbsoluteFileURL( 240 path_get_working_dir().pData, file_url.pData, &abs.pData ); 241 if (osl_File_E_None == rc) 242 { 243 return abs; 244 } 245 else 246 { 247 throw RuntimeException( 248 OUSTR("cannot make absolute: ") + file_url, 249 Reference< XInterface >() ); 250 } 251 } 252 else 253 { 254 throw RuntimeException( 255 OUSTR("cannot get file url from system path: ") + path, 256 Reference< XInterface >() ); 257 } 258 } 259 260 //============================================================================== 261 Reference< registry::XSimpleRegistry > open_registries( 262 vector< OUString > const & registries, 263 Reference< XComponentContext > xContext ) 264 { 265 if (registries.empty()) 266 { 267 throw RuntimeException( 268 OUSTR("no registries given!"), 269 Reference< XInterface >() ); 270 } 271 272 Reference< registry::XSimpleRegistry > xSimReg; 273 for ( size_t nPos = registries.size(); nPos--; ) 274 { 275 Reference< registry::XSimpleRegistry > xReg( 276 xContext->getServiceManager()->createInstanceWithContext( 277 OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ), 278 UNO_QUERY_THROW ); 279 xReg->open( registries[ nPos ], sal_True, sal_False ); 280 if (! xReg->isValid()) 281 { 282 throw RuntimeException( 283 OUSTR("invalid registry: ") + registries[ nPos ], 284 Reference< XInterface >() ); 285 } 286 287 if (xSimReg.is()) // nest? 288 { 289 Reference< registry::XSimpleRegistry > xNested( 290 xContext->getServiceManager()->createInstanceWithContext( 291 OUSTR("com.sun.star.registry.NestedRegistry"), xContext ), 292 UNO_QUERY_THROW ); 293 Reference< lang::XInitialization > xInit( 294 xNested, UNO_QUERY_THROW ); 295 Sequence< Any > args( 2 ); 296 args[ 0 ] <<= xReg; 297 args[ 1 ] <<= xSimReg; 298 xInit->initialize( args ); 299 xSimReg = xNested; 300 } 301 else 302 { 303 xSimReg = xReg; 304 } 305 } 306 307 return xSimReg; 308 } 309 310 } 311 312 using namespace ::climaker; 313 314 //############################################################################## 315 SAL_IMPLEMENT_MAIN() 316 { 317 sal_uInt32 nCount = osl_getCommandArgCount(); 318 if (0 == nCount) 319 { 320 printf( s_usingText ); 321 return 0; 322 } 323 324 int ret = 0; 325 Reference< XComponentContext > xContext; 326 327 try 328 { 329 OptionInfo const * info_help = 330 get_option_info( OUSTR("help") ); 331 OptionInfo const * info_verbose = 332 get_option_info( OUSTR("verbose") ); 333 OptionInfo const * info_out = 334 get_option_info( OUSTR("out") ); 335 OptionInfo const * info_types = 336 get_option_info( OUSTR("types") ); 337 OptionInfo const * info_reference = 338 get_option_info( OUSTR("reference") ); 339 OptionInfo const * info_extra = 340 get_option_info( OUSTR("extra") ); 341 OptionInfo const * info_keyfile = 342 get_option_info( OUSTR("keyfile") ); 343 OptionInfo const * info_delaySign = 344 get_option_info( OUSTR("delaySign") ); 345 OptionInfo const * info_version = 346 get_option_info( OUSTR("assembly-version") ); 347 OptionInfo const * info_product = 348 get_option_info( OUSTR("assembly-product") ); 349 OptionInfo const * info_description = 350 get_option_info( OUSTR("assembly-description") ); 351 OptionInfo const * info_company = 352 get_option_info( OUSTR("assembly-company") ); 353 OptionInfo const * info_copyright = 354 get_option_info( OUSTR("assembly-copyright") ); 355 OptionInfo const * info_trademark = 356 get_option_info( OUSTR("assembly-trademark") ); 357 358 OUString output; 359 vector< OUString > mandatory_registries; 360 vector< OUString > extra_registries; 361 vector< OUString > extra_assemblies; 362 vector< OUString > explicit_types; 363 OUString version, product, description, company, copyright, trademark, 364 keyfile, delaySign; 365 366 OUString cmd_arg; 367 for ( sal_uInt32 nPos = 0; nPos < nCount; ) 368 { 369 // options 370 if (is_option( info_help, &nPos )) 371 { 372 printf( s_usingText ); 373 return 0; 374 } 375 else if (read_argument( &cmd_arg, info_types, &nPos )) 376 { 377 sal_Int32 index = 0; 378 do 379 { 380 explicit_types.push_back( 381 cmd_arg.getToken( 0, ';', index ) ); 382 } 383 while (index >= 0); 384 } 385 else if (read_argument( &cmd_arg, info_extra, &nPos )) 386 { 387 extra_registries.push_back( 388 path_make_absolute_file_url( cmd_arg ) ); 389 } 390 else if (read_argument( &cmd_arg, info_reference, &nPos )) 391 { 392 extra_assemblies.push_back( 393 path_make_absolute_file_url( cmd_arg ) ); 394 } 395 else if (!read_option( &g_verbose, info_verbose, &nPos ) && 396 !read_argument( &output, info_out, &nPos ) && 397 !read_argument( &version, info_version, &nPos ) && 398 !read_argument( &description, info_description, &nPos ) && 399 !read_argument( &product, info_product, &nPos ) && 400 !read_argument( &company, info_company, &nPos ) && 401 !read_argument( ©right, info_copyright, &nPos ) && 402 !read_argument( &trademark, info_trademark, &nPos ) && 403 !read_argument( &keyfile, info_keyfile, &nPos ) && 404 !read_argument( &delaySign, info_delaySign, &nPos )) 405 { 406 if ( osl_getCommandArg( nPos, &cmd_arg.pData ) != 407 osl_Process_E_None ) 408 { 409 OSL_ASSERT( false ); 410 } 411 ++nPos; 412 cmd_arg = cmd_arg.trim(); 413 if (cmd_arg.getLength() > 0) 414 { 415 if (cmd_arg[ 0 ] == '-') // is option 416 { 417 OptionInfo const * option_info = 0; 418 if (cmd_arg.getLength() > 2 && 419 cmd_arg[ 1 ] == '-') 420 { 421 // long option 422 option_info = get_option_info( 423 cmd_arg.copy( 2 ), '\0' ); 424 } 425 else if (cmd_arg.getLength() == 2 && 426 cmd_arg[ 1 ] != '-') 427 { 428 // short option 429 option_info = get_option_info( 430 OUString(), cmd_arg[ 1 ] ); 431 } 432 if (option_info == 0) 433 { 434 OUStringBuffer buf; 435 buf.appendAscii( 436 RTL_CONSTASCII_STRINGPARAM("unknown option ") ); 437 buf.append( cmd_arg ); 438 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 439 "! Use climaker --help " 440 "to print all options.") ); 441 throw RuntimeException( 442 buf.makeStringAndClear(), 443 Reference< XInterface >() ); 444 } 445 else 446 { 447 OSL_ENSURE( 0, "unhandled valid option?!" ); 448 if (option_info->m_has_argument) 449 ++nPos; 450 } 451 } 452 else 453 { 454 mandatory_registries.push_back( 455 path_make_absolute_file_url( cmd_arg ) ); 456 } 457 } 458 } 459 } 460 461 // bootstrap uno 462 xContext = ::cppu::bootstrap_InitialComponentContext( 463 Reference< registry::XSimpleRegistry >() ); 464 Reference< container::XHierarchicalNameAccess > xTDmgr( 465 xContext->getValueByName( 466 OUSTR("/singletons/com.sun.star.reflection." 467 "theTypeDescriptionManager") ), 468 UNO_QUERY_THROW ); 469 470 // get rdb tdprovider factory 471 Reference< lang::XSingleComponentFactory > xTDprov_factory( 472 ::cppu::loadSharedLibComponentFactory( 473 OUSTR("bootstrap.uno" SAL_DLLEXTENSION), OUString(), 474 OUSTR("com.sun.star.comp.stoc.RegistryTypeDescriptionProvider"), 475 Reference< lang::XMultiServiceFactory >( 476 xContext->getServiceManager(), UNO_QUERY ), 477 Reference< registry::XRegistryKey >() ), UNO_QUERY ); 478 if (! xTDprov_factory.is()) 479 { 480 throw RuntimeException( 481 OUSTR("cannot get registry typedescription provider: " 482 "bootstrap.uno" SAL_DLLEXTENSION "!"), 483 Reference< XInterface >() ); 484 } 485 486 // create registry td provider for mandatory registry files 487 Any arg( makeAny( open_registries( mandatory_registries, xContext ) ) ); 488 Reference< XInterface > xTD_provider( 489 xTDprov_factory->createInstanceWithArgumentsAndContext( 490 Sequence< Any >( &arg, 1 ), xContext ) ); 491 // insert provider to tdmgr 492 Reference< container::XSet > xSet( xTDmgr, UNO_QUERY_THROW ); 493 Any provider( makeAny( xTD_provider ) ); 494 xSet->insert( provider ); 495 OSL_ASSERT( xSet->has( provider ) ); 496 if (! extra_registries.empty()) 497 { 498 arg = makeAny( open_registries( extra_registries, xContext ) ); 499 provider = makeAny( 500 xTDprov_factory->createInstanceWithArgumentsAndContext( 501 Sequence< Any >( &arg, 1 ), xContext ) ); 502 xSet->insert( provider ); 503 OSL_ASSERT( xSet->has( provider ) ); 504 } 505 506 if (0 == output.getLength()) // no output file specified 507 { 508 // if only one rdb has been given, then take rdb name 509 if (1 == mandatory_registries.size()) 510 { 511 output = mandatory_registries[ 0 ]; 512 output = output.copy( output.lastIndexOf( '/' ) +1 ); 513 sal_Int32 dot = output.lastIndexOf( '.' ); 514 if (dot > 0) 515 output = output.copy( 0, dot ); 516 } 517 else 518 { 519 output = OUSTR("cli_unotypes"); 520 } 521 } 522 output = path_make_absolute_file_url( output ); 523 sal_Int32 slash = output.lastIndexOf( '/' ); 524 OUString sys_output_dir; 525 if (FileBase::E_None != FileBase::getSystemPathFromFileURL( 526 output.copy( 0, slash ), sys_output_dir )) 527 { 528 throw RuntimeException( 529 OUSTR("cannot get system path from file url ") + 530 output.copy( 0, slash ), 531 Reference< XInterface >() ); 532 } 533 OUString filename( output.copy( slash +1 ) ); 534 sal_Int32 dot = filename.lastIndexOf( '.' ); 535 OUString name( filename ); 536 if (dot < 0) // has no extension 537 filename += OUSTR(".dll"); 538 else 539 name = name.copy( 0, dot ); 540 ::System::String ^ output_dir = ustring_to_String( sys_output_dir ); 541 ::System::String ^ output_file = ustring_to_String( filename ); 542 543 //Get the key pair for making a strong name 544 StrongNameKeyPair ^ kp = nullptr; 545 if (keyfile.getLength() > 0) 546 { 547 ::System::String ^ sKeyFile = ustring_to_String(keyfile); 548 try { 549 System::IO::FileStream ^ fs = gcnew System::IO::FileStream( 550 sKeyFile, System::IO::FileMode::Open); 551 kp = gcnew StrongNameKeyPair(fs); 552 fs->Close(); 553 } 554 catch (System::IO::FileNotFoundException ^ ) 555 { 556 throw Exception(OUSTR("Could not find the keyfile. Verify the --keyfile argument!"), 0); 557 } 558 } 559 else 560 { 561 if (g_verbose) 562 { 563 ::System::Console::Write( 564 "> no key file specified. Cannot create strong name!\n"); 565 } 566 } 567 // setup assembly info: xxx todo set more? e.g. avoid strong versioning 568 AssemblyName ^ assembly_name = gcnew AssemblyName(); 569 assembly_name->CodeBase = output_dir; 570 // MC++ converted a const wchar_t* to String* implicitly; C++/CLI does 571 // not, so say what was always meant. 572 assembly_name->Name = ustring_to_String( name ); 573 if (kp != nullptr) 574 assembly_name->KeyPair = kp; 575 576 if (version.getLength() != 0) 577 { 578 assembly_name->Version = gcnew ::System::Version( ustring_to_String( version ) ); 579 } 580 581 // app domain 582 ::System::AppDomain ^ current_appdomain = 583 ::System::AppDomain::CurrentDomain; 584 // target assembly 585 Emit::AssemblyBuilder ^ assembly_builder = 586 current_appdomain->DefineDynamicAssembly( 587 assembly_name, Emit::AssemblyBuilderAccess::Save, output_dir ); 588 if (product.getLength() != 0) 589 { 590 cli::array< ::System::Type ^ > ^ params = gcnew cli::array< ::System::Type ^ >( 1 ); 591 cli::array< ::System::Object ^ > ^ args = gcnew cli::array< ::System::Object ^ >( 1 ); 592 params[ 0 ] = ::System::String::typeid; 593 args[ 0 ] = ustring_to_String( product ); 594 assembly_builder->SetCustomAttribute( 595 gcnew Emit::CustomAttributeBuilder( 596 AssemblyProductAttribute::typeid->GetConstructor( 597 params ), args ) ); 598 } 599 if (description.getLength() != 0) 600 { 601 cli::array< ::System::Type ^ > ^ params = gcnew cli::array< ::System::Type ^ >( 1 ); 602 cli::array< ::System::Object ^ > ^ args = gcnew cli::array< ::System::Object ^ >( 1 ); 603 params[ 0 ] = ::System::String::typeid; 604 args[ 0 ] = ustring_to_String( description ); 605 assembly_builder->SetCustomAttribute( 606 gcnew Emit::CustomAttributeBuilder( 607 AssemblyDescriptionAttribute::typeid->GetConstructor( 608 params ), args ) ); 609 } 610 if (company.getLength() != 0) 611 { 612 cli::array< ::System::Type ^ > ^ params = gcnew cli::array< ::System::Type ^ >( 1 ); 613 cli::array< ::System::Object ^ > ^ args = gcnew cli::array< ::System::Object ^ >( 1 ); 614 params[ 0 ] = ::System::String::typeid; 615 args[ 0 ] = ustring_to_String( company ); 616 assembly_builder->SetCustomAttribute( 617 gcnew Emit::CustomAttributeBuilder( 618 AssemblyCompanyAttribute::typeid->GetConstructor( 619 params ), args ) ); 620 } 621 if (copyright.getLength() != 0) 622 { 623 cli::array< ::System::Type ^ > ^ params = gcnew cli::array< ::System::Type ^ >( 1 ); 624 cli::array< ::System::Object ^ > ^ args = gcnew cli::array< ::System::Object ^ >( 1 ); 625 params[ 0 ] = ::System::String::typeid; 626 args[ 0 ] = ustring_to_String( copyright ); 627 assembly_builder->SetCustomAttribute( 628 gcnew Emit::CustomAttributeBuilder( 629 AssemblyCopyrightAttribute::typeid->GetConstructor( 630 params ), args ) ); 631 } 632 if (trademark.getLength() != 0) 633 { 634 cli::array< ::System::Type ^ > ^ params = gcnew cli::array< ::System::Type ^ >( 1 ); 635 cli::array< ::System::Object ^ > ^ args = gcnew cli::array< ::System::Object ^ >( 1 ); 636 params[ 0 ] = ::System::String::typeid; 637 args[ 0 ] = ustring_to_String( trademark ); 638 assembly_builder->SetCustomAttribute( 639 gcnew Emit::CustomAttributeBuilder( 640 AssemblyTrademarkAttribute::typeid->GetConstructor( 641 params ), args ) ); 642 } 643 644 // load extra assemblies 645 cli::array< Assembly ^ > ^ assemblies = 646 gcnew cli::array< Assembly ^ >( extra_assemblies.size() ); 647 for ( size_t pos = 0; pos < extra_assemblies.size(); ++pos ) 648 { 649 assemblies[ pos ] = Assembly::LoadFrom( 650 ustring_to_String( extra_assemblies[ pos ] ) ); 651 } 652 653 // type emitter 654 TypeEmitter ^ type_emitter = gcnew TypeEmitter( 655 assembly_builder->DefineDynamicModule( output_file ), assemblies ); 656 // add handler resolving assembly's types 657 ::System::ResolveEventHandler ^ type_resolver = 658 gcnew ::System::ResolveEventHandler( 659 type_emitter, &TypeEmitter::type_resolve ); 660 // C++/CLI subscribes to an event with += rather than add_X(). 661 current_appdomain->TypeResolve += type_resolver; 662 663 // and emit types to it 664 if (explicit_types.empty()) 665 { 666 Reference< reflection::XTypeDescriptionEnumeration > xTD_enum( 667 Reference< reflection::XTypeDescriptionEnumerationAccess >( 668 xTD_provider, UNO_QUERY_THROW ) 669 ->createTypeDescriptionEnumeration( 670 OUString() /* all IDL modules */, 671 Sequence< TypeClass >() /* all classes of types */, 672 reflection::TypeDescriptionSearchDepth_INFINITE ) ); 673 while (xTD_enum->hasMoreElements()) 674 { 675 type_emitter->get_type( xTD_enum->nextTypeDescription() ); 676 } 677 } 678 else 679 { 680 Reference< container::XHierarchicalNameAccess > xHNA( 681 xTD_provider, UNO_QUERY_THROW ); 682 for ( size_t nPos = explicit_types.size(); nPos--; ) 683 { 684 type_emitter->get_type( 685 Reference< reflection::XTypeDescription >( 686 xHNA->getByHierarchicalName( explicit_types[ nPos ] ), 687 UNO_QUERY_THROW ) ); 688 } 689 } 690 // Dispose() is the destructor now, and delete is how it is called. 691 delete type_emitter; 692 693 if (g_verbose) 694 { 695 ::System::Console::Write( 696 "> saving assembly {0}{1}{2}...", 697 output_dir, 698 gcnew ::System::String( 699 ::System::IO::Path::DirectorySeparatorChar, 1 ), 700 output_file ); 701 } 702 assembly_builder->Save( output_file ); 703 if (g_verbose) 704 { 705 ::System::Console::WriteLine( "ok." ); 706 } 707 current_appdomain->TypeResolve -= type_resolver; 708 } 709 catch (Exception & exc) 710 { 711 OString msg( 712 OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) ); 713 fprintf( 714 stderr, "\n> error: %s\n> dying abnormally...\n", msg.getStr() ); 715 ret = 1; 716 } 717 catch (::System::Exception ^ exc) 718 { 719 OString msg( OUStringToOString( 720 String_to_ustring( exc->ToString() ), 721 osl_getThreadTextEncoding() ) ); 722 fprintf( 723 stderr, 724 "\n> error: .NET exception occurred: %s\n> dying abnormally...", 725 msg.getStr() ); 726 ret = 1; 727 } 728 729 try 730 { 731 Reference< lang::XComponent > xComp( xContext, UNO_QUERY ); 732 if (xComp.is()) 733 xComp->dispose(); 734 } 735 catch (Exception & exc) 736 { 737 OString msg( 738 OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) ); 739 fprintf( 740 stderr, 741 "\n> error disposing component context: %s\n" 742 "> dying abnormally...\n", 743 msg.getStr() ); 744 ret = 1; 745 } 746 747 return ret; 748 } 749