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_desktop.hxx" 26 27 #include <algorithm> 28 29 #include "app.hxx" 30 #include "cmdlineargs.hxx" 31 #include "desktopresid.hxx" 32 #include "desktop.hrc" 33 #include <com/sun/star/registry/XSimpleRegistry.hpp> 34 #include <com/sun/star/lang/XComponent.hpp> 35 #include <com/sun/star/lang/XInitialization.hpp> 36 #include <com/sun/star/uno/Exception.hpp> 37 #include <com/sun/star/uno/XCurrentContext.hpp> 38 #include <com/sun/star/packages/zip/ZipIOException.hpp> 39 40 41 #include <com/sun/star/beans/XPropertySet.hpp> 42 #include <com/sun/star/container/XContentEnumerationAccess.hpp> 43 #include <com/sun/star/ucb/XContentProviderManager.hpp> 44 #include <com/sun/star/ucb/XContentProviderFactory.hpp> 45 #include <uno/current_context.hxx> 46 #include <cppuhelper/servicefactory.hxx> 47 #include <cppuhelper/bootstrap.hxx> 48 #include <osl/file.hxx> 49 #include <osl/module.h> 50 #include <vos/process.hxx> 51 #include <rtl/uri.hxx> 52 #include <rtl/ustrbuf.hxx> 53 #include <rtl/bootstrap.hxx> 54 #include <comphelper/regpathhelper.hxx> 55 #include <tools/debug.hxx> 56 #include <tools/tempfile.hxx> 57 #include <ucbhelper/configurationkeys.hxx> 58 59 #include <cppuhelper/bootstrap.hxx> 60 #include <tools/urlobj.hxx> 61 #include <tools/rcid.h> 62 63 #include <rtl/logfile.hxx> 64 #include <rtl/instance.hxx> 65 #include <comphelper/processfactory.hxx> 66 #include <unotools/localfilehelper.hxx> 67 #include <unotools/ucbhelper.hxx> 68 #include <unotools/tempfile.hxx> 69 #include <ucbhelper/contentbroker.hxx> 70 #include <vcl/svapp.hxx> 71 #include <unotools/startoptions.hxx> 72 #include <unotools/pathoptions.hxx> 73 #include <unotools/internaloptions.hxx> 74 75 76 #define DEFINE_CONST_OUSTRING(CONSTASCII) OUString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) 77 78 #define DESKTOP_TEMPDIRNAME "soffice.tmp" 79 80 using namespace rtl; 81 using namespace vos; 82 using namespace desktop; 83 using namespace ::com::sun::star::uno; 84 using namespace ::com::sun::star::lang; 85 using namespace ::com::sun::star::beans; 86 using namespace ::com::sun::star::registry; 87 using namespace ::com::sun::star::ucb; 88 89 namespace desktop 90 { 91 92 // ----------------------------------------------------------------------------- 93 94 static bool configureUcb(bool bServer, rtl::OUString const & rPortalConnect) 95 { 96 RTL_LOGFILE_CONTEXT( aLog, "desktop (sb93797) ::configureUcb" ); 97 Reference< XMultiServiceFactory > 98 xServiceFactory( comphelper::getProcessServiceFactory() ); 99 if (!xServiceFactory.is()) 100 { 101 DBG_ERROR("configureUcb(): No XMultiServiceFactory"); 102 return false; 103 } 104 105 rtl::OUString aPipe; 106 vos::OSecurity().getUserIdent(aPipe); 107 108 rtl::OUStringBuffer aPortal; 109 if (rPortalConnect.getLength() != 0) 110 { 111 aPortal.append(sal_Unicode(',')); 112 aPortal.append(rPortalConnect); 113 } 114 115 Sequence< Any > aArgs(6); 116 aArgs[0] 117 <<= rtl::OUString::createFromAscii(bServer ? 118 UCB_CONFIGURATION_KEY1_SERVER : 119 UCB_CONFIGURATION_KEY1_LOCAL); 120 aArgs[1] 121 <<= rtl::OUString::createFromAscii(UCB_CONFIGURATION_KEY2_OFFICE); 122 aArgs[2] <<= rtl::OUString::createFromAscii("PIPE"); 123 aArgs[3] <<= aPipe; 124 aArgs[4] <<= rtl::OUString::createFromAscii("PORTAL"); 125 aArgs[5] <<= aPortal.makeStringAndClear(); 126 127 bool ret = 128 ::ucbhelper::ContentBroker::initialize( xServiceFactory, aArgs ) != false; 129 130 #ifdef GNOME_VFS_ENABLED 131 // register GnomeUCP if necessary 132 ::ucbhelper::ContentBroker* cb = ::ucbhelper::ContentBroker::get(); 133 if(cb) { 134 try { 135 Reference< XCurrentContext > xCurrentContext( 136 getCurrentContext()); 137 if (xCurrentContext.is()) 138 { 139 Any aValue = xCurrentContext->getValueByName( 140 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 141 "system.desktop-environment" ) ) 142 ); 143 rtl::OUString aDesktopEnvironment; 144 if ((aValue >>= aDesktopEnvironment) 145 && aDesktopEnvironment.equalsAscii("GNOME")) 146 { 147 Reference<XContentProviderManager> xCPM = 148 cb->getContentProviderManagerInterface(); 149 #if 0 150 try 151 { 152 153 Reference<XContentProviderFactory> xCPF( 154 xServiceFactory->createInstance( 155 rtl::OUString::createFromAscii( 156 "com.sun.star.ucb.ContentProviderProxyFactory")), 157 UNO_QUERY); 158 if(xCPF.is()) 159 xCPM->registerContentProvider( 160 xCPF->createContentProvider( 161 rtl::OUString::createFromAscii( 162 "com.sun.star.ucb.GnomeVFSContentProvider" 163 ) 164 ), 165 rtl::OUString::createFromAscii(".*"), 166 false); 167 } catch (...) 168 { 169 } 170 #else 171 172 // Workaround for P1 #124597#. Instanciate GNOME-VFS-UCP in the thread that initialized 173 // GNOME in order to avoid a deadlock that may occure in case UCP gets initialized from 174 // a different thread. The latter may happen when calling the Office remotely via UNO. 175 // THIS IS NOT A FIX, JUST A WORKAROUND! 176 177 try 178 { 179 Reference<XContentProvider> xCP( 180 xServiceFactory->createInstance( 181 rtl::OUString::createFromAscii( 182 "com.sun.star.ucb.GnomeVFSContentProvider")), 183 UNO_QUERY); 184 if(xCP.is()) 185 xCPM->registerContentProvider( 186 xCP, 187 rtl::OUString::createFromAscii(".*"), 188 false); 189 } catch (...) 190 { 191 } 192 } 193 #endif 194 } 195 } catch (RuntimeException e) { 196 } 197 } 198 #endif // GNOME_VFS_ENABLED 199 200 return ret;; 201 } 202 203 Reference< XMultiServiceFactory > Desktop::CreateApplicationServiceManager() 204 { 205 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createApplicationServiceManager" ); 206 207 try 208 { 209 Reference<XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext(); 210 Reference<XMultiServiceFactory> xMS(xComponentContext->getServiceManager(), UNO_QUERY); 211 212 return xMS; 213 } 214 catch( ::com::sun::star::uno::Exception& ) 215 { 216 } 217 218 return Reference< XMultiServiceFactory >(); 219 } 220 221 void Desktop::DestroyApplicationServiceManager( Reference< XMultiServiceFactory >& xSMgr ) 222 { 223 Reference< XPropertySet > xProps( xSMgr, UNO_QUERY ); 224 if ( xProps.is() ) 225 { 226 try 227 { 228 Reference< XComponent > xComp; 229 if (xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComp ) 230 { 231 xComp->dispose(); 232 } 233 } 234 catch ( UnknownPropertyException& ) 235 { 236 } 237 } 238 } 239 240 void Desktop::RegisterServices( Reference< XMultiServiceFactory >& xSMgr ) 241 { 242 if( !m_bServicesRegistered ) 243 { 244 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::registerServices" ); 245 246 // read command line parameters 247 ::rtl::OUString conDcp; 248 ::rtl::OUString aClientDisplay; 249 ::rtl::OUString aTmpString; 250 sal_Bool bHeadlessMode = sal_False; 251 252 // interpret command line arguments 253 CommandLineArgs* pCmdLine = GetCommandLineArgs(); 254 255 // read accept string from configuration 256 conDcp = SvtStartOptions().GetConnectionURL(); 257 258 if ( pCmdLine->GetAcceptString( aTmpString )) 259 conDcp = aTmpString; 260 261 // Headless mode for FAT Office 262 bHeadlessMode = pCmdLine->IsHeadless(); 263 if ( bHeadlessMode ) 264 Application::EnableHeadlessMode(); 265 266 // ConversionMode 267 if ( pCmdLine->IsConversionMode() ) 268 Application::EnableConversionMode(); 269 270 if ( conDcp.getLength() > 0 ) 271 { 272 // accept incoming connections (scripting and one rvp) 273 RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) desktop::Desktop::createAcceptor()" ); 274 createAcceptor(conDcp); 275 } 276 277 // improves parallel processing on Sun ONE Webtop 278 // servicemanager up -> copy user installation 279 if ( pCmdLine->IsServer() ) 280 { 281 // Check some mandatory environment states if "-server" is possible. Otherwise ignore 282 // this parameter. 283 Reference< com::sun::star::container::XContentEnumerationAccess > rContent( xSMgr , UNO_QUERY ); 284 if( rContent.is() ) 285 { 286 OUString sPortalService = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.portal.InstallUser" ) ); 287 Reference < com::sun::star::container::XEnumeration > rEnum = rContent->createContentEnumeration( sPortalService ); 288 if ( !rEnum.is() ) 289 { 290 // Reset server parameter so it is ignored in the furthermore startup process 291 pCmdLine->SetBoolParam( CommandLineArgs::CMD_BOOLPARAM_SERVER, sal_False ); 292 } 293 } 294 } 295 296 ::rtl::OUString aPortalConnect; 297 bool bServer = (bool)pCmdLine->IsServer(); 298 299 pCmdLine->GetPortalConnectString( aPortalConnect ); 300 if ( !configureUcb( bServer, aPortalConnect ) ) 301 { 302 DBG_ERROR( "Can't configure UCB" ); 303 throw com::sun::star::uno::Exception(rtl::OUString::createFromAscii("RegisterServices, configureUcb"), NULL); 304 } 305 306 CreateTemporaryDirectory(); 307 m_bServicesRegistered = true; 308 } 309 } 310 311 namespace 312 { 313 struct acceptorMap : public rtl::Static< AcceptorMap, acceptorMap > {}; 314 struct CurrentTempURL : public rtl::Static< String, CurrentTempURL > {}; 315 } 316 317 static sal_Bool bAccept = sal_False; 318 319 void Desktop::createAcceptor(const OUString& aAcceptString) 320 { 321 // check whether the requested acceptor already exists 322 AcceptorMap &rMap = acceptorMap::get(); 323 AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); 324 if (pIter == rMap.end() ) { 325 326 Sequence< Any > aSeq( 2 ); 327 aSeq[0] <<= aAcceptString; 328 aSeq[1] <<= bAccept; 329 Reference<XInitialization> rAcceptor( 330 ::comphelper::getProcessServiceFactory()->createInstance( 331 OUString::createFromAscii( "com.sun.star.office.Acceptor" )), UNO_QUERY ); 332 if ( rAcceptor.is() ) { 333 try{ 334 rAcceptor->initialize( aSeq ); 335 rMap.insert(AcceptorMap::value_type(aAcceptString, rAcceptor)); 336 } catch (com::sun::star::uno::Exception&) { 337 // no error handling needed... 338 // acceptor just won't come up 339 OSL_ENSURE(sal_False, "Acceptor could not be created."); 340 } 341 } else { 342 // there is already an acceptor with this description 343 OSL_ENSURE(sal_False, "Acceptor already exists."); 344 } 345 346 } 347 } 348 349 class enable 350 { 351 private: 352 Sequence<Any> m_aSeq; 353 public: 354 enable() : m_aSeq(1) { 355 m_aSeq[0] <<= sal_True; 356 } 357 void operator() (const AcceptorMap::value_type& val) { 358 if (val.second.is()) { 359 val.second->initialize(m_aSeq); 360 } 361 } 362 }; 363 364 void Desktop::enableAcceptors() 365 { 366 RTL_LOGFILE_CONTEXT(aLog, "desktop (lo119109) Desktop::enableAcceptors"); 367 if (!bAccept) 368 { 369 // from now on, all new acceptors are enabled 370 bAccept = sal_True; 371 // enable existing acceptors by calling initialize(true) 372 // on all existing acceptors 373 AcceptorMap &rMap = acceptorMap::get(); 374 std::for_each(rMap.begin(), rMap.end(), enable()); 375 } 376 } 377 378 void Desktop::destroyAcceptor(const OUString& aAcceptString) 379 { 380 // special case stop all acceptors 381 AcceptorMap &rMap = acceptorMap::get(); 382 if (aAcceptString.compareToAscii("all") == 0) { 383 rMap.clear(); 384 385 } else { 386 // try to remove acceptor from map 387 AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); 388 if (pIter != rMap.end() ) { 389 // remove reference from map 390 // this is the last reference and the acceptor will be destructed 391 rMap.erase(aAcceptString); 392 } else { 393 OSL_ENSURE(sal_False, "Found no acceptor to remove"); 394 } 395 } 396 } 397 398 399 void Desktop::DeregisterServices() 400 { 401 // stop all acceptors by clearing the map 402 acceptorMap::get().clear(); 403 } 404 405 void Desktop::CreateTemporaryDirectory() 406 { 407 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createTemporaryDirectory" ); 408 409 ::rtl::OUString aTempBaseURL; 410 try 411 { 412 SvtPathOptions aOpt; 413 aTempBaseURL = aOpt.GetTempPath(); 414 } 415 catch ( RuntimeException& e ) 416 { 417 // Catch runtime exception here: We have to add language dependent info 418 // to the exception message. Fallback solution uses hard coded string. 419 OUString aMsg; 420 DesktopResId aResId( STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE ); 421 aResId.SetRT( RSC_STRING ); 422 if ( aResId.GetResMgr()->IsAvailable( aResId )) 423 aMsg = String( aResId ); 424 else 425 aMsg = OUString( RTL_CONSTASCII_USTRINGPARAM( "The path manager is not available.\n" )); 426 e.Message = aMsg + e.Message; 427 throw e; 428 } 429 430 // remove possible old directory and base directory 431 SvtInternalOptions aInternalOpt; 432 433 // set temp base directory 434 sal_Int32 nLength = aTempBaseURL.getLength(); 435 if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) 436 aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); 437 438 String aOldTempURL = aInternalOpt.GetCurrentTempURL(); 439 if ( aOldTempURL.Len() > 0 ) 440 { 441 // remove old temporary directory 442 ::utl::UCBContentHelper::Kill( aOldTempURL ); 443 } 444 445 String aRet; 446 ::rtl::OUString aTempPath( aTempBaseURL ); 447 448 // create new current temporary directory 449 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTempBaseURL, aRet ); 450 ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); 451 aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); 452 if ( !aTempPath.getLength() ) 453 { 454 ::osl::File::getTempDirURL( aTempBaseURL ); 455 456 nLength = aTempBaseURL.getLength(); 457 if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) 458 aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); 459 460 aTempPath = aTempBaseURL; 461 ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); 462 aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); 463 } 464 465 // set new current temporary directory 466 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aTempPath, aRet ); 467 aInternalOpt.SetCurrentTempURL( aRet ); 468 CurrentTempURL::get() = aRet; 469 } 470 471 void Desktop::RemoveTemporaryDirectory() 472 { 473 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::removeTemporaryDirectory" ); 474 475 // remove current temporary directory 476 String &rCurrentTempURL = CurrentTempURL::get(); 477 if ( rCurrentTempURL.Len() > 0 ) 478 { 479 if ( ::utl::UCBContentHelper::Kill( rCurrentTempURL ) ) 480 SvtInternalOptions().SetCurrentTempURL( String() ); 481 } 482 } 483 484 } // namespace desktop 485