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_desktop.hxx" 30 31 #include <algorithm> 32 33 #include "app.hxx" 34 #include "cmdlineargs.hxx" 35 #include "desktopresid.hxx" 36 #include "desktop.hrc" 37 #include <com/sun/star/registry/XSimpleRegistry.hpp> 38 #include <com/sun/star/lang/XComponent.hpp> 39 #include <com/sun/star/lang/XInitialization.hpp> 40 #include <com/sun/star/uno/Exception.hpp> 41 #include <com/sun/star/uno/XCurrentContext.hpp> 42 #include <com/sun/star/packages/zip/ZipIOException.hpp> 43 44 45 #include <com/sun/star/beans/XPropertySet.hpp> 46 #include <com/sun/star/container/XContentEnumerationAccess.hpp> 47 #include <com/sun/star/ucb/XContentProviderManager.hpp> 48 #include <com/sun/star/ucb/XContentProviderFactory.hpp> 49 #include <uno/current_context.hxx> 50 #include <cppuhelper/servicefactory.hxx> 51 #include <cppuhelper/bootstrap.hxx> 52 #include <osl/file.hxx> 53 #include <osl/module.h> 54 #include <vos/process.hxx> 55 #include <rtl/uri.hxx> 56 #include <rtl/ustrbuf.hxx> 57 #include <rtl/bootstrap.hxx> 58 #include <comphelper/regpathhelper.hxx> 59 #include <tools/debug.hxx> 60 #include <tools/tempfile.hxx> 61 #include <ucbhelper/configurationkeys.hxx> 62 63 #include <cppuhelper/bootstrap.hxx> 64 #include <tools/urlobj.hxx> 65 #include <tools/rcid.h> 66 67 #include <rtl/logfile.hxx> 68 #include <rtl/instance.hxx> 69 #include <comphelper/processfactory.hxx> 70 #include <unotools/localfilehelper.hxx> 71 #include <unotools/ucbhelper.hxx> 72 #include <unotools/tempfile.hxx> 73 #include <ucbhelper/contentbroker.hxx> 74 #include <vcl/svapp.hxx> 75 #include <unotools/startoptions.hxx> 76 #include <unotools/pathoptions.hxx> 77 #include <unotools/internaloptions.hxx> 78 79 80 #define DEFINE_CONST_OUSTRING(CONSTASCII) OUString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) 81 82 #define DESKTOP_TEMPDIRNAME "soffice.tmp" 83 84 using namespace rtl; 85 using namespace vos; 86 using namespace desktop; 87 using namespace ::com::sun::star::uno; 88 using namespace ::com::sun::star::lang; 89 using namespace ::com::sun::star::beans; 90 using namespace ::com::sun::star::registry; 91 using namespace ::com::sun::star::ucb; 92 93 namespace desktop 94 { 95 96 // ----------------------------------------------------------------------------- 97 98 static bool configureUcb(bool bServer, rtl::OUString const & rPortalConnect) 99 { 100 RTL_LOGFILE_CONTEXT( aLog, "desktop (sb93797) ::configureUcb" ); 101 Reference< XMultiServiceFactory > 102 xServiceFactory( comphelper::getProcessServiceFactory() ); 103 if (!xServiceFactory.is()) 104 { 105 DBG_ERROR("configureUcb(): No XMultiServiceFactory"); 106 return false; 107 } 108 109 rtl::OUString aPipe; 110 vos::OSecurity().getUserIdent(aPipe); 111 112 rtl::OUStringBuffer aPortal; 113 if (rPortalConnect.getLength() != 0) 114 { 115 aPortal.append(sal_Unicode(',')); 116 aPortal.append(rPortalConnect); 117 } 118 119 Sequence< Any > aArgs(6); 120 aArgs[0] 121 <<= rtl::OUString::createFromAscii(bServer ? 122 UCB_CONFIGURATION_KEY1_SERVER : 123 UCB_CONFIGURATION_KEY1_LOCAL); 124 aArgs[1] 125 <<= rtl::OUString::createFromAscii(UCB_CONFIGURATION_KEY2_OFFICE); 126 aArgs[2] <<= rtl::OUString::createFromAscii("PIPE"); 127 aArgs[3] <<= aPipe; 128 aArgs[4] <<= rtl::OUString::createFromAscii("PORTAL"); 129 aArgs[5] <<= aPortal.makeStringAndClear(); 130 131 bool ret = 132 ::ucbhelper::ContentBroker::initialize( xServiceFactory, aArgs ) != false; 133 134 #ifdef GNOME_VFS_ENABLED 135 // register GnomeUCP if necessary 136 ::ucbhelper::ContentBroker* cb = ::ucbhelper::ContentBroker::get(); 137 if(cb) { 138 try { 139 Reference< XCurrentContext > xCurrentContext( 140 getCurrentContext()); 141 if (xCurrentContext.is()) 142 { 143 Any aValue = xCurrentContext->getValueByName( 144 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 145 "system.desktop-environment" ) ) 146 ); 147 rtl::OUString aDesktopEnvironment; 148 if ((aValue >>= aDesktopEnvironment) 149 && aDesktopEnvironment.equalsAscii("GNOME")) 150 { 151 Reference<XContentProviderManager> xCPM = 152 cb->getContentProviderManagerInterface(); 153 #if 0 154 try 155 { 156 157 Reference<XContentProviderFactory> xCPF( 158 xServiceFactory->createInstance( 159 rtl::OUString::createFromAscii( 160 "com.sun.star.ucb.ContentProviderProxyFactory")), 161 UNO_QUERY); 162 if(xCPF.is()) 163 xCPM->registerContentProvider( 164 xCPF->createContentProvider( 165 rtl::OUString::createFromAscii( 166 "com.sun.star.ucb.GnomeVFSContentProvider" 167 ) 168 ), 169 rtl::OUString::createFromAscii(".*"), 170 false); 171 } catch (...) 172 { 173 } 174 #else 175 176 // Workaround for P1 #124597#. Instanciate GNOME-VFS-UCP in the thread that initialized 177 // GNOME in order to avoid a deadlock that may occure in case UCP gets initialized from 178 // a different thread. The latter may happen when calling the Office remotely via UNO. 179 // THIS IS NOT A FIX, JUST A WORKAROUND! 180 181 try 182 { 183 Reference<XContentProvider> xCP( 184 xServiceFactory->createInstance( 185 rtl::OUString::createFromAscii( 186 "com.sun.star.ucb.GnomeVFSContentProvider")), 187 UNO_QUERY); 188 if(xCP.is()) 189 xCPM->registerContentProvider( 190 xCP, 191 rtl::OUString::createFromAscii(".*"), 192 false); 193 } catch (...) 194 { 195 } 196 } 197 #endif 198 } 199 } catch (RuntimeException e) { 200 } 201 } 202 #endif // GNOME_VFS_ENABLED 203 204 return ret;; 205 } 206 207 Reference< XMultiServiceFactory > Desktop::CreateApplicationServiceManager() 208 { 209 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createApplicationServiceManager" ); 210 211 try 212 { 213 Reference<XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext(); 214 Reference<XMultiServiceFactory> xMS(xComponentContext->getServiceManager(), UNO_QUERY); 215 216 return xMS; 217 } 218 catch( ::com::sun::star::uno::Exception& ) 219 { 220 } 221 222 return Reference< XMultiServiceFactory >(); 223 } 224 225 void Desktop::DestroyApplicationServiceManager( Reference< XMultiServiceFactory >& xSMgr ) 226 { 227 Reference< XPropertySet > xProps( xSMgr, UNO_QUERY ); 228 if ( xProps.is() ) 229 { 230 try 231 { 232 Reference< XComponent > xComp; 233 if (xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComp ) 234 { 235 xComp->dispose(); 236 } 237 } 238 catch ( UnknownPropertyException& ) 239 { 240 } 241 } 242 } 243 244 void Desktop::RegisterServices( Reference< XMultiServiceFactory >& xSMgr ) 245 { 246 if( !m_bServicesRegistered ) 247 { 248 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::registerServices" ); 249 250 // read command line parameters 251 ::rtl::OUString conDcp; 252 ::rtl::OUString aClientDisplay; 253 ::rtl::OUString aTmpString; 254 sal_Bool bHeadlessMode = sal_False; 255 256 // interpret command line arguments 257 CommandLineArgs* pCmdLine = GetCommandLineArgs(); 258 259 // read accept string from configuration 260 conDcp = SvtStartOptions().GetConnectionURL(); 261 262 if ( pCmdLine->GetAcceptString( aTmpString )) 263 conDcp = aTmpString; 264 265 // Headless mode for FAT Office 266 bHeadlessMode = pCmdLine->IsHeadless(); 267 if ( bHeadlessMode ) 268 Application::EnableHeadlessMode(); 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