xref: /trunk/main/cpputools/source/unoexe/unoexe.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 #include <stdio.h>
25 #include <vector>
26 
27 #include "sal/main.h"
28 #include <osl/diagnose.h>
29 #include <osl/mutex.hxx>
30 #include <osl/conditn.hxx>
31 #include <osl/module.h>
32 
33 #include <rtl/process.h>
34 #include <rtl/string.h>
35 #include <rtl/strbuf.hxx>
36 #include <rtl/ustrbuf.hxx>
37 
38 #include <uno/environment.h>
39 #include <uno/mapping.hxx>
40 
41 #include <cppuhelper/factory.hxx>
42 #include <cppuhelper/bootstrap.hxx>
43 #include <cppuhelper/servicefactory.hxx>
44 #include <cppuhelper/shlib.hxx>
45 #include <cppuhelper/implbase1.hxx>
46 
47 #include <com/sun/star/lang/XMain.hpp>
48 #include <com/sun/star/lang/XInitialization.hpp>
49 #include <com/sun/star/lang/XComponent.hpp>
50 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
52 #include <com/sun/star/lang/XEventListener.hpp>
53 #include <com/sun/star/container/XSet.hpp>
54 #include <com/sun/star/loader/XImplementationLoader.hpp>
55 #include <com/sun/star/registry/XSimpleRegistry.hpp>
56 #include <com/sun/star/registry/XRegistryKey.hpp>
57 #include <com/sun/star/connection/XAcceptor.hpp>
58 #include <com/sun/star/connection/XConnection.hpp>
59 #include <com/sun/star/bridge/XBridgeFactory.hpp>
60 #include <com/sun/star/bridge/XBridge.hpp>
61 #include <osl/process.h>
62 #include <osl/thread.h>
63 #include <osl/file.hxx>
64 
65 #ifdef SAL_UNX
66 #define SEPARATOR '/'
67 #else
68 #define SEPARATOR '\\'
69 #endif
70 
71 using namespace std;
72 using namespace rtl;
73 using namespace osl;
74 using namespace cppu;
75 using namespace com::sun::star::uno;
76 using namespace com::sun::star::lang;
77 using namespace com::sun::star::loader;
78 using namespace com::sun::star::registry;
79 using namespace com::sun::star::connection;
80 using namespace com::sun::star::bridge;
81 using namespace com::sun::star::container;
82 
83 namespace unoexe
84 {
85 
isFileUrl(const OUString & fileName)86 static sal_Bool isFileUrl(const OUString& fileName)
87 {
88     if (fileName.indexOf(OUString::createFromAscii("file://")) == 0 )
89         return sal_True;
90     return sal_False;
91 }
92 
convertToFileUrl(const OUString & fileName)93 static OUString convertToFileUrl(const OUString& fileName)
94 {
95     if ( isFileUrl(fileName) )
96     {
97         return fileName;
98     }
99 
100     OUString uUrlFileName;
101     if ( fileName.indexOf('.') == 0 || fileName.indexOf(SEPARATOR) < 0 )
102     {
103         OUString uWorkingDir;
104         if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None) {
105             OSL_ASSERT(false);
106         }
107         if (FileBase::getAbsoluteFileURL(uWorkingDir, fileName, uUrlFileName)
108             != FileBase::E_None)
109         {
110             OSL_ASSERT(false);
111         }
112     } else
113     {
114         if (FileBase::getFileURLFromSystemPath(fileName, uUrlFileName)
115             != FileBase::E_None)
116         {
117             OSL_ASSERT(false);
118         }
119     }
120 
121     return uUrlFileName;
122 }
123 
124 static sal_Bool s_quiet = false;
125 
126 //--------------------------------------------------------------------------------------------------
out(const sal_Char * pText)127 static inline void out( const sal_Char * pText )
128 {
129     if (! s_quiet)
130         fprintf( stderr, "%s", pText );
131 }
132 //--------------------------------------------------------------------------------------------------
out(const OUString & rText)133 static inline void out( const OUString & rText )
134 {
135     if (! s_quiet)
136     {
137         OString aText( OUStringToOString( rText, RTL_TEXTENCODING_ASCII_US ) );
138         fprintf( stderr, "%s", aText.getStr() );
139     }
140 }
141 
142 //--------------------------------------------------------------------------------------------------
143 static const char arUsingText[] =
144 "\nusing:\n\n"
145 "uno [-c ComponentImplementationName -l LocationUrl | -s ServiceName]\n"
146 "    [-ro ReadOnlyRegistry1] [-ro ReadOnlyRegistry2] ... [-rw ReadWriteRegistry]\n"
147 "    [-u uno:(socket[,host=HostName][,port=nnn]|pipe[,name=PipeName]);<protocol>;Name\n"
148 "        [--singleaccept] [--singleinstance]]\n"
149 "    [--quiet]\n"
150 "    [-- Argument1 Argument2 ...]\n";
151 
152 //--------------------------------------------------------------------------------------------------
readOption(OUString * pValue,const sal_Char * pOpt,sal_Int32 * pnIndex,const OUString & aArg)153 static sal_Bool readOption( OUString * pValue, const sal_Char * pOpt,
154                             sal_Int32 * pnIndex, const OUString & aArg)
155 {
156     const OUString dash = OUString(RTL_CONSTASCII_USTRINGPARAM("-"));
157     if(aArg.indexOf(dash) != 0)
158         return sal_False;
159 
160     OUString aOpt = OUString::createFromAscii( pOpt );
161 
162     if (aArg.getLength() < aOpt.getLength())
163         return sal_False;
164 
165     if (aOpt.equalsIgnoreAsciiCase( aArg.copy(1) ))
166     {
167         // take next argument
168         ++(*pnIndex);
169 
170         rtl_getAppCommandArg(*pnIndex, &pValue->pData);
171         if (*pnIndex >= (sal_Int32)rtl_getAppCommandArgCount() || pValue->copy(1).equals(dash))
172         {
173             OUStringBuffer buf( 32 );
174             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("incomplete option \"-") );
175             buf.appendAscii( pOpt );
176             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" given!") );
177             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
178         }
179         else
180         {
181 #if OSL_DEBUG_LEVEL > 1
182             out( "\n> identified option -" );
183             out( pOpt );
184             out( " = " );
185             OString tmp = OUStringToOString(aArg, RTL_TEXTENCODING_ASCII_US);
186             out( tmp.getStr() );
187 #endif
188             ++(*pnIndex);
189             return sal_True;
190         }
191     }
192     else if (aArg.indexOf(aOpt) == 1)
193     {
194         *pValue = aArg.copy(1 + aOpt.getLength());
195 #if OSL_DEBUG_LEVEL > 1
196         out( "\n> identified option -" );
197         out( pOpt );
198         out( " = " );
199         OString tmp = OUStringToOString(aArg.copy(aOpt.getLength()), RTL_TEXTENCODING_ASCII_US);
200         out( tmp.getStr() );
201 #endif
202         ++(*pnIndex);
203 
204         return sal_True;
205     }
206     return sal_False;
207 }
208 //--------------------------------------------------------------------------------------------------
readOption(sal_Bool * pbOpt,const sal_Char * pOpt,sal_Int32 * pnIndex,const OUString & aArg)209 static sal_Bool readOption( sal_Bool * pbOpt, const sal_Char * pOpt,
210                             sal_Int32 * pnIndex, const OUString & aArg)
211 {
212     const OUString dashdash(RTL_CONSTASCII_USTRINGPARAM("--"));
213     OUString aOpt = OUString::createFromAscii(pOpt);
214 
215     if(aArg.indexOf(dashdash) == 0 && aOpt.equals(aArg.copy(2)))
216     {
217         ++(*pnIndex);
218         *pbOpt = sal_True;
219 #if OSL_DEBUG_LEVEL > 1
220         out( "\n> identified option --" );
221         out( pOpt );
222 #endif
223         return sal_True;
224     }
225     return sal_False;
226 }
227 
228 
229 //##################################################################################################
230 //##################################################################################################
231 //##################################################################################################
232 
233 
234 //--------------------------------------------------------------------------------------------------
235 template< class T >
createInstance(Reference<T> & rxOut,const Reference<XComponentContext> & xContext,const OUString & rServiceName)236 void createInstance(
237     Reference< T > & rxOut,
238     const Reference< XComponentContext > & xContext,
239     const OUString & rServiceName )
240 {
241     Reference< XMultiComponentFactory > xMgr( xContext->getServiceManager() );
242     Reference< XInterface > x( xMgr->createInstanceWithContext( rServiceName, xContext ) );
243 
244     if (! x.is())
245     {
246         static sal_Bool s_bSet = sal_False;
247         if (! s_bSet)
248         {
249             MutexGuard aGuard( Mutex::getGlobalMutex() );
250             if (! s_bSet)
251             {
252                 Reference< XSet > xSet( xMgr, UNO_QUERY );
253                 if (xSet.is())
254                 {
255                     Reference< XMultiServiceFactory > xSF( xMgr, UNO_QUERY );
256                     // acceptor
257                     xSet->insert( makeAny( loadSharedLibComponentFactory(
258                         OUString( RTL_CONSTASCII_USTRINGPARAM(
259                                       "acceptor.uno" SAL_DLLEXTENSION) ),
260                         OUString(),
261                         OUString( RTL_CONSTASCII_USTRINGPARAM(
262                                       "com.sun.star.comp.io.Acceptor") ),
263                         xSF, Reference< XRegistryKey >() ) ) );
264                     // connector
265                     xSet->insert( makeAny( loadSharedLibComponentFactory(
266                         OUString( RTL_CONSTASCII_USTRINGPARAM(
267                                       "connector.uno" SAL_DLLEXTENSION) ),
268                         OUString(),
269                         OUString( RTL_CONSTASCII_USTRINGPARAM(
270                                       "com.sun.star.comp.io.Connector") ),
271                         xSF, Reference< XRegistryKey >() ) ) );
272                     // bridge factory
273                     xSet->insert( makeAny( loadSharedLibComponentFactory(
274                         OUString( RTL_CONSTASCII_USTRINGPARAM(
275                                       "binaryurp.uno" SAL_DLLEXTENSION) ),
276                         OUString(),
277                         OUString(
278                             RTL_CONSTASCII_USTRINGPARAM(
279                                 "com.sun.star.comp.bridge.BridgeFactory") ),
280                         xSF, Reference< XRegistryKey >() ) ) );
281                 }
282                 s_bSet = sal_True;
283             }
284         }
285         x = xMgr->createInstanceWithContext( rServiceName, xContext );
286     }
287 
288     if (! x.is())
289     {
290         OUStringBuffer buf( 64 );
291         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot get service instance \"") );
292         buf.append( rServiceName );
293         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
294         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
295     }
296 
297     rxOut = Reference< T >::query( x );
298     if (! rxOut.is())
299     {
300         OUStringBuffer buf( 64 );
301         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("service instance \"") );
302         buf.append( rServiceName );
303         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not support demanded interface \"") );
304         const Type & rType = ::getCppuType( (const Reference< T > *)0 );
305         buf.append( rType.getTypeName() );
306         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
307         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
308     }
309 }
310 //--------------------------------------------------------------------------------------------------
nestRegistries(const Reference<XSimpleRegistry> & xReadWrite,const Reference<XSimpleRegistry> & xReadOnly)311 static Reference< XSimpleRegistry > nestRegistries(
312     const Reference< XSimpleRegistry > & xReadWrite,
313     const Reference< XSimpleRegistry > & xReadOnly )
314 {
315     Reference< XSimpleRegistry > xReg( createNestedRegistry() );
316     if (! xReg.is())
317     {
318         throw RuntimeException(
319             OUString( RTL_CONSTASCII_USTRINGPARAM("no nested registry service!" ) ),
320             Reference< XInterface >() );
321     }
322 
323     Reference< XInitialization > xInit( xReg, UNO_QUERY );
324     if (! xInit.is())
325         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("nested registry does not export interface \"com.sun.star.lang.XInitialization\"!" ) ), Reference< XInterface >() );
326 
327     Sequence< Any > aArgs( 2 );
328     aArgs[0] <<= xReadWrite;
329     aArgs[1] <<= xReadOnly;
330     xInit->initialize( aArgs );
331 
332     return xReg;
333 }
334 //--------------------------------------------------------------------------------------------------
openRegistry(const OUString & rURL,sal_Bool bReadOnly,sal_Bool bCreate)335 static Reference< XSimpleRegistry > openRegistry(
336     const OUString & rURL,
337     sal_Bool bReadOnly, sal_Bool bCreate )
338 {
339     Reference< XSimpleRegistry > xNewReg( createSimpleRegistry() );
340     if (! xNewReg.is())
341     {
342         throw RuntimeException(
343             OUString( RTL_CONSTASCII_USTRINGPARAM("no simple registry service!" ) ),
344             Reference< XInterface >() );
345     }
346 
347     try
348     {
349         xNewReg->open( convertToFileUrl(rURL), bReadOnly, bCreate );
350         if (xNewReg->isValid())
351             return xNewReg;
352         else
353             xNewReg->close();
354     }
355     catch (Exception &)
356     {
357     }
358 
359     out( "\n> warning: cannot open registry \"" );
360     out( rURL );
361     if (bReadOnly)
362         out( "\" for reading, ignoring!" );
363     else
364         out( "\" for reading and writing, ignoring!" );
365     return Reference< XSimpleRegistry >();
366 }
367 //--------------------------------------------------------------------------------------------------
loadComponent(const Reference<XComponentContext> & xContext,const OUString & rImplName,const OUString & rLocation)368 static Reference< XInterface > loadComponent(
369     const Reference< XComponentContext > & xContext,
370     const OUString & rImplName, const OUString & rLocation )
371 {
372     // determine loader to be used
373     sal_Int32 nDot = rLocation.lastIndexOf( '.' );
374     if (nDot > 0 && nDot < rLocation.getLength())
375     {
376         Reference< XImplementationLoader > xLoader;
377 
378         OUString aExt( rLocation.copy( nDot +1 ) );
379 
380         if (aExt.compareToAscii( "dll" ) == 0 ||
381             aExt.compareToAscii( "exe" ) == 0 ||
382             aExt.compareToAscii( "dylib" ) == 0 ||
383             aExt.compareToAscii( "so" ) == 0)
384         {
385             createInstance(
386                 xLoader, xContext, OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.SharedLibrary") ) );
387         }
388         else if (aExt.compareToAscii( "jar" ) == 0 ||
389                  aExt.compareToAscii( "class" ) == 0)
390         {
391             createInstance(
392                 xLoader, xContext, OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.Java") ) );
393         }
394         else
395         {
396             OUStringBuffer buf( 64 );
397             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("unknown extension of \"") );
398             buf.append( rLocation );
399             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!  No loader available!") );
400             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
401         }
402 
403         Reference< XInterface > xInstance;
404 
405         // activate
406         Reference< XInterface > xFactory( xLoader->activate(
407             rImplName, OUString(), rLocation, Reference< XRegistryKey >() ) );
408         if (xFactory.is())
409         {
410             Reference< XSingleComponentFactory > xCFac( xFactory, UNO_QUERY );
411             if (xCFac.is())
412             {
413                 xInstance = xCFac->createInstanceWithContext( xContext );
414             }
415             else
416             {
417                 Reference< XSingleServiceFactory > xSFac( xFactory, UNO_QUERY );
418                 if (xSFac.is())
419                 {
420                     out( "\n> warning: ignoring context for implementation \"" );
421                     out( rImplName );
422                     out( "\"!" );
423                     xInstance = xSFac->createInstance();
424                 }
425             }
426         }
427 
428         if (! xInstance.is())
429         {
430             OUStringBuffer buf( 64 );
431             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("activating component \"") );
432             buf.append( rImplName );
433             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" from location \"") );
434             buf.append( rLocation );
435             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" failed!") );
436             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
437         }
438 
439         return xInstance;
440     }
441     else
442     {
443         OUStringBuffer buf( 64 );
444         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("location \"") );
445         buf.append( rLocation );
446         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" has no extension!  Cannot determine loader to be used!") );
447         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
448     }
449 }
450 
451 
452 //##################################################################################################
453 //##################################################################################################
454 //##################################################################################################
455 
456 
457 //==================================================================================================
458 class OInstanceProvider
459     : public WeakImplHelper1< XInstanceProvider >
460 {
461     Reference< XComponentContext > _xContext;
462 
463     Mutex                             _aSingleInstanceMutex;
464     Reference< XInterface >           _xSingleInstance;
465     sal_Bool                          _bSingleInstance;
466 
467     OUString                          _aImplName;
468     OUString                          _aLocation;
469     OUString                          _aServiceName;
470     Sequence< Any >                   _aInitParams;
471 
472     OUString                          _aInstanceName;
473 
474     inline Reference< XInterface > createInstance();
475 
476 public:
OInstanceProvider(const Reference<XComponentContext> & xContext,const OUString & rImplName,const OUString & rLocation,const OUString & rServiceName,const Sequence<Any> & rInitParams,sal_Bool bSingleInstance,const OUString & rInstanceName)477     OInstanceProvider( const Reference< XComponentContext > & xContext,
478                        const OUString & rImplName, const OUString & rLocation,
479                        const OUString & rServiceName, const Sequence< Any > & rInitParams,
480                        sal_Bool bSingleInstance, const OUString & rInstanceName )
481         : _xContext( xContext )
482         , _bSingleInstance( bSingleInstance )
483         , _aImplName( rImplName )
484         , _aLocation( rLocation )
485         , _aServiceName( rServiceName )
486         , _aInitParams( rInitParams )
487         , _aInstanceName( rInstanceName )
488         {}
489 
490     // XInstanceProvider
491     virtual Reference< XInterface > SAL_CALL getInstance( const OUString & rName );
492 };
493 //__________________________________________________________________________________________________
createInstance()494 inline Reference< XInterface > OInstanceProvider::createInstance()
495 {
496     Reference< XInterface > xRet;
497     if (_aImplName.getLength()) // manually via loader
498         xRet = loadComponent( _xContext, _aImplName, _aLocation );
499     else // via service manager
500         unoexe::createInstance( xRet, _xContext, _aServiceName );
501 
502     // opt XInit
503     Reference< XInitialization > xInit( xRet, UNO_QUERY );
504     if (xInit.is())
505         xInit->initialize( _aInitParams );
506 
507     return xRet;
508 }
509 //__________________________________________________________________________________________________
getInstance(const OUString & rName)510 Reference< XInterface > OInstanceProvider::getInstance( const OUString & rName )
511 {
512     try
513     {
514         if (_aInstanceName == rName)
515         {
516             Reference< XInterface > xRet;
517 
518             if (_aImplName.getLength() == 0 && _aServiceName.getLength() == 0)
519             {
520                 OSL_ASSERT(
521                     rName.equalsAsciiL(
522                         RTL_CONSTASCII_STRINGPARAM("uno.ComponentContext") ) );
523                 xRet = _xContext;
524             }
525             else if (_bSingleInstance)
526             {
527                 if (! _xSingleInstance.is())
528                 {
529                     MutexGuard aGuard( _aSingleInstanceMutex );
530                     if (! _xSingleInstance.is())
531                     {
532                         _xSingleInstance = createInstance();
533                     }
534                 }
535                 xRet = _xSingleInstance;
536             }
537             else
538             {
539                 xRet = createInstance();
540             }
541 
542             return xRet;
543         }
544     }
545     catch (Exception & rExc)
546     {
547         out( "\n> error: " );
548         out( rExc.Message );
549     }
550     OUStringBuffer buf( 64 );
551     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("no such element \"") );
552     buf.append( rName );
553     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
554     throw NoSuchElementException( buf.makeStringAndClear(), Reference< XInterface >() );
555 }
556 
557 //==================================================================================================
558 struct ODisposingListener : public WeakImplHelper1< XEventListener >
559 {
560     Condition cDisposed;
561 
562     // XEventListener
563     virtual void SAL_CALL disposing( const EventObject & rEvt );
564 
565     //----------------------------------------------------------------------------------------------
566     static void waitFor( const Reference< XComponent > & xComp );
567 };
568 //__________________________________________________________________________________________________
disposing(const EventObject &)569 void ODisposingListener::disposing( const EventObject & )
570 {
571     cDisposed.set();
572 }
573 //--------------------------------------------------------------------------------------------------
waitFor(const Reference<XComponent> & xComp)574 void ODisposingListener::waitFor( const Reference< XComponent > & xComp )
575 {
576     ODisposingListener * pListener = new ODisposingListener();
577     Reference< XEventListener > xListener( pListener );
578 
579     xComp->addEventListener( xListener );
580     pListener->cDisposed.wait();
581 }
582 
583 
584 //##################################################################################################
585 //##################################################################################################
586 //##################################################################################################
587 
588 
589 //##################################################################################################
590 } // namespace unoexe
591 
592 using namespace unoexe;
593 
594 SAL_IMPLEMENT_MAIN_WITH_ARGS(argc,)
595 {
596     if (argc <= 1)
597     {
598         out( arUsingText );
599         return 0;
600     }
601 
602     sal_Int32 nRet = 0;
603     Reference< XComponentContext > xContext;
604 
605 
606     try
607     {
608         OUString aImplName, aLocation, aServiceName, aUnoUrl;
609         vector< OUString > aReadOnlyRegistries;
610         Sequence< OUString > aParams;
611         sal_Bool bSingleAccept = sal_False;
612         sal_Bool bSingleInstance = sal_False;
613 
614         //#### read command line arguments #########################################################
615 
616         bool bOldRegistryMimic = false;
617         bool bNewRegistryMimic = false;
618         OUString aReadWriteRegistry;
619 
620         sal_Int32 nPos = 0;
621         sal_Int32 nCount = (sal_Int32)rtl_getAppCommandArgCount();
622         // read up to arguments
623         while (nPos < nCount)
624         {
625             OUString arg;
626 
627             rtl_getAppCommandArg(nPos, &arg.pData);
628 
629             const OUString dashdash = OUString(RTL_CONSTASCII_USTRINGPARAM("--"));
630             if (dashdash == arg)
631             {
632                 ++nPos;
633                 break;
634             }
635 
636             if (readOption( &aImplName, "c", &nPos, arg)                ||
637                 readOption( &aLocation, "l", &nPos, arg)                ||
638                 readOption( &aServiceName, "s", &nPos, arg)             ||
639                 readOption( &aUnoUrl, "u", &nPos, arg)                  ||
640                 readOption( &s_quiet, "quiet", &nPos, arg)              ||
641                 readOption( &bSingleAccept, "singleaccept", &nPos, arg) ||
642                 readOption( &bSingleInstance, "singleinstance", &nPos, arg))
643             {
644                 continue;
645             }
646             OUString aRegistry;
647             if (readOption( &aRegistry, "ro", &nPos, arg))
648             {
649                 aReadOnlyRegistries.push_back( aRegistry );
650                 bNewRegistryMimic = true;
651                 continue;
652             }
653             if (readOption( &aReadWriteRegistry, "rw", &nPos, arg))
654             {
655                 bNewRegistryMimic = true;
656                 continue;
657             }
658             if (readOption( &aRegistry, "r", &nPos, arg))
659             {
660                 aReadOnlyRegistries.push_back( aRegistry );
661                 aReadWriteRegistry = aRegistry;
662                 out( "\n> warning: DEPRECATED use of option -r, use -ro or -rw!" );
663                 bOldRegistryMimic = true;
664                 continue;
665             }
666 
667             // else illegal argument
668             OUStringBuffer buf( 64 );
669             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("unexpected parameter \"") );
670             buf.append(arg);
671             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
672             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
673         }
674 
675         if (bOldRegistryMimic) // last one was set to be read-write
676         {
677             aReadOnlyRegistries.pop_back();
678             if (bOldRegistryMimic && bNewRegistryMimic)
679             {
680                 throw RuntimeException(
681                     OUString( RTL_CONSTASCII_USTRINGPARAM("mixing with DEPRECATED registry options!") ),
682                     Reference< XInterface >() );
683             }
684         }
685 
686         if ((aImplName.getLength() != 0) && (aServiceName.getLength() != 0))
687             throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("give component exOR service name!" ) ), Reference< XInterface >() );
688         if (aImplName.getLength() == 0 && aServiceName.getLength() == 0)
689         {
690             if (! aUnoUrl.endsWithIgnoreAsciiCaseAsciiL(
691                     RTL_CONSTASCII_STRINGPARAM(";uno.ComponentContext") ))
692                 throw RuntimeException(
693                     OUString( RTL_CONSTASCII_USTRINGPARAM(
694                                   "expected UNO-URL with instance name "
695                                   "uno.ComponentContext!") ),
696                     Reference<XInterface>() );
697             if (bSingleInstance)
698                 throw RuntimeException(
699                     OUString( RTL_CONSTASCII_USTRINGPARAM(
700                                   "unexpected option --singleinstance!") ),
701                     Reference<XInterface>() );
702         }
703         if (aImplName.getLength() && !aLocation.getLength())
704             throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("give component location!" ) ), Reference< XInterface >() );
705         if (aServiceName.getLength() && aLocation.getLength())
706             out( "\n> warning: service name given, will ignore location!" );
707 
708         // read component params
709         aParams.realloc( nCount - nPos );
710         OUString * pParams = aParams.getArray();
711 
712         sal_Int32 nOffset = nPos;
713         for ( ; nPos < nCount; ++nPos )
714         {
715             if (rtl_getAppCommandArg( nPos, &pParams[nPos -nOffset].pData )
716                 != osl_Process_E_None)
717             {
718                 OSL_ASSERT(false);
719             }
720         }
721 
722         if (aReadOnlyRegistries.size() > 0 ||
723             aReadWriteRegistry.getLength() > 0)
724         {
725             //#### create registry #############################################
726 
727             Reference< XSimpleRegistry > xRegistry;
728 
729             // ReadOnly registries
730             for ( size_t nReg = 0; nReg < aReadOnlyRegistries.size(); ++nReg )
731             {
732 #if OSL_DEBUG_LEVEL > 1
733                 out( "\n> trying to open ro registry: " );
734                 out( OUStringToOString(
735                          aReadOnlyRegistries[ nReg ],
736                          RTL_TEXTENCODING_ASCII_US ).getStr() );
737 #endif
738                 Reference< XSimpleRegistry > xNewReg(
739                     openRegistry(
740                         aReadOnlyRegistries[ nReg ], sal_True, sal_False ) );
741                 if (xNewReg.is())
742                     xRegistry = (xRegistry.is() ? nestRegistries(
743                                      xNewReg, xRegistry ) : xNewReg);
744             }
745             if (aReadWriteRegistry.getLength())
746             {
747 #if OSL_DEBUG_LEVEL > 1
748                 out( "\n> trying to open rw registry: " );
749                 out( OUStringToOString(
750                          aReadWriteRegistry,
751                          RTL_TEXTENCODING_ASCII_US ).getStr() );
752 #endif
753                 // ReadWrite registry
754                 Reference< XSimpleRegistry > xNewReg(
755                     openRegistry( aReadWriteRegistry, sal_False, sal_True ) );
756                 if (xNewReg.is())
757                     xRegistry = (xRegistry.is()
758                                  ? nestRegistries( xNewReg, xRegistry )
759                                  : xNewReg);
760             }
761 
762             OSL_ASSERT( xRegistry.is() );
763             xContext = bootstrap_InitialComponentContext( xRegistry );
764         }
765         else // defaulting
766         {
767             xContext = defaultBootstrap_InitialComponentContext();
768         }
769 
770         //#### accept, instantiate, etc. ###########################################################
771 
772         if (aUnoUrl.getLength()) // accepting connections
773         {
774             sal_Int32 nIndex = 0, nTokens = 0;
775             do { aUnoUrl.getToken( 0, ';', nIndex ); nTokens++; } while( nIndex != -1 );
776             if (nTokens != 3 || aUnoUrl.getLength() < 10 ||
777                 !aUnoUrl.copy( 0, 4 ).equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("uno:") ) ))
778             {
779                 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("illegal uno url given!" ) ), Reference< XInterface >() );
780             }
781             nIndex = 0;
782             OUString aConnectDescr( aUnoUrl.getToken( 0, ';', nIndex ).copy( 4 ) ); // uno:CONNECTDESCR;iiop;InstanceName
783             OUString aInstanceName( aUnoUrl.getToken( 1, ';', nIndex ) );
784 
785             Reference< XAcceptor > xAcceptor;
786             createInstance(
787                 xAcceptor, xContext,
788                 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Acceptor") ) );
789 
790             // init params
791             Sequence< Any > aInitParams( aParams.getLength() );
792             const OUString * p = aParams.getConstArray();
793             Any * pInitParams = aInitParams.getArray();
794             for ( sal_Int32 i = aParams.getLength(); i--; )
795             {
796                 pInitParams[i] = makeAny( p[i] );
797             }
798 
799             // instance provider
800             Reference< XInstanceProvider > xInstanceProvider( new OInstanceProvider(
801                 xContext, aImplName, aLocation, aServiceName, aInitParams,
802                 bSingleInstance, aInstanceName ) );
803 
804             nIndex = 0;
805             OUString aUnoUrlToken( aUnoUrl.getToken( 1, ';', nIndex ) );
806             for (;;)
807             {
808                 // accepting
809                 out( "\n> accepting " );
810                 out( aConnectDescr );
811                 out( "..." );
812                 Reference< XConnection > xConnection( xAcceptor->accept( aConnectDescr ) );
813                 out( "connection established." );
814 
815                 Reference< XBridgeFactory > xBridgeFactory;
816                 createInstance(
817                     xBridgeFactory, xContext,
818                     OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory") ) );
819 
820                 // bridge
821                 Reference< XBridge > xBridge( xBridgeFactory->createBridge(
822                     OUString(), aUnoUrlToken,
823                     xConnection, xInstanceProvider ) );
824 
825                 if (bSingleAccept)
826                 {
827                     Reference< XComponent > xComp( xBridge, UNO_QUERY );
828                     if (! xComp.is())
829                         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("bridge factory does not export interface \"com.sun.star.lang.XComponent\"!" ) ), Reference< XInterface >() );
830                     ODisposingListener::waitFor( xComp );
831                     break;
832                 }
833             }
834         }
835         else // no uno url
836         {
837             Reference< XInterface > xInstance;
838             if (aImplName.getLength()) // manually via loader
839                 xInstance = loadComponent( xContext, aImplName, aLocation );
840             else // via service manager
841                 createInstance( xInstance, xContext, aServiceName );
842 
843             // execution
844             Reference< XMain > xMain( xInstance, UNO_QUERY );
845             if (xMain.is())
846             {
847                 nRet = xMain->run( aParams );
848             }
849             else
850             {
851                 Reference< XComponent > xComp( xInstance, UNO_QUERY );
852                 if (xComp.is())
853                     xComp->dispose();
854                 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("component does not export interface interface \"com.sun.star.lang.XMain\"!" ) ), Reference< XInterface >() );
855             }
856         }
857     }
858     catch (Exception & rExc)
859     {
860         out( "\n> error: " );
861         out( rExc.Message );
862         out( "\n> dying..." );
863         nRet = 1;
864     }
865 
866     // cleanup
867     Reference< XComponent > xComp( xContext, UNO_QUERY );
868     if (xComp.is())
869         xComp->dispose();
870 
871     out( "\n" );
872     return nRet;
873 }
874