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 = NULL;
545 if (keyfile.getLength() > 0)
546 {
547 ::System::String * sKeyFile = ustring_to_String(keyfile);
548 try {
549 System::IO::FileStream* fs = new System::IO::FileStream(
550 sKeyFile, System::IO::FileMode::Open);
551 kp = new 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 S"> 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 = new AssemblyName();
569 assembly_name->set_CodeBase( output_dir );
570 assembly_name->set_Name( name.getStr() );
571 if (kp != NULL)
572 assembly_name->set_KeyPair(kp);
573
574 if (version.getLength() != 0)
575 {
576 assembly_name->set_Version(
577 new ::System::Version( ustring_to_String( version ) ) );
578 }
579
580 // app domain
581 ::System::AppDomain * current_appdomain =
582 ::System::AppDomain::get_CurrentDomain();
583 // target assembly
584 Emit::AssemblyBuilder * assembly_builder =
585 current_appdomain->DefineDynamicAssembly(
586 assembly_name, Emit::AssemblyBuilderAccess::Save, output_dir );
587 if (product.getLength() != 0)
588 {
589 ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ];
590 ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ];
591 params[ 0 ] = __typeof (::System::String);
592 args[ 0 ] = ustring_to_String( product );
593 assembly_builder->SetCustomAttribute(
594 new Emit::CustomAttributeBuilder(
595 __typeof (AssemblyProductAttribute)->GetConstructor(
596 params ), args ) );
597 }
598 if (description.getLength() != 0)
599 {
600 ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ];
601 ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ];
602 params[ 0 ] = __typeof (::System::String);
603 args[ 0 ] = ustring_to_String( description );
604 assembly_builder->SetCustomAttribute(
605 new Emit::CustomAttributeBuilder(
606 __typeof (AssemblyDescriptionAttribute)->GetConstructor(
607 params ), args ) );
608 }
609 if (company.getLength() != 0)
610 {
611 ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ];
612 ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ];
613 params[ 0 ] = __typeof (::System::String);
614 args[ 0 ] = ustring_to_String( company );
615 assembly_builder->SetCustomAttribute(
616 new Emit::CustomAttributeBuilder(
617 __typeof (AssemblyCompanyAttribute)->GetConstructor(
618 params ), args ) );
619 }
620 if (copyright.getLength() != 0)
621 {
622 ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ];
623 ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ];
624 params[ 0 ] = __typeof (::System::String);
625 args[ 0 ] = ustring_to_String( copyright );
626 assembly_builder->SetCustomAttribute(
627 new Emit::CustomAttributeBuilder(
628 __typeof (AssemblyCopyrightAttribute)->GetConstructor(
629 params ), args ) );
630 }
631 if (trademark.getLength() != 0)
632 {
633 ::System::Type * params __gc [] = new ::System::Type * __gc [ 1 ];
634 ::System::Object * args __gc [] = new ::System::Object * __gc [ 1 ];
635 params[ 0 ] = __typeof (::System::String);
636 args[ 0 ] = ustring_to_String( trademark );
637 assembly_builder->SetCustomAttribute(
638 new Emit::CustomAttributeBuilder(
639 __typeof (AssemblyTrademarkAttribute)->GetConstructor(
640 params ), args ) );
641 }
642
643 // load extra assemblies
644 Assembly * assemblies __gc [] =
645 new Assembly * __gc [ extra_assemblies.size() ];
646 for ( size_t pos = 0; pos < extra_assemblies.size(); ++pos )
647 {
648 assemblies[ pos ] = Assembly::LoadFrom(
649 ustring_to_String( extra_assemblies[ pos ] ) );
650 }
651
652 // type emitter
653 TypeEmitter * type_emitter = new TypeEmitter(
654 assembly_builder->DefineDynamicModule( output_file ), assemblies );
655 // add handler resolving assembly's types
656 ::System::ResolveEventHandler * type_resolver =
657 new ::System::ResolveEventHandler(
658 type_emitter, &TypeEmitter::type_resolve );
659 current_appdomain->add_TypeResolve( type_resolver );
660
661 // and emit types to it
662 if (explicit_types.empty())
663 {
664 Reference< reflection::XTypeDescriptionEnumeration > xTD_enum(
665 Reference< reflection::XTypeDescriptionEnumerationAccess >(
666 xTD_provider, UNO_QUERY_THROW )
667 ->createTypeDescriptionEnumeration(
668 OUString() /* all IDL modules */,
669 Sequence< TypeClass >() /* all classes of types */,
670 reflection::TypeDescriptionSearchDepth_INFINITE ) );
671 while (xTD_enum->hasMoreElements())
672 {
673 type_emitter->get_type( xTD_enum->nextTypeDescription() );
674 }
675 }
676 else
677 {
678 Reference< container::XHierarchicalNameAccess > xHNA(
679 xTD_provider, UNO_QUERY_THROW );
680 for ( size_t nPos = explicit_types.size(); nPos--; )
681 {
682 type_emitter->get_type(
683 Reference< reflection::XTypeDescription >(
684 xHNA->getByHierarchicalName( explicit_types[ nPos ] ),
685 UNO_QUERY_THROW ) );
686 }
687 }
688 type_emitter->Dispose();
689
690 if (g_verbose)
691 {
692 ::System::Console::Write(
693 S"> saving assembly {0}{1}{2}...",
694 output_dir,
695 new ::System::String(
696 ::System::IO::Path::DirectorySeparatorChar, 1 ),
697 output_file );
698 }
699 assembly_builder->Save( output_file );
700 if (g_verbose)
701 {
702 ::System::Console::WriteLine( S"ok." );
703 }
704 current_appdomain->remove_TypeResolve( type_resolver );
705 }
706 catch (Exception & exc)
707 {
708 OString msg(
709 OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) );
710 fprintf(
711 stderr, "\n> error: %s\n> dying abnormally...\n", msg.getStr() );
712 ret = 1;
713 }
714 catch (::System::Exception * exc)
715 {
716 OString msg( OUStringToOString(
717 String_to_ustring( exc->ToString() ),
718 osl_getThreadTextEncoding() ) );
719 fprintf(
720 stderr,
721 "\n> error: .NET exception occurred: %s\n> dying abnormally...",
722 msg.getStr() );
723 ret = 1;
724 }
725
726 try
727 {
728 Reference< lang::XComponent > xComp( xContext, UNO_QUERY );
729 if (xComp.is())
730 xComp->dispose();
731 }
732 catch (Exception & exc)
733 {
734 OString msg(
735 OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) );
736 fprintf(
737 stderr,
738 "\n> error disposing component context: %s\n"
739 "> dying abnormally...\n",
740 msg.getStr() );
741 ret = 1;
742 }
743
744 return ret;
745 }
746