All pastes #1892575 Raw Edit

Stuff

public cpp v1 · immutable
#1892575 ·published 2010-07-01 06:53 UTC
rendered paste body
/************************************************************************* * * 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 <sfx2/docfile.hxx>#include <sfx2/docfilt.hxx>#include <sfx2/fcontnr.hxx>#include "osl/file.hxx"#include <svl/fstathelper.hxx>#include "dispatchwatcher.hxx"#include <rtl/ustring.hxx>#include <tools/string.hxx>#include <comphelper/processfactory.hxx>#include <comphelper/synchronousdispatch.hxx>#include <com/sun/star/util/XCloseable.hpp>#include <com/sun/star/util/CloseVetoException.hpp>#include <com/sun/star/task/XInteractionHandler.hpp>#include <com/sun/star/util/URL.hpp>#include <com/sun/star/frame/XDesktop.hpp>#include <com/sun/star/container/XEnumeration.hpp>#include <com/sun/star/frame/XFramesSupplier.hpp>#include <com/sun/star/frame/XDispatch.hpp>#include <com/sun/star/frame/XComponentLoader.hpp>#include <com/sun/star/beans/PropertyValue.hpp>#include <com/sun/star/view/XPrintable.hpp>#include <com/sun/star/frame/XDispatchProvider.hpp>#include <com/sun/star/util/XURLTransformer.hpp>#include <com/sun/star/document/MacroExecMode.hpp>#include <com/sun/star/document/UpdateDocMode.hpp>#include <com/sun/star/frame/XStorable.hpp>#include <tools/urlobj.hxx>#include <comphelper/mediadescriptor.hxx>#include <vector>#include <osl/thread.hxx>namespace{static void impl_sleep( sal_uInt32 nSec ){    TimeValue aTime;    aTime.Seconds = nSec;    aTime.Nanosec = 0;    osl::Thread::wait( aTime );}}using ::rtl::OUString;using namespace ::osl;using namespace ::com::sun::star::uno;using namespace ::com::sun::star::util;using namespace ::com::sun::star::lang;using namespace ::com::sun::star::frame;using namespace ::com::sun::star::container;using namespace ::com::sun::star::beans;using namespace ::com::sun::star::view;namespace desktop{String GetURL_Impl(    const String& rName, boost::optional< rtl::OUString > const & cwdUrl );struct DispatchHolder{    DispatchHolder( const URL& rURL, Reference< XDispatch >& rDispatch ) :        aURL( rURL ), xDispatch( rDispatch ) {}    URL	aURL;    rtl::OUString cwdUrl;    Reference< XDispatch > xDispatch;};static String impl_GetFilterFromExt( OUString aUrl, SfxFilterFlags nFlags,                                         String aAppl ){    String aFilter;    SfxMedium* pMedium = new SfxMedium( aUrl,                                         STREAM_STD_READ, FALSE );    const SfxFilter *pSfxFilter = NULL;    SfxFilterMatcher aMatcher;    if( nFlags == SFX_FILTER_EXPORT )        aMatcher = SfxFilterMatcher( aAppl );    aMatcher.GuessFilterIgnoringContent( *pMedium, &pSfxFilter, nFlags, 0 );    if( pSfxFilter )        aFilter = ( nFlags == SFX_FILTER_EXPORT ) ? pSfxFilter->GetFilterName() :                                                     pSfxFilter->GetServiceName();        delete pMedium;        return aFilter;}static OUString impl_GuessFilter( OUString aUrlIn, OUString aUrlOut ){    /* aAppl can also be set to Factory like scalc, swriter... */    String aAppl;    aAppl = impl_GetFilterFromExt( aUrlIn, SFX_FILTER_IMPORT, aAppl );    return  impl_GetFilterFromExt( aUrlOut, SFX_FILTER_EXPORT, aAppl );}Mutex* DispatchWatcher::pWatcherMutex = NULL;Mutex& DispatchWatcher::GetMutex(){    if ( !pWatcherMutex )    {        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );        if ( !pWatcherMutex )            pWatcherMutex = new osl::Mutex();    }    return *pWatcherMutex;}// Create or get the dispatch watcher implementation. This implementation must be // a singleton to prevent access to the framework after it wants to terminate.DispatchWatcher* DispatchWatcher::GetDispatchWatcher(){    static Reference< XInterface > xDispatchWatcher;    static DispatchWatcher*        pDispatchWatcher = NULL;    if ( !xDispatchWatcher.is() )    {        ::osl::MutexGuard aGuard( GetMutex() );        if ( !xDispatchWatcher.is() )        {            pDispatchWatcher = new DispatchWatcher();                        // We have to hold a reference to ourself forever to prevent our own destruction.            xDispatchWatcher = static_cast< cppu::OWeakObject *>( pDispatchWatcher );        }    }    return pDispatchWatcher;}DispatchWatcher::DispatchWatcher()    : m_nRequestCount(0){}DispatchWatcher::~DispatchWatcher(){}sal_Bool DispatchWatcher::executeDispatchRequests( const DispatchList& aDispatchRequestsList, bool bNoTerminate ){    Reference< XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(                                                OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),                                            UNO_QUERY );    DispatchList::const_iterator	p;    std::vector< DispatchHolder >	aDispatches;    ::rtl::OUString					aAsTemplateArg( RTL_CONSTASCII_USTRINGPARAM( "AsTemplate"));    for ( p = aDispatchRequestsList.begin(); p != aDispatchRequestsList.end(); p++ )    {        String					aPrinterName;        const DispatchRequest&	aDispatchRequest = *p;        // create parameter array        sal_Int32 nCount = 4;        if ( aDispatchRequest.aPreselectedFactory.getLength() )            nCount++;        // we need more properties for a print/print to request        if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||             aDispatchRequest.aRequestType == REQUEST_PRINTTO ||             aDispatchRequest.aRequestType == REQUEST_CONVERSION)            nCount++;        Sequence < PropertyValue > aArgs( nCount );        // mark request as user interaction from outside        aArgs[0].Name = ::rtl::OUString::createFromAscii("Referer");        aArgs[0].Value <<= ::rtl::OUString::createFromAscii("private:OpenEvent");        if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||             aDispatchRequest.aRequestType == REQUEST_PRINTTO ||             aDispatchRequest.aRequestType == REQUEST_CONVERSION)        {            aArgs[1].Name = ::rtl::OUString::createFromAscii("ReadOnly");            aArgs[2].Name = ::rtl::OUString::createFromAscii("OpenNewView");            aArgs[3].Name = ::rtl::OUString::createFromAscii("Hidden");            aArgs[4].Name = ::rtl::OUString::createFromAscii("Silent");        }        else        {            Reference < com::sun::star::task::XInteractionHandler > xInteraction(                ::comphelper::getProcessServiceFactory()->createInstance( OUString::createFromAscii("com.sun.star.task.InteractionHandler") ),                com::sun::star::uno::UNO_QUERY );            aArgs[1].Name = OUString::createFromAscii( "InteractionHandler" );            aArgs[1].Value <<= xInteraction;            sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;            aArgs[2].Name = OUString::createFromAscii( "MacroExecutionMode" );            aArgs[2].Value <<= nMacroExecMode;            sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;            aArgs[3].Name = OUString::createFromAscii( "UpdateDocMode" );            aArgs[3].Value <<= nUpdateDoc;        }        if ( aDispatchRequest.aPreselectedFactory.getLength() )        {            aArgs[nCount-1].Name = ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE();            aArgs[nCount-1].Value <<= aDispatchRequest.aPreselectedFactory;        }        String aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );        ::rtl::OUString aTarget( RTL_CONSTASCII_USTRINGPARAM("_default") );        if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||             aDispatchRequest.aRequestType == REQUEST_PRINTTO ||             aDispatchRequest.aRequestType == REQUEST_CONVERSION)        {            // documents opened for printing are opened readonly because they must be opened as a new document and this            // document could be open already            aArgs[1].Value <<= sal_True;            // always open a new document for printing, because it must be disposed afterwards            aArgs[2].Value <<= sal_True;            // printing is done in a hidden view            aArgs[3].Value <<= sal_True;            // load document for printing without user interaction            aArgs[4].Value <<= sal_True;            // hidden documents should never be put into open tasks            aTarget = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_blank") );        }        // load the document ... if they are loadable!        // Otherwise try to dispatch it ...        Reference < XPrintable > xDoc;        if(            ( aName.CompareToAscii( ".uno"  , 4 ) == COMPARE_EQUAL )  ||            ( aName.CompareToAscii( "slot:" , 5 ) == COMPARE_EQUAL )  ||            ( aName.CompareToAscii( "macro:", 6 ) == COMPARE_EQUAL )  ||            ( aName.CompareToAscii("vnd.sun.star.script", 19) == COMPARE_EQUAL)          )        {            // Attention: URL must be parsed full. Otherwise some detections on it will fail!            // It doesnt matter, if parser isn't available. Because; We try loading of URL then ...            URL             aURL ;            aURL.Complete = aName;            Reference < XDispatch >         xDispatcher ;            Reference < XDispatchProvider > xProvider   ( xDesktop, UNO_QUERY );            Reference < XURLTransformer >   xParser     ( ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), ::com::sun::star::uno::UNO_QUERY );            if( xParser.is() == sal_True )                xParser->parseStrict( aURL );            if( xProvider.is() == sal_True )                xDispatcher = xProvider->queryDispatch( aURL, ::rtl::OUString(), 0 );            if( xDispatcher.is() == sal_True )            {                {                    ::osl::ClearableMutexGuard aGuard( GetMutex() );                    // Remember request so we can find it in statusChanged!                    m_aRequestContainer.insert( DispatchWatcherHashMap::value_type( aURL.Complete, (sal_Int32)1 ) );                    m_nRequestCount++;                }                // Use local vector to store dispatcher because we have to fill our request container before                // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!                aDispatches.push_back( DispatchHolder( aURL, xDispatcher ));            }        }        else if ( ( aName.CompareToAscii( "service:"  , 8 ) == COMPARE_EQUAL ) )        {            // TODO: the dispatch has to be done for loadComponentFromURL as well. Please ask AS for more details.            URL             aURL ;            aURL.Complete = aName;            Reference < XDispatch >         xDispatcher ;            Reference < XDispatchProvider > xProvider   ( xDesktop, UNO_QUERY );            Reference < XURLTransformer >   xParser     ( ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), ::com::sun::star::uno::UNO_QUERY );            if( xParser.is() == sal_True )                xParser->parseStrict( aURL );            if( xProvider.is() == sal_True )                xDispatcher = xProvider->queryDispatch( aURL, ::rtl::OUString(), 0 );            if( xDispatcher.is() == sal_True )            {                try                {                    // We have to be listener to catch errors during dispatching URLs.                    // Otherwise it would be possible to have an office running without an open                    // window!!                    Sequence < PropertyValue > aArgs2(1);                    aArgs2[0].Name    = ::rtl::OUString::createFromAscii("SynchronMode");                    aArgs2[0].Value <<= sal_True;                    Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );                    if ( xDisp.is() )                        xDisp->dispatchWithNotification( aURL, aArgs2, DispatchWatcher::GetDispatchWatcher() );                    else                        xDispatcher->dispatch( aURL, aArgs2 );                }                catch ( ::com::sun::star::uno::Exception& )                {                    OUString aMsg = OUString::createFromAscii(                        "Desktop::OpenDefault() IllegalArgumentException while calling XNotifyingDispatch: ");                    OSL_ENSURE( sal_False, OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr());                }            }        }        else        {            INetURLObject aObj( aName );            if ( aObj.GetProtocol() == INET_PROT_PRIVATE )                aTarget = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_default") );            // Set "AsTemplate" argument according to request type            if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||                 aDispatchRequest.aRequestType == REQUEST_FORCEOPEN		)            {                sal_Int32 nIndex = aArgs.getLength();                aArgs.realloc( nIndex+1 );                aArgs[nIndex].Name = aAsTemplateArg;                if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW )                    aArgs[nIndex].Value <<= sal_True;                else                    aArgs[nIndex].Value <<= sal_False;            }            // if we are called in viewmode, open document read-only            // #95425#            if(aDispatchRequest.aRequestType == REQUEST_VIEW) {                sal_Int32 nIndex = aArgs.getLength();                aArgs.realloc(nIndex+1);                aArgs[nIndex].Name = OUString::createFromAscii("ReadOnly");                aArgs[nIndex].Value <<= sal_True;            }            // if we are called with -start set Start in mediadescriptor            if(aDispatchRequest.aRequestType == REQUEST_START) {                sal_Int32 nIndex = aArgs.getLength();                aArgs.realloc(nIndex+1);                aArgs[nIndex].Name = OUString::createFromAscii("StartPresentation");                aArgs[nIndex].Value <<= sal_True;            }            // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.            try            {                xDoc = Reference < XPrintable >( ::comphelper::SynchronousDispatch::dispatch( xDesktop, aName, aTarget, 0, aArgs ), UNO_QUERY );                //xDoc = Reference < XPrintable >( xDesktop->loadComponentFromURL( aName, aTarget, 0, aArgs ), UNO_QUERY );            }            catch ( ::com::sun::star::lang::IllegalArgumentException& iae)            {                OUString aMsg = OUString::createFromAscii(                    "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL: ")                    + iae.Message;                OSL_ENSURE( sal_False, OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr());            }            catch (com::sun::star::io::IOException& ioe)            {                OUString aMsg = OUString::createFromAscii(                    "Dispatchwatcher IOException while calling loadComponentFromURL: ")                    + ioe.Message;                OSL_ENSURE( sal_False, OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr());            }            if ( aDispatchRequest.aRequestType == REQUEST_OPEN ||                 aDispatchRequest.aRequestType == REQUEST_VIEW ||                 aDispatchRequest.aRequestType == REQUEST_START ||                 aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ||                 aDispatchRequest.aRequestType == REQUEST_FORCENEW		)            {                // request is completed                OfficeIPCThread::RequestsCompleted( 1 );            }            else if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||                      aDispatchRequest.aRequestType == REQUEST_PRINTTO ||                      aDispatchRequest.aRequestType == REQUEST_CONVERSION )            {                if ( xDoc.is() )                {                    if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ) {                        Reference< XStorable > xStorable( xDoc, UNO_QUERY );                        if ( xStorable.is() ) {                            rtl::OUString aParam = aDispatchRequest.aPrinterName;                            sal_Int32 nPathIndex =  aParam.lastIndexOfAsciiL( ";", 1 );                            sal_Int32 nFilterIndex = aParam.lastIndexOfAsciiL( ":", 1 );                            rtl::OUString aFilterOut=aParam.copy( nPathIndex+1 );                            rtl::OUString aFilter;                            rtl::OUString aFilterExt;                            sal_Bool bGuess = sal_False;                            if( nFilterIndex >= 0 )                            {                                aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );                                aFilterExt = aParam.copy( 0, nFilterIndex );                            }                            else                            {                                // Guess                                bGuess = sal_True;                                aFilterExt = aParam.copy( 0, nPathIndex );                            }                            INetURLObject aOutFilename( aObj );                            aOutFilename.SetExtension( aFilterExt );                            FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );                            rtl::OUString aOutFile = aFilterOut+                                                     ::rtl::OUString::createFromAscii( "/" )+                                                     aOutFilename.getName();                            //FileBase::getFileURLFromSystemPath( aOutFile, aOutFile );                            if ( bGuess )                            {                                aFilter = impl_GuessFilter( aName, aOutFile );                            }                            Sequence<PropertyValue> conversionProperties( 2 );                            conversionProperties[0].Name = ::rtl::OUString::createFromAscii( "Overwrite" );                            conversionProperties[0].Value <<= sal_True;                            conversionProperties[1].Name = ::rtl::OUString::createFromAscii( "FilterName" );                            conversionProperties[1].Value <<= aFilter;                            rtl::OUString aTempName;                            FileBase::getSystemPathFromFileURL( aName, aTempName );                            rtl::OString aSource8 = ::rtl::OUStringToOString ( aTempName, RTL_TEXTENCODING_UTF8 );                            FileBase::getSystemPathFromFileURL( aOutFile, aTempName );                            rtl::OString aTargetURL8 = ::rtl::OUStringToOString(aTempName, RTL_TEXTENCODING_UTF8 );                            printf("convert %s->%s using %s\n", aSource8.getStr(), aTargetURL8.getStr(),                                                                 ::rtl::OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr());                            if( FStatHelper::IsDocument(aOutFile) )                                printf("Overwriting: %s\n",::rtl::OUStringToOString( aTempName, RTL_TEXTENCODING_UTF8 ).getStr() );                            try                             {                                xStorable->storeToURL( aOutFile, conversionProperties );                            }                             catch ( Exception& )                             {                                fprintf( stderr, "Error: Please reverify input parameters...\n" );                            }                        }                    } else {                        if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )                        {                            // create the printer                            Sequence < PropertyValue > aPrinterArgs( 1 );                            aPrinterArgs[0].Name = ::rtl::OUString::createFromAscii("Name");                            aPrinterArgs[0].Value <<= ::rtl::OUString( aDispatchRequest.aPrinterName );                            xDoc->setPrinter( aPrinterArgs );                        }                        // print ( also without user interaction )                        Sequence < PropertyValue > aPrinterArgs( 1 );                        aPrinterArgs[0].Name = ::rtl::OUString::createFromAscii("Wait");                        aPrinterArgs[0].Value <<= ( sal_Bool ) sal_True;                        xDoc->print( aPrinterArgs );                    }                }                else                {                    // place error message here ...                }                // remove the document                try                {                    Reference < XCloseable > xClose( xDoc, UNO_QUERY );                    if ( xClose.is() )                        xClose->close( sal_True );                    else                    {                        Reference < XComponent > xComp( xDoc, UNO_QUERY );                        if ( xComp.is() )                            xComp->dispose();                    }                }                catch ( com::sun::star::util::CloseVetoException& )                {                }                // request is completed                OfficeIPCThread::RequestsCompleted( 1 );            }        }    }    if ( aDispatches.size() > 0 )    {        // Execute all asynchronous dispatches now after we placed them into our request container!        Sequence < PropertyValue > aArgs( 2 );        aArgs[0].Name = ::rtl::OUString::createFromAscii("Referer");        aArgs[0].Value <<= ::rtl::OUString::createFromAscii("private:OpenEvent");        aArgs[1].Name = ::rtl::OUString::createFromAscii("SynchronMode");        aArgs[1].Value <<= sal_True;        for ( sal_uInt32 n = 0; n < aDispatches.size(); n++ )        {            Reference< XDispatch > xDispatch = aDispatches[n].xDispatch;            Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );            if ( xDisp.is() )                xDisp->dispatchWithNotification( aDispatches[n].aURL, aArgs, this );            else            {                ::osl::ClearableMutexGuard aGuard( GetMutex() );                m_nRequestCount--;                aGuard.clear();                xDispatch->dispatch( aDispatches[n].aURL, aArgs );            }        }    }    ::osl::ClearableMutexGuard aGuard( GetMutex() );    bool bEmpty = (m_nRequestCount == 0);    aGuard.clear();    // No more asynchronous requests?    // The requests are removed from the request container after they called back to this    // implementation via statusChanged!!    if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ )    {        // Delay give a chance for threads to complete work        impl_sleep(2);        // We have to check if we have an open task otherwise we have to shutdown the office.        Reference< XFramesSupplier > xTasksSupplier( xDesktop, UNO_QUERY );        aGuard.clear();                // Delay give a chance for threads to complete work        impl_sleep(1);        Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY );        if ( !xList->hasElements() )        {            // We don't have any task open so we have to shutdown ourself!!            Reference< XDesktop > xDesktop2( xTasksSupplier, UNO_QUERY );            if ( xDesktop2.is() )                return xDesktop2->terminate();        }    }    return sal_False;}void SAL_CALL DispatchWatcher::disposing( const ::com::sun::star::lang::EventObject& )throw(::com::sun::star::uno::RuntimeException){}void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException ){    osl::ClearableMutexGuard aGuard( GetMutex() );    sal_Int16 nCount = m_nRequestCount;    aGuard.clear();    OfficeIPCThread::RequestsCompleted( 1 );/*    // Find request in our hash map and remove it as a pending request    DispatchWatcherHashMap::iterator pDispatchEntry = m_aRequestContainer.find( rEvent.FeatureURL.Complete ) ;    if ( pDispatchEntry != m_aRequestContainer.end() )    {        m_aRequestContainer.erase( pDispatchEntry );        aGuard.clear();        OfficeIPCThread::RequestsCompleted( 1 );    }    else        aGuard.clear();*/    if ( !nCount && !OfficeIPCThread::AreRequestsPending() )    {        // We have to check if we have an open task otherwise we have to shutdown the office.        Reference< XFramesSupplier > xTasksSupplier( ::comphelper::getProcessServiceFactory()->createInstance(                                                    OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),                                                UNO_QUERY );        Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY );        if ( !xList->hasElements() )        {            // We don't have any task open so we have to shutdown ourself!!            Reference< XDesktop > xDesktop( xTasksSupplier, UNO_QUERY );            if ( xDesktop.is() )                xDesktop->terminate();        }    }}}