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