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