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 //==============================================================================
get_option_info(OUString const & opt,sal_Unicode copt='\\0')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 //==============================================================================
is_option(OptionInfo const * option_info,sal_uInt32 * pIndex)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 //==============================================================================
read_option(bool * flag,OptionInfo const * option_info,sal_uInt32 * pIndex)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 //==============================================================================
read_argument(OUString * pValue,OptionInfo const * option_info,sal_uInt32 * pIndex)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 //==============================================================================
path_get_working_dir()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 //==============================================================================
path_make_absolute_file_url(OUString const & path)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 //==============================================================================
open_registries(vector<OUString> const & registries,Reference<XComponentContext> xContext)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 //##############################################################################
SAL_IMPLEMENT_MAIN()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