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 if ( conDcp.getLength() > 0 ) 267 { 268 // accept incoming connections (scripting and one rvp) 269 RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) desktop::Desktop::createAcceptor()" ); 270 createAcceptor(conDcp); 271 } 272 273 // improves parallel processing on Sun ONE Webtop 274 // servicemanager up -> copy user installation 275 if ( pCmdLine->IsServer() ) 276 { 277 // Check some mandatory environment states if "-server" is possible. Otherwise ignore 278 // this parameter. 279 Reference< com::sun::star::container::XContentEnumerationAccess > rContent( xSMgr , UNO_QUERY ); 280 if( rContent.is() ) 281 { 282 OUString sPortalService = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.portal.InstallUser" ) ); 283 Reference < com::sun::star::container::XEnumeration > rEnum = rContent->createContentEnumeration( sPortalService ); 284 if ( !rEnum.is() ) 285 { 286 // Reset server parameter so it is ignored in the furthermore startup process 287 pCmdLine->SetBoolParam( CommandLineArgs::CMD_BOOLPARAM_SERVER, sal_False ); 288 } 289 } 290 } 291 292 ::rtl::OUString aPortalConnect; 293 bool bServer = (bool)pCmdLine->IsServer(); 294 295 pCmdLine->GetPortalConnectString( aPortalConnect ); 296 if ( !configureUcb( bServer, aPortalConnect ) ) 297 { 298 DBG_ERROR( "Can't configure UCB" ); 299 throw com::sun::star::uno::Exception(rtl::OUString::createFromAscii("RegisterServices, configureUcb"), NULL); 300 } 301 302 CreateTemporaryDirectory(); 303 m_bServicesRegistered = true; 304 } 305 } 306 307 namespace 308 { 309 struct acceptorMap : public rtl::Static< AcceptorMap, acceptorMap > {}; 310 struct CurrentTempURL : public rtl::Static< String, CurrentTempURL > {}; 311 } 312 313 static sal_Bool bAccept = sal_False; 314 315 void Desktop::createAcceptor(const OUString& aAcceptString) 316 { 317 // check whether the requested acceptor already exists 318 AcceptorMap &rMap = acceptorMap::get(); 319 AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); 320 if (pIter == rMap.end() ) { 321 322 Sequence< Any > aSeq( 2 ); 323 aSeq[0] <<= aAcceptString; 324 aSeq[1] <<= bAccept; 325 Reference<XInitialization> rAcceptor( 326 ::comphelper::getProcessServiceFactory()->createInstance( 327 OUString::createFromAscii( "com.sun.star.office.Acceptor" )), UNO_QUERY ); 328 if ( rAcceptor.is() ) { 329 try{ 330 rAcceptor->initialize( aSeq ); 331 rMap.insert(AcceptorMap::value_type(aAcceptString, rAcceptor)); 332 } catch (com::sun::star::uno::Exception&) { 333 // no error handling needed... 334 // acceptor just won't come up 335 OSL_ENSURE(sal_False, "Acceptor could not be created."); 336 } 337 } else { 338 // there is already an acceptor with this description 339 OSL_ENSURE(sal_False, "Acceptor already exists."); 340 } 341 342 } 343 } 344 345 class enable 346 { 347 private: 348 Sequence<Any> m_aSeq; 349 public: 350 enable() : m_aSeq(1) { 351 m_aSeq[0] <<= sal_True; 352 } 353 void operator() (const AcceptorMap::value_type& val) { 354 if (val.second.is()) { 355 val.second->initialize(m_aSeq); 356 } 357 } 358 }; 359 360 void Desktop::enableAcceptors() 361 { 362 RTL_LOGFILE_CONTEXT(aLog, "desktop (lo119109) Desktop::enableAcceptors"); 363 if (!bAccept) 364 { 365 // from now on, all new acceptors are enabled 366 bAccept = sal_True; 367 // enable existing acceptors by calling initialize(true) 368 // on all existing acceptors 369 AcceptorMap &rMap = acceptorMap::get(); 370 std::for_each(rMap.begin(), rMap.end(), enable()); 371 } 372 } 373 374 void Desktop::destroyAcceptor(const OUString& aAcceptString) 375 { 376 // special case stop all acceptors 377 AcceptorMap &rMap = acceptorMap::get(); 378 if (aAcceptString.compareToAscii("all") == 0) { 379 rMap.clear(); 380 381 } else { 382 // try to remove acceptor from map 383 AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); 384 if (pIter != rMap.end() ) { 385 // remove reference from map 386 // this is the last reference and the acceptor will be destructed 387 rMap.erase(aAcceptString); 388 } else { 389 OSL_ENSURE(sal_False, "Found no acceptor to remove"); 390 } 391 } 392 } 393 394 395 void Desktop::DeregisterServices() 396 { 397 // stop all acceptors by clearing the map 398 acceptorMap::get().clear(); 399 } 400 401 void Desktop::CreateTemporaryDirectory() 402 { 403 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createTemporaryDirectory" ); 404 405 ::rtl::OUString aTempBaseURL; 406 try 407 { 408 SvtPathOptions aOpt; 409 aTempBaseURL = aOpt.GetTempPath(); 410 } 411 catch ( RuntimeException& e ) 412 { 413 // Catch runtime exception here: We have to add language dependent info 414 // to the exception message. Fallback solution uses hard coded string. 415 OUString aMsg; 416 DesktopResId aResId( STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE ); 417 aResId.SetRT( RSC_STRING ); 418 if ( aResId.GetResMgr()->IsAvailable( aResId )) 419 aMsg = String( aResId ); 420 else 421 aMsg = OUString( RTL_CONSTASCII_USTRINGPARAM( "The path manager is not available.\n" )); 422 e.Message = aMsg + e.Message; 423 throw e; 424 } 425 426 // remove possible old directory and base directory 427 SvtInternalOptions aInternalOpt; 428 429 // set temp base directory 430 sal_Int32 nLength = aTempBaseURL.getLength(); 431 if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) 432 aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); 433 434 String aOldTempURL = aInternalOpt.GetCurrentTempURL(); 435 if ( aOldTempURL.Len() > 0 ) 436 { 437 // remove old temporary directory 438 ::utl::UCBContentHelper::Kill( aOldTempURL ); 439 } 440 441 String aRet; 442 ::rtl::OUString aTempPath( aTempBaseURL ); 443 444 // create new current temporary directory 445 ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTempBaseURL, aRet ); 446 ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); 447 aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); 448 if ( !aTempPath.getLength() ) 449 { 450 ::osl::File::getTempDirURL( aTempBaseURL ); 451 452 nLength = aTempBaseURL.getLength(); 453 if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) 454 aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); 455 456 aTempPath = aTempBaseURL; 457 ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); 458 aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); 459 } 460 461 // set new current temporary directory 462 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aTempPath, aRet ); 463 aInternalOpt.SetCurrentTempURL( aRet ); 464 CurrentTempURL::get() = aRet; 465 } 466 467 void Desktop::RemoveTemporaryDirectory() 468 { 469 RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::removeTemporaryDirectory" ); 470 471 // remove current temporary directory 472 String &rCurrentTempURL = CurrentTempURL::get(); 473 if ( rCurrentTempURL.Len() > 0 ) 474 { 475 if ( ::utl::UCBContentHelper::Kill( rCurrentTempURL ) ) 476 SvtInternalOptions().SetCurrentTempURL( String() ); 477 } 478 } 479 480 } // namespace desktop 481