Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "app.hxx"
31 : : #include "officeipcthread.hxx"
32 : : #include "cmdlineargs.hxx"
33 : : #include "dispatchwatcher.hxx"
34 : : #include <memory>
35 : : #include <stdio.h>
36 : : #include <osl/process.h>
37 : : #include <unotools/bootstrap.hxx>
38 : : #include <vcl/svapp.hxx>
39 : : #include <vcl/help.hxx>
40 : : #include <unotools/configmgr.hxx>
41 : : #include <osl/thread.hxx>
42 : : #include <rtl/digest.h>
43 : : #include <rtl/ustrbuf.hxx>
44 : : #include <rtl/instance.hxx>
45 : : #include <osl/conditn.hxx>
46 : : #include <unotools/moduleoptions.hxx>
47 : : #include <rtl/bootstrap.hxx>
48 : : #include <rtl/strbuf.hxx>
49 : : #include <comphelper/processfactory.hxx>
50 : : #include <osl/file.hxx>
51 : : #include <rtl/process.h>
52 : : #include "tools/getprocessworkingdir.hxx"
53 : :
54 : : using namespace desktop;
55 : : using namespace ::com::sun::star::uno;
56 : : using namespace ::com::sun::star::lang;
57 : : using namespace ::com::sun::star::frame;
58 : :
59 : : using ::rtl::OString;
60 : : using ::rtl::OUString;
61 : : using ::rtl::OUStringBuffer;
62 : :
63 : : const char *OfficeIPCThread::sc_aTerminationSequence = "InternalIPC::TerminateThread";
64 : : const int OfficeIPCThread::sc_nTSeqLength = 28;
65 : : const char *OfficeIPCThread::sc_aShowSequence = "-tofront";
66 : : const int OfficeIPCThread::sc_nShSeqLength = 5;
67 : : const char *OfficeIPCThread::sc_aConfirmationSequence = "InternalIPC::ProcessingDone";
68 : : const int OfficeIPCThread::sc_nCSeqLength = 27;
69 : :
70 : : namespace { static char const ARGUMENT_PREFIX[] = "InternalIPC::Arguments"; }
71 : :
72 : : // Type of pipe we use
73 : : enum PipeMode
74 : : {
75 : : PIPEMODE_DONTKNOW,
76 : : PIPEMODE_CREATED,
77 : : PIPEMODE_CONNECTED
78 : : };
79 : :
80 : : namespace desktop
81 : : {
82 : :
83 : : namespace {
84 : :
85 : : class Parser: public CommandLineArgs::Supplier {
86 : : public:
87 [ # # ]: 0 : explicit Parser(rtl::OString const & input): m_input(input) {
88 [ # # ]: 0 : if (!m_input.match(ARGUMENT_PREFIX) ||
[ # # # # ]
89 : 0 : m_input.getLength() == RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX))
90 : : {
91 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
92 : : }
93 : 0 : m_index = RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX);
94 [ # # # # ]: 0 : switch (m_input[m_index++]) {
95 : : case '0':
96 : 0 : break;
97 : : case '1':
98 : : {
99 : 0 : rtl::OUString url;
100 [ # # ][ # # ]: 0 : if (!next(&url, false)) {
101 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
102 : : }
103 [ # # ]: 0 : m_cwdUrl.reset(url);
104 : 0 : break;
105 : : }
106 : : case '2':
107 : : {
108 : 0 : rtl::OUString path;
109 [ # # ][ # # ]: 0 : if (!next(&path, false)) {
110 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
111 : : }
112 : 0 : rtl::OUString url;
113 [ # # ][ # # ]: 0 : if (osl::FileBase::getFileURLFromSystemPath(path, url) ==
114 : : osl::FileBase::E_None)
115 : : {
116 [ # # ]: 0 : m_cwdUrl.reset(url);
117 : : }
118 : 0 : break;
119 : : }
120 : : default:
121 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
122 : : }
123 : 0 : }
124 : :
125 [ # # ][ # # ]: 0 : virtual ~Parser() {}
126 : :
127 : 0 : virtual boost::optional< rtl::OUString > getCwdUrl() { return m_cwdUrl; }
128 : :
129 : 0 : virtual bool next(rtl::OUString * argument) { return next(argument, true); }
130 : :
131 : : private:
132 : 0 : virtual bool next(rtl::OUString * argument, bool prefix) {
133 : : OSL_ASSERT(argument != NULL);
134 [ # # ]: 0 : if (m_index < m_input.getLength()) {
135 [ # # ]: 0 : if (prefix) {
136 [ # # ]: 0 : if (m_input[m_index] != ',') {
137 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
138 : : }
139 : 0 : ++m_index;
140 : : }
141 : 0 : rtl::OStringBuffer b;
142 [ # # ]: 0 : while (m_index < m_input.getLength()) {
143 : 0 : char c = m_input[m_index];
144 [ # # ]: 0 : if (c == ',') {
145 : 0 : break;
146 : : }
147 : 0 : ++m_index;
148 [ # # ]: 0 : if (c == '\\') {
149 [ # # ]: 0 : if (m_index < m_input.getLength()) {
150 : 0 : c = m_input[m_index++];
151 [ # # # ]: 0 : switch (c) {
152 : : case '0':
153 : 0 : c = '\0';
154 : 0 : break;
155 : : case ',':
156 : : case '\\':
157 : 0 : break;
158 : : default:
159 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
160 : : }
161 : : } else {
162 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
163 : : }
164 : : }
165 [ # # ]: 0 : b.append(c);
166 : : }
167 : 0 : rtl::OString b2(b.makeStringAndClear());
168 [ # # ]: 0 : if (!rtl_convertStringToUString(
169 : : &argument->pData, b2.getStr(), b2.getLength(),
170 : : RTL_TEXTENCODING_UTF8,
171 : : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
172 : : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
173 : 0 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
174 : : {
175 [ # # ]: 0 : throw CommandLineArgs::Supplier::Exception();
176 : : }
177 : 0 : return true;
178 : : } else {
179 : 0 : return false;
180 : : }
181 : : }
182 : :
183 : : boost::optional< rtl::OUString > m_cwdUrl;
184 : : rtl::OString m_input;
185 : : sal_Int32 m_index;
186 : : };
187 : :
188 : 0 : bool addArgument(rtl::OStringBuffer &rArguments, char prefix,
189 : : const rtl::OUString &rArgument)
190 : : {
191 : 0 : rtl::OString utf8;
192 [ # # ]: 0 : if (!rArgument.convertToString(
193 : : &utf8, RTL_TEXTENCODING_UTF8,
194 : : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
195 : 0 : RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
196 : : {
197 : 0 : return false;
198 : : }
199 [ # # ]: 0 : rArguments.append(prefix);
200 [ # # ]: 0 : for (sal_Int32 i = 0; i < utf8.getLength(); ++i) {
201 : 0 : char c = utf8[i];
202 [ # # # # ]: 0 : switch (c) {
203 : : case '\0':
204 [ # # ]: 0 : rArguments.append("\\0");
205 : 0 : break;
206 : : case ',':
207 [ # # ]: 0 : rArguments.append("\\,");
208 : 0 : break;
209 : : case '\\':
210 [ # # ]: 0 : rArguments.append("\\\\");
211 : 0 : break;
212 : : default:
213 [ # # ]: 0 : rArguments.append(c);
214 : 0 : break;
215 : : }
216 : : }
217 : 0 : return true;
218 : : }
219 : :
220 : : }
221 : :
222 : 158 : rtl::Reference< OfficeIPCThread > OfficeIPCThread::pGlobalOfficeIPCThread;
223 : : namespace { struct Security : public rtl::Static<osl::Security, Security> {}; }
224 : :
225 : : // Turns a string in aMsg such as file:///home/foo/.libreoffice/3
226 : : // Into a hex string of well known length ff132a86...
227 : 158 : String CreateMD5FromString( const OUString& aMsg )
228 : : {
229 : : #if (OSL_DEBUG_LEVEL > 2)
230 : : fprintf( stderr, "create md5 from '%s'\n",
231 : : rtl::OUStringToOString (aMsg, RTL_TEXTENCODING_UTF8).getStr() );
232 : : #endif
233 : :
234 : 158 : rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
235 [ + - ]: 158 : if ( handle )
236 : : {
237 : 158 : const sal_uInt8* pData = (const sal_uInt8*)aMsg.getStr();
238 : 158 : sal_uInt32 nSize = ( aMsg.getLength() * sizeof( sal_Unicode ));
239 : 158 : sal_uInt32 nMD5KeyLen = rtl_digest_queryLength( handle );
240 [ + - ]: 158 : sal_uInt8* pMD5KeyBuffer = new sal_uInt8[ nMD5KeyLen ];
241 : :
242 : 158 : rtl_digest_init( handle, pData, nSize );
243 : 158 : rtl_digest_update( handle, pData, nSize );
244 : 158 : rtl_digest_get( handle, pMD5KeyBuffer, nMD5KeyLen );
245 : 158 : rtl_digest_destroy( handle );
246 : :
247 : : // Create hex-value string from the MD5 value to keep the string size minimal
248 : 158 : OUStringBuffer aBuffer( nMD5KeyLen * 2 + 1 );
249 [ + + ]: 2686 : for ( sal_uInt32 i = 0; i < nMD5KeyLen; i++ )
250 [ + - ]: 2528 : aBuffer.append( (sal_Int32)pMD5KeyBuffer[i], 16 );
251 : :
252 [ + - ]: 158 : delete [] pMD5KeyBuffer;
253 [ + - ][ + - ]: 158 : return aBuffer.makeStringAndClear();
254 : : }
255 : :
256 : 158 : return String();
257 : : }
258 : :
259 : : class ProcessEventsClass_Impl
260 : : {
261 : : public:
262 : : DECL_STATIC_LINK( ProcessEventsClass_Impl, CallEvent, void* pEvent );
263 : : DECL_STATIC_LINK( ProcessEventsClass_Impl, ProcessDocumentsEvent, void* pEvent );
264 : : };
265 : :
266 : 0 : IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, CallEvent, void*, pEvent )
267 : : {
268 : : // Application events are processed by the Desktop::HandleAppEvent implementation.
269 : 0 : Desktop::HandleAppEvent( *((ApplicationEvent*)pEvent) );
270 [ # # ]: 0 : delete (ApplicationEvent*)pEvent;
271 : 0 : return 0;
272 : : }
273 : :
274 : 0 : IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, ProcessDocumentsEvent, void*, pEvent )
275 : : {
276 : : // Documents requests are processed by the OfficeIPCThread implementation
277 : 0 : ProcessDocumentsRequest* pDocsRequest = (ProcessDocumentsRequest*)pEvent;
278 : :
279 [ # # ]: 0 : if ( pDocsRequest )
280 : : {
281 : 0 : OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
282 [ # # ]: 0 : delete pDocsRequest;
283 : : }
284 : 0 : return 0;
285 : : }
286 : :
287 : 0 : void ImplPostForeignAppEvent( ApplicationEvent* pEvent )
288 : : {
289 [ # # ]: 0 : Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, CallEvent ), pEvent );
290 : 0 : }
291 : :
292 : 0 : void ImplPostProcessDocumentsEvent( ProcessDocumentsRequest* pEvent )
293 : : {
294 [ # # ]: 0 : Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, ProcessDocumentsEvent ), pEvent );
295 : 0 : }
296 : :
297 : 0 : oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* pInfo)
298 : : {
299 [ # # ]: 0 : if( pInfo->Signal == osl_Signal_Terminate )
300 : 0 : OfficeIPCThread::DisableOfficeIPCThread(false);
301 : 0 : return osl_Signal_ActCallNextHdl;
302 : : }
303 : :
304 : : // ----------------------------------------------------------------------------
305 : :
306 : : // The OfficeIPCThreadController implementation is a bookkeeper for all pending requests
307 : : // that were created by the OfficeIPCThread. The requests are waiting to be processed by
308 : : // our framework loadComponentFromURL function (e.g. open/print request).
309 : : // During shutdown the framework is asking OfficeIPCThreadController about pending requests.
310 : : // If there are pending requests framework has to stop the shutdown process. It is waiting
311 : : // for these requests because framework is not able to handle shutdown and open a document
312 : : // concurrently.
313 : :
314 : :
315 : : // XServiceInfo
316 : 96 : OUString SAL_CALL OfficeIPCThreadController::getImplementationName()
317 : : throw ( RuntimeException )
318 : : {
319 : 96 : return OUString( "com.sun.star.comp.OfficeIPCThreadController" );
320 : : }
321 : :
322 : 0 : sal_Bool SAL_CALL OfficeIPCThreadController::supportsService( const OUString& )
323 : : throw ( RuntimeException )
324 : : {
325 : 0 : return sal_False;
326 : : }
327 : :
328 : 0 : Sequence< OUString > SAL_CALL OfficeIPCThreadController::getSupportedServiceNames()
329 : : throw ( RuntimeException )
330 : : {
331 : 0 : Sequence< OUString > aSeq( 0 );
332 : 0 : return aSeq;
333 : : }
334 : :
335 : : // XEventListener
336 : 0 : void SAL_CALL OfficeIPCThreadController::disposing( const EventObject& )
337 : : throw( RuntimeException )
338 : : {
339 : 0 : }
340 : :
341 : : // XTerminateListener
342 : 96 : void SAL_CALL OfficeIPCThreadController::queryTermination( const EventObject& )
343 : : throw( TerminationVetoException, RuntimeException )
344 : : {
345 : : // Desktop ask about pending request through our office ipc pipe. We have to
346 : : // be sure that no pending request is waiting because framework is not able to
347 : : // handle shutdown and open a document concurrently.
348 : :
349 [ - + ]: 96 : if ( OfficeIPCThread::AreRequestsPending() )
350 [ # # ]: 0 : throw TerminationVetoException();
351 : : else
352 : 96 : OfficeIPCThread::SetDowning();
353 : 96 : }
354 : :
355 : 96 : void SAL_CALL OfficeIPCThreadController::notifyTermination( const EventObject& )
356 : : throw( RuntimeException )
357 : : {
358 : 96 : }
359 : :
360 : : namespace
361 : : {
362 : : class theOfficeIPCThreadMutex
363 : : : public rtl::Static<osl::Mutex, theOfficeIPCThreadMutex> {};
364 : : }
365 : :
366 : 858 : ::osl::Mutex& OfficeIPCThread::GetMutex()
367 : : {
368 : 858 : return theOfficeIPCThreadMutex::get();
369 : : }
370 : :
371 : 96 : void OfficeIPCThread::SetDowning()
372 : : {
373 : : // We have the order to block all incoming requests. Framework
374 : : // wants to shutdown and we have to make sure that no loading/printing
375 : : // requests are executed anymore.
376 [ + - ][ + - ]: 96 : ::osl::MutexGuard aGuard( GetMutex() );
377 : :
378 [ + - ]: 96 : if ( pGlobalOfficeIPCThread.is() )
379 [ + - ]: 96 : pGlobalOfficeIPCThread->mbDowning = true;
380 : 96 : }
381 : :
382 : : static bool s_bInEnableRequests = false;
383 : :
384 : 96 : void OfficeIPCThread::EnableRequests( bool i_bEnable )
385 : : {
386 : : // switch between just queueing the requests and executing them
387 [ + - ][ + - ]: 96 : ::osl::MutexGuard aGuard( GetMutex() );
388 : :
389 [ + - ]: 96 : if ( pGlobalOfficeIPCThread.is() )
390 : : {
391 : 96 : s_bInEnableRequests = true;
392 : 96 : pGlobalOfficeIPCThread->mbRequestsEnabled = i_bEnable;
393 [ + - ]: 96 : if( i_bEnable )
394 : : {
395 : : // hit the compiler over the head
396 [ + - ][ + - ]: 96 : ProcessDocumentsRequest aEmptyReq = ProcessDocumentsRequest( boost::optional< rtl::OUString >() );
[ + - ]
397 : : // trigger already queued requests
398 [ + - ][ + - ]: 96 : OfficeIPCThread::ExecuteCmdLineRequests( aEmptyReq );
399 : : }
400 : 96 : s_bInEnableRequests = false;
401 [ + - ]: 96 : }
402 : 96 : }
403 : :
404 : 96 : sal_Bool OfficeIPCThread::AreRequestsPending()
405 : : {
406 : : // Give info about pending requests
407 [ + - ][ + - ]: 96 : ::osl::MutexGuard aGuard( GetMutex() );
408 [ + - ]: 96 : if ( pGlobalOfficeIPCThread.is() )
409 : 96 : return ( pGlobalOfficeIPCThread->mnPendingRequests > 0 );
410 : : else
411 [ + - ]: 96 : return sal_False;
412 : : }
413 : :
414 : 0 : void OfficeIPCThread::RequestsCompleted( int nCount )
415 : : {
416 : : // Remove nCount pending requests from our internal counter
417 [ # # ][ # # ]: 0 : ::osl::MutexGuard aGuard( GetMutex() );
418 [ # # ]: 0 : if ( pGlobalOfficeIPCThread.is() )
419 : : {
420 [ # # ]: 0 : if ( pGlobalOfficeIPCThread->mnPendingRequests > 0 )
421 : 0 : pGlobalOfficeIPCThread->mnPendingRequests -= nCount;
422 [ # # ]: 0 : }
423 : 0 : }
424 : :
425 : 158 : OfficeIPCThread::Status OfficeIPCThread::EnableOfficeIPCThread()
426 : : {
427 [ + - ][ + - ]: 158 : ::osl::MutexGuard aGuard( GetMutex() );
428 : :
429 [ - + ]: 158 : if( pGlobalOfficeIPCThread.is() )
430 : 0 : return IPC_STATUS_OK;
431 : :
432 : 158 : ::rtl::OUString aUserInstallPath;
433 : 158 : ::rtl::OUString aDummy;
434 : :
435 [ + - ][ + - ]: 158 : rtl::Reference< OfficeIPCThread > pThread(new OfficeIPCThread);
[ + - ]
436 : :
437 : 158 : pThread->maPipeIdent = OUString( "SingleOfficeIPC_" );
438 : :
439 : : // The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve
440 : : // this information from a unotools implementation.
441 [ + - ]: 158 : ::utl::Bootstrap::PathStatus aLocateResult = ::utl::Bootstrap::locateUserInstallation( aUserInstallPath );
442 [ - + ][ # # ]: 158 : if ( aLocateResult == ::utl::Bootstrap::PATH_EXISTS || aLocateResult == ::utl::Bootstrap::PATH_VALID)
443 : 158 : aDummy = aUserInstallPath;
444 : : else
445 : : {
446 : 0 : return IPC_STATUS_BOOTSTRAP_ERROR;
447 : : }
448 : :
449 : : // Try to determine if we are the first office or not! This should prevent multiple
450 : : // access to the user directory !
451 : : // First we try to create our pipe if this fails we try to connect. We have to do this
452 : : // in a loop because the the other office can crash or shutdown between createPipe
453 : : // and connectPipe!!
454 : :
455 : 158 : OUString aIniName;
456 : :
457 [ + - ]: 158 : osl_getExecutableFile( &aIniName.pData );
458 : :
459 : 158 : sal_uInt32 lastIndex = aIniName.lastIndexOf('/');
460 [ + - ]: 158 : if ( lastIndex > 0 )
461 : : {
462 : 158 : aIniName = aIniName.copy( 0, lastIndex+1 );
463 : 158 : aIniName += OUString( "perftune" );
464 : : #if defined(WNT)
465 : : aIniName += OUString( ".ini" );
466 : : #else
467 : 158 : aIniName += OUString( "rc" );
468 : : #endif
469 : : }
470 : :
471 : 158 : ::rtl::Bootstrap aPerfTuneIniFile( aIniName );
472 : :
473 : 158 : OUString aDefault( "0" );
474 : 158 : OUString aPreloadData;
475 : :
476 : 158 : aPerfTuneIniFile.getFrom( OUString( "FastPipeCommunication" ), aPreloadData, aDefault );
477 : :
478 : :
479 : 158 : OUString aUserInstallPathHashCode;
480 : :
481 [ - + ]: 158 : if ( aPreloadData == "1" )
482 : : {
483 : : sal_Char szBuffer[32];
484 : 0 : sprintf( szBuffer, "%d", SUPD );
485 [ # # ][ # # ]: 0 : aUserInstallPathHashCode = OUString( szBuffer, strlen(szBuffer), osl_getThreadTextEncoding() );
486 : : }
487 : : else
488 [ + - ][ + - ]: 158 : aUserInstallPathHashCode = CreateMD5FromString( aDummy );
[ + - ]
489 : :
490 : :
491 : : // Check result to create a hash code from the user install path
492 [ - + ]: 158 : if ( aUserInstallPathHashCode.isEmpty() )
493 : 0 : return IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code!
494 : :
495 : 158 : pThread->maPipeIdent = pThread->maPipeIdent + aUserInstallPathHashCode;
496 : :
497 : 158 : PipeMode nPipeMode = PIPEMODE_DONTKNOW;
498 [ - + ]: 158 : do
499 : : {
500 [ + - ]: 158 : osl::Security &rSecurity = Security::get();
501 : : // Try to create pipe
502 [ + - ][ + - ]: 158 : if ( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_CREATE, rSecurity ))
503 : : {
504 : : // Pipe created
505 : 158 : nPipeMode = PIPEMODE_CREATED;
506 : : }
507 [ # # ][ # # ]: 0 : else if( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_OPEN, rSecurity )) // Creation not successfull, now we try to connect
508 : : {
509 : : // Pipe connected to first office
510 : 0 : nPipeMode = PIPEMODE_CONNECTED;
511 : : }
512 : : else
513 : : {
514 [ # # ]: 0 : oslPipeError eReason = pThread->maPipe.getError();
515 [ # # ][ # # ]: 0 : if ((eReason == osl_Pipe_E_ConnectionRefused) || (eReason == osl_Pipe_E_invalidError))
516 : 0 : return IPC_STATUS_BOOTSTRAP_ERROR;
517 : :
518 : : // Wait for second office to be ready
519 : : TimeValue aTimeValue;
520 : 0 : aTimeValue.Seconds = 0;
521 : 0 : aTimeValue.Nanosec = 10000000; // 10ms
522 [ # # ]: 0 : salhelper::Thread::wait( aTimeValue );
523 : : }
524 : :
525 : : } while ( nPipeMode == PIPEMODE_DONTKNOW );
526 : :
527 [ + - ]: 158 : if ( nPipeMode == PIPEMODE_CREATED )
528 : : {
529 : : // Seems we are the one and only, so start listening thread
530 [ + - ]: 158 : pGlobalOfficeIPCThread = pThread;
531 [ + - ]: 158 : pThread->launch();
532 : : }
533 : : else
534 : : {
535 : : // Seems another office is running. Pipe arguments to it and self terminate
536 [ # # ]: 0 : osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle());
537 : :
538 : : rtl::OStringBuffer aArguments(RTL_CONSTASCII_STRINGPARAM(
539 [ # # ]: 0 : ARGUMENT_PREFIX));
540 : 0 : rtl::OUString cwdUrl;
541 [ # # ][ # # ]: 0 : if (!(tools::getProcessWorkingDir(cwdUrl) &&
542 [ # # ][ # # ]: 0 : addArgument(aArguments, '1', cwdUrl)))
[ # # ]
543 : : {
544 [ # # ]: 0 : aArguments.append('0');
545 : : }
546 [ # # ]: 0 : sal_uInt32 nCount = rtl_getAppCommandArgCount();
547 [ # # ]: 0 : for( sal_uInt32 i=0; i < nCount; i++ )
548 : : {
549 [ # # ]: 0 : rtl_getAppCommandArg( i, &aDummy.pData );
550 [ # # ][ # # ]: 0 : if (!addArgument(aArguments, ',', aDummy)) {
551 : 0 : return IPC_STATUS_BOOTSTRAP_ERROR;
552 : : }
553 : : }
554 : : // finally, write the string onto the pipe
555 [ # # ]: 0 : aStreamPipe.write(aArguments.getStr(), aArguments.getLength());
556 [ # # ]: 0 : aStreamPipe.write("\0", 1);
557 : :
558 : 0 : rtl::OString aToken(sc_aConfirmationSequence);
559 [ # # ]: 0 : char *pReceiveBuffer = new char[aToken.getLength()+1];
560 [ # # ]: 0 : sal_Int32 n = aStreamPipe.read(pReceiveBuffer, aToken.getLength());
561 : 0 : pReceiveBuffer[n]='\0';
562 : :
563 : 0 : bool bIsConfirmationSequence = aToken.equals(pReceiveBuffer);
564 [ # # ]: 0 : delete[] pReceiveBuffer;
565 : :
566 [ # # ]: 0 : if (!bIsConfirmationSequence)
567 : : {
568 : : // something went wrong
569 : 0 : return IPC_STATUS_BOOTSTRAP_ERROR;
570 : : }
571 : :
572 [ # # ]: 0 : return IPC_STATUS_2ND_OFFICE;
573 : : }
574 : :
575 [ + - ][ + - ]: 158 : return IPC_STATUS_OK;
576 : : }
577 : :
578 : 158 : void OfficeIPCThread::DisableOfficeIPCThread(bool join)
579 : : {
580 [ + - ][ + - ]: 158 : osl::ClearableMutexGuard aMutex( GetMutex() );
581 : :
582 [ + - ]: 158 : if( pGlobalOfficeIPCThread.is() )
583 : : {
584 : : rtl::Reference< OfficeIPCThread > pOfficeIPCThread(
585 [ + - ]: 158 : pGlobalOfficeIPCThread);
586 [ + - ]: 158 : pGlobalOfficeIPCThread.clear();
587 : :
588 : : // send thread a termination message
589 : : // this is done so the subsequent join will not hang
590 : : // because the thread hangs in accept of pipe
591 [ + - ][ + - ]: 158 : osl::StreamPipe aPipe ( pOfficeIPCThread->maPipeIdent, osl_Pipe_OPEN, Security::get() );
592 [ + - ]: 158 : if (aPipe.is())
593 : : {
594 [ + - ]: 158 : aPipe.send( sc_aTerminationSequence, sc_nTSeqLength+1 ); // also send 0-byte
595 : :
596 : : // close the pipe so that the streampipe on the other
597 : : // side produces EOF
598 [ + - ]: 158 : aPipe.close();
599 : : }
600 : :
601 : : // release mutex to avoid deadlocks
602 [ + - ]: 158 : aMutex.clear();
603 : :
604 [ + - ]: 158 : OfficeIPCThread::SetReady(pOfficeIPCThread);
605 : :
606 : : // exit gracefully and join
607 [ + - ]: 158 : if (join)
608 : : {
609 [ + - ]: 158 : pOfficeIPCThread->join();
610 [ + - ][ + - ]: 158 : }
611 [ + - ]: 158 : }
612 : 158 : }
613 : :
614 : 158 : OfficeIPCThread::OfficeIPCThread() :
615 : : Thread( "OfficeIPCThread" ),
616 : : mbDowning( false ),
617 : : mbRequestsEnabled( false ),
618 : : mnPendingRequests( 0 ),
619 [ + - ][ + - ]: 158 : mpDispatchWatcher( 0 )
[ + - ]
620 : : {
621 : 158 : }
622 : :
623 [ + - ][ + - ]: 158 : OfficeIPCThread::~OfficeIPCThread()
[ + - ][ + - ]
624 : : {
625 [ + - ][ + - ]: 158 : ::osl::ClearableMutexGuard aGuard( GetMutex() );
626 : :
627 [ + + ]: 158 : if ( mpDispatchWatcher )
628 : 96 : mpDispatchWatcher->release();
629 [ + - ]: 158 : maPipe.close();
630 [ + - ]: 158 : maStreamPipe.close();
631 [ + - ][ + - ]: 158 : pGlobalOfficeIPCThread.clear();
632 [ - + ]: 316 : }
633 : :
634 : 254 : void OfficeIPCThread::SetReady(
635 : : rtl::Reference< OfficeIPCThread > const & pThread)
636 : : {
637 : : rtl::Reference< OfficeIPCThread > const & t(
638 [ + + ]: 254 : pThread.is() ? pThread : pGlobalOfficeIPCThread);
639 [ + - ]: 254 : if (t.is())
640 : : {
641 : 254 : t->cReady.set();
642 : : }
643 : 254 : }
644 : :
645 : 158 : void OfficeIPCThread::execute()
646 : : {
647 [ # # ]: 158 : do
648 : : {
649 : 158 : oslPipeError nError = maPipe.accept( maStreamPipe );
650 : :
651 : :
652 [ + - ]: 158 : if( nError == osl_Pipe_E_None )
653 : : {
654 : : // if we receive a request while the office is displaying some dialog or error during
655 : : // bootstrap, that dialogs event loop might get events that are dispatched by this thread
656 : : // we have to wait for cReady to be set by the real main loop.
657 : : // only reqests that dont dispatch events may be processed before cReady is set.
658 [ + - ]: 158 : cReady.wait();
659 : :
660 : : // we might have decided to shutdown while we were sleeping
661 [ - + ]: 158 : if (!pGlobalOfficeIPCThread.is()) return;
662 : :
663 : : // only lock the mutex when processing starts, othewise we deadlock when the office goes
664 : : // down during wait
665 [ # # ][ # # ]: 0 : osl::ClearableMutexGuard aGuard( GetMutex() );
666 : :
667 : : // test byte by byte
668 : 0 : const int nBufSz = 2048;
669 : : char pBuf[nBufSz];
670 : 0 : int nBytes = 0;
671 : 0 : int nResult = 0;
672 : 0 : rtl::OStringBuffer aBuf;
673 : : // read into pBuf until '\0' is read or read-error
674 [ # # ][ # # ]: 0 : while ((nResult=maStreamPipe.recv( pBuf+nBytes, nBufSz-nBytes))>0) {
675 : 0 : nBytes += nResult;
676 [ # # ]: 0 : if (pBuf[nBytes-1]=='\0') {
677 [ # # ]: 0 : aBuf.append(pBuf);
678 : 0 : break;
679 : : }
680 : : }
681 : : // don't close pipe ...
682 : :
683 : 0 : rtl::OString aArguments = aBuf.makeStringAndClear();
684 : :
685 : : // Is this a lookup message from another application? if so, ignore
686 [ # # ]: 0 : if (aArguments.isEmpty())
687 : 0 : continue;
688 : :
689 : : // is this a termination message ? if so, terminate
690 [ # # ][ # # ]: 0 : if (aArguments.equalsL(sc_aTerminationSequence, sc_nTSeqLength) || mbDowning)
[ # # ]
691 : : return;
692 : 0 : std::auto_ptr< CommandLineArgs > aCmdLineArgs;
693 : : try
694 : : {
695 [ # # ]: 0 : Parser p(aArguments);
696 [ # # ][ # # ]: 0 : aCmdLineArgs.reset( new CommandLineArgs( p ) );
[ # # # # ]
697 : : }
698 [ # # ]: 0 : catch ( const CommandLineArgs::Supplier::Exception & )
699 : : {
700 : : #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
701 : : fprintf( stderr, "Error in received command line arguments\n" );
702 : : #endif
703 : 0 : continue;
704 : : }
705 : :
706 : : #ifdef UNX
707 [ # # ][ # # ]: 0 : if (aCmdLineArgs->HasUnknown() || aCmdLineArgs->IsVersion() || aCmdLineArgs->IsHelp())
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
708 : 0 : continue;
709 : : #endif
710 : :
711 [ # # ]: 0 : const CommandLineArgs &rCurrentCmdLineArgs = Desktop::GetCommandLineArgs();
712 : :
713 [ # # ][ # # ]: 0 : if ( aCmdLineArgs->IsQuickstart() )
714 : : {
715 : : // we have to use application event, because we have to start quickstart service in main thread!!
716 : : ApplicationEvent* pAppEvent =
717 [ # # ]: 0 : new ApplicationEvent(ApplicationEvent::TYPE_QUICKSTART);
718 [ # # ]: 0 : ImplPostForeignAppEvent( pAppEvent );
719 : : }
720 : :
721 : : // handle request for acceptor
722 : : std::vector< rtl::OUString > const & accept = aCmdLineArgs->
723 [ # # ]: 0 : GetAccept();
724 [ # # ][ # # ]: 0 : for (std::vector< rtl::OUString >::const_iterator i(accept.begin());
725 : 0 : i != accept.end(); ++i)
726 : : {
727 : : ApplicationEvent* pAppEvent = new ApplicationEvent(
728 [ # # ]: 0 : ApplicationEvent::TYPE_ACCEPT, *i);
729 [ # # ]: 0 : ImplPostForeignAppEvent( pAppEvent );
730 : : }
731 : : // handle acceptor removal
732 : : std::vector< rtl::OUString > const & unaccept = aCmdLineArgs->
733 [ # # ]: 0 : GetUnaccept();
734 [ # # ][ # # ]: 0 : for (std::vector< rtl::OUString >::const_iterator i(
735 : 0 : unaccept.begin());
736 : 0 : i != unaccept.end(); ++i)
737 : : {
738 : : ApplicationEvent* pAppEvent = new ApplicationEvent(
739 [ # # ]: 0 : ApplicationEvent::TYPE_UNACCEPT, *i);
740 [ # # ]: 0 : ImplPostForeignAppEvent( pAppEvent );
741 : : }
742 : :
743 : : #ifndef UNX
744 : : // only in non-unix version, we need to handle a -help request
745 : : // in a running instance in order to display the command line help
746 : : if ( aCmdLineArgs->IsHelp() ) {
747 : : ApplicationEvent* pAppEvent =
748 : : new ApplicationEvent(ApplicationEvent::TYPE_HELP);
749 : : ImplPostForeignAppEvent( pAppEvent );
750 : : }
751 : : #endif
752 : :
753 : 0 : sal_Bool bDocRequestSent = sal_False;
754 : : ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest(
755 [ # # ][ # # ]: 0 : aCmdLineArgs->getCwdUrl());
[ # # ][ # # ]
756 [ # # ]: 0 : cProcessed.reset();
757 : 0 : pRequest->pcProcessed = &cProcessed;
758 : :
759 : : // Print requests are not dependent on the --invisible cmdline argument as they are
760 : : // loaded with the "hidden" flag! So they are always checked.
761 [ # # ]: 0 : pRequest->aPrintList = aCmdLineArgs->GetPrintList();
762 : 0 : bDocRequestSent |= !pRequest->aPrintList.empty();
763 [ # # ]: 0 : pRequest->aPrintToList = aCmdLineArgs->GetPrintToList();
764 [ # # ]: 0 : pRequest->aPrinterName = aCmdLineArgs->GetPrinterName();
765 [ # # ][ # # ]: 0 : bDocRequestSent |= !( pRequest->aPrintToList.empty() || pRequest->aPrinterName.isEmpty() );
766 : :
767 [ # # ][ # # ]: 0 : if ( !rCurrentCmdLineArgs.IsInvisible() )
768 : : {
769 : : // Read cmdline args that can open/create documents. As they would open a window
770 : : // they are only allowed if the "--invisible" is currently not used!
771 [ # # ]: 0 : pRequest->aOpenList = aCmdLineArgs->GetOpenList();
772 : 0 : bDocRequestSent |= !pRequest->aOpenList.empty();
773 [ # # ]: 0 : pRequest->aViewList = aCmdLineArgs->GetViewList();
774 : 0 : bDocRequestSent |= !pRequest->aViewList.empty();
775 [ # # ]: 0 : pRequest->aStartList = aCmdLineArgs->GetStartList();
776 : 0 : bDocRequestSent |= !pRequest->aStartList.empty();
777 [ # # ]: 0 : pRequest->aForceOpenList = aCmdLineArgs->GetForceOpenList();
778 : 0 : bDocRequestSent |= !pRequest->aForceOpenList.empty();
779 [ # # ]: 0 : pRequest->aForceNewList = aCmdLineArgs->GetForceNewList();
780 : 0 : bDocRequestSent |= !pRequest->aForceNewList.empty();
781 : :
782 : : // Special command line args to create an empty document for a given module
783 : :
784 : : // #i18338# (lo)
785 : : // we only do this if no document was specified on the command line,
786 : : // since this would be inconsistent with the the behaviour of
787 : : // the first process, see OpenClients() (call to OpenDefault()) in app.cxx
788 [ # # ][ # # ]: 0 : if ( aCmdLineArgs->HasModuleParam() && (!bDocRequestSent) )
[ # # ][ # # ]
789 : : {
790 [ # # ]: 0 : SvtModuleOptions aOpt;
791 : 0 : SvtModuleOptions::EFactory eFactory = SvtModuleOptions::E_WRITER;
792 [ # # ][ # # ]: 0 : if ( aCmdLineArgs->IsWriter() )
793 : 0 : eFactory = SvtModuleOptions::E_WRITER;
794 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsCalc() )
795 : 0 : eFactory = SvtModuleOptions::E_CALC;
796 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsDraw() )
797 : 0 : eFactory = SvtModuleOptions::E_DRAW;
798 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsImpress() )
799 : 0 : eFactory = SvtModuleOptions::E_IMPRESS;
800 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsBase() )
801 : 0 : eFactory = SvtModuleOptions::E_DATABASE;
802 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsMath() )
803 : 0 : eFactory = SvtModuleOptions::E_MATH;
804 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsGlobal() )
805 : 0 : eFactory = SvtModuleOptions::E_WRITERGLOBAL;
806 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsWeb() )
807 : 0 : eFactory = SvtModuleOptions::E_WRITERWEB;
808 : :
809 [ # # ]: 0 : if ( !pRequest->aOpenList.empty() )
810 [ # # ]: 0 : pRequest->aModule = aOpt.GetFactoryName( eFactory );
811 : : else
812 [ # # ][ # # ]: 0 : pRequest->aOpenList.push_back( aOpt.GetFactoryEmptyDocumentURL( eFactory ) );
813 [ # # ]: 0 : bDocRequestSent = sal_True;
814 : : }
815 : : }
816 : :
817 [ # # ][ # # ]: 0 : if ( !aCmdLineArgs->IsQuickstart() ) {
818 : 0 : sal_Bool bShowHelp = sal_False;
819 : 0 : rtl::OUStringBuffer aHelpURLBuffer;
820 [ # # ][ # # ]: 0 : if (aCmdLineArgs->IsHelpWriter()) {
821 : 0 : bShowHelp = sal_True;
822 [ # # ]: 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
823 [ # # ][ # # ]: 0 : } else if (aCmdLineArgs->IsHelpCalc()) {
824 : 0 : bShowHelp = sal_True;
825 [ # # ]: 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
826 [ # # ][ # # ]: 0 : } else if (aCmdLineArgs->IsHelpDraw()) {
827 : 0 : bShowHelp = sal_True;
828 [ # # ]: 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
829 [ # # ][ # # ]: 0 : } else if (aCmdLineArgs->IsHelpImpress()) {
830 : 0 : bShowHelp = sal_True;
831 [ # # ]: 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
832 [ # # ][ # # ]: 0 : } else if (aCmdLineArgs->IsHelpBase()) {
833 : 0 : bShowHelp = sal_True;
834 [ # # ]: 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
835 [ # # ][ # # ]: 0 : } else if (aCmdLineArgs->IsHelpBasic()) {
836 : 0 : bShowHelp = sal_True;
837 [ # # ]: 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
838 [ # # ][ # # ]: 0 : } else if (aCmdLineArgs->IsHelpMath()) {
839 : 0 : bShowHelp = sal_True;
840 [ # # ]: 0 : aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
841 : : }
842 [ # # ]: 0 : if (bShowHelp) {
843 [ # # ]: 0 : aHelpURLBuffer.appendAscii("?Language=");
844 [ # # ][ # # ]: 0 : aHelpURLBuffer.append(utl::ConfigManager::getLocale());
845 : : #if defined UNX
846 [ # # ]: 0 : aHelpURLBuffer.appendAscii("&System=UNX");
847 : : #elif defined WNT
848 : : aHelpURLBuffer.appendAscii("&System=WIN");
849 : : #endif
850 : : ApplicationEvent* pAppEvent = new ApplicationEvent(
851 : : ApplicationEvent::TYPE_OPENHELPURL,
852 [ # # ][ # # ]: 0 : aHelpURLBuffer.makeStringAndClear());
853 [ # # ]: 0 : ImplPostForeignAppEvent( pAppEvent );
854 : 0 : }
855 : : }
856 : :
857 [ # # ]: 0 : if ( bDocRequestSent )
858 : : {
859 : : // Send requests to dispatch watcher if we have at least one. The receiver
860 : : // is responsible to delete the request after processing it.
861 [ # # ][ # # ]: 0 : if ( aCmdLineArgs->HasModuleParam() )
862 : : {
863 [ # # ]: 0 : SvtModuleOptions aOpt;
864 : :
865 : : // Support command line parameters to start a module (as preselection)
866 [ # # ][ # # ]: 0 : if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
[ # # ][ # # ]
[ # # ]
867 [ # # ]: 0 : pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER );
868 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
[ # # ][ # # ]
[ # # ]
869 [ # # ]: 0 : pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC );
870 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
[ # # ][ # # ]
[ # # ]
871 [ # # ]: 0 : pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS );
872 [ # # ][ # # ]: 0 : else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
[ # # ][ # # ]
[ # # ]
873 [ # # ][ # # ]: 0 : pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW );
874 : : }
875 : :
876 : :
877 [ # # ]: 0 : ImplPostProcessDocumentsEvent( pRequest );
878 : : }
879 : : else
880 : : {
881 : : // delete not used request again
882 [ # # ][ # # ]: 0 : delete pRequest;
883 : 0 : pRequest = NULL;
884 : : }
885 [ # # ][ # # ]: 0 : if (aArguments.equalsL(sc_aShowSequence, sc_nShSeqLength) ||
[ # # ]
886 [ # # ]: 0 : aCmdLineArgs->IsEmpty())
887 : : {
888 : : // no document was sent, just bring Office to front
889 : : ApplicationEvent* pAppEvent =
890 [ # # ]: 0 : new ApplicationEvent(ApplicationEvent::TYPE_APPEAR);
891 [ # # ]: 0 : ImplPostForeignAppEvent( pAppEvent );
892 : : }
893 : :
894 : : // we don't need the mutex any longer...
895 [ # # ]: 0 : aGuard.clear();
896 : : // wait for processing to finish
897 [ # # ]: 0 : if (bDocRequestSent)
898 [ # # ]: 0 : cProcessed.wait();
899 : : // processing finished, inform the requesting end
900 : 0 : nBytes = 0;
901 [ # # ][ # # ]: 0 : while (
[ # # ][ # # ]
902 : 0 : (nResult = maStreamPipe.send(sc_aConfirmationSequence+nBytes, sc_nCSeqLength-nBytes))>0 &&
903 [ # # ][ # # ]: 158 : ((nBytes += nResult) < sc_nCSeqLength) ) ;
[ # # # ]
[ # # # ]
[ # # ]
[ # # # ]
904 : : }
905 : : else
906 : : {
907 : : #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
908 : : fprintf( stderr, "Error on accept: %d\n", (int)nError );
909 : : #endif
910 : : TimeValue tval;
911 : 0 : tval.Seconds = 1;
912 : 0 : tval.Nanosec = 0;
913 [ # # ]: 0 : salhelper::Thread::wait( tval );
914 : : }
915 : 0 : } while( schedule() );
916 : : }
917 : :
918 : 768 : static void AddToDispatchList(
919 : : DispatchWatcher::DispatchList& rDispatchList,
920 : : boost::optional< rtl::OUString > const & cwdUrl,
921 : : std::vector< rtl::OUString > const & aRequestList,
922 : : DispatchWatcher::RequestType nType,
923 : : const OUString& aParam,
924 : : const OUString& aFactory )
925 : : {
926 [ + - ][ - + ]: 1536 : for (std::vector< rtl::OUString >::const_iterator i(aRequestList.begin());
927 : 768 : i != aRequestList.end(); ++i)
928 : : {
929 : : rDispatchList.push_back(
930 [ # # ][ # # ]: 0 : DispatchWatcher::DispatchRequest( nType, *i, cwdUrl, aParam, aFactory ));
[ # # ]
931 : : }
932 : 768 : }
933 : :
934 : 96 : static void AddConversionsToDispatchList(
935 : : DispatchWatcher::DispatchList& rDispatchList,
936 : : boost::optional< rtl::OUString > const & cwdUrl,
937 : : std::vector< rtl::OUString > const & rRequestList,
938 : : const OUString& rParam,
939 : : const OUString& rPrinterName,
940 : : const OUString& rFactory,
941 : : const OUString& rParamOut )
942 : : {
943 : : DispatchWatcher::RequestType nType;
944 : 96 : OUString aParam( rParam );
945 : :
946 [ - + ]: 96 : if( !rParam.isEmpty() )
947 : : {
948 : 0 : nType = DispatchWatcher::REQUEST_CONVERSION;
949 : 0 : aParam = rParam;
950 : : }
951 : : else
952 : : {
953 : 96 : nType = DispatchWatcher::REQUEST_BATCHPRINT;
954 : 96 : aParam = rPrinterName;
955 : : }
956 : :
957 : 96 : OUString aOutDir( rParamOut.trim() );
958 : 96 : ::rtl::OUString aPWD;
959 [ + - ]: 96 : ::tools::getProcessWorkingDir( aPWD );
960 : :
961 [ + - ][ - + ]: 96 : if( !::osl::FileBase::getAbsoluteFileURL( aPWD, rParamOut, aOutDir ) )
962 [ # # ]: 0 : ::osl::FileBase::getSystemPathFromFileURL( aOutDir, aOutDir );
963 : :
964 [ - + ]: 96 : if( !rParamOut.trim().isEmpty() )
965 : : {
966 : 0 : aParam += ::rtl::OUString(";");
967 : 0 : aParam += aOutDir;
968 : : }
969 : : else
970 : : {
971 [ + - ]: 96 : ::osl::FileBase::getSystemPathFromFileURL( aPWD, aPWD );
972 : 96 : aParam += ::rtl::OUString(";" ) + aPWD;
973 : : }
974 : :
975 [ + - ][ - + ]: 192 : for (std::vector< rtl::OUString >::const_iterator i(rRequestList.begin());
976 : 96 : i != rRequestList.end(); ++i)
977 : : {
978 : : rDispatchList.push_back(
979 [ # # ][ # # ]: 0 : DispatchWatcher::DispatchRequest( nType, *i, cwdUrl, aParam, rFactory ));
[ # # ]
980 : 96 : }
981 : 96 : }
982 : :
983 : :
984 : 96 : sal_Bool OfficeIPCThread::ExecuteCmdLineRequests( ProcessDocumentsRequest& aRequest )
985 : : {
986 : : // protect the dispatch list
987 [ + - ][ + - ]: 96 : osl::ClearableMutexGuard aGuard( GetMutex() );
988 : :
989 [ + - ][ + - ]: 96 : static DispatchWatcher::DispatchList aDispatchList;
[ + - ][ # # ]
990 : :
991 : 96 : rtl::OUString aEmpty;
992 : : // Create dispatch list for dispatch watcher
993 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aInFilter, DispatchWatcher::REQUEST_INFILTER, aEmpty, aRequest.aModule );
994 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aOpenList, DispatchWatcher::REQUEST_OPEN, aEmpty, aRequest.aModule );
995 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aViewList, DispatchWatcher::REQUEST_VIEW, aEmpty, aRequest.aModule );
996 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aStartList, DispatchWatcher::REQUEST_START, aEmpty, aRequest.aModule );
997 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintList, DispatchWatcher::REQUEST_PRINT, aEmpty, aRequest.aModule );
998 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintToList, DispatchWatcher::REQUEST_PRINTTO, aRequest.aPrinterName, aRequest.aModule );
999 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceOpenList, DispatchWatcher::REQUEST_FORCEOPEN, aEmpty, aRequest.aModule );
1000 [ + - ]: 96 : AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceNewList, DispatchWatcher::REQUEST_FORCENEW, aEmpty, aRequest.aModule );
1001 [ + - ]: 96 : AddConversionsToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aConversionList, aRequest.aConversionParams, aRequest.aPrinterName, aRequest.aModule, aRequest.aConversionOut );
1002 : 96 : sal_Bool bShutdown( sal_False );
1003 : :
1004 [ + - ]: 96 : if ( pGlobalOfficeIPCThread.is() )
1005 : : {
1006 [ - + ]: 96 : if( ! pGlobalOfficeIPCThread->AreRequestsEnabled() )
1007 : 0 : return bShutdown;
1008 : :
1009 : 96 : pGlobalOfficeIPCThread->mnPendingRequests += aDispatchList.size();
1010 [ + - ]: 96 : if ( !pGlobalOfficeIPCThread->mpDispatchWatcher )
1011 : : {
1012 [ + - ]: 96 : pGlobalOfficeIPCThread->mpDispatchWatcher = DispatchWatcher::GetDispatchWatcher();
1013 : 96 : pGlobalOfficeIPCThread->mpDispatchWatcher->acquire();
1014 : : }
1015 : :
1016 : : // copy for execute
1017 [ + - ]: 96 : DispatchWatcher::DispatchList aTempList( aDispatchList );
1018 : 96 : aDispatchList.clear();
1019 : :
1020 [ + - ]: 96 : aGuard.clear();
1021 : :
1022 : : // Execute dispatch requests
1023 [ + - ]: 96 : bShutdown = pGlobalOfficeIPCThread->mpDispatchWatcher->executeDispatchRequests( aTempList, s_bInEnableRequests );
1024 : :
1025 : : // set processed flag
1026 [ - + ]: 96 : if (aRequest.pcProcessed != NULL)
1027 [ # # ]: 96 : aRequest.pcProcessed->set();
1028 : : }
1029 : :
1030 [ + - ]: 96 : return bShutdown;
1031 : : }
1032 : :
1033 [ + - ][ + - ]: 474 : }
1034 : :
1035 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|