Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / desktop / source / app / dispatchwatcher.cxx
blobf3857d8cff572f3b2262fc22a2b795cce7c4b85c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
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>
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/io/IOException.hpp>
35 #include <com/sun/star/util/XCloseable.hpp>
36 #include <com/sun/star/util/CloseVetoException.hpp>
37 #include <com/sun/star/task/InteractionHandler.hpp>
38 #include <com/sun/star/util/URL.hpp>
39 #include <com/sun/star/frame/Desktop.hpp>
40 #include <com/sun/star/container/XContainerQuery.hpp>
41 #include <com/sun/star/container/XEnumeration.hpp>
42 #include <com/sun/star/frame/XDispatch.hpp>
43 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
44 #include <com/sun/star/beans/PropertyValue.hpp>
45 #include <com/sun/star/view/XPrintable.hpp>
46 #include <com/sun/star/util/URLTransformer.hpp>
47 #include <com/sun/star/util/XURLTransformer.hpp>
48 #include <com/sun/star/document/MacroExecMode.hpp>
49 #include <com/sun/star/document/XTypeDetection.hpp>
50 #include <com/sun/star/document/UpdateDocMode.hpp>
51 #include <com/sun/star/frame/XStorable.hpp>
52 #include <com/sun/star/script/ModuleInfo.hpp>
53 #include <com/sun/star/script/ModuleType.hpp>
54 #include <com/sun/star/script/XLibraryContainer2.hpp>
55 #include <com/sun/star/document/XEmbeddedScripts.hpp>
57 #include <comphelper/sequence.hxx>
58 #include <tools/diagnose_ex.h>
59 #include <tools/urlobj.hxx>
60 #include <unotools/mediadescriptor.hxx>
61 #include <unotools/tempfile.hxx>
63 #include <vector>
64 #include <osl/thread.hxx>
65 #include <osl/file.hxx>
66 #include <osl/file.h>
67 #include <rtl/byteseq.hxx>
68 #include <iostream>
70 using namespace ::osl;
71 using namespace ::com::sun::star::uno;
72 using namespace ::com::sun::star::util;
73 using namespace ::com::sun::star::lang;
74 using namespace ::com::sun::star::frame;
75 using namespace ::com::sun::star::container;
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::view;
78 using namespace ::com::sun::star::task;
79 using namespace ::com::sun::star::document;
81 namespace document = ::com::sun::star::document;
83 namespace desktop
86 struct DispatchHolder
88 DispatchHolder( const URL& rURL, Reference< XDispatch > const & rDispatch ) :
89 aURL( rURL ), xDispatch( rDispatch ) {}
91 URL aURL;
92 Reference< XDispatch > xDispatch;
95 namespace
98 std::shared_ptr<const SfxFilter> impl_lookupExportFilterForUrl( const OUString& rUrl, const OUString& rFactory )
100 // create the list of filters
101 OUStringBuffer sQuery(256);
102 sQuery.append("getSortedFilterList()");
103 sQuery.append(":module=");
104 sQuery.append(rFactory); // use long name here !
105 sQuery.append(":iflags=");
106 sQuery.append(OUString::number(static_cast<sal_Int32>(SfxFilterFlags::EXPORT)));
107 sQuery.append(":eflags=");
108 sQuery.append(OUString::number(static_cast<int>(SFX_FILTER_NOTINSTALLED)));
110 const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
111 const Reference< XContainerQuery > xFilterFactory(
112 xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
113 UNO_QUERY_THROW );
115 std::shared_ptr<const SfxFilter> pBestMatch;
117 const Reference< XEnumeration > xFilterEnum(
118 xFilterFactory->createSubSetEnumerationByQuery( sQuery.makeStringAndClear() ), UNO_SET_THROW );
119 while ( xFilterEnum->hasMoreElements() )
121 comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
122 const OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", OUString() ) );
123 if ( !aName.isEmpty() )
125 std::shared_ptr<const SfxFilter> pFilter( SfxFilter::GetFilterByName( aName ) );
126 if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
128 if ( !pBestMatch || ( SfxFilterFlags::PREFERED & pFilter->GetFilterFlags() ) )
129 pBestMatch = pFilter;
134 return pBestMatch;
137 std::shared_ptr<const SfxFilter> impl_getExportFilterFromUrl(
138 const OUString& rUrl, const OUString& rFactory)
142 const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
143 const Reference< document::XTypeDetection > xTypeDetector(
144 xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext ),
145 UNO_QUERY_THROW );
146 const OUString aTypeName( xTypeDetector->queryTypeByURL( rUrl ) );
148 std::shared_ptr<const SfxFilter> pFilter( SfxFilterMatcher( rFactory ).GetFilter4EA( aTypeName, SfxFilterFlags::EXPORT ) );
149 if ( !pFilter )
150 pFilter = impl_lookupExportFilterForUrl( rUrl, rFactory );
151 if ( !pFilter )
153 OUString aTempName;
154 FileBase::getSystemPathFromFileURL( rUrl, aTempName );
155 OString aSource = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
156 std::cerr << "Error: no export filter for " << aSource << " found, aborting." << std::endl;
159 return pFilter;
161 catch ( const Exception& )
163 return nullptr;
167 OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
169 OUString aOutFilter;
170 std::shared_ptr<const SfxFilter> pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
171 if (pOutFilter)
172 aOutFilter = pOutFilter->GetFilterName();
174 return aOutFilter;
177 /// dump scripts in a document to the console.
178 void scriptCat(const Reference< XModel >& xDoc )
180 Reference< XEmbeddedScripts > xScriptAccess( xDoc, UNO_QUERY );
181 if (!xScriptAccess)
183 std::cout << "No script access\n";
184 return;
187 // ignore xScriptAccess->getDialogLibraries() for now
188 Reference< css::script::XLibraryContainer2 > xLibraries(
189 xScriptAccess->getBasicLibraries() );
191 if ( !xLibraries.is() )
193 std::cout << "No script libraries\n";
194 return;
197 Sequence< OUString > aLibNames = xLibraries->getElementNames();
198 std::cout << "Libraries: " << aLibNames.getLength() << "\n";
199 for ( sal_Int32 i = 0 ; i < aLibNames.getLength() ; ++i )
201 std::cout << "Library: '" << aLibNames[i] << "' children: ";
202 Reference< XNameContainer > xContainer;
203 try {
204 if (!xLibraries->isLibraryLoaded( aLibNames[i] ))
205 xLibraries->loadLibrary( aLibNames[i] );
206 xContainer = Reference< XNameContainer >(
207 xLibraries->getByName( aLibNames[i] ), UNO_QUERY );
209 catch (const css::uno::Exception &e)
211 std::cout << "[" << aLibNames[i] << "] - failed to load library: " << e.Message << "\n";
212 continue;
214 if( !xContainer.is() )
215 std::cout << "0\n";
216 else
218 Sequence< OUString > aObjectNames = xContainer->getElementNames();
220 std::cout << aObjectNames.getLength() << "\n\n";
221 for ( sal_Int32 j = 0 ; j < aObjectNames.getLength() ; ++j )
223 OUString &rObjectName = aObjectNames[j];
225 OUString aCodeString;
228 Any aCode = xContainer->getByName( rObjectName );
230 if (! (aCode >>= aCodeString ) )
231 std::cout << "[" << rObjectName << "] - error fetching code\n";
232 else
233 std::cout << "[" << rObjectName << "]\n"
234 << aCodeString.trim()
235 << "\n[/" << rObjectName << "]\n";
237 catch (const css::uno::Exception &e)
239 std::cout << "[" << rObjectName << "] - exception " << e.Message << " fetching code\n";
242 if (j < aObjectNames.getLength() - 1)
243 std::cout << "\n----------------------------------------------------------\n";
244 std::cout << "\n";
250 // Perform batch print
251 void batchPrint( const OUString &rPrinterName, const Reference< XPrintable > &xDoc,
252 const INetURLObject &aObj, const OUString &aName )
254 OUString aFilterOut;
255 OUString aPrinterName;
256 sal_Int32 nPathIndex = rPrinterName.lastIndexOf( ';' );
257 if( nPathIndex != -1 )
258 aFilterOut=rPrinterName.copy( nPathIndex+1 );
259 if( nPathIndex != 0 )
260 aPrinterName=rPrinterName.copy( 0, nPathIndex );
262 INetURLObject aOutFilename( aObj );
263 aOutFilename.SetExtension( "ps" );
264 FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
265 OUString aOutFile = aFilterOut + "/" + aOutFilename.getName();
267 OUString aTempName;
268 FileBase::getSystemPathFromFileURL( aName, aTempName );
269 OString aSource8 = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
270 FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
271 OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding() );
273 std::cout << "print " << aSource8 << " -> " << aTargetURL8;
274 std::cout << " using " << (aPrinterName.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName, osl_getThreadTextEncoding() ));
275 std::cout << std::endl;
277 // create the custom printer, if given
278 Sequence < PropertyValue > aPrinterArgs( 1 );
279 if( !aPrinterName.isEmpty() )
281 aPrinterArgs[0].Name = "Name";
282 aPrinterArgs[0].Value <<= aPrinterName;
283 xDoc->setPrinter( aPrinterArgs );
286 // print ( also without user interaction )
287 aPrinterArgs.realloc(2);
288 aPrinterArgs[0].Name = "FileName";
289 aPrinterArgs[0].Value <<= aOutFile;
290 aPrinterArgs[1].Name = "Wait";
291 aPrinterArgs[1].Value <<= true;
292 xDoc->print( aPrinterArgs );
295 } // anonymous namespace
297 DispatchWatcher::DispatchWatcher()
298 : m_nRequestCount(0)
303 DispatchWatcher::~DispatchWatcher()
308 bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest>& aDispatchRequestsList, bool bNoTerminate )
310 Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
312 std::vector< DispatchHolder > aDispatches;
313 bool bSetInputFilter = false;
314 OUString aForcedInputFilter;
316 for (auto const & aDispatchRequest: aDispatchRequestsList)
318 // Set Input Filter
319 if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
321 bSetInputFilter = true;
322 aForcedInputFilter = aDispatchRequest.aURL;
323 RequestHandler::RequestsCompleted();
324 continue;
327 // create parameter array
328 std::vector<PropertyValue> aArgs;
330 // mark request as user interaction from outside
331 aArgs.emplace_back("Referer", 0, Any(OUString("private:OpenEvent")),
332 PropertyState_DIRECT_VALUE);
334 OUString aTarget("_default");
336 if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
337 aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
338 aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
339 aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
340 aDispatchRequest.aRequestType == REQUEST_CAT ||
341 aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT)
343 // documents opened for printing are opened readonly because they must be opened as a
344 // new document and this document could be open already
345 aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
346 // always open a new document for printing, because it must be disposed afterwards
347 aArgs.emplace_back("OpenNewView", 0, Any(true), PropertyState_DIRECT_VALUE);
348 // printing is done in a hidden view
349 aArgs.emplace_back("Hidden", 0, Any(true), PropertyState_DIRECT_VALUE);
350 // load document for printing without user interaction
351 aArgs.emplace_back("Silent", 0, Any(true), PropertyState_DIRECT_VALUE);
353 // hidden documents should never be put into open tasks
354 aTarget = "_blank";
356 else
358 Reference < XInteractionHandler2 > xInteraction(
359 InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
361 aArgs.emplace_back("InteractionHandler", 0, Any(xInteraction),
362 PropertyState_DIRECT_VALUE);
364 aArgs.emplace_back("MacroExecutionMode", 0,
365 Any(css::document::MacroExecMode::USE_CONFIG),
366 PropertyState_DIRECT_VALUE);
368 aArgs.emplace_back("UpdateDocMode", 0,
369 Any(css::document::UpdateDocMode::ACCORDING_TO_CONFIG),
370 PropertyState_DIRECT_VALUE);
373 if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
375 aArgs.emplace_back(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), 0,
376 Any(aDispatchRequest.aPreselectedFactory),
377 PropertyState_DIRECT_VALUE);
380 OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
382 // load the document ... if they are loadable!
383 // Otherwise try to dispatch it ...
384 Reference < XPrintable > xDoc;
386 ( aName.startsWith( ".uno" ) ) ||
387 ( aName.startsWith( "slot:" ) ) ||
388 ( aName.startsWith( "macro:" ) ) ||
389 ( aName.startsWith("vnd.sun.star.script") )
392 // Attention: URL must be parsed full. Otherwise some detections on it will fail!
393 // It doesn't matter, if parser isn't available. Because; We try loading of URL then ...
394 URL aURL ;
395 aURL.Complete = aName;
397 Reference < XDispatch > xDispatcher ;
398 Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
400 if( xParser.is() )
401 xParser->parseStrict( aURL );
403 xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
404 SAL_WARN_IF(
405 !xDispatcher.is(), "desktop.app",
406 "unsupported dispatch request <" << aName << ">");
407 if( xDispatcher.is() )
410 osl::MutexGuard aGuard(m_mutex);
411 // Remember request so we can find it in statusChanged!
412 m_nRequestCount++;
415 // Use local vector to store dispatcher because we have to fill our request container before
416 // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!
417 aDispatches.emplace_back( aURL, xDispatcher );
420 else if ( aName.startsWith( "service:" ) )
422 // TODO: the dispatch has to be done for loadComponentFromURL as well.
423 URL aURL ;
424 aURL.Complete = aName;
426 Reference < XDispatch > xDispatcher ;
427 Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
429 if( xParser.is() )
430 xParser->parseStrict( aURL );
432 xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
434 if( xDispatcher.is() )
438 // We have to be listener to catch errors during dispatching URLs.
439 // Otherwise it would be possible to have an office running without an open
440 // window!!
441 Sequence < PropertyValue > aArgs2(1);
442 aArgs2[0].Name = "SynchronMode";
443 aArgs2[0].Value <<= true;
444 Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );
445 if ( xDisp.is() )
446 xDisp->dispatchWithNotification( aURL, aArgs2, this );
447 else
448 xDispatcher->dispatch( aURL, aArgs2 );
450 catch (const css::uno::Exception&)
452 TOOLS_WARN_EXCEPTION(
453 "desktop.app",
454 "Desktop::OpenDefault() ignoring Exception while calling XNotifyingDispatch");
458 else
460 INetURLObject aObj( aName );
461 if ( aObj.GetProtocol() == INetProtocol::PrivSoffice )
462 aTarget = "_default";
464 // Set "AsTemplate" argument according to request type
465 if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
466 aDispatchRequest.aRequestType == REQUEST_FORCEOPEN )
468 aArgs.emplace_back("AsTemplate", 0,
469 Any(aDispatchRequest.aRequestType == REQUEST_FORCENEW),
470 PropertyState_DIRECT_VALUE);
473 // if we are called in viewmode, open document read-only
474 if(aDispatchRequest.aRequestType == REQUEST_VIEW) {
475 aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
478 // if we are called with -start set Start in mediadescriptor
479 if(aDispatchRequest.aRequestType == REQUEST_START) {
480 aArgs.emplace_back("StartPresentation", 0, Any(true), PropertyState_DIRECT_VALUE);
483 // Force input filter, if possible
484 if( bSetInputFilter )
486 sal_Int32 nFilterOptionsIndex = 0;
487 aArgs.emplace_back("FilterName", 0,
488 Any(aForcedInputFilter.getToken(0, ':', nFilterOptionsIndex)),
489 PropertyState_DIRECT_VALUE);
491 if (0 < nFilterOptionsIndex)
493 aArgs.emplace_back("FilterOptions", 0,
494 Any(aForcedInputFilter.copy(nFilterOptionsIndex)),
495 PropertyState_DIRECT_VALUE);
499 // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
502 xDoc.set(comphelper::SynchronousDispatch::dispatch(
503 xDesktop, aName, aTarget, comphelper::containerToSequence(aArgs)),
504 UNO_QUERY);
506 catch (const css::lang::IllegalArgumentException&)
508 TOOLS_WARN_EXCEPTION(
509 "desktop.app",
510 "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL");
512 catch (const css::io::IOException&)
514 TOOLS_WARN_EXCEPTION(
515 "desktop.app",
516 "Dispatchwatcher IOException while calling loadComponentFromURL");
518 if ( aDispatchRequest.aRequestType == REQUEST_OPEN ||
519 aDispatchRequest.aRequestType == REQUEST_VIEW ||
520 aDispatchRequest.aRequestType == REQUEST_START ||
521 aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ||
522 aDispatchRequest.aRequestType == REQUEST_FORCENEW )
524 // request is completed
525 RequestHandler::RequestsCompleted();
527 else if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
528 aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
529 aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
530 aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
531 aDispatchRequest.aRequestType == REQUEST_CAT ||
532 aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
534 if ( xDoc.is() )
536 // Do we need to save the document in a different format?
537 if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
538 aDispatchRequest.aRequestType == REQUEST_CAT )
540 // FIXME: factor out into a method ...
541 Reference< XStorable > xStorable( xDoc, UNO_QUERY );
542 if ( xStorable.is() ) {
543 OUString aParam = aDispatchRequest.aPrinterName;
544 sal_Int32 nPathIndex = aParam.lastIndexOf( ';' );
545 sal_Int32 nFilterIndex = aParam.indexOf( ':' );
546 sal_Int32 nImgFilterIndex = aParam.lastIndexOf( '|' );
547 if( nPathIndex < nFilterIndex )
548 nFilterIndex = -1;
550 OUString aFilterOut;
551 OUString aImgOut;
552 OUString aFilter;
553 OUString aFilterExt;
554 bool bGuess = false;
556 if( nFilterIndex >= 0 )
558 aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
559 aFilterExt = aParam.copy( 0, nFilterIndex );
561 else
563 // Guess
564 bGuess = true;
565 aFilterExt = aParam.copy( 0, nPathIndex );
568 if( nImgFilterIndex >= 0 )
570 aImgOut = aParam.copy( nImgFilterIndex+1 );
571 aFilterOut = aParam.copy( nPathIndex+1, nImgFilterIndex-nPathIndex-1 );
573 else
574 aFilterOut = aParam.copy( nPathIndex+1 );
576 FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
577 INetURLObject aOutFilename(aFilterOut);
578 aOutFilename.Append(aObj.getName(INetURLObject::LAST_SEGMENT, true,
579 INetURLObject::DecodeMechanism::NONE));
580 aOutFilename.SetExtension(aFilterExt);
581 OUString aOutFile
582 = aOutFilename.GetMainURL(INetURLObject::DecodeMechanism::NONE);
584 std::unique_ptr<utl::TempFile> fileForCat;
585 if( aDispatchRequest.aRequestType == REQUEST_CAT )
587 fileForCat = std::make_unique<utl::TempFile>();
588 if (fileForCat->IsValid())
589 fileForCat->EnableKillingFile();
590 else
591 std::cerr << "Error: Cannot create temporary file..." << std::endl ;
592 aOutFile = fileForCat->GetURL();
595 if ( bGuess )
597 OUString aDocService;
598 Reference< XModel > xModel( xDoc, UNO_QUERY );
599 if ( xModel.is() )
601 utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
602 aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
604 aFilter = impl_GuessFilter( aOutFile, aDocService );
607 if (aFilter.isEmpty())
609 std::cerr << "Error: no export filter" << std::endl;
611 else
613 sal_Int32 nFilterOptionsIndex = aFilter.indexOf(':');
614 sal_Int32 nProps = ( 0 < nFilterOptionsIndex ) ? 3 : 2;
616 if ( !aImgOut.isEmpty() )
617 nProps +=1;
618 Sequence<PropertyValue> conversionProperties( nProps );
619 conversionProperties[0].Name = "Overwrite";
620 conversionProperties[0].Value <<= true;
622 conversionProperties[1].Name = "FilterName";
623 if( 0 < nFilterOptionsIndex )
625 conversionProperties[1].Value <<= aFilter.copy(0, nFilterOptionsIndex);
627 conversionProperties[2].Name = "FilterOptions";
628 conversionProperties[2].Value <<= aFilter.copy(nFilterOptionsIndex + 1);
630 else
632 conversionProperties[1].Value <<= aFilter;
635 if ( !aImgOut.isEmpty() )
637 conversionProperties[nProps-1].Name = "ImageFilter";
638 conversionProperties[nProps-1].Value <<= aImgOut;
641 OUString aTempName;
642 FileBase::getSystemPathFromFileURL(aName, aTempName);
643 OString aSource8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
644 FileBase::getSystemPathFromFileURL(aOutFile, aTempName);
645 OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
646 if (aDispatchRequest.aRequestType != REQUEST_CAT)
648 std::cout << "convert " << aSource8 << " -> " << aTargetURL8;
649 std::cout << " using filter : " << OUStringToOString(aFilter, osl_getThreadTextEncoding()) << std::endl;
650 if (FStatHelper::IsDocument(aOutFile))
651 std::cout << "Overwriting: " << OUStringToOString(aTempName, osl_getThreadTextEncoding()) << std::endl ;
655 xStorable->storeToURL(aOutFile, conversionProperties);
657 catch (const Exception& rException)
659 std::cerr << "Error: Please verify input parameters...";
660 if (!rException.Message.isEmpty())
661 std::cerr << " (" << rException.Message << ")";
662 std::cerr << std::endl;
665 if (fileForCat && fileForCat->IsValid())
667 SvStream* aStream = fileForCat->GetStream(StreamMode::STD_READ);
668 while (aStream->good())
670 OString aStr;
671 aStream->ReadLine(aStr, SAL_MAX_INT32);
672 for (sal_Int32 i = 0; i < aStr.getLength(); ++i)
674 std::cout << aStr[i];
676 std::cout << std::endl;
682 else if ( aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
684 Reference< XModel > xModel( xDoc, UNO_QUERY );
685 if( xModel.is() )
686 scriptCat( xModel );
688 else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT )
690 batchPrint( aDispatchRequest.aPrinterName, xDoc, aObj, aName );
692 else
694 if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
696 // create the printer
697 Sequence < PropertyValue > aPrinterArgs( 1 );
698 aPrinterArgs[0].Name = "Name";
699 aPrinterArgs[0].Value <<= aDispatchRequest.aPrinterName;
700 xDoc->setPrinter( aPrinterArgs );
703 // print ( also without user interaction )
704 Sequence < PropertyValue > aPrinterArgs( 1 );
705 aPrinterArgs[0].Name = "Wait";
706 aPrinterArgs[0].Value <<= true;
707 xDoc->print( aPrinterArgs );
710 else
712 std::cerr << "Error: source file could not be loaded" << std::endl;
715 // remove the document
718 Reference < XCloseable > xClose( xDoc, UNO_QUERY );
719 if ( xClose.is() )
720 xClose->close( true );
721 else
723 Reference < XComponent > xComp( xDoc, UNO_QUERY );
724 if ( xComp.is() )
725 xComp->dispose();
728 catch (const css::util::CloseVetoException&)
732 // request is completed
733 RequestHandler::RequestsCompleted();
738 if ( !aDispatches.empty() )
740 // Execute all asynchronous dispatches now after we placed them into our request container!
741 Sequence < PropertyValue > aArgs( 2 );
742 aArgs[0].Name = "Referer";
743 aArgs[0].Value <<= OUString("private:OpenEvent");
744 aArgs[1].Name = "SynchronMode";
745 aArgs[1].Value <<= true;
747 for (const DispatchHolder & aDispatche : aDispatches)
749 Reference< XDispatch > xDispatch = aDispatche.xDispatch;
750 Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );
751 if ( xDisp.is() )
752 xDisp->dispatchWithNotification( aDispatche.aURL, aArgs, this );
753 else
756 osl::MutexGuard aGuard(m_mutex);
757 m_nRequestCount--;
759 xDispatch->dispatch( aDispatche.aURL, aArgs );
764 ::osl::ClearableMutexGuard aGuard(m_mutex);
765 bool bEmpty = (m_nRequestCount == 0);
766 aGuard.clear();
768 // No more asynchronous requests?
769 // The requests are removed from the request container after they called back to this
770 // implementation via statusChanged!!
771 if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ )
773 // We have to check if we have an open task otherwise we have to shutdown the office.
774 Reference< XElementAccess > xList = xDesktop->getFrames();
776 if ( !xList->hasElements() )
778 // We don't have any task open so we have to shutdown ourself!!
779 return xDesktop->terminate();
783 return false;
787 void SAL_CALL DispatchWatcher::disposing( const css::lang::EventObject& )
792 void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& )
794 osl::ClearableMutexGuard aGuard(m_mutex);
795 sal_Int16 nCount = --m_nRequestCount;
796 aGuard.clear();
797 RequestHandler::RequestsCompleted();
798 if ( !nCount && !RequestHandler::AreRequestsPending() )
800 // We have to check if we have an open task otherwise we have to shutdown the office.
801 Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
802 Reference< XElementAccess > xList = xDesktop->getFrames();
804 if ( !xList->hasElements() )
806 // We don't have any task open so we have to shutdown ourself!!
807 xDesktop->terminate();
812 } // namespace desktop
814 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */