LibreOffice Module desktop (master)  1
dispatchwatcher.cxx
Go to the documentation of this file.
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 <svl/fstathelper.hxx>
27 
28 #include <app.hxx>
29 #include "dispatchwatcher.hxx"
30 #include "officeipcthread.hxx"
31 #include <rtl/ustring.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>
54 
55 #include <comphelper/sequence.hxx>
56 #include <tools/diagnose_ex.h>
57 #include <tools/urlobj.hxx>
59 #include <unotools/tempfile.hxx>
60 
61 #include <osl/thread.hxx>
62 #include <osl/file.hxx>
63 #include <iostream>
64 
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;
75 
76 namespace document = ::com::sun::star::document;
77 
78 namespace desktop
79 {
80 
81 namespace {
82 
83 struct DispatchHolder
84 {
85  DispatchHolder( const URL& rURL, Reference< XDispatch > const & rDispatch ) :
86  aURL( rURL ), xDispatch( rDispatch ) {}
87 
89  Reference< XDispatch > xDispatch;
90 };
91 
92 std::shared_ptr<const SfxFilter> impl_lookupExportFilterForUrl( const OUString& rUrl, const OUString& rFactory )
93 {
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)));
103 
105  const Reference< XContainerQuery > xFilterFactory(
106  xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
107  UNO_QUERY_THROW );
108 
109  std::shared_ptr<const SfxFilter> pBestMatch;
110 
111  const Reference< XEnumeration > xFilterEnum(
112  xFilterFactory->createSubSetEnumerationByQuery( sQuery.makeStringAndClear() ), UNO_SET_THROW );
113  while ( xFilterEnum->hasMoreElements() )
114  {
115  comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
116  const OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", OUString() ) );
117  if ( !aName.isEmpty() )
118  {
119  std::shared_ptr<const SfxFilter> pFilter( SfxFilter::GetFilterByName( aName ) );
120  if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
121  {
122  if ( !pBestMatch || ( SfxFilterFlags::PREFERED & pFilter->GetFilterFlags() ) )
123  pBestMatch = pFilter;
124  }
125  }
126  }
127 
128  return pBestMatch;
129 }
130 
131 std::shared_ptr<const SfxFilter> impl_getExportFilterFromUrl(
132  const OUString& rUrl, const OUString& rFactory)
133 {
134  try
135  {
137  const Reference< document::XTypeDetection > xTypeDetector(
138  xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext ),
139  UNO_QUERY_THROW );
140  const OUString aTypeName( xTypeDetector->queryTypeByURL( rUrl ) );
141 
142  std::shared_ptr<const SfxFilter> pFilter( SfxFilterMatcher( rFactory ).GetFilter4EA( aTypeName, SfxFilterFlags::EXPORT ) );
143  if ( !pFilter )
144  pFilter = impl_lookupExportFilterForUrl( rUrl, rFactory );
145  if ( !pFilter )
146  {
147  OUString aTempName;
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;
151  }
152 
153  return pFilter;
154  }
155  catch ( const Exception& )
156  {
157  return nullptr;
158  }
159 }
160 
161 OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
162 {
163  OUString aOutFilter;
164  std::shared_ptr<const SfxFilter> pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
165  if (pOutFilter)
166  aOutFilter = pOutFilter->GetFilterName();
167 
168  return aOutFilter;
169 }
170 
172 void scriptCat(const Reference< XModel >& xDoc )
173 {
174  Reference< XEmbeddedScripts > xScriptAccess( xDoc, UNO_QUERY );
175  if (!xScriptAccess)
176  {
177  std::cout << "No script access\n";
178  return;
179  }
180 
181  // ignore xScriptAccess->getDialogLibraries() for now
182  Reference< css::script::XLibraryContainer2 > xLibraries(
183  xScriptAccess->getBasicLibraries() );
184 
185  if ( !xLibraries.is() )
186  {
187  std::cout << "No script libraries\n";
188  return;
189  }
190 
191  const Sequence< OUString > aLibNames = xLibraries->getElementNames();
192  std::cout << "Libraries: " << aLibNames.getLength() << "\n";
193  for (OUString const & libName : aLibNames)
194  {
195  std::cout << "Library: '" << libName << "' children: ";
196  Reference< XNameContainer > xContainer;
197  try {
198  if (!xLibraries->isLibraryLoaded( libName ))
199  xLibraries->loadLibrary( libName );
200  xContainer = Reference< XNameContainer >(
201  xLibraries->getByName( libName ), UNO_QUERY );
202  }
203  catch (const css::uno::Exception &e)
204  {
205  std::cout << "[" << libName << "] - failed to load library: " << e.Message << "\n";
206  continue;
207  }
208  if( !xContainer.is() )
209  std::cout << "0\n";
210  else
211  {
212  Sequence< OUString > aObjectNames = xContainer->getElementNames();
213 
214  std::cout << aObjectNames.getLength() << "\n\n";
215  for ( sal_Int32 j = 0 ; j < aObjectNames.getLength() ; ++j )
216  {
217  OUString &rObjectName = aObjectNames[j];
218 
219  OUString aCodeString;
220  try
221  {
222  Any aCode = xContainer->getByName( rObjectName );
223 
224  if (! (aCode >>= aCodeString ) )
225  std::cout << "[" << rObjectName << "] - error fetching code\n";
226  else
227  std::cout << "[" << rObjectName << "]\n"
228  << aCodeString.trim()
229  << "\n[/" << rObjectName << "]\n";
230  }
231  catch (const css::uno::Exception &e)
232  {
233  std::cout << "[" << rObjectName << "] - exception " << e.Message << " fetching code\n";
234  }
235 
236  if (j < aObjectNames.getLength() - 1)
237  std::cout << "\n----------------------------------------------------------\n";
238  std::cout << "\n";
239  }
240  }
241  }
242 }
243 
244 // Perform batch print
245 void batchPrint( const OUString &rPrinterName, const Reference< XPrintable > &xDoc,
246  const INetURLObject &aObj, const OUString &aName )
247 {
248  OUString aFilterOut;
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 );
255 
256  INetURLObject aOutFilename( aObj );
257  aOutFilename.SetExtension( "pdf" );
258  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
259  OUString aOutFile = aFilterOut + "/" + aOutFilename.getName();
260 
261  OUString aTempName;
262  FileBase::getSystemPathFromFileURL( aName, aTempName );
263  OString aSource8 = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
264  FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
265  OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding() );
266 
267  std::cout << "print " << aSource8 << " -> " << aTargetURL8;
268  std::cout << " using " << (aPrinterName.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName, osl_getThreadTextEncoding() ));
269  std::cout << std::endl;
270 
271  // create the custom printer, if given
272  Sequence < PropertyValue > aPrinterArgs( 1 );
273  if( !aPrinterName.isEmpty() )
274  {
275  aPrinterArgs[0].Name = "Name";
276  aPrinterArgs[0].Value <<= aPrinterName;
277  xDoc->setPrinter( aPrinterArgs );
278  }
279 
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 );
287 }
288 
289 } // anonymous namespace
290 
292  : m_nRequestCount(0)
293 {
294 }
295 
296 
298 {
299 }
300 
301 
302 bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest>& aDispatchRequestsList, bool bNoTerminate )
303 {
304  Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
305 
306  std::vector< DispatchHolder > aDispatches;
307  bool bSetInputFilter = false;
308  OUString aForcedInputFilter;
309 
310  for (auto const & aDispatchRequest: aDispatchRequestsList)
311  {
312  // Set Input Filter
313  if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
314  {
315  bSetInputFilter = true;
316  aForcedInputFilter = aDispatchRequest.aURL;
318  continue;
319  }
320 
321  // create parameter array
322  std::vector<PropertyValue> aArgs;
323 
324  // mark request as user interaction from outside
325  aArgs.emplace_back("Referer", 0, Any(OUString("private:OpenEvent")),
326  PropertyState_DIRECT_VALUE);
327 
328  OUString aTarget("_default");
329 
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)
336  {
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);
346 
347  // hidden documents should never be put into open tasks
348  aTarget = "_blank";
349  }
350  else
351  {
352  Reference < XInteractionHandler2 > xInteraction(
353  InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
354 
355  aArgs.emplace_back("InteractionHandler", 0, Any(xInteraction),
356  PropertyState_DIRECT_VALUE);
357 
358  aArgs.emplace_back("MacroExecutionMode", 0,
359  Any(css::document::MacroExecMode::USE_CONFIG),
360  PropertyState_DIRECT_VALUE);
361 
362  aArgs.emplace_back("UpdateDocMode", 0,
363  Any(css::document::UpdateDocMode::ACCORDING_TO_CONFIG),
364  PropertyState_DIRECT_VALUE);
365  }
366 
367  if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
368  {
369  aArgs.emplace_back(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), 0,
370  Any(aDispatchRequest.aPreselectedFactory),
371  PropertyState_DIRECT_VALUE);
372  }
373 
374  OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
375 
376  // load the document ... if they are loadable!
377  // Otherwise try to dispatch it ...
378  Reference < XPrintable > xDoc;
379  if(
380  ( aName.startsWith( ".uno" ) ) ||
381  ( aName.startsWith( "slot:" ) ) ||
382  ( aName.startsWith( "macro:" ) ) ||
383  ( aName.startsWith("vnd.sun.star.script") )
384  )
385  {
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 ...
388  URL aURL ;
389  aURL.Complete = aName;
390 
391  Reference < XDispatch > xDispatcher ;
392  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
393 
394  if( xParser.is() )
395  xParser->parseStrict( aURL );
396 
397  xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
398  SAL_WARN_IF(
399  !xDispatcher.is(), "desktop.app",
400  "unsupported dispatch request <" << aName << ">");
401  if( xDispatcher.is() )
402  {
403  {
404  osl::MutexGuard aGuard(m_mutex);
405  // Remember request so we can find it in statusChanged!
406  m_nRequestCount++;
407  }
408 
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 );
412  }
413  }
414  else if ( aName.startsWith( "service:" ) )
415  {
416  // TODO: the dispatch has to be done for loadComponentFromURL as well.
417  URL aURL ;
418  aURL.Complete = aName;
419 
420  Reference < XDispatch > xDispatcher ;
421  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
422 
423  if( xParser.is() )
424  xParser->parseStrict( aURL );
425 
426  xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
427 
428  if( xDispatcher.is() )
429  {
430  try
431  {
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
434  // window!!
435  Sequence < PropertyValue > aArgs2(1);
436  aArgs2[0].Name = "SynchronMode";
437  aArgs2[0].Value <<= true;
438  Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );
439  if ( xDisp.is() )
440  xDisp->dispatchWithNotification( aURL, aArgs2, this );
441  else
442  xDispatcher->dispatch( aURL, aArgs2 );
443  }
444  catch (const css::uno::Exception&)
445  {
447  "desktop.app",
448  "Desktop::OpenDefault() ignoring Exception while calling XNotifyingDispatch");
449  }
450  }
451  }
452  else
453  {
454  INetURLObject aObj( aName );
455  if ( aObj.GetProtocol() == INetProtocol::PrivSoffice )
456  aTarget = "_default";
457 
458  // Set "AsTemplate" argument according to request type
459  if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
460  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN )
461  {
462  aArgs.emplace_back("AsTemplate", 0,
463  Any(aDispatchRequest.aRequestType == REQUEST_FORCENEW),
464  PropertyState_DIRECT_VALUE);
465  }
466 
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);
470  }
471 
472  // if we are called with -start set Start in mediadescriptor
473  if(aDispatchRequest.aRequestType == REQUEST_START) {
474  aArgs.emplace_back("StartPresentation", 0, Any(true), PropertyState_DIRECT_VALUE);
475  }
476 
477  // Force input filter, if possible
478  if( bSetInputFilter )
479  {
480  sal_Int32 nFilterOptionsIndex = 0;
481  aArgs.emplace_back("FilterName", 0,
482  Any(aForcedInputFilter.getToken(0, ':', nFilterOptionsIndex)),
483  PropertyState_DIRECT_VALUE);
484 
485  if (0 < nFilterOptionsIndex)
486  {
487  aArgs.emplace_back("FilterOptions", 0,
488  Any(aForcedInputFilter.copy(nFilterOptionsIndex)),
489  PropertyState_DIRECT_VALUE);
490  }
491  }
492 
493  // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
494  try
495  {
497  xDesktop, aName, aTarget, comphelper::containerToSequence(aArgs)),
498  UNO_QUERY);
499  }
500  catch (const css::lang::IllegalArgumentException&)
501  {
503  "desktop.app",
504  "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL");
505  }
506  catch (const css::io::IOException&)
507  {
509  "desktop.app",
510  "Dispatchwatcher IOException while calling loadComponentFromURL");
511  }
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 )
517  {
518  // request is completed
520  }
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 )
527  {
528  if ( xDoc.is() )
529  {
530  // Do we need to save the document in a different format?
531  if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
532  aDispatchRequest.aRequestType == REQUEST_CAT )
533  {
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 )
542  nFilterIndex = -1;
543 
544  OUString aFilterOut;
545  OUString aImgOut;
546  OUString aFilter;
547  OUString aFilterExt;
548  bool bGuess = false;
549 
550  if( nFilterIndex >= 0 )
551  {
552  aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
553  aFilterExt = aParam.copy( 0, nFilterIndex );
554  }
555  else
556  {
557  // Guess
558  bGuess = true;
559  aFilterExt = aParam.copy( 0, nPathIndex );
560  }
561 
562  if( nImgFilterIndex >= 0 )
563  {
564  aImgOut = aParam.copy( nImgFilterIndex+1 );
565  aFilterOut = aParam.copy( nPathIndex+1, nImgFilterIndex-nPathIndex-1 );
566  }
567  else
568  aFilterOut = aParam.copy( nPathIndex+1 );
569 
570  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
571  INetURLObject aOutFilename(aFilterOut);
572  aOutFilename.Append(aObj.getName(INetURLObject::LAST_SEGMENT, true,
574  aOutFilename.SetExtension(aFilterExt);
575  OUString aOutFile
577 
578  std::unique_ptr<utl::TempFile> fileForCat;
579  if( aDispatchRequest.aRequestType == REQUEST_CAT )
580  {
581  fileForCat = std::make_unique<utl::TempFile>();
582  if (fileForCat->IsValid())
583  fileForCat->EnableKillingFile();
584  else
585  std::cerr << "Error: Cannot create temporary file..." << std::endl ;
586  aOutFile = fileForCat->GetURL();
587  }
588 
589  if ( bGuess )
590  {
591  OUString aDocService;
592  Reference< XModel > xModel( xDoc, UNO_QUERY );
593  if ( xModel.is() )
594  {
595  utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
596  aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
597  }
598  aFilter = impl_GuessFilter( aOutFile, aDocService );
599  }
600 
601  if (aFilter.isEmpty())
602  {
603  std::cerr << "Error: no export filter" << std::endl;
604  }
605  else
606  {
607  sal_Int32 nFilterOptionsIndex = aFilter.indexOf(':');
608  sal_Int32 nProps = ( 0 < nFilterOptionsIndex ) ? 3 : 2;
609 
610  if ( !aImgOut.isEmpty() )
611  nProps +=1;
612  Sequence<PropertyValue> conversionProperties( nProps );
613  conversionProperties[0].Name = "Overwrite";
614  conversionProperties[0].Value <<= true;
615 
616  conversionProperties[1].Name = "FilterName";
617  if( 0 < nFilterOptionsIndex )
618  {
619  conversionProperties[1].Value <<= aFilter.copy(0, nFilterOptionsIndex);
620 
621  conversionProperties[2].Name = "FilterOptions";
622  conversionProperties[2].Value <<= aFilter.copy(nFilterOptionsIndex + 1);
623  }
624  else
625  {
626  conversionProperties[1].Value <<= aFilter;
627  }
628 
629  if ( !aImgOut.isEmpty() )
630  {
631  conversionProperties[nProps-1].Name = "ImageFilter";
632  conversionProperties[nProps-1].Value <<= aImgOut;
633  }
634 
635  OUString aTempName;
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)
641  {
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 ;
646  }
647  try
648  {
649  xStorable->storeToURL(aOutFile, conversionProperties);
650  }
651  catch (const Exception& rException)
652  {
653  std::cerr << "Error: Please verify input parameters...";
654  if (!rException.Message.isEmpty())
655  std::cerr << " (" << rException.Message << ")";
656  std::cerr << std::endl;
657  }
658 
659  if (fileForCat && fileForCat->IsValid())
660  {
661  SvStream* aStream = fileForCat->GetStream(StreamMode::STD_READ);
662  while (aStream->good())
663  {
664  OString aStr;
665  aStream->ReadLine(aStr, SAL_MAX_INT32);
666  for (sal_Int32 i = 0; i < aStr.getLength(); ++i)
667  {
668  std::cout << aStr[i];
669  }
670  std::cout << std::endl;
671  }
672  }
673  }
674  }
675  }
676  else if ( aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
677  {
678  Reference< XModel > xModel( xDoc, UNO_QUERY );
679  if( xModel.is() )
680  scriptCat( xModel );
681  }
682  else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT )
683  {
684  batchPrint( aDispatchRequest.aPrinterName, xDoc, aObj, aName );
685  }
686  else
687  {
688  if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
689  {
690  // create the printer
691  Sequence < PropertyValue > aPrinterArgs( 1 );
692  aPrinterArgs[0].Name = "Name";
693  aPrinterArgs[0].Value <<= aDispatchRequest.aPrinterName;
694  xDoc->setPrinter( aPrinterArgs );
695  }
696 
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 );
702  }
703  }
704  else
705  {
706  std::cerr << "Error: source file could not be loaded" << std::endl;
707  }
708 
709  // remove the document
710  try
711  {
712  Reference < XCloseable > xClose( xDoc, UNO_QUERY );
713  if ( xClose.is() )
714  xClose->close( true );
715  else
716  {
717  Reference < XComponent > xComp( xDoc, UNO_QUERY );
718  if ( xComp.is() )
719  xComp->dispose();
720  }
721  }
722  catch (const css::util::CloseVetoException&)
723  {
724  }
725 
726  // request is completed
728  }
729  }
730  }
731 
732  if ( !aDispatches.empty() )
733  {
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;
740 
741  for (const DispatchHolder & aDispatche : aDispatches)
742  {
743  Reference< XDispatch > xDispatch = aDispatche.xDispatch;
744  Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );
745  if ( xDisp.is() )
746  xDisp->dispatchWithNotification( aDispatche.aURL, aArgs, this );
747  else
748  {
749  {
750  osl::MutexGuard aGuard(m_mutex);
751  m_nRequestCount--;
752  }
753  xDispatch->dispatch( aDispatche.aURL, aArgs );
754  }
755  }
756  }
757 
758  ::osl::ClearableMutexGuard aGuard(m_mutex);
759  bool bEmpty = (m_nRequestCount == 0);
760  aGuard.clear();
761 
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()*/ )
766  {
767  // We have to check if we have an open task otherwise we have to shutdown the office.
768  Reference< XElementAccess > xList = xDesktop->getFrames();
769 
770  if ( !xList->hasElements() )
771  {
772  // We don't have any task open so we have to shutdown ourself!!
773  return xDesktop->terminate();
774  }
775  }
776 
777  return false;
778 }
779 
780 
781 void SAL_CALL DispatchWatcher::disposing( const css::lang::EventObject& )
782 {
783 }
784 
785 
786 void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& )
787 {
788  osl::ClearableMutexGuard aGuard(m_mutex);
789  sal_Int16 nCount = --m_nRequestCount;
790  aGuard.clear();
792  if ( !nCount && !RequestHandler::AreRequestsPending() )
793  {
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();
797 
798  if ( !xList->hasElements() )
799  {
800  // We don't have any task open so we have to shutdown ourself!!
801  xDesktop->terminate();
802  }
803  }
804 }
805 
806 } // namespace desktop
807 
808 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SVL_DLLPUBLIC bool IsDocument(const OUString &rURL)
URL aURL
OUString GetURL_Impl(const OUString &rName, std::optional< OUString > const &cwdUrl)
Definition: app.cxx:2211
#define SFX_FILTER_NOTINSTALLED
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
Definition: app.cxx:161
bool ReadLine(OString &rStr, sal_Int32 nMaxBytesToRead=0xFFFE)
int nCount
static COMPHELPER_DLLPUBLIC css::uno::Reference< css::lang::XComponent > dispatch(const css::uno::Reference< css::uno::XInterface > &xStartPoint, const OUString &sURL, const OUString &sTarget, const css::uno::Sequence< css::beans::PropertyValue > &lArguments)
void SetExtension(OUString const &rTheExtension)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define SAL_MAX_INT32
static bool AreRequestsPending()
int i
bool Append(OUString const &rTheSegment, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
OUString getName(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static std::shared_ptr< const SfxFilter > GetFilterByName(const OUString &rName)
OString OUStringToOString(const OUString &str, ConnectionSettings const *settings)
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2142
Reference< XDispatch > xDispatch
#define SAL_WARN_IF(condition, area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OUString aName
INetProtocol GetProtocol() const
Reference< XComponentContext > getProcessComponentContext()
bool good() const
Reference< XModel > xModel
virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent &aEvent) override
static const OUString & PROP_DOCUMENTSERVICE()
aStr
virtual ~DispatchWatcher() override
bool executeDispatchRequests(const std::vector< DispatchRequest > &aDispatches, bool bNoTerminate)