summaryrefslogtreecommitdiff
path: root/desktop/source/app/officeipcthread.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/source/app/officeipcthread.cxx')
-rw-r--r--desktop/source/app/officeipcthread.cxx1037
1 files changed, 0 insertions, 1037 deletions
diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx
deleted file mode 100644
index 3540ad0fd9..0000000000
--- a/desktop/source/app/officeipcthread.cxx
+++ /dev/null
@@ -1,1037 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-// MARKER(update_precomp.py): autogen include statement, do not remove
-#include "precompiled_desktop.hxx"
-
-#include "app.hxx"
-#include "officeipcthread.hxx"
-#include "cmdlineargs.hxx"
-#include "dispatchwatcher.hxx"
-#include <memory>
-#include <stdio.h>
-#include <osl/process.h>
-#include <unotools/bootstrap.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/help.hxx>
-#include <unotools/configmgr.hxx>
-#include <osl/thread.hxx>
-#include <rtl/digest.h>
-#include <rtl/ustrbuf.hxx>
-#include <rtl/instance.hxx>
-#include <osl/conditn.hxx>
-#include <unotools/moduleoptions.hxx>
-#include <rtl/bootstrap.hxx>
-#include <rtl/strbuf.hxx>
-#include <comphelper/processfactory.hxx>
-#include <osl/file.hxx>
-#include <rtl/process.h>
-#include <rtl/instance.hxx>
-#include "tools/getprocessworkingdir.hxx"
-
-using namespace desktop;
-using namespace ::com::sun::star::uno;
-using namespace ::com::sun::star::lang;
-using namespace ::com::sun::star::frame;
-
-using ::rtl::OString;
-using ::rtl::OUString;
-using ::rtl::OUStringBuffer;
-
-const char *OfficeIPCThread::sc_aTerminationSequence = "InternalIPC::TerminateThread";
-const int OfficeIPCThread::sc_nTSeqLength = 28;
-const char *OfficeIPCThread::sc_aShowSequence = "-tofront";
-const int OfficeIPCThread::sc_nShSeqLength = 5;
-const char *OfficeIPCThread::sc_aConfirmationSequence = "InternalIPC::ProcessingDone";
-const int OfficeIPCThread::sc_nCSeqLength = 27;
-
-namespace { static char const ARGUMENT_PREFIX[] = "InternalIPC::Arguments"; }
-
-// Type of pipe we use
-enum PipeMode
-{
- PIPEMODE_DONTKNOW,
- PIPEMODE_CREATED,
- PIPEMODE_CONNECTED
-};
-
-namespace desktop
-{
-
-namespace {
-
-class Parser: public CommandLineArgs::Supplier {
-public:
- explicit Parser(rtl::OString const & input): m_input(input) {
- if (!m_input.match(ARGUMENT_PREFIX) ||
- m_input.getLength() == RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX))
- {
- throw CommandLineArgs::Supplier::Exception();
- }
- m_index = RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX);
- switch (m_input[m_index++]) {
- case '0':
- break;
- case '1':
- {
- rtl::OUString url;
- if (!next(&url, false)) {
- throw CommandLineArgs::Supplier::Exception();
- }
- m_cwdUrl.reset(url);
- break;
- }
- case '2':
- {
- rtl::OUString path;
- if (!next(&path, false)) {
- throw CommandLineArgs::Supplier::Exception();
- }
- rtl::OUString url;
- if (osl::FileBase::getFileURLFromSystemPath(path, url) ==
- osl::FileBase::E_None)
- {
- m_cwdUrl.reset(url);
- }
- break;
- }
- default:
- throw CommandLineArgs::Supplier::Exception();
- }
- }
-
- virtual ~Parser() {}
-
- virtual boost::optional< rtl::OUString > getCwdUrl() { return m_cwdUrl; }
-
- virtual bool next(rtl::OUString * argument) { return next(argument, true); }
-
-private:
- virtual bool next(rtl::OUString * argument, bool prefix) {
- OSL_ASSERT(argument != NULL);
- if (m_index < m_input.getLength()) {
- if (prefix) {
- if (m_input[m_index] != ',') {
- throw CommandLineArgs::Supplier::Exception();
- }
- ++m_index;
- }
- rtl::OStringBuffer b;
- while (m_index < m_input.getLength()) {
- char c = m_input[m_index];
- if (c == ',') {
- break;
- }
- ++m_index;
- if (c == '\\') {
- if (m_index < m_input.getLength()) {
- c = m_input[m_index++];
- switch (c) {
- case '0':
- c = '\0';
- break;
- case ',':
- case '\\':
- break;
- default:
- throw CommandLineArgs::Supplier::Exception();
- }
- } else {
- throw CommandLineArgs::Supplier::Exception();
- }
- }
- b.append(c);
- }
- rtl::OString b2(b.makeStringAndClear());
- if (!rtl_convertStringToUString(
- &argument->pData, b2.getStr(), b2.getLength(),
- RTL_TEXTENCODING_UTF8,
- (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
- RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
- RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
- {
- throw CommandLineArgs::Supplier::Exception();
- }
- return true;
- } else {
- return false;
- }
- }
-
- boost::optional< rtl::OUString > m_cwdUrl;
- rtl::OString m_input;
- sal_Int32 m_index;
-};
-
-bool addArgument(
- ByteString * arguments, char prefix, rtl::OUString const & argument)
-{
- rtl::OString utf8;
- if (!argument.convertToString(
- &utf8, RTL_TEXTENCODING_UTF8,
- (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
- RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
- {
- return false;
- }
- *arguments += prefix;
- for (sal_Int32 i = 0; i < utf8.getLength(); ++i) {
- char c = utf8[i];
- switch (c) {
- case '\0':
- *arguments += "\\0";
- break;
- case ',':
- *arguments += "\\,";
- break;
- case '\\':
- *arguments += "\\\\";
- break;
- default:
- *arguments += c;
- break;
- }
- }
- return true;
-}
-
-}
-
-OfficeIPCThread* OfficeIPCThread::pGlobalOfficeIPCThread = 0;
- namespace { struct Security : public rtl::Static<osl::Security, Security> {}; }
-
-// Turns a string in aMsg such as file:///home/foo/.libreoffice/3
-// Into a hex string of well known length ff132a86...
-String CreateMD5FromString( const OUString& aMsg )
-{
-#if (OSL_DEBUG_LEVEL > 2)
- fprintf (stderr, "create md5 from '%s'\n",
- (const sal_Char *)rtl::OUStringToOString (aMsg, RTL_TEXTENCODING_UTF8));
-#endif
-
- rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
- if ( handle > 0 )
- {
- const sal_uInt8* pData = (const sal_uInt8*)aMsg.getStr();
- sal_uInt32 nSize = ( aMsg.getLength() * sizeof( sal_Unicode ));
- sal_uInt32 nMD5KeyLen = rtl_digest_queryLength( handle );
- sal_uInt8* pMD5KeyBuffer = new sal_uInt8[ nMD5KeyLen ];
-
- rtl_digest_init( handle, pData, nSize );
- rtl_digest_update( handle, pData, nSize );
- rtl_digest_get( handle, pMD5KeyBuffer, nMD5KeyLen );
- rtl_digest_destroy( handle );
-
- // Create hex-value string from the MD5 value to keep the string size minimal
- OUStringBuffer aBuffer( nMD5KeyLen * 2 + 1 );
- for ( sal_uInt32 i = 0; i < nMD5KeyLen; i++ )
- aBuffer.append( (sal_Int32)pMD5KeyBuffer[i], 16 );
-
- delete [] pMD5KeyBuffer;
- return aBuffer.makeStringAndClear();
- }
-
- return String();
-}
-
-class ProcessEventsClass_Impl
-{
-public:
- DECL_STATIC_LINK( ProcessEventsClass_Impl, CallEvent, void* pEvent );
- DECL_STATIC_LINK( ProcessEventsClass_Impl, ProcessDocumentsEvent, void* pEvent );
-};
-
-IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, CallEvent, void*, pEvent )
-{
- // Application events are processed by the Desktop::HandleAppEvent implementation.
- Desktop::HandleAppEvent( *((ApplicationEvent*)pEvent) );
- delete (ApplicationEvent*)pEvent;
- return 0;
-}
-
-IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, ProcessDocumentsEvent, void*, pEvent )
-{
- // Documents requests are processed by the OfficeIPCThread implementation
- ProcessDocumentsRequest* pDocsRequest = (ProcessDocumentsRequest*)pEvent;
-
- if ( pDocsRequest )
- {
- OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
- delete pDocsRequest;
- }
- return 0;
-}
-
-void ImplPostForeignAppEvent( ApplicationEvent* pEvent )
-{
- Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, CallEvent ), pEvent );
-}
-
-void ImplPostProcessDocumentsEvent( ProcessDocumentsRequest* pEvent )
-{
- Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, ProcessDocumentsEvent ), pEvent );
-}
-
-oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* pInfo)
-{
- if( pInfo->Signal == osl_Signal_Terminate )
- OfficeIPCThread::DisableOfficeIPCThread();
- return osl_Signal_ActCallNextHdl;
-}
-
-// ----------------------------------------------------------------------------
-
-// The OfficeIPCThreadController implementation is a bookkeeper for all pending requests
-// that were created by the OfficeIPCThread. The requests are waiting to be processed by
-// our framework loadComponentFromURL function (e.g. open/print request).
-// During shutdown the framework is asking OfficeIPCThreadController about pending requests.
-// If there are pending requests framework has to stop the shutdown process. It is waiting
-// for these requests because framework is not able to handle shutdown and open a document
-// concurrently.
-
-
-// XServiceInfo
-OUString SAL_CALL OfficeIPCThreadController::getImplementationName()
-throw ( RuntimeException )
-{
- return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.OfficeIPCThreadController" ));
-}
-
-sal_Bool SAL_CALL OfficeIPCThreadController::supportsService( const OUString& )
-throw ( RuntimeException )
-{
- return sal_False;
-}
-
-Sequence< OUString > SAL_CALL OfficeIPCThreadController::getSupportedServiceNames()
-throw ( RuntimeException )
-{
- Sequence< OUString > aSeq( 0 );
- return aSeq;
-}
-
-// XEventListener
-void SAL_CALL OfficeIPCThreadController::disposing( const EventObject& )
-throw( RuntimeException )
-{
-}
-
-// XTerminateListener
-void SAL_CALL OfficeIPCThreadController::queryTermination( const EventObject& )
-throw( TerminationVetoException, RuntimeException )
-{
- // Desktop ask about pending request through our office ipc pipe. We have to
- // be sure that no pending request is waiting because framework is not able to
- // handle shutdown and open a document concurrently.
-
- if ( OfficeIPCThread::AreRequestsPending() )
- throw TerminationVetoException();
- else
- OfficeIPCThread::SetDowning();
-}
-
-void SAL_CALL OfficeIPCThreadController::notifyTermination( const EventObject& )
-throw( RuntimeException )
-{
-}
-
-namespace
-{
- class theOfficeIPCThreadMutex
- : public rtl::Static<osl::Mutex, theOfficeIPCThreadMutex> {};
-}
-
-::osl::Mutex& OfficeIPCThread::GetMutex()
-{
- return theOfficeIPCThreadMutex::get();
-}
-
-void OfficeIPCThread::SetDowning()
-{
- // We have the order to block all incoming requests. Framework
- // wants to shutdown and we have to make sure that no loading/printing
- // requests are executed anymore.
- ::osl::MutexGuard aGuard( GetMutex() );
-
- if ( pGlobalOfficeIPCThread )
- pGlobalOfficeIPCThread->mbDowning = true;
-}
-
-static bool s_bInEnableRequests = false;
-
-void OfficeIPCThread::EnableRequests( bool i_bEnable )
-{
- // switch between just queueing the requests and executing them
- ::osl::MutexGuard aGuard( GetMutex() );
-
- if ( pGlobalOfficeIPCThread )
- {
- s_bInEnableRequests = true;
- pGlobalOfficeIPCThread->mbRequestsEnabled = i_bEnable;
- if( i_bEnable )
- {
- // hit the compiler over the head
- ProcessDocumentsRequest aEmptyReq = ProcessDocumentsRequest( boost::optional< rtl::OUString >() );
- // trigger already queued requests
- OfficeIPCThread::ExecuteCmdLineRequests( aEmptyReq );
- }
- s_bInEnableRequests = false;
- }
-}
-
-sal_Bool OfficeIPCThread::AreRequestsPending()
-{
- // Give info about pending requests
- ::osl::MutexGuard aGuard( GetMutex() );
- if ( pGlobalOfficeIPCThread )
- return ( pGlobalOfficeIPCThread->mnPendingRequests > 0 );
- else
- return sal_False;
-}
-
-void OfficeIPCThread::RequestsCompleted( int nCount )
-{
- // Remove nCount pending requests from our internal counter
- ::osl::MutexGuard aGuard( GetMutex() );
- if ( pGlobalOfficeIPCThread )
- {
- if ( pGlobalOfficeIPCThread->mnPendingRequests > 0 )
- pGlobalOfficeIPCThread->mnPendingRequests -= nCount;
- }
-}
-
-OfficeIPCThread::Status OfficeIPCThread::EnableOfficeIPCThread()
-{
- ::osl::MutexGuard aGuard( GetMutex() );
-
- if( pGlobalOfficeIPCThread )
- return IPC_STATUS_OK;
-
- ::rtl::OUString aUserInstallPath;
- ::rtl::OUString aDummy;
-
- OfficeIPCThread* pThread = new OfficeIPCThread;
-
- pThread->maPipeIdent = OUString( RTL_CONSTASCII_USTRINGPARAM( "SingleOfficeIPC_" ) );
-
- // The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve
- // this information from a unotools implementation.
- ::utl::Bootstrap::PathStatus aLocateResult = ::utl::Bootstrap::locateUserInstallation( aUserInstallPath );
- if ( aLocateResult == ::utl::Bootstrap::PATH_EXISTS || aLocateResult == ::utl::Bootstrap::PATH_VALID)
- aDummy = aUserInstallPath;
- else
- {
- delete pThread;
- return IPC_STATUS_BOOTSTRAP_ERROR;
- }
-
- // Try to determine if we are the first office or not! This should prevent multiple
- // access to the user directory !
- // First we try to create our pipe if this fails we try to connect. We have to do this
- // in a loop because the the other office can crash or shutdown between createPipe
- // and connectPipe!!
-
- OUString aIniName;
-
- osl_getExecutableFile( &aIniName.pData );
-
- sal_uInt32 lastIndex = aIniName.lastIndexOf('/');
- if ( lastIndex > 0 )
- {
- aIniName = aIniName.copy( 0, lastIndex+1 );
- aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" ));
-#if defined(WNT)
- aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" ));
-#else
- aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" ));
-#endif
- }
-
- ::rtl::Bootstrap aPerfTuneIniFile( aIniName );
-
- OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" ));
- OUString aPreloadData;
-
- aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "FastPipeCommunication" )), aPreloadData, aDefault );
-
-
- OUString aUserInstallPathHashCode;
-
- if ( aPreloadData.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "1" ) ))
- {
- sal_Char szBuffer[32];
- sprintf( szBuffer, "%d", SUPD );
- aUserInstallPathHashCode = OUString( szBuffer, strlen(szBuffer), osl_getThreadTextEncoding() );
- }
- else
- aUserInstallPathHashCode = CreateMD5FromString( aDummy );
-
-
- // Check result to create a hash code from the user install path
- if ( aUserInstallPathHashCode.getLength() == 0 )
- return IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code!
-
- pThread->maPipeIdent = pThread->maPipeIdent + aUserInstallPathHashCode;
-
- PipeMode nPipeMode = PIPEMODE_DONTKNOW;
- do
- {
- osl::Security &rSecurity = Security::get();
- // Try to create pipe
- if ( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_CREATE, rSecurity ))
- {
- // Pipe created
- nPipeMode = PIPEMODE_CREATED;
- }
- else if( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_OPEN, rSecurity )) // Creation not successfull, now we try to connect
- {
- // Pipe connected to first office
- nPipeMode = PIPEMODE_CONNECTED;
- }
- else
- {
- oslPipeError eReason = pThread->maPipe.getError();
- if ((eReason == osl_Pipe_E_ConnectionRefused) || (eReason == osl_Pipe_E_invalidError))
- return IPC_STATUS_BOOTSTRAP_ERROR;
-
- // Wait for second office to be ready
- TimeValue aTimeValue;
- aTimeValue.Seconds = 0;
- aTimeValue.Nanosec = 10000000; // 10ms
- osl::Thread::wait( aTimeValue );
- }
-
- } while ( nPipeMode == PIPEMODE_DONTKNOW );
-
- if ( nPipeMode == PIPEMODE_CREATED )
- {
- // Seems we are the one and only, so start listening thread
- pGlobalOfficeIPCThread = pThread;
- pThread->create(); // starts thread
- }
- else
- {
- // Seems another office is running. Pipe arguments to it and self terminate
- osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle());
-
- ByteString aArguments(RTL_CONSTASCII_STRINGPARAM(ARGUMENT_PREFIX));
- rtl::OUString cwdUrl;
- if (!(tools::getProcessWorkingDir(cwdUrl) &&
- addArgument(&aArguments, '1', cwdUrl)))
- {
- aArguments += '0';
- }
- sal_uInt32 nCount = rtl_getAppCommandArgCount();
- for( sal_uInt32 i=0; i < nCount; i++ )
- {
- rtl_getAppCommandArg( i, &aDummy.pData );
- if (!addArgument(&aArguments, ',', aDummy)) {
- return IPC_STATUS_BOOTSTRAP_ERROR;
- }
- }
- // finally, write the string onto the pipe
- aStreamPipe.write( aArguments.GetBuffer(), aArguments.Len() );
- aStreamPipe.write( "\0", 1 );
-
- ByteString aToken(sc_aConfirmationSequence);
- char *aReceiveBuffer = new char[aToken.Len()+1];
- int n = aStreamPipe.read( aReceiveBuffer, aToken.Len() );
- aReceiveBuffer[n]='\0';
-
- delete pThread;
- if (aToken.CompareTo(aReceiveBuffer)!= COMPARE_EQUAL) {
- // something went wrong
- delete[] aReceiveBuffer;
- return IPC_STATUS_BOOTSTRAP_ERROR;
- } else {
- delete[] aReceiveBuffer;
- return IPC_STATUS_2ND_OFFICE;
- }
- }
-
- return IPC_STATUS_OK;
-}
-
-void OfficeIPCThread::DisableOfficeIPCThread()
-{
- osl::ClearableMutexGuard aMutex( GetMutex() );
-
- if( pGlobalOfficeIPCThread )
- {
- OfficeIPCThread *pOfficeIPCThread = pGlobalOfficeIPCThread;
- pGlobalOfficeIPCThread = 0;
-
- // send thread a termination message
- // this is done so the subsequent join will not hang
- // because the thread hangs in accept of pipe
- osl::StreamPipe aPipe ( pOfficeIPCThread->maPipeIdent, osl_Pipe_OPEN, Security::get() );
- if (aPipe.is())
- {
- aPipe.send( sc_aTerminationSequence, sc_nTSeqLength+1 ); // also send 0-byte
-
- // close the pipe so that the streampipe on the other
- // side produces EOF
- aPipe.close();
- }
-
- // release mutex to avoid deadlocks
- aMutex.clear();
-
- OfficeIPCThread::SetReady(pOfficeIPCThread);
-
- // exit gracefully and join
- pOfficeIPCThread->join();
- delete pOfficeIPCThread;
-
-
- }
-}
-
-OfficeIPCThread::OfficeIPCThread() :
- mbDowning( false ),
- mbRequestsEnabled( false ),
- mnPendingRequests( 0 ),
- mpDispatchWatcher( 0 )
-{
-}
-
-OfficeIPCThread::~OfficeIPCThread()
-{
- ::osl::ClearableMutexGuard aGuard( GetMutex() );
-
- if ( mpDispatchWatcher )
- mpDispatchWatcher->release();
- maPipe.close();
- maStreamPipe.close();
- pGlobalOfficeIPCThread = 0;
-}
-
-static void AddURLToStringList( const rtl::OUString& aURL, rtl::OUString& aStringList )
-{
- if ( aStringList.getLength() )
- aStringList += ::rtl::OUString::valueOf( (sal_Unicode)APPEVENT_PARAM_DELIMITER );
- aStringList += aURL;
-}
-
-void OfficeIPCThread::SetReady(OfficeIPCThread* pThread)
-{
- if (pThread == NULL) pThread = pGlobalOfficeIPCThread;
- if (pThread != NULL)
- {
- pThread->cReady.set();
- }
-}
-
-void SAL_CALL OfficeIPCThread::run()
-{
- do
- {
- oslPipeError nError = maPipe.accept( maStreamPipe );
-
-
- if( nError == osl_Pipe_E_None )
- {
- // if we receive a request while the office is displaying some dialog or error during
- // bootstrap, that dialogs event loop might get events that are dispatched by this thread
- // we have to wait for cReady to be set by the real main loop.
- // only reqests that dont dispatch events may be processed before cReady is set.
- cReady.wait();
-
- // we might have decided to shutdown while we were sleeping
- if (!pGlobalOfficeIPCThread) return;
-
- // only lock the mutex when processing starts, othewise we deadlock when the office goes
- // down during wait
- osl::ClearableMutexGuard aGuard( GetMutex() );
-
- ByteString aArguments;
- // test byte by byte
- const int nBufSz = 2048;
- char pBuf[nBufSz];
- int nBytes = 0;
- int nResult = 0;
- // read into pBuf until '\0' is read or read-error
- while ((nResult=maStreamPipe.recv( pBuf+nBytes, nBufSz-nBytes))>0) {
- nBytes += nResult;
- if (pBuf[nBytes-1]=='\0') {
- aArguments += pBuf;
- break;
- }
- }
- // don't close pipe ...
-
- // Is this a lookup message from another application? if so, ignore
- if ( aArguments.Len() == 0 )
- continue;
-
- // is this a termination message ? if so, terminate
- if(( aArguments.CompareTo( sc_aTerminationSequence, sc_nTSeqLength ) == COMPARE_EQUAL ) ||
- mbDowning ) return;
- String aEmpty;
- std::auto_ptr< CommandLineArgs > aCmdLineArgs;
- try
- {
- Parser p( aArguments );
- aCmdLineArgs.reset( new CommandLineArgs( p ) );
- }
- catch ( CommandLineArgs::Supplier::Exception & )
- {
-#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
- fprintf( stderr, "Error in received command line arguments\n" );
-#endif
- continue;
- }
- const CommandLineArgs &rCurrentCmdLineArgs = Desktop::GetCommandLineArgs();
-
- if ( aCmdLineArgs->IsQuickstart() )
- {
- // we have to use application event, because we have to start quickstart service in main thread!!
- ApplicationEvent* pAppEvent =
- new ApplicationEvent( aEmpty, aEmpty,
- "QUICKSTART", aEmpty );
- ImplPostForeignAppEvent( pAppEvent );
- }
-
- // handle request for acceptor
- OUString aAcceptString;
- if ( aCmdLineArgs->GetAcceptString(aAcceptString) ) {
- ApplicationEvent* pAppEvent =
- new ApplicationEvent( aEmpty, aEmpty,
- "ACCEPT", aAcceptString );
- ImplPostForeignAppEvent( pAppEvent );
- }
- // handle acceptor removal
- OUString aUnAcceptString;
- if ( aCmdLineArgs->GetUnAcceptString(aUnAcceptString) ) {
- ApplicationEvent* pAppEvent =
- new ApplicationEvent( aEmpty, aEmpty,
- "UNACCEPT", aUnAcceptString );
- ImplPostForeignAppEvent( pAppEvent );
- }
-
-#ifndef UNX
- // only in non-unix version, we need to handle a -help request
- // in a running instance in order to display the command line help
- if ( aCmdLineArgs->IsHelp() ) {
- ApplicationEvent* pAppEvent =
- new ApplicationEvent( aEmpty, aEmpty, "HELP", aEmpty );
- ImplPostForeignAppEvent( pAppEvent );
- }
-#endif
-
- sal_Bool bDocRequestSent = sal_False;
- ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest(
- aCmdLineArgs->getCwdUrl());
- cProcessed.reset();
- pRequest->pcProcessed = &cProcessed;
-
- // Print requests are not dependent on the -invisible cmdline argument as they are
- // loaded with the "hidden" flag! So they are always checked.
- bDocRequestSent |= aCmdLineArgs->GetPrintList( pRequest->aPrintList );
- bDocRequestSent |= ( aCmdLineArgs->GetPrintToList( pRequest->aPrintToList ) &&
- aCmdLineArgs->GetPrinterName( pRequest->aPrinterName ) );
-
- if ( !rCurrentCmdLineArgs.IsInvisible() )
- {
- // Read cmdline args that can open/create documents. As they would open a window
- // they are only allowed if the "-invisible" is currently not used!
- bDocRequestSent |= aCmdLineArgs->GetOpenList( pRequest->aOpenList );
- bDocRequestSent |= aCmdLineArgs->GetViewList( pRequest->aViewList );
- bDocRequestSent |= aCmdLineArgs->GetStartList( pRequest->aStartList );
- bDocRequestSent |= aCmdLineArgs->GetForceOpenList( pRequest->aForceOpenList );
- bDocRequestSent |= aCmdLineArgs->GetForceNewList( pRequest->aForceNewList );
-
- // Special command line args to create an empty document for a given module
-
- // #i18338# (lo)
- // we only do this if no document was specified on the command line,
- // since this would be inconsistent with the the behaviour of
- // the first process, see OpenClients() (call to OpenDefault()) in app.cxx
- if ( aCmdLineArgs->HasModuleParam() && (!bDocRequestSent) )
- {
- SvtModuleOptions aOpt;
- SvtModuleOptions::EFactory eFactory = SvtModuleOptions::E_WRITER;
- if ( aCmdLineArgs->IsWriter() )
- eFactory = SvtModuleOptions::E_WRITER;
- else if ( aCmdLineArgs->IsCalc() )
- eFactory = SvtModuleOptions::E_CALC;
- else if ( aCmdLineArgs->IsDraw() )
- eFactory = SvtModuleOptions::E_DRAW;
- else if ( aCmdLineArgs->IsImpress() )
- eFactory = SvtModuleOptions::E_IMPRESS;
- else if ( aCmdLineArgs->IsBase() )
- eFactory = SvtModuleOptions::E_DATABASE;
- else if ( aCmdLineArgs->IsMath() )
- eFactory = SvtModuleOptions::E_MATH;
- else if ( aCmdLineArgs->IsGlobal() )
- eFactory = SvtModuleOptions::E_WRITERGLOBAL;
- else if ( aCmdLineArgs->IsWeb() )
- eFactory = SvtModuleOptions::E_WRITERWEB;
-
- if ( pRequest->aOpenList.getLength() )
- pRequest->aModule = aOpt.GetFactoryName( eFactory );
- else
- AddURLToStringList( aOpt.GetFactoryEmptyDocumentURL( eFactory ), pRequest->aOpenList );
- bDocRequestSent = sal_True;
- }
- }
-
- if ( !aCmdLineArgs->IsQuickstart() ) {
- sal_Bool bShowHelp = sal_False;
- rtl::OUStringBuffer aHelpURLBuffer;
- if (aCmdLineArgs->IsHelpWriter()) {
- bShowHelp = sal_True;
- aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
- } else if (aCmdLineArgs->IsHelpCalc()) {
- bShowHelp = sal_True;
- aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
- } else if (aCmdLineArgs->IsHelpDraw()) {
- bShowHelp = sal_True;
- aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
- } else if (aCmdLineArgs->IsHelpImpress()) {
- bShowHelp = sal_True;
- aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
- } else if (aCmdLineArgs->IsHelpBase()) {
- bShowHelp = sal_True;
- aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
- } else if (aCmdLineArgs->IsHelpBasic()) {
- bShowHelp = sal_True;
- aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
- } else if (aCmdLineArgs->IsHelpMath()) {
- bShowHelp = sal_True;
- aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
- }
- if (bShowHelp) {
- Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE );
- rtl::OUString aTmp;
- aRet >>= aTmp;
- aHelpURLBuffer.appendAscii("?Language=");
- aHelpURLBuffer.append(aTmp);
-#if defined UNX
- aHelpURLBuffer.appendAscii("&System=UNX");
-#elif defined WNT
- aHelpURLBuffer.appendAscii("&System=WIN");
-#endif
- ApplicationEvent* pAppEvent =
- new ApplicationEvent( aEmpty, aEmpty,
- "OPENHELPURL", aHelpURLBuffer.makeStringAndClear());
- ImplPostForeignAppEvent( pAppEvent );
- }
- }
-
- if ( bDocRequestSent )
- {
- // Send requests to dispatch watcher if we have at least one. The receiver
- // is responsible to delete the request after processing it.
- if ( aCmdLineArgs->HasModuleParam() )
- {
- SvtModuleOptions aOpt;
-
- // Support command line parameters to start a module (as preselection)
- if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
- pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER );
- else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
- pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC );
- else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
- pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS );
- else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
- pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW );
- }
-
-
- ImplPostProcessDocumentsEvent( pRequest );
- }
- else
- {
- // delete not used request again
- delete pRequest;
- pRequest = NULL;
- }
- if (( aArguments.CompareTo( sc_aShowSequence, sc_nShSeqLength ) == COMPARE_EQUAL ) ||
- aCmdLineArgs->IsEmpty() )
- {
- // no document was sent, just bring Office to front
- ApplicationEvent* pAppEvent =
- new ApplicationEvent( aEmpty, aEmpty, "APPEAR", aEmpty );
- ImplPostForeignAppEvent( pAppEvent );
- }
-
- // we don't need the mutex any longer...
- aGuard.clear();
- // wait for processing to finish
- if (bDocRequestSent)
- cProcessed.wait();
- // processing finished, inform the requesting end
- nBytes = 0;
- while (
- (nResult = maStreamPipe.send(sc_aConfirmationSequence+nBytes, sc_nCSeqLength-nBytes))>0 &&
- ((nBytes += nResult) < sc_nCSeqLength) ) ;
- }
- else
- {
-#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
- fprintf( stderr, "Error on accept: %d\n", (int)nError );
-#endif
- TimeValue tval;
- tval.Seconds = 1;
- tval.Nanosec = 0;
- wait( tval );
- }
- } while( schedule() );
-}
-
-static void AddToDispatchList(
- DispatchWatcher::DispatchList& rDispatchList,
- boost::optional< rtl::OUString > const & cwdUrl,
- const OUString& aRequestList,
- DispatchWatcher::RequestType nType,
- const OUString& aParam,
- const OUString& aFactory )
-{
- if ( aRequestList.getLength() > 0 )
- {
- sal_Int32 nIndex = 0;
- do
- {
- OUString aToken = aRequestList.getToken( 0, APPEVENT_PARAM_DELIMITER, nIndex );
- if ( aToken.getLength() > 0 )
- rDispatchList.push_back(
- DispatchWatcher::DispatchRequest( nType, aToken, cwdUrl, aParam, aFactory ));
- }
- while ( nIndex >= 0 );
- }
-}
-
-static void AddConversionsToDispatchList(
- DispatchWatcher::DispatchList& rDispatchList,
- boost::optional< rtl::OUString > const & cwdUrl,
- const OUString& rRequestList,
- const OUString& rParam,
- const OUString& rPrinterName,
- const OUString& rFactory,
- const OUString& rParamOut )
-{
- DispatchWatcher::RequestType nType;
- OUString aParam( rParam );
-
- if( rParam.getLength() )
- {
- nType = DispatchWatcher::REQUEST_CONVERSION;
- aParam = rParam;
- }
- else
- {
- nType = DispatchWatcher::REQUEST_BATCHPRINT;
- aParam = rPrinterName;
- }
-
- OUString aOutDir( rParamOut.trim() );
- ::rtl::OUString aPWD;
- ::tools::getProcessWorkingDir( aPWD );
-
- if( !::osl::FileBase::getAbsoluteFileURL( aPWD, rParamOut, aOutDir ) )
- ::osl::FileBase::getSystemPathFromFileURL( aOutDir, aOutDir );
-
- if( rParamOut.trim().getLength() )
- {
- aParam += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
- aParam += aOutDir;
- }
- else
- {
- ::osl::FileBase::getSystemPathFromFileURL( aPWD, aPWD );
- aParam += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";" )) + aPWD;
- }
-
- if ( rRequestList.getLength() > 0 )
- {
- sal_Int32 nIndex = 0;
- do
- {
- OUString aToken = rRequestList.getToken( 0, APPEVENT_PARAM_DELIMITER, nIndex );
- if ( aToken.getLength() > 0 )
- rDispatchList.push_back(
- DispatchWatcher::DispatchRequest( nType, aToken, cwdUrl, aParam, rFactory ));
- }
- while ( nIndex >= 0 );
- }
-}
-
-
-sal_Bool OfficeIPCThread::ExecuteCmdLineRequests( ProcessDocumentsRequest& aRequest )
-{
- // protect the dispatch list
- osl::ClearableMutexGuard aGuard( GetMutex() );
-
- static DispatchWatcher::DispatchList aDispatchList;
-
- rtl::OUString aEmpty;
- // Create dispatch list for dispatch watcher
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aInFilter, DispatchWatcher::REQUEST_INFILTER, aEmpty, aRequest.aModule );
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aOpenList, DispatchWatcher::REQUEST_OPEN, aEmpty, aRequest.aModule );
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aViewList, DispatchWatcher::REQUEST_VIEW, aEmpty, aRequest.aModule );
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aStartList, DispatchWatcher::REQUEST_START, aEmpty, aRequest.aModule );
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintList, DispatchWatcher::REQUEST_PRINT, aEmpty, aRequest.aModule );
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintToList, DispatchWatcher::REQUEST_PRINTTO, aRequest.aPrinterName, aRequest.aModule );
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceOpenList, DispatchWatcher::REQUEST_FORCEOPEN, aEmpty, aRequest.aModule );
- AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceNewList, DispatchWatcher::REQUEST_FORCENEW, aEmpty, aRequest.aModule );
- AddConversionsToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aConversionList, aRequest.aConversionParams, aRequest.aPrinterName, aRequest.aModule, aRequest.aConversionOut );
- sal_Bool bShutdown( sal_False );
-
- if ( pGlobalOfficeIPCThread )
- {
- if( ! pGlobalOfficeIPCThread->AreRequestsEnabled() )
- return bShutdown;
-
- pGlobalOfficeIPCThread->mnPendingRequests += aDispatchList.size();
- if ( !pGlobalOfficeIPCThread->mpDispatchWatcher )
- {
- pGlobalOfficeIPCThread->mpDispatchWatcher = DispatchWatcher::GetDispatchWatcher();
- pGlobalOfficeIPCThread->mpDispatchWatcher->acquire();
- }
-
- // copy for execute
- DispatchWatcher::DispatchList aTempList( aDispatchList );
- aDispatchList.clear();
-
- aGuard.clear();
-
- // Execute dispatch requests
- bShutdown = pGlobalOfficeIPCThread->mpDispatchWatcher->executeDispatchRequests( aTempList, s_bInEnableRequests );
-
- // set processed flag
- if (aRequest.pcProcessed != NULL)
- aRequest.pcProcessed->set();
- }
-
- return bShutdown;
-}
-
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */