1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cppuhelper.hxx"
26
27 #include <string.h>
28 #include <vector>
29
30 #include "rtl/process.h"
31 #include "rtl/bootstrap.hxx"
32 #include "rtl/random.h"
33 #include "rtl/string.hxx"
34 #include "rtl/ustrbuf.hxx"
35 #include "rtl/uri.hxx"
36 #if OSL_DEBUG_LEVEL > 0
37 #include "rtl/strbuf.hxx"
38 #endif
39 #include "osl/diagnose.h"
40 #include "osl/file.hxx"
41 #include "osl/module.hxx"
42 #include "osl/security.hxx"
43 #include "osl/thread.hxx"
44
45 #include "cppuhelper/shlib.hxx"
46 #include "cppuhelper/bootstrap.hxx"
47 #include "cppuhelper/component_context.hxx"
48 #include "cppuhelper/access_control.hxx"
49 #include "cppuhelper/findsofficepath.h"
50
51 #include "com/sun/star/container/XElementAccess.hpp"
52
53 #include "com/sun/star/uno/XComponentContext.hpp"
54 #include "com/sun/star/uno/XCurrentContext.hpp"
55
56 #include "com/sun/star/lang/XSingleServiceFactory.hpp"
57 #include "com/sun/star/lang/XSingleComponentFactory.hpp"
58 #include "com/sun/star/lang/XInitialization.hpp"
59 #include "com/sun/star/lang/XServiceInfo.hpp"
60 #include "com/sun/star/registry/XSimpleRegistry.hpp"
61 #include "com/sun/star/container/XSet.hpp"
62 #include "com/sun/star/beans/PropertyValue.hpp"
63 #include "com/sun/star/io/IOException.hpp"
64 #include "com/sun/star/bridge/UnoUrlResolver.hpp"
65 #include "com/sun/star/bridge/XUnoUrlResolver.hpp"
66
67 #include "macro_expander.hxx"
68
69 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
70 #define ARLEN(x) sizeof (x) / sizeof *(x)
71
72 void primeWeakMap( void); // as defined in primeweak.cxx
73
74 using namespace ::rtl;
75 using namespace ::osl;
76 using namespace ::com::sun::star;
77 using namespace ::com::sun::star::uno;
78
79 namespace cppu
80 {
81
get_this_libpath()82 OUString const & get_this_libpath()
83 {
84 static OUString s_path;
85 if (0 == s_path.getLength())
86 {
87 OUString path;
88 Module::getUrlFromAddress( reinterpret_cast<oslGenericFunction>(get_this_libpath), path );
89 path = path.copy( 0, path.lastIndexOf( '/' ) );
90 MutexGuard guard( Mutex::getGlobalMutex() );
91 if (0 == s_path.getLength())
92 s_path = path;
93 }
94 return s_path;
95 }
96
get_unorc()97 Bootstrap const & get_unorc() SAL_THROW( () )
98 {
99 static rtlBootstrapHandle s_bstrap = 0;
100 if (! s_bstrap)
101 {
102 OUString iniName(
103 get_this_libpath() + OUSTR("/" SAL_CONFIGFILE("uno")) );
104 rtlBootstrapHandle bstrap = rtl_bootstrap_args_open( iniName.pData );
105
106 ClearableMutexGuard guard( Mutex::getGlobalMutex() );
107 if (s_bstrap)
108 {
109 guard.clear();
110 rtl_bootstrap_args_close( bstrap );
111 }
112 else
113 {
114 s_bstrap = bstrap;
115 }
116 }
117 return *(Bootstrap const *)&s_bstrap;
118 }
119
120
addFactories(char const * const * ppNames,OUString const & bootstrapPath,Reference<lang::XMultiComponentFactory> const & xMgr,Reference<registry::XRegistryKey> const & xKey)121 void addFactories(
122 char const * const * ppNames /* lib, implname, ..., 0 */,
123 OUString const & bootstrapPath,
124 Reference< lang::XMultiComponentFactory > const & xMgr,
125 Reference< registry::XRegistryKey > const & xKey )
126 SAL_THROW( (Exception) )
127 {
128 Reference< container::XSet > xSet( xMgr, UNO_QUERY );
129 OSL_ASSERT( xSet.is() );
130 Reference< lang::XMultiServiceFactory > xSF( xMgr, UNO_QUERY );
131
132 while (*ppNames)
133 {
134 OUString lib( OUString::createFromAscii( *ppNames++ ) );
135 OUString implName( OUString::createFromAscii( *ppNames++ ) );
136
137 Any aFac( makeAny( loadSharedLibComponentFactory(
138 lib, bootstrapPath, implName, xSF, xKey ) ) );
139 xSet->insert( aFac );
140 #if OSL_DEBUG_LEVEL > 1
141 if (xSet->has( aFac ))
142 {
143 Reference< lang::XServiceInfo > xInfo;
144 if (aFac >>= xInfo)
145 {
146 ::fprintf(
147 stderr, "> implementation %s supports: ", ppNames[ -1 ] );
148 Sequence< OUString > supported(
149 xInfo->getSupportedServiceNames() );
150 for ( sal_Int32 nPos = supported.getLength(); nPos--; )
151 {
152 OString str( OUStringToOString(
153 supported[ nPos ], RTL_TEXTENCODING_ASCII_US ) );
154 ::fprintf( stderr, nPos ? "%s, " : "%s\n", str.getStr() );
155 }
156 }
157 else
158 {
159 ::fprintf(
160 stderr,
161 "> implementation %s provides NO lang::XServiceInfo!!!\n",
162 ppNames[ -1 ] );
163 }
164 }
165 #endif
166 #if OSL_DEBUG_LEVEL > 0
167 if (! xSet->has( aFac ))
168 {
169 OStringBuffer buf( 64 );
170 buf.append( "### failed inserting shared lib \"" );
171 buf.append( ppNames[ -2 ] );
172 buf.append( "\"!!!" );
173 OString str( buf.makeStringAndClear() );
174 OSL_ENSURE( 0, str.getStr() );
175 }
176 #endif
177 }
178 }
179
180 // private forward decl
181 Reference< lang::XMultiComponentFactory > bootstrapInitialSF(
182 OUString const & rBootstrapPath )
183 SAL_THROW( (Exception) );
184
185 Reference< XComponentContext > bootstrapInitialContext(
186 Reference< lang::XMultiComponentFactory > const & xSF,
187 Reference< registry::XSimpleRegistry > const & types_xRegistry,
188 Reference< registry::XSimpleRegistry > const & services_xRegistry,
189 OUString const & rBootstrapPath, Bootstrap const & bootstrap )
190 SAL_THROW( (Exception) );
191
192 Reference< XComponentContext > SAL_CALL createInitialCfgComponentContext(
193 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
194 Reference< XComponentContext > const & xDelegate )
195 SAL_THROW( () );
196
197 Reference< registry::XSimpleRegistry > SAL_CALL createRegistryWrapper(
198 const Reference< XComponentContext >& xContext );
199
200 namespace {
201
202 template< class T >
createPropertyValue(OUString const & name,T const & value)203 inline beans::PropertyValue createPropertyValue(
204 OUString const & name, T const & value )
205 SAL_THROW( () )
206 {
207 return beans::PropertyValue(
208 name, -1, makeAny( value ), beans::PropertyState_DIRECT_VALUE );
209 }
210
findBoostrapArgument(const Bootstrap & bootstrap,const OUString & arg_name,sal_Bool * pFallenBack)211 OUString findBoostrapArgument(
212 const Bootstrap & bootstrap,
213 const OUString & arg_name,
214 sal_Bool * pFallenBack )
215 SAL_THROW(())
216 {
217 OUString result;
218
219 OUString prefixed_arg_name = OUSTR("UNO_");
220 prefixed_arg_name += arg_name.toAsciiUpperCase();
221
222 // environment not set -> try relative to executable
223 if(!bootstrap.getFrom(prefixed_arg_name, result))
224 {
225 if(pFallenBack)
226 *pFallenBack = sal_True;
227
228 OUString fileName;
229 bootstrap.getIniName(fileName);
230
231 // cut the rc extension
232 OUStringBuffer result_buf( 64 );
233 result_buf.append(
234 fileName.copy(
235 0, fileName.getLength() - strlen(SAL_CONFIGFILE(""))) );
236 result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_") );
237 result_buf.append( arg_name.toAsciiLowerCase() );
238 result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".rdb") );
239 result = result_buf.makeStringAndClear();
240
241 #if OSL_DEBUG_LEVEL > 1
242 OString result_dbg =
243 OUStringToOString(result, RTL_TEXTENCODING_ASCII_US);
244 OString arg_name_dbg =
245 OUStringToOString(arg_name, RTL_TEXTENCODING_ASCII_US);
246 OSL_TRACE(
247 "cppuhelper::findBoostrapArgument - "
248 "setting %s relative to executable: %s\n",
249 arg_name_dbg.getStr(),
250 result_dbg.getStr() );
251 #endif
252 }
253 else
254 {
255 if(pFallenBack)
256 *pFallenBack = sal_False;
257
258 #if OSL_DEBUG_LEVEL > 1
259 OString prefixed_arg_name_dbg = OUStringToOString(
260 prefixed_arg_name, RTL_TEXTENCODING_ASCII_US );
261 OString result_dbg = OUStringToOString(
262 result, RTL_TEXTENCODING_ASCII_US );
263 OSL_TRACE(
264 "cppuhelper::findBoostrapArgument - found %s in env: %s",
265 prefixed_arg_name_dbg.getStr(),
266 result_dbg.getStr() );
267 #endif
268 }
269
270 return result;
271 }
272
nestRegistries(const OUString baseDir,const Reference<lang::XSingleServiceFactory> & xSimRegFac,const Reference<lang::XSingleServiceFactory> & xNesRegFac,OUString csl_rdbs,const OUString & write_rdb,sal_Bool forceWrite_rdb,sal_Bool bFallenBack)273 Reference< registry::XSimpleRegistry > nestRegistries(
274 const OUString baseDir,
275 const Reference< lang::XSingleServiceFactory > & xSimRegFac,
276 const Reference< lang::XSingleServiceFactory > & xNesRegFac,
277 OUString csl_rdbs,
278 const OUString & write_rdb,
279 sal_Bool forceWrite_rdb,
280 sal_Bool bFallenBack )
281 SAL_THROW((Exception))
282 {
283 sal_Int32 index;
284 Reference< registry::XSimpleRegistry > lastRegistry;
285
286 if(write_rdb.getLength()) // is there a write registry given?
287 {
288 lastRegistry.set(xSimRegFac->createInstance(), UNO_QUERY);
289
290 try
291 {
292 lastRegistry->open(write_rdb, sal_False, forceWrite_rdb);
293 }
294 catch (registry::InvalidRegistryException & invalidRegistryException)
295 {
296 (void) invalidRegistryException;
297 #if OSL_DEBUG_LEVEL > 1
298 OString rdb_name_tmp = OUStringToOString(
299 write_rdb, RTL_TEXTENCODING_ASCII_US);
300 OString message_dbg = OUStringToOString(
301 invalidRegistryException.Message, RTL_TEXTENCODING_ASCII_US);
302 OSL_TRACE(
303 "warning: couldn't open %s cause of %s",
304 rdb_name_tmp.getStr(), message_dbg.getStr() );
305 #endif
306 }
307
308 if(!lastRegistry->isValid())
309 lastRegistry.clear();
310 }
311
312 do
313 {
314 index = csl_rdbs.indexOf((sal_Unicode)' ');
315 OUString rdb_name = (index == -1) ? csl_rdbs : csl_rdbs.copy(0, index);
316 csl_rdbs = (index == -1) ? OUString() : csl_rdbs.copy(index + 1);
317
318 if (! rdb_name.getLength())
319 continue;
320
321 bool optional = ('?' == rdb_name[ 0 ]);
322 if (optional)
323 rdb_name = rdb_name.copy( 1 );
324
325 try
326 {
327 Reference<registry::XSimpleRegistry> simpleRegistry(
328 xSimRegFac->createInstance(), UNO_QUERY_THROW );
329
330 osl::FileBase::getAbsoluteFileURL(baseDir, rdb_name, rdb_name);
331 simpleRegistry->open(rdb_name, sal_True, sal_False);
332
333 if(lastRegistry.is())
334 {
335 Reference< registry::XSimpleRegistry > nestedRegistry(
336 xNesRegFac->createInstance(), UNO_QUERY );
337 Reference< lang::XInitialization > nestedRegistry_xInit(
338 nestedRegistry, UNO_QUERY );
339
340 Sequence<Any> aArgs(2);
341 aArgs[0] <<= lastRegistry;
342 aArgs[1] <<= simpleRegistry;
343
344 nestedRegistry_xInit->initialize(aArgs);
345
346 lastRegistry = nestedRegistry;
347 }
348 else
349 lastRegistry = simpleRegistry;
350 }
351 catch(registry::InvalidRegistryException & invalidRegistryException)
352 {
353 if (! optional)
354 {
355 // if a registry was explicitly given, the exception shall fly
356 if( ! bFallenBack )
357 throw;
358 }
359
360 (void) invalidRegistryException;
361 #if OSL_DEBUG_LEVEL > 1
362 OString rdb_name_tmp = OUStringToOString(
363 rdb_name, RTL_TEXTENCODING_ASCII_US );
364 OString message_dbg = OUStringToOString(
365 invalidRegistryException.Message, RTL_TEXTENCODING_ASCII_US );
366 OSL_TRACE(
367 "warning: couldn't open %s cause of %s",
368 rdb_name_tmp.getStr(), message_dbg.getStr() );
369 #endif
370 }
371 }
372 while(index != -1 && csl_rdbs.getLength()); // are there more rdbs in list?
373
374 return lastRegistry;
375 }
376
377 Reference< XComponentContext >
defaultBootstrap_InitialComponentContext(Bootstrap const & bootstrap)378 SAL_CALL defaultBootstrap_InitialComponentContext(
379 Bootstrap const & bootstrap )
380 SAL_THROW( (Exception) )
381 {
382 primeWeakMap();
383
384 OUString bootstrapPath;
385 if (!bootstrap.getFrom(
386 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_INTERNAL_LIB_DIR")),
387 bootstrapPath))
388 {
389 bootstrapPath = get_this_libpath();
390 }
391
392 OUString iniDir;
393 osl_getProcessWorkingDir(&iniDir.pData);
394
395 Reference<lang::XMultiComponentFactory> smgr_XMultiComponentFactory(
396 bootstrapInitialSF(bootstrapPath) );
397 Reference<lang::XMultiServiceFactory> smgr_XMultiServiceFactory(
398 smgr_XMultiComponentFactory, UNO_QUERY );
399
400 Reference<registry::XRegistryKey> xEmptyKey;
401 Reference<lang::XSingleServiceFactory> xSimRegFac(
402 loadSharedLibComponentFactory(
403 OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath,
404 OUSTR("com.sun.star.comp.stoc.SimpleRegistry"),
405 smgr_XMultiServiceFactory,
406 xEmptyKey),
407 UNO_QUERY);
408
409 Reference<lang::XSingleServiceFactory> xNesRegFac(
410 loadSharedLibComponentFactory(
411 OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath,
412 OUSTR("com.sun.star.comp.stoc.NestedRegistry"),
413 smgr_XMultiServiceFactory,
414 xEmptyKey),
415 UNO_QUERY);
416
417 sal_Bool bFallenback_types;
418 OUString cls_uno_types =
419 findBoostrapArgument( bootstrap, OUSTR("TYPES"), &bFallenback_types );
420
421 Reference<registry::XSimpleRegistry> types_xRegistry =
422 nestRegistries(
423 iniDir, xSimRegFac, xNesRegFac, cls_uno_types,
424 OUString(), sal_False, bFallenback_types );
425
426 // ==== bootstrap from services registry ====
427
428 sal_Bool bFallenback_services;
429 OUString cls_uno_services = findBoostrapArgument(
430 bootstrap, OUSTR("SERVICES"), &bFallenback_services );
431
432 sal_Bool fallenBackWriteRegistry;
433 OUString write_rdb = findBoostrapArgument(
434 bootstrap, OUSTR("WRITERDB"), &fallenBackWriteRegistry );
435 if (fallenBackWriteRegistry)
436 {
437 // no standard write rdb anymore
438 write_rdb = OUString();
439 }
440
441 Reference<registry::XSimpleRegistry> services_xRegistry = nestRegistries(
442 iniDir, xSimRegFac, xNesRegFac, cls_uno_services, write_rdb,
443 !fallenBackWriteRegistry, bFallenback_services );
444
445 Reference< XComponentContext > xContext(
446 bootstrapInitialContext(
447 smgr_XMultiComponentFactory, types_xRegistry, services_xRegistry,
448 bootstrapPath, bootstrap ) );
449
450 // initialize sf
451 Reference< lang::XInitialization > xInit(
452 smgr_XMultiComponentFactory, UNO_QUERY );
453 OSL_ASSERT( xInit.is() );
454 Sequence< Any > aSFInit( 1 );
455 aSFInit[ 0 ] <<= services_xRegistry;
456 xInit->initialize( aSFInit );
457
458 return xContext;
459 }
460
461 }
462
463 Reference< XComponentContext >
defaultBootstrap_InitialComponentContext(OUString const & iniFile)464 SAL_CALL defaultBootstrap_InitialComponentContext(
465 OUString const & iniFile )
466 SAL_THROW( (Exception) )
467 {
468 Bootstrap bootstrap( iniFile );
469 if (bootstrap.getHandle() == 0)
470 throw io::IOException(OUSTR("Cannot open for reading: ") + iniFile, 0);
471 return defaultBootstrap_InitialComponentContext( bootstrap );
472 }
473
474 Reference< XComponentContext >
defaultBootstrap_InitialComponentContext()475 SAL_CALL defaultBootstrap_InitialComponentContext()
476 SAL_THROW( (Exception) )
477 {
478 return defaultBootstrap_InitialComponentContext( get_unorc() );
479 }
480
BootstrapException()481 BootstrapException::BootstrapException()
482 {
483 }
484
BootstrapException(const::rtl::OUString & rMessage)485 BootstrapException::BootstrapException( const ::rtl::OUString & rMessage )
486 :m_aMessage( rMessage )
487 {
488 }
489
BootstrapException(const BootstrapException & e)490 BootstrapException::BootstrapException( const BootstrapException & e )
491 {
492 m_aMessage = e.m_aMessage;
493 }
494
~BootstrapException()495 BootstrapException::~BootstrapException()
496 {
497 }
498
operator =(const BootstrapException & e)499 BootstrapException & BootstrapException::operator=( const BootstrapException & e )
500 {
501 m_aMessage = e.m_aMessage;
502 return *this;
503 }
504
getMessage() const505 const ::rtl::OUString & BootstrapException::getMessage() const
506 {
507 return m_aMessage;
508 }
509
bootstrap()510 Reference< XComponentContext > SAL_CALL bootstrap()
511 {
512 Reference< XComponentContext > xRemoteContext;
513
514 try
515 {
516 char const * p1 = cppuhelper_detail_findSofficePath();
517 if (p1 == NULL) {
518 throw BootstrapException(
519 OUSTR("no soffice installation found!"));
520 }
521 rtl::OUString p2;
522 if (!rtl_convertStringToUString(
523 &p2.pData, p1, strlen(p1), osl_getThreadTextEncoding(),
524 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
525 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
526 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
527 {
528 throw BootstrapException(
529 OUSTR("bad characters in soffice installation path!"));
530 }
531 OUString path;
532 if (osl::FileBase::getFileURLFromSystemPath(p2, path) !=
533 osl::FileBase::E_None)
534 {
535 throw BootstrapException(
536 OUSTR("cannot convert soffice installation path to URL!"));
537 }
538 if (path.getLength() > 0 && path[path.getLength() - 1] != '/') {
539 path += OUSTR("/");
540 }
541
542 OUString uri;
543 if (!Bootstrap::get(OUSTR("URE_BOOTSTRAP"), uri)) {
544 Bootstrap::set(
545 OUSTR("URE_BOOTSTRAP"),
546 Bootstrap::encode(path + OUSTR(SAL_CONFIGFILE("fundamental"))));
547 }
548
549 // create default local component context
550 Reference< XComponentContext > xLocalContext(
551 defaultBootstrap_InitialComponentContext() );
552 if ( !xLocalContext.is() )
553 throw BootstrapException( OUSTR( "no local component context!" ) );
554
555 // create a random pipe name
556 rtlRandomPool hPool = rtl_random_createPool();
557 if ( hPool == 0 )
558 throw BootstrapException( OUSTR( "cannot create random pool!" ) );
559 sal_uInt8 bytes[ 16 ];
560 if ( rtl_random_getBytes( hPool, bytes, ARLEN( bytes ) )
561 != rtl_Random_E_None )
562 throw BootstrapException( OUSTR( "random pool error!" ) );
563 rtl_random_destroyPool( hPool );
564 ::rtl::OUStringBuffer buf;
565 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno" ) );
566 for ( sal_uInt32 i = 0; i < ARLEN( bytes ); ++i )
567 buf.append( static_cast< sal_Int32 >( bytes[ i ] ) );
568 OUString sPipeName( buf.makeStringAndClear() );
569
570 // accept string
571 OSL_ASSERT( buf.getLength() == 0 );
572 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "-accept=pipe,name=" ) );
573 buf.append( sPipeName );
574 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ";urp;" ) );
575
576 // arguments
577 OUString args [] = {
578 OUSTR( "-nologo" ),
579 OUSTR( "-nodefault" ),
580 OUSTR( "-norestore" ),
581 OUSTR( "-nocrashreport" ),
582 OUSTR( "-nolockcheck" ),
583 buf.makeStringAndClear()
584 };
585 rtl_uString * ar_args [] = {
586 args[ 0 ].pData,
587 args[ 1 ].pData,
588 args[ 2 ].pData,
589 args[ 3 ].pData,
590 args[ 4 ].pData,
591 args[ 5 ].pData
592 };
593 ::osl::Security sec;
594
595 // start office process
596 oslProcess hProcess = 0;
597 oslProcessError rc = osl_executeProcess(
598 (path + OUSTR("soffice")).pData, ar_args, ARLEN( ar_args ),
599 osl_Process_DETACHED,
600 sec.getHandle(),
601 0, // => current working dir
602 0, 0, // => no env vars
603 &hProcess );
604 switch ( rc )
605 {
606 case osl_Process_E_None:
607 osl_freeProcessHandle( hProcess );
608 break;
609 case osl_Process_E_NotFound:
610 throw BootstrapException( OUSTR( "image not found!" ) );
611 case osl_Process_E_TimedOut:
612 throw BootstrapException( OUSTR( "timeout occurred!" ) );
613 case osl_Process_E_NoPermission:
614 throw BootstrapException( OUSTR( "permission denied!" ) );
615 case osl_Process_E_Unknown:
616 throw BootstrapException( OUSTR( "unknown error!" ) );
617 case osl_Process_E_InvalidError:
618 default:
619 throw BootstrapException( OUSTR( "unmapped error!" ) );
620 }
621
622 // create a URL resolver
623 Reference< bridge::XUnoUrlResolver > xUrlResolver(
624 bridge::UnoUrlResolver::create( xLocalContext ) );
625
626 // connection string
627 OSL_ASSERT( buf.getLength() == 0 );
628 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno:pipe,name=" ) );
629 buf.append( sPipeName );
630 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
631 ";urp;StarOffice.ComponentContext" ) );
632 OUString sConnectString( buf.makeStringAndClear() );
633
634 // wait until office is started
635 for ( ; ; )
636 {
637 try
638 {
639 // try to connect to office
640 xRemoteContext.set(
641 xUrlResolver->resolve( sConnectString ), UNO_QUERY_THROW );
642 break;
643 }
644 catch ( connection::NoConnectException & )
645 {
646 // wait 500 ms, then try to connect again
647 TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ };
648 ::osl::Thread::wait( tv );
649 }
650 }
651 }
652 catch ( Exception & e )
653 {
654 throw BootstrapException(
655 OUSTR( "unexpected UNO exception caught: " ) + e.Message );
656 }
657
658 return xRemoteContext;
659 }
660
bootstrap_expandUri(OUString const & uri)661 OUString bootstrap_expandUri(OUString const & uri) {
662 static char const PREFIX[] = "vnd.sun.star.expand:";
663 return uri.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX))
664 ? cppuhelper::detail::expandMacros(
665 rtl::Uri::decode(
666 uri.copy(RTL_CONSTASCII_LENGTH(PREFIX)),
667 rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8))
668 : uri;
669 }
670
671 } // namespace cppu
672