xref: /trunk/main/cpputools/source/unoexe/unoexe.cxx (revision cdf0e10c)
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