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