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
configureUcb(bool bServer,rtl::OUString const & rPortalConnect)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 occur 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
CreateApplicationServiceManager()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
DestroyApplicationServiceManager(Reference<XMultiServiceFactory> & xSMgr)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
RegisterServices(Reference<XMultiServiceFactory> & xSMgr)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
createAcceptor(const OUString & aAcceptString)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:
enable()354 enable() : m_aSeq(1) {
355 m_aSeq[0] <<= sal_True;
356 }
operator ()(const AcceptorMap::value_type & val)357 void operator() (const AcceptorMap::value_type& val) {
358 if (val.second.is()) {
359 val.second->initialize(m_aSeq);
360 }
361 }
362 };
363
enableAcceptors()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
destroyAcceptor(const OUString & aAcceptString)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
DeregisterServices()399 void Desktop::DeregisterServices()
400 {
401 // stop all acceptors by clearing the map
402 acceptorMap::get().clear();
403 }
404
CreateTemporaryDirectory()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
RemoveTemporaryDirectory()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