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 <sfx2/app.hxx>
27 #include <svl/fstathelper.hxx>
28 
29 #include <app.hxx>
30 #include "dispatchwatcher.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/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>
56 
57 #include <comphelper/sequence.hxx>
58 #include <tools/diagnose_ex.h>
59 #include <tools/urlobj.hxx>
61 #include <unotools/tempfile.hxx>
62 
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>
69 
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;
80 
81 namespace document = ::com::sun::star::document;
82 
83 namespace desktop
84 {
85 
87 {
88  DispatchHolder( const URL& rURL, Reference< XDispatch > const & rDispatch ) :
89  aURL( rURL ), xDispatch( rDispatch ) {}
90 
93 };
94 
95 namespace
96 {
97 
98 std::shared_ptr<const SfxFilter> impl_lookupExportFilterForUrl( const OUString& rUrl, const OUString& rFactory )
99 {
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)));
109 
111  const Reference< XContainerQuery > xFilterFactory(
112  xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
113  UNO_QUERY_THROW );
114 
115  std::shared_ptr<const SfxFilter> pBestMatch;
116 
117  const Reference< XEnumeration > xFilterEnum(
118  xFilterFactory->createSubSetEnumerationByQuery( sQuery.makeStringAndClear() ), UNO_SET_THROW );
119  while ( xFilterEnum->hasMoreElements() )
120  {
121  comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
122  const OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", OUString() ) );
123  if ( !aName.isEmpty() )
124  {
125  std::shared_ptr<const SfxFilter> pFilter( SfxFilter::GetFilterByName( aName ) );
126  if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
127  {
128  if ( !pBestMatch || ( SfxFilterFlags::PREFERED & pFilter->GetFilterFlags() ) )
129  pBestMatch = pFilter;
130  }
131  }
132  }
133 
134  return pBestMatch;
135 }
136 
137 std::shared_ptr<const SfxFilter> impl_getExportFilterFromUrl(
138  const OUString& rUrl, const OUString& rFactory)
139 {
140  try
141  {
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 ) );
147 
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 )
152  {
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;
157  }
158 
159  return pFilter;
160  }
161  catch ( const Exception& )
162  {
163  return nullptr;
164  }
165 }
166 
167 OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
168 {
169  OUString aOutFilter;
170  std::shared_ptr<const SfxFilter> pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
171  if (pOutFilter)
172  aOutFilter = pOutFilter->GetFilterName();
173 
174  return aOutFilter;
175 }
176 
178 void scriptCat(const Reference< XModel >& xDoc )
179 {
180  Reference< XEmbeddedScripts > xScriptAccess( xDoc, UNO_QUERY );
181  if (!xScriptAccess)
182  {
183  std::cout << "No script access\n";
184  return;
185  }
186 
187  // ignore xScriptAccess->getDialogLibraries() for now
188  Reference< css::script::XLibraryContainer2 > xLibraries(
189  xScriptAccess->getBasicLibraries() );
190 
191  if ( !xLibraries.is() )
192  {
193  std::cout << "No script libraries\n";
194  return;
195  }
196 
197  Sequence< OUString > aLibNames = xLibraries->getElementNames();
198  std::cout << "Libraries: " << aLibNames.getLength() << "\n";
199  for ( sal_Int32 i = 0 ; i < aLibNames.getLength() ; ++i )
200  {
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 );
208  }
209  catch (const css::uno::Exception &e)
210  {
211  std::cout << "[" << aLibNames[i] << "] - failed to load library: " << e.Message << "\n";
212  continue;
213  }
214  if( !xContainer.is() )
215  std::cout << "0\n";
216  else
217  {
218  Sequence< OUString > aObjectNames = xContainer->getElementNames();
219 
220  std::cout << aObjectNames.getLength() << "\n\n";
221  for ( sal_Int32 j = 0 ; j < aObjectNames.getLength() ; ++j )
222  {
223  OUString &rObjectName = aObjectNames[j];
224 
225  OUString aCodeString;
226  try
227  {
228  Any aCode = xContainer->getByName( rObjectName );
229 
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";
236  }
237  catch (const css::uno::Exception &e)
238  {
239  std::cout << "[" << rObjectName << "] - exception " << e.Message << " fetching code\n";
240  }
241 
242  if (j < aObjectNames.getLength() - 1)
243  std::cout << "\n----------------------------------------------------------\n";
244  std::cout << "\n";
245  }
246  }
247  }
248 }
249 
250 // Perform batch print
251 void batchPrint( const OUString &rPrinterName, const Reference< XPrintable > &xDoc,
252  const INetURLObject &aObj, const OUString &aName )
253 {
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 );
261 
262  INetURLObject aOutFilename( aObj );
263  aOutFilename.SetExtension( "ps" );
264  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
265  OUString aOutFile = aFilterOut + "/" + aOutFilename.getName();
266 
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() );
272 
273  std::cout << "print " << aSource8 << " -> " << aTargetURL8;
274  std::cout << " using " << (aPrinterName.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName, osl_getThreadTextEncoding() ));
275  std::cout << std::endl;
276 
277  // create the custom printer, if given
278  Sequence < PropertyValue > aPrinterArgs( 1 );
279  if( !aPrinterName.isEmpty() )
280  {
281  aPrinterArgs[0].Name = "Name";
282  aPrinterArgs[0].Value <<= aPrinterName;
283  xDoc->setPrinter( aPrinterArgs );
284  }
285 
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 );
293 }
294 
295 } // anonymous namespace
296 
298  : m_nRequestCount(0)
299 {
300 }
301 
302 
304 {
305 }
306 
307 
308 bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest>& aDispatchRequestsList, bool bNoTerminate )
309 {
310  Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
311 
312  std::vector< DispatchHolder > aDispatches;
313  bool bSetInputFilter = false;
314  OUString aForcedInputFilter;
315 
316  for (auto const & aDispatchRequest: aDispatchRequestsList)
317  {
318  // Set Input Filter
319  if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
320  {
321  bSetInputFilter = true;
322  aForcedInputFilter = aDispatchRequest.aURL;
324  continue;
325  }
326 
327  // create parameter array
328  std::vector<PropertyValue> aArgs;
329 
330  // mark request as user interaction from outside
331  aArgs.emplace_back("Referer", 0, Any(OUString("private:OpenEvent")),
332  PropertyState_DIRECT_VALUE);
333 
334  OUString aTarget("_default");
335 
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)
342  {
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);
352 
353  // hidden documents should never be put into open tasks
354  aTarget = "_blank";
355  }
356  else
357  {
358  Reference < XInteractionHandler2 > xInteraction(
359  InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
360 
361  aArgs.emplace_back("InteractionHandler", 0, Any(xInteraction),
362  PropertyState_DIRECT_VALUE);
363 
364  aArgs.emplace_back("MacroExecutionMode", 0,
365  Any(css::document::MacroExecMode::USE_CONFIG),
366  PropertyState_DIRECT_VALUE);
367 
368  aArgs.emplace_back("UpdateDocMode", 0,
369  Any(css::document::UpdateDocMode::ACCORDING_TO_CONFIG),
370  PropertyState_DIRECT_VALUE);
371  }
372 
373  if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
374  {
375  aArgs.emplace_back(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), 0,
376  Any(aDispatchRequest.aPreselectedFactory),
377  PropertyState_DIRECT_VALUE);
378  }
379 
380  OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
381 
382  // load the document ... if they are loadable!
383  // Otherwise try to dispatch it ...
384  Reference < XPrintable > xDoc;
385  if(
386  ( aName.startsWith( ".uno" ) ) ||
387  ( aName.startsWith( "slot:" ) ) ||
388  ( aName.startsWith( "macro:" ) ) ||
389  ( aName.startsWith("vnd.sun.star.script") )
390  )
391  {
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;
396 
397  Reference < XDispatch > xDispatcher ;
398  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
399 
400  if( xParser.is() )
401  xParser->parseStrict( aURL );
402 
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() )
408  {
409  {
410  osl::MutexGuard aGuard(m_mutex);
411  // Remember request so we can find it in statusChanged!
412  m_nRequestCount++;
413  }
414 
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 );
418  }
419  }
420  else if ( aName.startsWith( "service:" ) )
421  {
422  // TODO: the dispatch has to be done for loadComponentFromURL as well.
423  URL aURL ;
424  aURL.Complete = aName;
425 
426  Reference < XDispatch > xDispatcher ;
427  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
428 
429  if( xParser.is() )
430  xParser->parseStrict( aURL );
431 
432  xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
433 
434  if( xDispatcher.is() )
435  {
436  try
437  {
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 );
449  }
450  catch (const css::uno::Exception&)
451  {
453  "desktop.app",
454  "Desktop::OpenDefault() ignoring Exception while calling XNotifyingDispatch");
455  }
456  }
457  }
458  else
459  {
460  INetURLObject aObj( aName );
461  if ( aObj.GetProtocol() == INetProtocol::PrivSoffice )
462  aTarget = "_default";
463 
464  // Set "AsTemplate" argument according to request type
465  if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
466  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN )
467  {
468  aArgs.emplace_back("AsTemplate", 0,
469  Any(aDispatchRequest.aRequestType == REQUEST_FORCENEW),
470  PropertyState_DIRECT_VALUE);
471  }
472 
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);
476  }
477 
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);
481  }
482 
483  // Force input filter, if possible
484  if( bSetInputFilter )
485  {
486  sal_Int32 nFilterOptionsIndex = 0;
487  aArgs.emplace_back("FilterName", 0,
488  Any(aForcedInputFilter.getToken(0, ':', nFilterOptionsIndex)),
489  PropertyState_DIRECT_VALUE);
490 
491  if (0 < nFilterOptionsIndex)
492  {
493  aArgs.emplace_back("FilterOptions", 0,
494  Any(aForcedInputFilter.copy(nFilterOptionsIndex)),
495  PropertyState_DIRECT_VALUE);
496  }
497  }
498 
499  // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
500  try
501  {
503  xDesktop, aName, aTarget, comphelper::containerToSequence(aArgs)),
504  UNO_QUERY);
505  }
506  catch (const css::lang::IllegalArgumentException&)
507  {
509  "desktop.app",
510  "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL");
511  }
512  catch (const css::io::IOException&)
513  {
515  "desktop.app",
516  "Dispatchwatcher IOException while calling loadComponentFromURL");
517  }
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 )
523  {
524  // request is completed
526  }
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 )
533  {
534  if ( xDoc.is() )
535  {
536  // Do we need to save the document in a different format?
537  if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
538  aDispatchRequest.aRequestType == REQUEST_CAT )
539  {
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;
549 
550  OUString aFilterOut;
551  OUString aImgOut;
552  OUString aFilter;
553  OUString aFilterExt;
554  bool bGuess = false;
555 
556  if( nFilterIndex >= 0 )
557  {
558  aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
559  aFilterExt = aParam.copy( 0, nFilterIndex );
560  }
561  else
562  {
563  // Guess
564  bGuess = true;
565  aFilterExt = aParam.copy( 0, nPathIndex );
566  }
567 
568  if( nImgFilterIndex >= 0 )
569  {
570  aImgOut = aParam.copy( nImgFilterIndex+1 );
571  aFilterOut = aParam.copy( nPathIndex+1, nImgFilterIndex-nPathIndex-1 );
572  }
573  else
574  aFilterOut = aParam.copy( nPathIndex+1 );
575 
576  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
577  INetURLObject aOutFilename(aFilterOut);
578  aOutFilename.Append(aObj.getName(INetURLObject::LAST_SEGMENT, true,
580  aOutFilename.SetExtension(aFilterExt);
581  OUString aOutFile
583 
584  std::unique_ptr<utl::TempFile> fileForCat;
585  if( aDispatchRequest.aRequestType == REQUEST_CAT )
586  {
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();
593  }
594 
595  if ( bGuess )
596  {
597  OUString aDocService;
598  Reference< XModel > xModel( xDoc, UNO_QUERY );
599  if ( xModel.is() )
600  {
601  utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
602  aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
603  }
604  aFilter = impl_GuessFilter( aOutFile, aDocService );
605  }
606 
607  if (aFilter.isEmpty())
608  {
609  std::cerr << "Error: no export filter" << std::endl;
610  }
611  else
612  {
613  sal_Int32 nFilterOptionsIndex = aFilter.indexOf(':');
614  sal_Int32 nProps = ( 0 < nFilterOptionsIndex ) ? 3 : 2;
615 
616  if ( !aImgOut.isEmpty() )
617  nProps +=1;
618  Sequence<PropertyValue> conversionProperties( nProps );
619  conversionProperties[0].Name = "Overwrite";
620  conversionProperties[0].Value <<= true;
621 
622  conversionProperties[1].Name = "FilterName";
623  if( 0 < nFilterOptionsIndex )
624  {
625  conversionProperties[1].Value <<= aFilter.copy(0, nFilterOptionsIndex);
626 
627  conversionProperties[2].Name = "FilterOptions";
628  conversionProperties[2].Value <<= aFilter.copy(nFilterOptionsIndex + 1);
629  }
630  else
631  {
632  conversionProperties[1].Value <<= aFilter;
633  }
634 
635  if ( !aImgOut.isEmpty() )
636  {
637  conversionProperties[nProps-1].Name = "ImageFilter";
638  conversionProperties[nProps-1].Value <<= aImgOut;
639  }
640 
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)
647  {
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 ;
652  }
653  try
654  {
655  xStorable->storeToURL(aOutFile, conversionProperties);
656  }
657  catch (const Exception& rException)
658  {
659  std::cerr << "Error: Please verify input parameters...";
660  if (!rException.Message.isEmpty())
661  std::cerr << " (" << rException.Message << ")";
662  std::cerr << std::endl;
663  }
664 
665  if (fileForCat && fileForCat->IsValid())
666  {
667  SvStream* aStream = fileForCat->GetStream(StreamMode::STD_READ);
668  while (aStream->good())
669  {
670  OString aStr;
671  aStream->ReadLine(aStr, SAL_MAX_INT32);
672  for (sal_Int32 i = 0; i < aStr.getLength(); ++i)
673  {
674  std::cout << aStr[i];
675  }
676  std::cout << std::endl;
677  }
678  }
679  }
680  }
681  }
682  else if ( aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
683  {
684  Reference< XModel > xModel( xDoc, UNO_QUERY );
685  if( xModel.is() )
686  scriptCat( xModel );
687  }
688  else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT )
689  {
690  batchPrint( aDispatchRequest.aPrinterName, xDoc, aObj, aName );
691  }
692  else
693  {
694  if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
695  {
696  // create the printer
697  Sequence < PropertyValue > aPrinterArgs( 1 );
698  aPrinterArgs[0].Name = "Name";
699  aPrinterArgs[0].Value <<= aDispatchRequest.aPrinterName;
700  xDoc->setPrinter( aPrinterArgs );
701  }
702 
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 );
708  }
709  }
710  else
711  {
712  std::cerr << "Error: source file could not be loaded" << std::endl;
713  }
714 
715  // remove the document
716  try
717  {
718  Reference < XCloseable > xClose( xDoc, UNO_QUERY );
719  if ( xClose.is() )
720  xClose->close( true );
721  else
722  {
723  Reference < XComponent > xComp( xDoc, UNO_QUERY );
724  if ( xComp.is() )
725  xComp->dispose();
726  }
727  }
728  catch (const css::util::CloseVetoException&)
729  {
730  }
731 
732  // request is completed
734  }
735  }
736  }
737 
738  if ( !aDispatches.empty() )
739  {
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;
746 
747  for (const DispatchHolder & aDispatche : aDispatches)
748  {
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
754  {
755  {
756  osl::MutexGuard aGuard(m_mutex);
757  m_nRequestCount--;
758  }
759  xDispatch->dispatch( aDispatche.aURL, aArgs );
760  }
761  }
762  }
763 
764  ::osl::ClearableMutexGuard aGuard(m_mutex);
765  bool bEmpty = (m_nRequestCount == 0);
766  aGuard.clear();
767 
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()*/ )
772  {
773  // We have to check if we have an open task otherwise we have to shutdown the office.
774  Reference< XElementAccess > xList = xDesktop->getFrames();
775 
776  if ( !xList->hasElements() )
777  {
778  // We don't have any task open so we have to shutdown ourself!!
779  return xDesktop->terminate();
780  }
781  }
782 
783  return false;
784 }
785 
786 
787 void SAL_CALL DispatchWatcher::disposing( const css::lang::EventObject& )
788 {
789 }
790 
791 
792 void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& )
793 {
794  osl::ClearableMutexGuard aGuard(m_mutex);
795  sal_Int16 nCount = --m_nRequestCount;
796  aGuard.clear();
798  if ( !nCount && !RequestHandler::AreRequestsPending() )
799  {
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();
803 
804  if ( !xList->hasElements() )
805  {
806  // We don't have any task open so we have to shutdown ourself!!
807  xDesktop->terminate();
808  }
809  }
810 }
811 
812 } // namespace desktop
813 
814 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SVL_DLLPUBLIC bool IsDocument(const OUString &rURL)
#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:168
bool ReadLine(OString &rStr, sal_Int32 nMaxBytesToRead=0xFFFE)
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()
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
int i
DispatchHolder(const URL &rURL, Reference< XDispatch > const &rDispatch)
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:1798
#define SAL_WARN_IF(condition, area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
INetProtocol GetProtocol() const
Reference< XComponentContext > getProcessComponentContext()
bool good() const
OString const aName
Reference< XModel > xModel
virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent &aEvent) override
static const OUString & PROP_DOCUMENTSERVICE()
OUString GetURL_Impl(const OUString &rName, boost::optional< OUString > const &cwdUrl)
Definition: app.cxx:2225
Reference< XDispatch > xDispatch
aStr
virtual ~DispatchWatcher() override
bool executeDispatchRequests(const std::vector< DispatchRequest > &aDispatches, bool bNoTerminate)