LCOV - code coverage report
Current view: top level - desktop/source/app - dispatchwatcher.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 85 386 22.0 %
Date: 2015-06-13 12:38:46 Functions: 8 17 47.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sal/config.h>
      21             : 
      22             : #include <sal/log.hxx>
      23             : #include <sfx2/docfile.hxx>
      24             : #include <sfx2/docfilt.hxx>
      25             : #include <sfx2/fcontnr.hxx>
      26             : #include <sfx2/app.hxx>
      27             : #include <svl/fstathelper.hxx>
      28             : 
      29             : #include "app.hxx"
      30             : #include "dispatchwatcher.hxx"
      31             : #include <rtl/ustring.hxx>
      32             : #include <comphelper/processfactory.hxx>
      33             : #include <comphelper/synchronousdispatch.hxx>
      34             : #include <com/sun/star/util/XCloseable.hpp>
      35             : #include <com/sun/star/util/CloseVetoException.hpp>
      36             : #include <com/sun/star/task/InteractionHandler.hpp>
      37             : #include <com/sun/star/util/URL.hpp>
      38             : #include <com/sun/star/frame/Desktop.hpp>
      39             : #include <com/sun/star/container/XContainerQuery.hpp>
      40             : #include <com/sun/star/container/XEnumeration.hpp>
      41             : #include <com/sun/star/frame/XFramesSupplier.hpp>
      42             : #include <com/sun/star/frame/XDispatch.hpp>
      43             : #include <com/sun/star/frame/XComponentLoader.hpp>
      44             : #include <com/sun/star/beans/PropertyValue.hpp>
      45             : #include <com/sun/star/view/XPrintable.hpp>
      46             : #include <com/sun/star/frame/XDispatchProvider.hpp>
      47             : #include <com/sun/star/util/URLTransformer.hpp>
      48             : #include <com/sun/star/util/XURLTransformer.hpp>
      49             : #include <com/sun/star/document/MacroExecMode.hpp>
      50             : #include <com/sun/star/document/XTypeDetection.hpp>
      51             : #include <com/sun/star/document/UpdateDocMode.hpp>
      52             : #include <com/sun/star/frame/XStorable.hpp>
      53             : 
      54             : #include <tools/urlobj.hxx>
      55             : #include <unotools/mediadescriptor.hxx>
      56             : 
      57             : #include <vector>
      58             : #include <osl/thread.hxx>
      59             : #include <osl/file.hxx>
      60             : #include <osl/file.h>
      61             : #include <rtl/instance.hxx>
      62             : #include <iostream>
      63             : 
      64             : using namespace ::osl;
      65             : using namespace ::com::sun::star::uno;
      66             : using namespace ::com::sun::star::util;
      67             : using namespace ::com::sun::star::lang;
      68             : using namespace ::com::sun::star::frame;
      69             : using namespace ::com::sun::star::container;
      70             : using namespace ::com::sun::star::beans;
      71             : using namespace ::com::sun::star::view;
      72             : using namespace ::com::sun::star::task;
      73             : 
      74             : namespace document = ::com::sun::star::document;
      75             : 
      76             : namespace desktop
      77             : {
      78             : 
      79           0 : struct DispatchHolder
      80             : {
      81           0 :     DispatchHolder( const URL& rURL, Reference< XDispatch >& rDispatch ) :
      82           0 :         aURL( rURL ), xDispatch( rDispatch ) {}
      83             : 
      84             :     URL aURL;
      85             :     OUString cwdUrl;
      86             :     Reference< XDispatch > xDispatch;
      87             : };
      88             : 
      89             : namespace
      90             : {
      91             : 
      92           0 : const SfxFilter* impl_lookupExportFilterForUrl( const rtl::OUString& rUrl, const rtl::OUString& rFactory )
      93             : {
      94             :     // create the list of filters
      95           0 :     OUStringBuffer sQuery(256);
      96           0 :     sQuery.append("getSortedFilterList()");
      97           0 :     sQuery.append(":module=");
      98           0 :     sQuery.append(rFactory); // use long name here !
      99           0 :     sQuery.append(":iflags=");
     100           0 :     sQuery.append(OUString::number(static_cast<sal_Int32>(SfxFilterFlags::EXPORT)));
     101           0 :     sQuery.append(":eflags=");
     102           0 :     sQuery.append(OUString::number(static_cast<int>(SFX_FILTER_NOTINSTALLED)));
     103             : 
     104           0 :     const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
     105             :     const Reference< XContainerQuery > xFilterFactory(
     106           0 :             xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
     107           0 :             UNO_QUERY_THROW );
     108             : 
     109           0 :     const SfxFilter* pBestMatch = 0;
     110             : 
     111             :     const Reference< XEnumeration > xFilterEnum(
     112           0 :             xFilterFactory->createSubSetEnumerationByQuery( sQuery.makeStringAndClear() ), UNO_QUERY_THROW );
     113           0 :     while ( xFilterEnum->hasMoreElements() )
     114             :     {
     115           0 :         comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
     116           0 :         const rtl::OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", rtl::OUString() ) );
     117           0 :         if ( !aName.isEmpty() )
     118             :         {
     119           0 :             const SfxFilter* const pFilter( SfxFilter::GetFilterByName( aName ) );
     120           0 :             if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
     121             :             {
     122           0 :                 if ( !pBestMatch || ( SfxFilterFlags::PREFERED & pFilter->GetFilterFlags() ) )
     123           0 :                     pBestMatch = pFilter;
     124             :             }
     125             :         }
     126           0 :     }
     127             : 
     128           0 :     return pBestMatch;
     129             : }
     130             : 
     131           0 : const SfxFilter* impl_getExportFilterFromUrl( const rtl::OUString& rUrl, const rtl::OUString& rFactory )
     132             : {
     133             : try
     134             : {
     135           0 :     const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
     136             :     const Reference< document::XTypeDetection > xTypeDetector(
     137           0 :             xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext ),
     138           0 :             UNO_QUERY_THROW );
     139           0 :     const rtl::OUString aTypeName( xTypeDetector->queryTypeByURL( rUrl ) );
     140             : 
     141           0 :     const SfxFilter* pFilter( SfxFilterMatcher( rFactory ).GetFilter4EA( aTypeName, SfxFilterFlags::EXPORT ) );
     142           0 :     if ( !pFilter )
     143           0 :         pFilter = impl_lookupExportFilterForUrl( rUrl, rFactory );
     144           0 :     if ( !pFilter )
     145             :     {
     146           0 :         OUString aTempName;
     147           0 :         FileBase::getSystemPathFromFileURL( rUrl, aTempName );
     148           0 :         OString aSource = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
     149           0 :         OString aFactory = OUStringToOString ( rFactory, osl_getThreadTextEncoding() );
     150           0 :         std::cerr << "Error:  no export filter for " << aSource << " found, now using the default filter for " << aFactory << std::endl;
     151             : 
     152           0 :         pFilter = SfxFilter::GetDefaultFilterFromFactory( rFactory );
     153             :     }
     154             : 
     155           0 :     return pFilter;
     156             : }
     157           0 : catch ( const Exception& )
     158             : {
     159           0 :     return 0;
     160             : }
     161             : }
     162             : 
     163           0 : OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
     164             : {
     165           0 :     OUString aOutFilter;
     166           0 :     const SfxFilter* pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
     167           0 :     if (pOutFilter)
     168           0 :         aOutFilter = pOutFilter->GetFilterName();
     169             : 
     170           0 :     return aOutFilter;
     171             : }
     172             : 
     173             : }
     174             : 
     175             : namespace
     176             : {
     177             :     class theWatcherMutex : public rtl::Static<Mutex, theWatcherMutex> {};
     178             : }
     179             : 
     180         129 : Mutex& DispatchWatcher::GetMutex()
     181             : {
     182         129 :     return theWatcherMutex::get();
     183             : }
     184             : 
     185             : // Create or get the dispatch watcher implementation. This implementation must be
     186             : // a singleton to prevent access to the framework after it wants to terminate.
     187          64 : DispatchWatcher* DispatchWatcher::GetDispatchWatcher()
     188             : {
     189          64 :     static Reference< XInterface > xDispatchWatcher;
     190             :     static DispatchWatcher*        pDispatchWatcher = NULL;
     191             : 
     192          64 :     if ( !xDispatchWatcher.is() )
     193             :     {
     194          64 :         ::osl::MutexGuard aGuard( GetMutex() );
     195             : 
     196          64 :         if ( !xDispatchWatcher.is() )
     197             :         {
     198          64 :             pDispatchWatcher = new DispatchWatcher();
     199             : 
     200             :             // We have to hold a reference to ourself forever to prevent our own destruction.
     201          64 :             xDispatchWatcher = static_cast< cppu::OWeakObject *>( pDispatchWatcher );
     202          64 :         }
     203             :     }
     204             : 
     205          64 :     return pDispatchWatcher;
     206             : }
     207             : 
     208             : 
     209          64 : DispatchWatcher::DispatchWatcher()
     210          64 :     : m_nRequestCount(0)
     211             : {
     212          64 : }
     213             : 
     214             : 
     215         128 : DispatchWatcher::~DispatchWatcher()
     216             : {
     217         128 : }
     218             : 
     219             : 
     220          65 : bool DispatchWatcher::executeDispatchRequests( const DispatchList& aDispatchRequestsList, bool bNoTerminate )
     221             : {
     222          65 :     Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
     223             : 
     224          65 :     DispatchList::const_iterator    p;
     225         130 :     std::vector< DispatchHolder >   aDispatches;
     226         130 :     OUString                 aAsTemplateArg( "AsTemplate" );
     227          65 :     bool                     bSetInputFilter = false;
     228         130 :     OUString                 aForcedInputFilter;
     229             : 
     230          66 :     for ( p = aDispatchRequestsList.begin(); p != aDispatchRequestsList.end(); ++p )
     231             :     {
     232           1 :         const DispatchRequest&  aDispatchRequest = *p;
     233             : 
     234             :         // create parameter array
     235           1 :         sal_Int32 nCount = 4;
     236           1 :         if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
     237           0 :             nCount++;
     238             : 
     239             :         // Set Input Filter
     240           1 :         if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
     241             :         {
     242           0 :             bSetInputFilter = true;
     243           0 :             aForcedInputFilter = aDispatchRequest.aURL;
     244           0 :             OfficeIPCThread::RequestsCompleted( 1 );
     245           0 :             continue;
     246             :         }
     247             : 
     248             :         // we need more properties for a print/print to request
     249           2 :         if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
     250           2 :              aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
     251           2 :              aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
     252           1 :              aDispatchRequest.aRequestType == REQUEST_CONVERSION)
     253           0 :             nCount++;
     254             : 
     255           1 :         Sequence < PropertyValue > aArgs( nCount );
     256             : 
     257             :         // mark request as user interaction from outside
     258           1 :         aArgs[0].Name = "Referer";
     259           1 :         aArgs[0].Value <<= OUString("private:OpenEvent");
     260             : 
     261           2 :         if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
     262           2 :              aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
     263           2 :              aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
     264           1 :              aDispatchRequest.aRequestType == REQUEST_CONVERSION)
     265             :         {
     266           0 :             aArgs[1].Name = "ReadOnly";
     267           0 :             aArgs[2].Name = "OpenNewView";
     268           0 :             aArgs[3].Name = "Hidden";
     269           0 :             aArgs[4].Name = "Silent";
     270             :         }
     271             :         else
     272             :         {
     273             :             Reference < XInteractionHandler2 > xInteraction(
     274           1 :                 InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), 0) );
     275             : 
     276           1 :             aArgs[1].Name = "InteractionHandler";
     277           1 :             aArgs[1].Value <<= xInteraction;
     278             : 
     279           1 :             sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;
     280           1 :             aArgs[2].Name = "MacroExecutionMode";
     281           1 :             aArgs[2].Value <<= nMacroExecMode;
     282             : 
     283           1 :             sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;
     284           1 :             aArgs[3].Name = "UpdateDocMode";
     285           1 :             aArgs[3].Value <<= nUpdateDoc;
     286             :         }
     287             : 
     288           1 :         if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
     289             :         {
     290           0 :             aArgs[nCount-1].Name = utl::MediaDescriptor::PROP_DOCUMENTSERVICE();
     291           0 :             aArgs[nCount-1].Value <<= aDispatchRequest.aPreselectedFactory;
     292             :         }
     293             : 
     294           2 :         OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
     295           2 :         OUString aTarget("_default");
     296             : 
     297           2 :         if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
     298           2 :              aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
     299           2 :              aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
     300           1 :              aDispatchRequest.aRequestType == REQUEST_CONVERSION)
     301             :         {
     302             :             // documents opened for printing are opened readonly because they must be opened as a new document and this
     303             :             // document could be open already
     304           0 :             aArgs[1].Value <<= sal_True;
     305             : 
     306             :             // always open a new document for printing, because it must be disposed afterwards
     307           0 :             aArgs[2].Value <<= sal_True;
     308             : 
     309             :             // printing is done in a hidden view
     310           0 :             aArgs[3].Value <<= sal_True;
     311             : 
     312             :             // load document for printing without user interaction
     313           0 :             aArgs[4].Value <<= sal_True;
     314             : 
     315             :             // hidden documents should never be put into open tasks
     316           0 :             aTarget = "_blank";
     317             :         }
     318             :         // load the document ... if they are loadable!
     319             :         // Otherwise try to dispatch it ...
     320           2 :         Reference < XPrintable > xDoc;
     321           1 :         if(
     322           2 :             ( aName.startsWith( ".uno" ) )  ||
     323           2 :             ( aName.startsWith( "slot:" ) )  ||
     324           3 :             ( aName.startsWith( "macro:" ) )  ||
     325           1 :             ( aName.startsWith("vnd.sun.star.script") )
     326             :           )
     327             :         {
     328             :             // Attention: URL must be parsed full. Otherwise some detections on it will fail!
     329             :             // It doesn't matter, if parser isn't available. Because; We try loading of URL then ...
     330           0 :             URL             aURL ;
     331           0 :             aURL.Complete = aName;
     332             : 
     333           0 :             Reference < XDispatch >         xDispatcher ;
     334           0 :             Reference < XURLTransformer >   xParser     ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
     335             : 
     336           0 :             if( xParser.is() )
     337           0 :                 xParser->parseStrict( aURL );
     338             : 
     339           0 :             xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
     340             :             SAL_WARN_IF(
     341             :                 !xDispatcher.is(), "desktop.app",
     342             :                 "unsupported dispatch request <" << aName << ">");
     343           0 :             if( xDispatcher.is() )
     344             :             {
     345             :                 {
     346           0 :                     ::osl::ClearableMutexGuard aGuard( GetMutex() );
     347             :                     // Remember request so we can find it in statusChanged!
     348           0 :                     m_aRequestContainer.insert( DispatchWatcherHashMap::value_type( aURL.Complete, (sal_Int32)1 ) );
     349           0 :                     m_nRequestCount++;
     350             :                 }
     351             : 
     352             :                 // Use local vector to store dispatcher because we have to fill our request container before
     353             :                 // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!
     354           0 :                 aDispatches.push_back( DispatchHolder( aURL, xDispatcher ));
     355           0 :             }
     356             :         }
     357           1 :         else if ( ( aName.startsWith( "service:" ) ) )
     358             :         {
     359             :             // TODO: the dispatch has to be done for loadComponentFromURL as well. Please ask AS for more details.
     360           0 :             URL             aURL ;
     361           0 :             aURL.Complete = aName;
     362             : 
     363           0 :             Reference < XDispatch >         xDispatcher ;
     364           0 :             Reference < XURLTransformer >   xParser     ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
     365             : 
     366           0 :             if( xParser.is() )
     367           0 :                 xParser->parseStrict( aURL );
     368             : 
     369           0 :             xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
     370             : 
     371           0 :             if( xDispatcher.is() )
     372             :             {
     373             :                 try
     374             :                 {
     375             :                     // We have to be listener to catch errors during dispatching URLs.
     376             :                     // Otherwise it would be possible to have an office running without an open
     377             :                     // window!!
     378           0 :                     Sequence < PropertyValue > aArgs2(1);
     379           0 :                     aArgs2[0].Name    = "SynchronMode";
     380           0 :                     aArgs2[0].Value <<= sal_True;
     381           0 :                     Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );
     382           0 :                     if ( xDisp.is() )
     383           0 :                         xDisp->dispatchWithNotification( aURL, aArgs2, DispatchWatcher::GetDispatchWatcher() );
     384             :                     else
     385           0 :                         xDispatcher->dispatch( aURL, aArgs2 );
     386             :                 }
     387           0 :                 catch (const ::com::sun::star::uno::Exception& e)
     388             :                 {
     389             :                     SAL_WARN(
     390             :                         "desktop.app",
     391             :                         "Desktop::OpenDefault() ignoring Exception while"
     392             :                             " calling XNotifyingDispatch: \"" << e.Message
     393             :                             << "\"");
     394             :                 }
     395           0 :             }
     396             :         }
     397             :         else
     398             :         {
     399           1 :             INetURLObject aObj( aName );
     400           1 :             if ( aObj.GetProtocol() == INetProtocol::PrivSoffice )
     401           0 :                 aTarget = "_default";
     402             : 
     403             :             // Set "AsTemplate" argument according to request type
     404           2 :             if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
     405           1 :                  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN     )
     406             :             {
     407           0 :                 sal_Int32 nIndex = aArgs.getLength();
     408           0 :                 aArgs.realloc( nIndex+1 );
     409           0 :                 aArgs[nIndex].Name = aAsTemplateArg;
     410           0 :                 if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW )
     411           0 :                     aArgs[nIndex].Value <<= sal_True;
     412             :                 else
     413           0 :                     aArgs[nIndex].Value <<= sal_False;
     414             :             }
     415             : 
     416             :             // if we are called in viewmode, open document read-only
     417           1 :             if(aDispatchRequest.aRequestType == REQUEST_VIEW) {
     418           0 :                 sal_Int32 nIndex = aArgs.getLength();
     419           0 :                 aArgs.realloc(nIndex+1);
     420           0 :                 aArgs[nIndex].Name = "ReadOnly";
     421           0 :                 aArgs[nIndex].Value <<= sal_True;
     422             :             }
     423             : 
     424             :             // if we are called with -start set Start in mediadescriptor
     425           1 :             if(aDispatchRequest.aRequestType == REQUEST_START) {
     426           0 :                 sal_Int32 nIndex = aArgs.getLength();
     427           0 :                 aArgs.realloc(nIndex+1);
     428           0 :                 aArgs[nIndex].Name = "StartPresentation";
     429           0 :                 aArgs[nIndex].Value <<= sal_True;
     430             :             }
     431             : 
     432             :             // Force input filter, if possible
     433           1 :             if( bSetInputFilter )
     434             :             {
     435           0 :                 sal_Int32 nIndex = aArgs.getLength();
     436           0 :                 aArgs.realloc(nIndex+1);
     437           0 :                 aArgs[nIndex].Name = "FilterName";
     438             : 
     439           0 :                 sal_Int32 nFilterOptionsIndex = aForcedInputFilter.indexOf( ':' );
     440           0 :                 if( 0 < nFilterOptionsIndex )
     441             :                 {
     442           0 :                     aArgs[nIndex].Value <<= aForcedInputFilter.copy( 0, nFilterOptionsIndex );
     443             : 
     444           0 :                     nIndex = aArgs.getLength();
     445           0 :                     aArgs.realloc(nIndex+1);
     446           0 :                     aArgs[nIndex].Name = "FilterOptions";
     447           0 :                     aArgs[nIndex].Value <<= aForcedInputFilter.copy( nFilterOptionsIndex+1 );
     448             :                 }
     449             :                 else
     450             :                 {
     451           0 :                     aArgs[nIndex].Value <<= aForcedInputFilter;
     452             :                 }
     453             :             }
     454             : 
     455             :             // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
     456             :             try
     457             :             {
     458           1 :                 xDoc = Reference < XPrintable >( ::comphelper::SynchronousDispatch::dispatch( xDesktop, aName, aTarget, 0, aArgs ), UNO_QUERY );
     459             :             }
     460           0 :             catch (const ::com::sun::star::lang::IllegalArgumentException& iae)
     461             :             {
     462             :                 SAL_WARN(
     463             :                     "desktop.app",
     464             :                     "Dispatchwatcher IllegalArgumentException while calling"
     465             :                         " loadComponentFromURL: \"" << iae.Message << "\"");
     466             :             }
     467           0 :             catch (const com::sun::star::io::IOException& ioe)
     468             :             {
     469             :                 SAL_WARN(
     470             :                     "desktop.app",
     471             :                     "Dispatchwatcher IOException while calling"
     472             :                         " loadComponentFromURL: \"" << ioe.Message << "\"");
     473             :             }
     474           1 :             if ( aDispatchRequest.aRequestType == REQUEST_OPEN ||
     475           0 :                  aDispatchRequest.aRequestType == REQUEST_VIEW ||
     476           0 :                  aDispatchRequest.aRequestType == REQUEST_START ||
     477           0 :                  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ||
     478           0 :                  aDispatchRequest.aRequestType == REQUEST_FORCENEW      )
     479             :             {
     480             :                 // request is completed
     481           1 :                 OfficeIPCThread::RequestsCompleted( 1 );
     482             :             }
     483           0 :             else if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
     484           0 :                       aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
     485           0 :                       aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
     486           0 :                       aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
     487           0 :                       aDispatchRequest.aRequestType == REQUEST_CAT )
     488             :             {
     489           0 :                 if ( xDoc.is() )
     490             :                 {
     491           0 :                     if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION || aDispatchRequest.aRequestType == REQUEST_CAT ) {
     492           0 :                         Reference< XStorable > xStorable( xDoc, UNO_QUERY );
     493           0 :                         if ( xStorable.is() ) {
     494           0 :                             OUString aParam = aDispatchRequest.aPrinterName;
     495           0 :                             sal_Int32 nPathIndex =  aParam.lastIndexOf( ';' );
     496           0 :                             sal_Int32 nFilterIndex = aParam.indexOf( ':' );
     497           0 :                             if( nPathIndex < nFilterIndex )
     498           0 :                                 nFilterIndex = -1;
     499           0 :                             OUString aFilterOut=aParam.copy( nPathIndex+1 );
     500           0 :                             OUString aFilter;
     501           0 :                             OUString aFilterExt;
     502           0 :                             bool bGuess = false;
     503             : 
     504           0 :                             if( nFilterIndex >= 0 )
     505             :                             {
     506           0 :                                 aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
     507           0 :                                 aFilterExt = aParam.copy( 0, nFilterIndex );
     508             :                             }
     509             :                             else
     510             :                             {
     511             :                                 // Guess
     512           0 :                                 bGuess = true;
     513           0 :                                 aFilterExt = aParam.copy( 0, nPathIndex );
     514             :                             }
     515           0 :                             INetURLObject aOutFilename( aObj );
     516           0 :                             aOutFilename.SetExtension( aFilterExt );
     517           0 :                             FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
     518           0 :                             OUString aOutFile = aFilterOut+
     519           0 :                                                      "/" +
     520           0 :                                                      aOutFilename.getName();
     521             : 
     522           0 :                             OUString fileForCat;
     523           0 :                             if( aDispatchRequest.aRequestType == REQUEST_CAT )
     524             :                             {
     525           0 :                                 if( ::osl::FileBase::createTempFile(0, 0, &fileForCat) != ::osl::FileBase::E_None )
     526           0 :                                     std::cerr << "Error: Cannot create temporary file..." << std::endl ;
     527           0 :                                 aOutFile = fileForCat;
     528             :                             }
     529             : 
     530           0 :                             if ( bGuess )
     531             :                             {
     532           0 :                                 OUString aDocService;
     533           0 :                                 Reference< XModel > xModel( xDoc, UNO_QUERY );
     534           0 :                                 if ( xModel.is() )
     535             :                                 {
     536           0 :                                     utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
     537           0 :                                     aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
     538             :                                 }
     539           0 :                                 aFilter = impl_GuessFilter( aOutFile, aDocService );
     540             :                             }
     541             : 
     542           0 :                             sal_Int32 nFilterOptionsIndex = aFilter.indexOf( ':' );
     543           0 :                             Sequence<PropertyValue> conversionProperties( 0 < nFilterOptionsIndex ? 3 : 2 );
     544           0 :                             conversionProperties[0].Name = "Overwrite";
     545           0 :                             conversionProperties[0].Value <<= sal_True;
     546             : 
     547           0 :                             conversionProperties[1].Name = "FilterName";
     548           0 :                             if( 0 < nFilterOptionsIndex )
     549             :                             {
     550           0 :                                 conversionProperties[1].Value <<= aFilter.copy( 0, nFilterOptionsIndex );
     551             : 
     552           0 :                                 conversionProperties[2].Name = "FilterOptions";
     553           0 :                                 conversionProperties[2].Value <<= aFilter.copy( nFilterOptionsIndex+1 );
     554             :                             }
     555             :                             else
     556             :                             {
     557           0 :                                 conversionProperties[1].Value <<= aFilter;
     558             :                             }
     559             : 
     560           0 :                             OUString aTempName;
     561           0 :                             FileBase::getSystemPathFromFileURL( aName, aTempName );
     562           0 :                             OString aSource8 = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
     563           0 :                             FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
     564           0 :                             OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding() );
     565           0 :                             if( aDispatchRequest.aRequestType != REQUEST_CAT )
     566             :                             {
     567           0 :                                 std::cout << "convert " << aSource8 << " -> " << aTargetURL8;
     568           0 :                                 std::cout << " using filter : " << OUStringToOString( aFilter, osl_getThreadTextEncoding() ) << std::endl;
     569           0 :                                 if( FStatHelper::IsDocument( aOutFile ) )
     570           0 :                                     std::cout << "Overwriting: " << OUStringToOString( aTempName, osl_getThreadTextEncoding() ) << std::endl ;
     571             :                             }
     572             :                             try
     573             :                             {
     574           0 :                                 xStorable->storeToURL( aOutFile, conversionProperties );
     575             :                             }
     576           0 :                             catch (const Exception& rException)
     577             :                             {
     578           0 :                                 std::cerr << "Error: Please verify input parameters...";
     579           0 :                                 if (!rException.Message.isEmpty())
     580           0 :                                     std::cerr << " (" << rException.Message << ")";
     581           0 :                                 std::cerr << std::endl;
     582             :                             }
     583             : 
     584           0 :                             if( aDispatchRequest.aRequestType == REQUEST_CAT )
     585             :                             {
     586           0 :                                 osl::File aFile( fileForCat );
     587           0 :                                 osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
     588           0 :                                 if( aRC != osl::File::E_None )
     589             :                                 {
     590           0 :                                     std::cerr << "Error: Cannot read from temp file" << std::endl;
     591             :                                 }
     592             :                                 else
     593             :                                 {
     594             :                                     sal_Bool eof;
     595             :                                     for( ;; )
     596             :                                     {
     597           0 :                                         aFile.isEndOfFile( &eof );
     598           0 :                                         if( eof )
     599           0 :                                             break;
     600           0 :                                         rtl::ByteSequence bseq;
     601           0 :                                         aFile.readLine( bseq );
     602           0 :                                         unsigned const char * aStr = reinterpret_cast< unsigned char const * >( bseq.getConstArray() );
     603           0 :                                         for( sal_Int32 i = 0; i < bseq.getLength(); i++ )
     604             :                                         {
     605           0 :                                             std::cout << aStr[i];
     606             :                                         }
     607           0 :                                         std::cout << std::endl;
     608           0 :                                     }
     609           0 :                                     aFile.close();
     610           0 :                                     osl::File::remove( fileForCat );
     611           0 :                                 }
     612           0 :                             }
     613           0 :                         }
     614           0 :                     } else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ) {
     615           0 :                         OUString aParam = aDispatchRequest.aPrinterName;
     616           0 :                         sal_Int32 nPathIndex =  aParam.lastIndexOf( ';' );
     617             : 
     618           0 :                         OUString aFilterOut;
     619           0 :                         OUString aPrinterName;
     620           0 :                         if( nPathIndex != -1 )
     621           0 :                             aFilterOut=aParam.copy( nPathIndex+1 );
     622           0 :                         if( nPathIndex != 0 )
     623           0 :                             aPrinterName=aParam.copy( 0, nPathIndex );
     624             : 
     625           0 :                         INetURLObject aOutFilename( aObj );
     626           0 :                         aOutFilename.SetExtension( "ps" );
     627           0 :                         FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
     628           0 :                         OUString aOutFile = aFilterOut+
     629           0 :                             "/" +
     630           0 :                             aOutFilename.getName();
     631             : 
     632           0 :                         OUString aTempName;
     633           0 :                         FileBase::getSystemPathFromFileURL( aName, aTempName );
     634           0 :                         OString aSource8 = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
     635           0 :                         FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
     636           0 :                         OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding() );
     637             : 
     638           0 :                         std::cout << "print " << aSource8 << " -> " << aTargetURL8;
     639           0 :                         std::cout << " using " << (aPrinterName.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName, osl_getThreadTextEncoding() ));
     640           0 :                         std::cout << std::endl;
     641             : 
     642             :                         // create the custom printer, if given
     643           0 :                         Sequence < PropertyValue > aPrinterArgs( 1 );
     644           0 :                         if( !aPrinterName.isEmpty() )
     645             :                         {
     646           0 :                             aPrinterArgs[0].Name = "Name";
     647           0 :                             aPrinterArgs[0].Value <<= aPrinterName;
     648           0 :                             xDoc->setPrinter( aPrinterArgs );
     649             :                         }
     650             : 
     651             :                         // print ( also without user interaction )
     652           0 :                         aPrinterArgs.realloc(2);
     653           0 :                         aPrinterArgs[0].Name = "FileName";
     654           0 :                         aPrinterArgs[0].Value <<= aOutFile;
     655           0 :                         aPrinterArgs[1].Name = "Wait";
     656           0 :                         aPrinterArgs[1].Value <<= true;
     657           0 :                         xDoc->print( aPrinterArgs );
     658             :                     } else {
     659           0 :                         if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
     660             :                         {
     661             :                             // create the printer
     662           0 :                             Sequence < PropertyValue > aPrinterArgs( 1 );
     663           0 :                             aPrinterArgs[0].Name = "Name";
     664           0 :                             aPrinterArgs[0].Value <<= OUString( aDispatchRequest.aPrinterName );
     665           0 :                             xDoc->setPrinter( aPrinterArgs );
     666             :                         }
     667             : 
     668             :                         // print ( also without user interaction )
     669           0 :                         Sequence < PropertyValue > aPrinterArgs( 1 );
     670           0 :                         aPrinterArgs[0].Name = "Wait";
     671           0 :                         aPrinterArgs[0].Value <<= true;
     672           0 :                         xDoc->print( aPrinterArgs );
     673             :                     }
     674             :                 }
     675             :                 else
     676             :                 {
     677           0 :                     std::cerr << "Error: source file could not be loaded" << std::endl;
     678             :                 }
     679             : 
     680             :                 // remove the document
     681             :                 try
     682             :                 {
     683           0 :                     Reference < XCloseable > xClose( xDoc, UNO_QUERY );
     684           0 :                     if ( xClose.is() )
     685           0 :                         xClose->close( sal_True );
     686             :                     else
     687             :                     {
     688           0 :                         Reference < XComponent > xComp( xDoc, UNO_QUERY );
     689           0 :                         if ( xComp.is() )
     690           0 :                             xComp->dispose();
     691           0 :                     }
     692             :                 }
     693           0 :                 catch (const com::sun::star::util::CloseVetoException&)
     694             :                 {
     695             :                 }
     696             : 
     697             :                 // request is completed
     698           0 :                 OfficeIPCThread::RequestsCompleted( 1 );
     699           1 :             }
     700             :         }
     701           1 :     }
     702             : 
     703          65 :     if ( !aDispatches.empty() )
     704             :     {
     705             :         // Execute all asynchronous dispatches now after we placed them into our request container!
     706           0 :         Sequence < PropertyValue > aArgs( 2 );
     707           0 :         aArgs[0].Name = "Referer";
     708           0 :         aArgs[0].Value <<= OUString("private:OpenEvent");
     709           0 :         aArgs[1].Name = "SynchronMode";
     710           0 :         aArgs[1].Value <<= sal_True;
     711             : 
     712           0 :         for ( size_t n = 0; n < aDispatches.size(); n++ )
     713             :         {
     714           0 :             Reference< XDispatch > xDispatch = aDispatches[n].xDispatch;
     715           0 :             Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );
     716           0 :             if ( xDisp.is() )
     717           0 :                 xDisp->dispatchWithNotification( aDispatches[n].aURL, aArgs, this );
     718             :             else
     719             :             {
     720           0 :                 ::osl::ClearableMutexGuard aGuard( GetMutex() );
     721           0 :                 m_nRequestCount--;
     722           0 :                 aGuard.clear();
     723           0 :                 xDispatch->dispatch( aDispatches[n].aURL, aArgs );
     724             :             }
     725           0 :         }
     726             :     }
     727             : 
     728         130 :     ::osl::ClearableMutexGuard aGuard( GetMutex() );
     729          65 :     bool bEmpty = (m_nRequestCount == 0);
     730          65 :     aGuard.clear();
     731             : 
     732             :     // No more asynchronous requests?
     733             :     // The requests are removed from the request container after they called back to this
     734             :     // implementation via statusChanged!!
     735          65 :     if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ )
     736             :     {
     737             :         // We have to check if we have an open task otherwise we have to shutdown the office.
     738           1 :         aGuard.clear();
     739           1 :         Reference< XElementAccess > xList( xDesktop->getFrames(), UNO_QUERY );
     740             : 
     741           1 :         if ( !xList->hasElements() )
     742             :         {
     743             :             // We don't have any task open so we have to shutdown ourself!!
     744           0 :             return xDesktop->terminate();
     745           1 :         }
     746             :     }
     747             : 
     748         130 :     return false;
     749             : }
     750             : 
     751             : 
     752           0 : void SAL_CALL DispatchWatcher::disposing( const ::com::sun::star::lang::EventObject& )
     753             : throw(::com::sun::star::uno::RuntimeException, std::exception)
     754             : {
     755           0 : }
     756             : 
     757             : 
     758           0 : void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException, std::exception )
     759             : {
     760           0 :     osl::ClearableMutexGuard aGuard( GetMutex() );
     761           0 :     sal_Int16 nCount = --m_nRequestCount;
     762           0 :     aGuard.clear();
     763           0 :     OfficeIPCThread::RequestsCompleted( 1 );
     764           0 :     if ( !nCount && !OfficeIPCThread::AreRequestsPending() )
     765             :     {
     766             :         // We have to check if we have an open task otherwise we have to shutdown the office.
     767           0 :         Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
     768           0 :         Reference< XElementAccess > xList( xDesktop->getFrames(), UNO_QUERY );
     769             : 
     770           0 :         if ( !xList->hasElements() )
     771             :         {
     772             :             // We don't have any task open so we have to shutdown ourself!!
     773           0 :             xDesktop->terminate();
     774           0 :         }
     775           0 :     }
     776           0 : }
     777             : 
     778         348 : }
     779             : 
     780             : 
     781             : 
     782             : 
     783             : 
     784             : 
     785             : 
     786             : 
     787             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11