1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <svl/fstathelper.hxx>
29 #include "dispatchwatcher.hxx"
30 #include "officeipcthread.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/XLibraryContainer2.hpp>
53 #include <com/sun/star/document/XEmbeddedScripts.hpp>
55 #include <comphelper/sequence.hxx>
56 #include <tools/diagnose_ex.h>
57 #include <tools/urlobj.hxx>
58 #include <unotools/mediadescriptor.hxx>
59 #include <unotools/tempfile.hxx>
61 #include <osl/thread.hxx>
62 #include <osl/file.hxx>
65 using namespace ::osl
;
66 using namespace ::com::sun::star::uno
;
67 using namespace ::com::sun::star::util
;
68 using namespace ::com::sun::star::lang
;
69 using namespace ::com::sun::star::frame
;
70 using namespace ::com::sun::star::container
;
71 using namespace ::com::sun::star::beans
;
72 using namespace ::com::sun::star::view
;
73 using namespace ::com::sun::star::task
;
74 using namespace ::com::sun::star::document
;
76 namespace document
= ::com::sun::star::document
;
85 DispatchHolder( const URL
& rURL
, Reference
< XDispatch
> const & rDispatch
) :
86 aURL( rURL
), xDispatch( rDispatch
) {}
89 Reference
< XDispatch
> xDispatch
;
92 std::shared_ptr
<const SfxFilter
> impl_lookupExportFilterForUrl( const OUString
& rUrl
, const OUString
& rFactory
)
94 // create the list of filters
95 OUStringBuffer
sQuery(256);
96 sQuery
.append("getSortedFilterList()");
97 sQuery
.append(":module=");
98 sQuery
.append(rFactory
); // use long name here !
99 sQuery
.append(":iflags=");
100 sQuery
.append(OUString::number(static_cast<sal_Int32
>(SfxFilterFlags::EXPORT
)));
101 sQuery
.append(":eflags=");
102 sQuery
.append(OUString::number(static_cast<int>(SFX_FILTER_NOTINSTALLED
)));
104 const Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
105 const Reference
< XContainerQuery
> xFilterFactory(
106 xContext
->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext
),
109 std::shared_ptr
<const SfxFilter
> pBestMatch
;
111 const Reference
< XEnumeration
> xFilterEnum(
112 xFilterFactory
->createSubSetEnumerationByQuery( sQuery
.makeStringAndClear() ), UNO_SET_THROW
);
113 while ( xFilterEnum
->hasMoreElements() )
115 comphelper::SequenceAsHashMap
aFilterProps( xFilterEnum
->nextElement() );
116 const OUString
aName( aFilterProps
.getUnpackedValueOrDefault( "Name", OUString() ) );
117 if ( !aName
.isEmpty() )
119 std::shared_ptr
<const SfxFilter
> pFilter( SfxFilter::GetFilterByName( aName
) );
120 if ( pFilter
&& pFilter
->CanExport() && pFilter
->GetWildcard().Matches( rUrl
) )
122 if ( !pBestMatch
|| ( SfxFilterFlags::PREFERED
& pFilter
->GetFilterFlags() ) )
123 pBestMatch
= pFilter
;
131 std::shared_ptr
<const SfxFilter
> impl_getExportFilterFromUrl(
132 const OUString
& rUrl
, const OUString
& rFactory
)
136 const Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
137 const Reference
< document::XTypeDetection
> xTypeDetector(
138 xContext
->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext
),
140 const OUString
aTypeName( xTypeDetector
->queryTypeByURL( rUrl
) );
142 std::shared_ptr
<const SfxFilter
> pFilter( SfxFilterMatcher( rFactory
).GetFilter4EA( aTypeName
, SfxFilterFlags::EXPORT
) );
144 pFilter
= impl_lookupExportFilterForUrl( rUrl
, rFactory
);
148 FileBase::getSystemPathFromFileURL( rUrl
, aTempName
);
149 OString aSource
= OUStringToOString ( aTempName
, osl_getThreadTextEncoding() );
150 std::cerr
<< "Error: no export filter for " << aSource
<< " found, aborting." << std::endl
;
155 catch ( const Exception
& )
161 OUString
impl_GuessFilter( const OUString
& rUrlOut
, const OUString
& rDocService
)
164 std::shared_ptr
<const SfxFilter
> pOutFilter
= impl_getExportFilterFromUrl( rUrlOut
, rDocService
);
166 aOutFilter
= pOutFilter
->GetFilterName();
171 /// dump scripts in a document to the console.
172 void scriptCat(const Reference
< XModel
>& xDoc
)
174 Reference
< XEmbeddedScripts
> xScriptAccess( xDoc
, UNO_QUERY
);
177 std::cout
<< "No script access\n";
181 // ignore xScriptAccess->getDialogLibraries() for now
182 Reference
< css::script::XLibraryContainer2
> xLibraries(
183 xScriptAccess
->getBasicLibraries() );
185 if ( !xLibraries
.is() )
187 std::cout
<< "No script libraries\n";
191 const Sequence
< OUString
> aLibNames
= xLibraries
->getElementNames();
192 std::cout
<< "Libraries: " << aLibNames
.getLength() << "\n";
193 for (OUString
const & libName
: aLibNames
)
195 std::cout
<< "Library: '" << libName
<< "' children: ";
196 Reference
< XNameContainer
> xContainer
;
198 if (!xLibraries
->isLibraryLoaded( libName
))
199 xLibraries
->loadLibrary( libName
);
200 xContainer
= Reference
< XNameContainer
>(
201 xLibraries
->getByName( libName
), UNO_QUERY
);
203 catch (const css::uno::Exception
&e
)
205 std::cout
<< "[" << libName
<< "] - failed to load library: " << e
.Message
<< "\n";
208 if( !xContainer
.is() )
212 Sequence
< OUString
> aObjectNames
= xContainer
->getElementNames();
214 std::cout
<< aObjectNames
.getLength() << "\n\n";
215 for ( sal_Int32 j
= 0 ; j
< aObjectNames
.getLength() ; ++j
)
217 OUString
&rObjectName
= aObjectNames
[j
];
221 Any aCode
= xContainer
->getByName( rObjectName
);
222 OUString aCodeString
;
224 if (! (aCode
>>= aCodeString
) )
225 std::cout
<< "[" << rObjectName
<< "] - error fetching code\n";
227 std::cout
<< "[" << rObjectName
<< "]\n"
228 << aCodeString
.trim()
229 << "\n[/" << rObjectName
<< "]\n";
231 catch (const css::uno::Exception
&e
)
233 std::cout
<< "[" << rObjectName
<< "] - exception " << e
.Message
<< " fetching code\n";
236 if (j
< aObjectNames
.getLength() - 1)
237 std::cout
<< "\n----------------------------------------------------------\n";
244 // Perform batch print
245 void batchPrint( const OUString
&rPrinterName
, const Reference
< XPrintable
> &xDoc
,
246 const INetURLObject
&aObj
, const OUString
&aName
)
249 OUString aPrinterName
;
250 sal_Int32 nPathIndex
= rPrinterName
.lastIndexOf( ';' );
251 if( nPathIndex
!= -1 )
252 aFilterOut
=rPrinterName
.copy( nPathIndex
+1 );
253 if( nPathIndex
!= 0 )
254 aPrinterName
=rPrinterName
.copy( 0, nPathIndex
);
256 INetURLObject
aOutFilename( aObj
);
257 aOutFilename
.SetExtension( "pdf" );
258 FileBase::getFileURLFromSystemPath( aFilterOut
, aFilterOut
);
259 OUString aOutFile
= aFilterOut
+ "/" + aOutFilename
.getName();
262 FileBase::getSystemPathFromFileURL( aName
, aTempName
);
263 OString aSource8
= OUStringToOString ( aTempName
, osl_getThreadTextEncoding() );
264 FileBase::getSystemPathFromFileURL( aOutFile
, aTempName
);
265 OString aTargetURL8
= OUStringToOString(aTempName
, osl_getThreadTextEncoding() );
267 std::cout
<< "print " << aSource8
<< " -> " << aTargetURL8
;
268 std::cout
<< " using " << (aPrinterName
.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName
, osl_getThreadTextEncoding() ));
269 std::cout
<< std::endl
;
271 // create the custom printer, if given
272 Sequence
< PropertyValue
> aPrinterArgs( 1 );
273 if( !aPrinterName
.isEmpty() )
275 aPrinterArgs
[0].Name
= "Name";
276 aPrinterArgs
[0].Value
<<= aPrinterName
;
277 xDoc
->setPrinter( aPrinterArgs
);
280 // print ( also without user interaction )
281 aPrinterArgs
.realloc(2);
282 aPrinterArgs
[0].Name
= "FileName";
283 aPrinterArgs
[0].Value
<<= aOutFile
;
284 aPrinterArgs
[1].Name
= "Wait";
285 aPrinterArgs
[1].Value
<<= true;
286 xDoc
->print( aPrinterArgs
);
289 } // anonymous namespace
291 DispatchWatcher::DispatchWatcher()
297 DispatchWatcher::~DispatchWatcher()
302 bool DispatchWatcher::executeDispatchRequests( const std::vector
<DispatchRequest
>& aDispatchRequestsList
, bool bNoTerminate
)
304 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
306 std::vector
< DispatchHolder
> aDispatches
;
307 bool bSetInputFilter
= false;
308 OUString aForcedInputFilter
;
310 for (auto const & aDispatchRequest
: aDispatchRequestsList
)
313 if ( aDispatchRequest
.aRequestType
== REQUEST_INFILTER
)
315 bSetInputFilter
= true;
316 aForcedInputFilter
= aDispatchRequest
.aURL
;
317 RequestHandler::RequestsCompleted();
321 // create parameter array
322 std::vector
<PropertyValue
> aArgs
;
324 // mark request as user interaction from outside
325 aArgs
.emplace_back("Referer", 0, Any(OUString("private:OpenEvent")),
326 PropertyState_DIRECT_VALUE
);
328 OUString
aTarget("_default");
330 if ( aDispatchRequest
.aRequestType
== REQUEST_PRINT
||
331 aDispatchRequest
.aRequestType
== REQUEST_PRINTTO
||
332 aDispatchRequest
.aRequestType
== REQUEST_BATCHPRINT
||
333 aDispatchRequest
.aRequestType
== REQUEST_CONVERSION
||
334 aDispatchRequest
.aRequestType
== REQUEST_CAT
||
335 aDispatchRequest
.aRequestType
== REQUEST_SCRIPT_CAT
)
337 // documents opened for printing are opened readonly because they must be opened as a
338 // new document and this document could be open already
339 aArgs
.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE
);
340 // always open a new document for printing, because it must be disposed afterwards
341 aArgs
.emplace_back("OpenNewView", 0, Any(true), PropertyState_DIRECT_VALUE
);
342 // printing is done in a hidden view
343 aArgs
.emplace_back("Hidden", 0, Any(true), PropertyState_DIRECT_VALUE
);
344 // load document for printing without user interaction
345 aArgs
.emplace_back("Silent", 0, Any(true), PropertyState_DIRECT_VALUE
);
347 // hidden documents should never be put into open tasks
352 Reference
< XInteractionHandler2
> xInteraction(
353 InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
355 aArgs
.emplace_back("InteractionHandler", 0, Any(xInteraction
),
356 PropertyState_DIRECT_VALUE
);
358 aArgs
.emplace_back("MacroExecutionMode", 0,
359 Any(css::document::MacroExecMode::USE_CONFIG
),
360 PropertyState_DIRECT_VALUE
);
362 aArgs
.emplace_back("UpdateDocMode", 0,
363 Any(css::document::UpdateDocMode::ACCORDING_TO_CONFIG
),
364 PropertyState_DIRECT_VALUE
);
367 if ( !aDispatchRequest
.aPreselectedFactory
.isEmpty() )
369 aArgs
.emplace_back(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), 0,
370 Any(aDispatchRequest
.aPreselectedFactory
),
371 PropertyState_DIRECT_VALUE
);
374 OUString
aName( GetURL_Impl( aDispatchRequest
.aURL
, aDispatchRequest
.aCwdUrl
) );
376 // load the document ... if they are loadable!
377 // Otherwise try to dispatch it ...
378 Reference
< XPrintable
> xDoc
;
380 ( aName
.startsWith( ".uno" ) ) ||
381 ( aName
.startsWith( "slot:" ) ) ||
382 ( aName
.startsWith( "macro:" ) ) ||
383 ( aName
.startsWith("vnd.sun.star.script") )
386 // Attention: URL must be parsed full. Otherwise some detections on it will fail!
387 // It doesn't matter, if parser isn't available. Because; We try loading of URL then ...
389 aURL
.Complete
= aName
;
391 Reference
< XDispatch
> xDispatcher
;
392 Reference
< XURLTransformer
> xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
395 xParser
->parseStrict( aURL
);
397 xDispatcher
= xDesktop
->queryDispatch( aURL
, OUString(), 0 );
399 !xDispatcher
.is(), "desktop.app",
400 "unsupported dispatch request <" << aName
<< ">");
401 if( xDispatcher
.is() )
404 osl::MutexGuard
aGuard(m_mutex
);
405 // Remember request so we can find it in statusChanged!
409 // Use local vector to store dispatcher because we have to fill our request container before
410 // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!
411 aDispatches
.emplace_back( aURL
, xDispatcher
);
414 else if ( aName
.startsWith( "service:" ) )
416 // TODO: the dispatch has to be done for loadComponentFromURL as well.
418 aURL
.Complete
= aName
;
420 Reference
< XDispatch
> xDispatcher
;
421 Reference
< XURLTransformer
> xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
424 xParser
->parseStrict( aURL
);
426 xDispatcher
= xDesktop
->queryDispatch( aURL
, OUString(), 0 );
428 if( xDispatcher
.is() )
432 // We have to be listener to catch errors during dispatching URLs.
433 // Otherwise it would be possible to have an office running without an open
435 Sequence
< PropertyValue
> aArgs2(1);
436 aArgs2
[0].Name
= "SynchronMode";
437 aArgs2
[0].Value
<<= true;
438 Reference
< XNotifyingDispatch
> xDisp( xDispatcher
, UNO_QUERY
);
440 xDisp
->dispatchWithNotification( aURL
, aArgs2
, this );
442 xDispatcher
->dispatch( aURL
, aArgs2
);
444 catch (const css::uno::Exception
&)
446 TOOLS_WARN_EXCEPTION(
448 "Desktop::OpenDefault() ignoring Exception while calling XNotifyingDispatch");
454 INetURLObject
aObj( aName
);
455 if ( aObj
.GetProtocol() == INetProtocol::PrivSoffice
)
456 aTarget
= "_default";
458 // Set "AsTemplate" argument according to request type
459 if ( aDispatchRequest
.aRequestType
== REQUEST_FORCENEW
||
460 aDispatchRequest
.aRequestType
== REQUEST_FORCEOPEN
)
462 aArgs
.emplace_back("AsTemplate", 0,
463 Any(aDispatchRequest
.aRequestType
== REQUEST_FORCENEW
),
464 PropertyState_DIRECT_VALUE
);
467 // if we are called in viewmode, open document read-only
468 if(aDispatchRequest
.aRequestType
== REQUEST_VIEW
) {
469 aArgs
.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE
);
472 // if we are called with --show set Start in mediadescriptor
473 if(aDispatchRequest
.aRequestType
== REQUEST_START
) {
474 aArgs
.emplace_back("StartPresentation", 0, Any(true), PropertyState_DIRECT_VALUE
);
477 // Force input filter, if possible
478 if( bSetInputFilter
)
480 sal_Int32 nFilterOptionsIndex
= 0;
481 aArgs
.emplace_back("FilterName", 0,
482 Any(aForcedInputFilter
.getToken(0, ':', nFilterOptionsIndex
)),
483 PropertyState_DIRECT_VALUE
);
485 if (0 < nFilterOptionsIndex
)
487 aArgs
.emplace_back("FilterOptions", 0,
488 Any(aForcedInputFilter
.copy(nFilterOptionsIndex
)),
489 PropertyState_DIRECT_VALUE
);
493 // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
496 xDoc
.set(comphelper::SynchronousDispatch::dispatch(
497 xDesktop
, aName
, aTarget
, comphelper::containerToSequence(aArgs
)),
500 catch (const css::lang::IllegalArgumentException
&)
502 TOOLS_WARN_EXCEPTION(
504 "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL");
506 catch (const css::io::IOException
&)
508 TOOLS_WARN_EXCEPTION(
510 "Dispatchwatcher IOException while calling loadComponentFromURL");
512 if ( aDispatchRequest
.aRequestType
== REQUEST_OPEN
||
513 aDispatchRequest
.aRequestType
== REQUEST_VIEW
||
514 aDispatchRequest
.aRequestType
== REQUEST_START
||
515 aDispatchRequest
.aRequestType
== REQUEST_FORCEOPEN
||
516 aDispatchRequest
.aRequestType
== REQUEST_FORCENEW
)
518 // request is completed
519 RequestHandler::RequestsCompleted();
521 else if ( aDispatchRequest
.aRequestType
== REQUEST_PRINT
||
522 aDispatchRequest
.aRequestType
== REQUEST_PRINTTO
||
523 aDispatchRequest
.aRequestType
== REQUEST_BATCHPRINT
||
524 aDispatchRequest
.aRequestType
== REQUEST_CONVERSION
||
525 aDispatchRequest
.aRequestType
== REQUEST_CAT
||
526 aDispatchRequest
.aRequestType
== REQUEST_SCRIPT_CAT
)
530 // Do we need to save the document in a different format?
531 if ( aDispatchRequest
.aRequestType
== REQUEST_CONVERSION
||
532 aDispatchRequest
.aRequestType
== REQUEST_CAT
)
534 // FIXME: factor out into a method ...
535 Reference
< XStorable
> xStorable( xDoc
, UNO_QUERY
);
536 if ( xStorable
.is() ) {
537 OUString aParam
= aDispatchRequest
.aPrinterName
;
538 sal_Int32 nPathIndex
= aParam
.lastIndexOf( ';' );
539 sal_Int32 nFilterIndex
= aParam
.indexOf( ':' );
540 sal_Int32 nImgFilterIndex
= aParam
.lastIndexOf( '|' );
541 if( nPathIndex
< nFilterIndex
)
550 if( nFilterIndex
>= 0 )
552 aFilter
= aParam
.copy( nFilterIndex
+1, nPathIndex
-nFilterIndex
-1 );
553 aFilterExt
= aParam
.copy( 0, nFilterIndex
);
559 aFilterExt
= aParam
.copy( 0, nPathIndex
);
562 if( nImgFilterIndex
>= 0 )
564 aImgOut
= aParam
.copy( nImgFilterIndex
+1 );
565 aFilterOut
= aParam
.copy( nPathIndex
+1, nImgFilterIndex
-nPathIndex
-1 );
568 aFilterOut
= aParam
.copy( nPathIndex
+1 );
570 FileBase::getFileURLFromSystemPath( aFilterOut
, aFilterOut
);
571 INetURLObject
aOutFilename(aFilterOut
);
572 aOutFilename
.Append(aObj
.getName(INetURLObject::LAST_SEGMENT
, true,
573 INetURLObject::DecodeMechanism::NONE
));
574 aOutFilename
.SetExtension(aFilterExt
);
576 = aOutFilename
.GetMainURL(INetURLObject::DecodeMechanism::NONE
);
578 std::unique_ptr
<utl::TempFile
> fileForCat
;
579 if( aDispatchRequest
.aRequestType
== REQUEST_CAT
)
581 fileForCat
= std::make_unique
<utl::TempFile
>();
582 if (fileForCat
->IsValid())
583 fileForCat
->EnableKillingFile();
585 std::cerr
<< "Error: Cannot create temporary file..." << std::endl
;
586 aOutFile
= fileForCat
->GetURL();
591 OUString aDocService
;
592 Reference
< XModel
> xModel( xDoc
, UNO_QUERY
);
595 utl::MediaDescriptor
aMediaDesc( xModel
->getArgs() );
596 aDocService
= aMediaDesc
.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
598 aFilter
= impl_GuessFilter( aOutFile
, aDocService
);
601 if (aFilter
.isEmpty())
603 std::cerr
<< "Error: no export filter" << std::endl
;
607 sal_Int32 nFilterOptionsIndex
= aFilter
.indexOf(':');
608 sal_Int32 nProps
= ( 0 < nFilterOptionsIndex
) ? 3 : 2;
610 if ( !aImgOut
.isEmpty() )
612 Sequence
<PropertyValue
> conversionProperties( nProps
);
613 conversionProperties
[0].Name
= "Overwrite";
614 conversionProperties
[0].Value
<<= true;
616 conversionProperties
[1].Name
= "FilterName";
617 if( 0 < nFilterOptionsIndex
)
619 conversionProperties
[1].Value
<<= aFilter
.copy(0, nFilterOptionsIndex
);
621 conversionProperties
[2].Name
= "FilterOptions";
622 conversionProperties
[2].Value
<<= aFilter
.copy(nFilterOptionsIndex
+ 1);
626 conversionProperties
[1].Value
<<= aFilter
;
629 if ( !aImgOut
.isEmpty() )
631 conversionProperties
[nProps
-1].Name
= "ImageFilter";
632 conversionProperties
[nProps
-1].Value
<<= aImgOut
;
636 FileBase::getSystemPathFromFileURL(aName
, aTempName
);
637 OString aSource8
= OUStringToOString(aTempName
, osl_getThreadTextEncoding());
638 FileBase::getSystemPathFromFileURL(aOutFile
, aTempName
);
639 OString aTargetURL8
= OUStringToOString(aTempName
, osl_getThreadTextEncoding());
640 if (aDispatchRequest
.aRequestType
!= REQUEST_CAT
)
642 std::cout
<< "convert " << aSource8
<< " -> " << aTargetURL8
;
643 std::cout
<< " using filter : " << OUStringToOString(aFilter
, osl_getThreadTextEncoding()) << std::endl
;
644 if (FStatHelper::IsDocument(aOutFile
))
645 std::cout
<< "Overwriting: " << OUStringToOString(aTempName
, osl_getThreadTextEncoding()) << std::endl
;
649 xStorable
->storeToURL(aOutFile
, conversionProperties
);
651 catch (const Exception
& rException
)
653 std::cerr
<< "Error: Please verify input parameters...";
654 if (!rException
.Message
.isEmpty())
655 std::cerr
<< " (" << rException
.Message
<< ")";
656 std::cerr
<< std::endl
;
659 if (fileForCat
&& fileForCat
->IsValid())
661 SvStream
* aStream
= fileForCat
->GetStream(StreamMode::STD_READ
);
662 while (aStream
->good())
665 aStream
->ReadLine(aStr
, SAL_MAX_INT32
);
666 for (sal_Int32 i
= 0; i
< aStr
.getLength(); ++i
)
668 std::cout
<< aStr
[i
];
670 std::cout
<< std::endl
;
676 else if ( aDispatchRequest
.aRequestType
== REQUEST_SCRIPT_CAT
)
678 Reference
< XModel
> xModel( xDoc
, UNO_QUERY
);
682 else if ( aDispatchRequest
.aRequestType
== REQUEST_BATCHPRINT
)
684 batchPrint( aDispatchRequest
.aPrinterName
, xDoc
, aObj
, aName
);
688 if ( aDispatchRequest
.aRequestType
== REQUEST_PRINTTO
)
690 // create the printer
691 Sequence
< PropertyValue
> aPrinterArgs( 1 );
692 aPrinterArgs
[0].Name
= "Name";
693 aPrinterArgs
[0].Value
<<= aDispatchRequest
.aPrinterName
;
694 xDoc
->setPrinter( aPrinterArgs
);
697 // print ( also without user interaction )
698 Sequence
< PropertyValue
> aPrinterArgs( 1 );
699 aPrinterArgs
[0].Name
= "Wait";
700 aPrinterArgs
[0].Value
<<= true;
701 xDoc
->print( aPrinterArgs
);
706 std::cerr
<< "Error: source file could not be loaded" << std::endl
;
709 // remove the document
712 Reference
< XCloseable
> xClose( xDoc
, UNO_QUERY
);
714 xClose
->close( true );
717 Reference
< XComponent
> xComp( xDoc
, UNO_QUERY
);
722 catch (const css::util::CloseVetoException
&)
726 // request is completed
727 RequestHandler::RequestsCompleted();
732 if ( !aDispatches
.empty() )
734 // Execute all asynchronous dispatches now after we placed them into our request container!
735 Sequence
< PropertyValue
> aArgs( 2 );
736 aArgs
[0].Name
= "Referer";
737 aArgs
[0].Value
<<= OUString("private:OpenEvent");
738 aArgs
[1].Name
= "SynchronMode";
739 aArgs
[1].Value
<<= true;
741 for (const DispatchHolder
& aDispatche
: aDispatches
)
743 Reference
< XDispatch
> xDispatch
= aDispatche
.xDispatch
;
744 Reference
< XNotifyingDispatch
> xDisp( xDispatch
, UNO_QUERY
);
746 xDisp
->dispatchWithNotification( aDispatche
.aURL
, aArgs
, this );
750 osl::MutexGuard
aGuard(m_mutex
);
753 xDispatch
->dispatch( aDispatche
.aURL
, aArgs
);
758 ::osl::ClearableMutexGuard
aGuard(m_mutex
);
759 bool bEmpty
= (m_nRequestCount
== 0);
762 // No more asynchronous requests?
763 // The requests are removed from the request container after they called back to this
764 // implementation via statusChanged!!
765 if ( bEmpty
&& !bNoTerminate
/*m_aRequestContainer.empty()*/ )
767 // We have to check if we have an open task otherwise we have to shutdown the office.
768 Reference
< XElementAccess
> xList
= xDesktop
->getFrames();
770 if ( !xList
->hasElements() )
772 // We don't have any task open so we have to shutdown ourself!!
773 return xDesktop
->terminate();
781 void SAL_CALL
DispatchWatcher::disposing( const css::lang::EventObject
& )
786 void SAL_CALL
DispatchWatcher::dispatchFinished( const DispatchResultEvent
& )
788 osl::ClearableMutexGuard
aGuard(m_mutex
);
789 sal_Int16 nCount
= --m_nRequestCount
;
791 RequestHandler::RequestsCompleted();
792 if ( !nCount
&& !RequestHandler::AreRequestsPending() )
794 // We have to check if we have an open task otherwise we have to shutdown the office.
795 Reference
< XDesktop2
> xDesktop
= css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
796 Reference
< XElementAccess
> xList
= xDesktop
->getFrames();
798 if ( !xList
->hasElements() )
800 // We don't have any task open so we have to shutdown ourself!!
801 xDesktop
->terminate();
806 } // namespace desktop
808 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */