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 
86 namespace {
87 
88 struct DispatchHolder
89 {
90  DispatchHolder( const URL& rURL, Reference< XDispatch > const & rDispatch ) :
91  aURL( rURL ), xDispatch( rDispatch ) {}
92 
94  Reference< XDispatch > xDispatch;
95 };
96 
97 std::shared_ptr<const SfxFilter> impl_lookupExportFilterForUrl( const OUString& rUrl, const OUString& rFactory )
98 {
99  // create the list of filters
100  OUStringBuffer sQuery(256);
101  sQuery.append("getSortedFilterList()");
102  sQuery.append(":module=");
103  sQuery.append(rFactory); // use long name here !
104  sQuery.append(":iflags=");
105  sQuery.append(OUString::number(static_cast<sal_Int32>(SfxFilterFlags::EXPORT)));
106  sQuery.append(":eflags=");
107  sQuery.append(OUString::number(static_cast<int>(SFX_FILTER_NOTINSTALLED)));
108 
110  const Reference< XContainerQuery > xFilterFactory(
111  xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
112  UNO_QUERY_THROW );
113 
114  std::shared_ptr<const SfxFilter> pBestMatch;
115 
116  const Reference< XEnumeration > xFilterEnum(
117  xFilterFactory->createSubSetEnumerationByQuery( sQuery.makeStringAndClear() ), UNO_SET_THROW );
118  while ( xFilterEnum->hasMoreElements() )
119  {
120  comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
121  const OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", OUString() ) );
122  if ( !aName.isEmpty() )
123  {
124  std::shared_ptr<const SfxFilter> pFilter( SfxFilter::GetFilterByName( aName ) );
125  if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
126  {
127  if ( !pBestMatch || ( SfxFilterFlags::PREFERED & pFilter->GetFilterFlags() ) )
128  pBestMatch = pFilter;
129  }
130  }
131  }
132 
133  return pBestMatch;
134 }
135 
136 std::shared_ptr<const SfxFilter> impl_getExportFilterFromUrl(
137  const OUString& rUrl, const OUString& rFactory)
138 {
139  try
140  {
142  const Reference< document::XTypeDetection > xTypeDetector(
143  xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext ),
144  UNO_QUERY_THROW );
145  const OUString aTypeName( xTypeDetector->queryTypeByURL( rUrl ) );
146 
147  std::shared_ptr<const SfxFilter> pFilter( SfxFilterMatcher( rFactory ).GetFilter4EA( aTypeName, SfxFilterFlags::EXPORT ) );
148  if ( !pFilter )
149  pFilter = impl_lookupExportFilterForUrl( rUrl, rFactory );
150  if ( !pFilter )
151  {
152  OUString aTempName;
153  FileBase::getSystemPathFromFileURL( rUrl, aTempName );
154  OString aSource = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
155  std::cerr << "Error: no export filter for " << aSource << " found, aborting." << std::endl;
156  }
157 
158  return pFilter;
159  }
160  catch ( const Exception& )
161  {
162  return nullptr;
163  }
164 }
165 
166 OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
167 {
168  OUString aOutFilter;
169  std::shared_ptr<const SfxFilter> pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
170  if (pOutFilter)
171  aOutFilter = pOutFilter->GetFilterName();
172 
173  return aOutFilter;
174 }
175 
177 void scriptCat(const Reference< XModel >& xDoc )
178 {
179  Reference< XEmbeddedScripts > xScriptAccess( xDoc, UNO_QUERY );
180  if (!xScriptAccess)
181  {
182  std::cout << "No script access\n";
183  return;
184  }
185 
186  // ignore xScriptAccess->getDialogLibraries() for now
187  Reference< css::script::XLibraryContainer2 > xLibraries(
188  xScriptAccess->getBasicLibraries() );
189 
190  if ( !xLibraries.is() )
191  {
192  std::cout << "No script libraries\n";
193  return;
194  }
195 
196  Sequence< OUString > aLibNames = xLibraries->getElementNames();
197  std::cout << "Libraries: " << aLibNames.getLength() << "\n";
198  for ( sal_Int32 i = 0 ; i < aLibNames.getLength() ; ++i )
199  {
200  std::cout << "Library: '" << aLibNames[i] << "' children: ";
201  Reference< XNameContainer > xContainer;
202  try {
203  if (!xLibraries->isLibraryLoaded( aLibNames[i] ))
204  xLibraries->loadLibrary( aLibNames[i] );
205  xContainer = Reference< XNameContainer >(
206  xLibraries->getByName( aLibNames[i] ), UNO_QUERY );
207  }
208  catch (const css::uno::Exception &e)
209  {
210  std::cout << "[" << aLibNames[i] << "] - failed to load library: " << e.Message << "\n";
211  continue;
212  }
213  if( !xContainer.is() )
214  std::cout << "0\n";
215  else
216  {
217  Sequence< OUString > aObjectNames = xContainer->getElementNames();
218 
219  std::cout << aObjectNames.getLength() << "\n\n";
220  for ( sal_Int32 j = 0 ; j < aObjectNames.getLength() ; ++j )
221  {
222  OUString &rObjectName = aObjectNames[j];
223 
224  OUString aCodeString;
225  try
226  {
227  Any aCode = xContainer->getByName( rObjectName );
228 
229  if (! (aCode >>= aCodeString ) )
230  std::cout << "[" << rObjectName << "] - error fetching code\n";
231  else
232  std::cout << "[" << rObjectName << "]\n"
233  << aCodeString.trim()
234  << "\n[/" << rObjectName << "]\n";
235  }
236  catch (const css::uno::Exception &e)
237  {
238  std::cout << "[" << rObjectName << "] - exception " << e.Message << " fetching code\n";
239  }
240 
241  if (j < aObjectNames.getLength() - 1)
242  std::cout << "\n----------------------------------------------------------\n";
243  std::cout << "\n";
244  }
245  }
246  }
247 }
248 
249 // Perform batch print
250 void batchPrint( const OUString &rPrinterName, const Reference< XPrintable > &xDoc,
251  const INetURLObject &aObj, const OUString &aName )
252 {
253  OUString aFilterOut;
254  OUString aPrinterName;
255  sal_Int32 nPathIndex = rPrinterName.lastIndexOf( ';' );
256  if( nPathIndex != -1 )
257  aFilterOut=rPrinterName.copy( nPathIndex+1 );
258  if( nPathIndex != 0 )
259  aPrinterName=rPrinterName.copy( 0, nPathIndex );
260 
261  INetURLObject aOutFilename( aObj );
262  aOutFilename.SetExtension( "ps" );
263  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
264  OUString aOutFile = aFilterOut + "/" + aOutFilename.getName();
265 
266  OUString aTempName;
267  FileBase::getSystemPathFromFileURL( aName, aTempName );
268  OString aSource8 = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
269  FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
270  OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding() );
271 
272  std::cout << "print " << aSource8 << " -> " << aTargetURL8;
273  std::cout << " using " << (aPrinterName.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName, osl_getThreadTextEncoding() ));
274  std::cout << std::endl;
275 
276  // create the custom printer, if given
277  Sequence < PropertyValue > aPrinterArgs( 1 );
278  if( !aPrinterName.isEmpty() )
279  {
280  aPrinterArgs[0].Name = "Name";
281  aPrinterArgs[0].Value <<= aPrinterName;
282  xDoc->setPrinter( aPrinterArgs );
283  }
284 
285  // print ( also without user interaction )
286  aPrinterArgs.realloc(2);
287  aPrinterArgs[0].Name = "FileName";
288  aPrinterArgs[0].Value <<= aOutFile;
289  aPrinterArgs[1].Name = "Wait";
290  aPrinterArgs[1].Value <<= true;
291  xDoc->print( aPrinterArgs );
292 }
293 
294 } // anonymous namespace
295 
297  : m_nRequestCount(0)
298 {
299 }
300 
301 
303 {
304 }
305 
306 
307 bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest>& aDispatchRequestsList, bool bNoTerminate )
308 {
309  Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
310 
311  std::vector< DispatchHolder > aDispatches;
312  bool bSetInputFilter = false;
313  OUString aForcedInputFilter;
314 
315  for (auto const & aDispatchRequest: aDispatchRequestsList)
316  {
317  // Set Input Filter
318  if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
319  {
320  bSetInputFilter = true;
321  aForcedInputFilter = aDispatchRequest.aURL;
323  continue;
324  }
325 
326  // create parameter array
327  std::vector<PropertyValue> aArgs;
328 
329  // mark request as user interaction from outside
330  aArgs.emplace_back("Referer", 0, Any(OUString("private:OpenEvent")),
331  PropertyState_DIRECT_VALUE);
332 
333  OUString aTarget("_default");
334 
335  if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
336  aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
337  aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
338  aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
339  aDispatchRequest.aRequestType == REQUEST_CAT ||
340  aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT)
341  {
342  // documents opened for printing are opened readonly because they must be opened as a
343  // new document and this document could be open already
344  aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
345  // always open a new document for printing, because it must be disposed afterwards
346  aArgs.emplace_back("OpenNewView", 0, Any(true), PropertyState_DIRECT_VALUE);
347  // printing is done in a hidden view
348  aArgs.emplace_back("Hidden", 0, Any(true), PropertyState_DIRECT_VALUE);
349  // load document for printing without user interaction
350  aArgs.emplace_back("Silent", 0, Any(true), PropertyState_DIRECT_VALUE);
351 
352  // hidden documents should never be put into open tasks
353  aTarget = "_blank";
354  }
355  else
356  {
357  Reference < XInteractionHandler2 > xInteraction(
358  InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
359 
360  aArgs.emplace_back("InteractionHandler", 0, Any(xInteraction),
361  PropertyState_DIRECT_VALUE);
362 
363  aArgs.emplace_back("MacroExecutionMode", 0,
364  Any(css::document::MacroExecMode::USE_CONFIG),
365  PropertyState_DIRECT_VALUE);
366 
367  aArgs.emplace_back("UpdateDocMode", 0,
368  Any(css::document::UpdateDocMode::ACCORDING_TO_CONFIG),
369  PropertyState_DIRECT_VALUE);
370  }
371 
372  if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
373  {
374  aArgs.emplace_back(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), 0,
375  Any(aDispatchRequest.aPreselectedFactory),
376  PropertyState_DIRECT_VALUE);
377  }
378 
379  OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
380 
381  // load the document ... if they are loadable!
382  // Otherwise try to dispatch it ...
383  Reference < XPrintable > xDoc;
384  if(
385  ( aName.startsWith( ".uno" ) ) ||
386  ( aName.startsWith( "slot:" ) ) ||
387  ( aName.startsWith( "macro:" ) ) ||
388  ( aName.startsWith("vnd.sun.star.script") )
389  )
390  {
391  // Attention: URL must be parsed full. Otherwise some detections on it will fail!
392  // It doesn't matter, if parser isn't available. Because; We try loading of URL then ...
393  URL aURL ;
394  aURL.Complete = aName;
395 
396  Reference < XDispatch > xDispatcher ;
397  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
398 
399  if( xParser.is() )
400  xParser->parseStrict( aURL );
401 
402  xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
403  SAL_WARN_IF(
404  !xDispatcher.is(), "desktop.app",
405  "unsupported dispatch request <" << aName << ">");
406  if( xDispatcher.is() )
407  {
408  {
409  osl::MutexGuard aGuard(m_mutex);
410  // Remember request so we can find it in statusChanged!
411  m_nRequestCount++;
412  }
413 
414  // Use local vector to store dispatcher because we have to fill our request container before
415  // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!
416  aDispatches.emplace_back( aURL, xDispatcher );
417  }
418  }
419  else if ( aName.startsWith( "service:" ) )
420  {
421  // TODO: the dispatch has to be done for loadComponentFromURL as well.
422  URL aURL ;
423  aURL.Complete = aName;
424 
425  Reference < XDispatch > xDispatcher ;
426  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
427 
428  if( xParser.is() )
429  xParser->parseStrict( aURL );
430 
431  xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
432 
433  if( xDispatcher.is() )
434  {
435  try
436  {
437  // We have to be listener to catch errors during dispatching URLs.
438  // Otherwise it would be possible to have an office running without an open
439  // window!!
440  Sequence < PropertyValue > aArgs2(1);
441  aArgs2[0].Name = "SynchronMode";
442  aArgs2[0].Value <<= true;
443  Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );
444  if ( xDisp.is() )
445  xDisp->dispatchWithNotification( aURL, aArgs2, this );
446  else
447  xDispatcher->dispatch( aURL, aArgs2 );
448  }
449  catch (const css::uno::Exception&)
450  {
452  "desktop.app",
453  "Desktop::OpenDefault() ignoring Exception while calling XNotifyingDispatch");
454  }
455  }
456  }
457  else
458  {
459  INetURLObject aObj( aName );
460  if ( aObj.GetProtocol() == INetProtocol::PrivSoffice )
461  aTarget = "_default";
462 
463  // Set "AsTemplate" argument according to request type
464  if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
465  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN )
466  {
467  aArgs.emplace_back("AsTemplate", 0,
468  Any(aDispatchRequest.aRequestType == REQUEST_FORCENEW),
469  PropertyState_DIRECT_VALUE);
470  }
471 
472  // if we are called in viewmode, open document read-only
473  if(aDispatchRequest.aRequestType == REQUEST_VIEW) {
474  aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
475  }
476 
477  // if we are called with -start set Start in mediadescriptor
478  if(aDispatchRequest.aRequestType == REQUEST_START) {
479  aArgs.emplace_back("StartPresentation", 0, Any(true), PropertyState_DIRECT_VALUE);
480  }
481 
482  // Force input filter, if possible
483  if( bSetInputFilter )
484  {
485  sal_Int32 nFilterOptionsIndex = 0;
486  aArgs.emplace_back("FilterName", 0,
487  Any(aForcedInputFilter.getToken(0, ':', nFilterOptionsIndex)),
488  PropertyState_DIRECT_VALUE);
489 
490  if (0 < nFilterOptionsIndex)
491  {
492  aArgs.emplace_back("FilterOptions", 0,
493  Any(aForcedInputFilter.copy(nFilterOptionsIndex)),
494  PropertyState_DIRECT_VALUE);
495  }
496  }
497 
498  // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
499  try
500  {
502  xDesktop, aName, aTarget, comphelper::containerToSequence(aArgs)),
503  UNO_QUERY);
504  }
505  catch (const css::lang::IllegalArgumentException&)
506  {
508  "desktop.app",
509  "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL");
510  }
511  catch (const css::io::IOException&)
512  {
514  "desktop.app",
515  "Dispatchwatcher IOException while calling loadComponentFromURL");
516  }
517  if ( aDispatchRequest.aRequestType == REQUEST_OPEN ||
518  aDispatchRequest.aRequestType == REQUEST_VIEW ||
519  aDispatchRequest.aRequestType == REQUEST_START ||
520  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ||
521  aDispatchRequest.aRequestType == REQUEST_FORCENEW )
522  {
523  // request is completed
525  }
526  else if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
527  aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
528  aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
529  aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
530  aDispatchRequest.aRequestType == REQUEST_CAT ||
531  aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
532  {
533  if ( xDoc.is() )
534  {
535  // Do we need to save the document in a different format?
536  if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
537  aDispatchRequest.aRequestType == REQUEST_CAT )
538  {
539 // FIXME: factor out into a method ...
540  Reference< XStorable > xStorable( xDoc, UNO_QUERY );
541  if ( xStorable.is() ) {
542  OUString aParam = aDispatchRequest.aPrinterName;
543  sal_Int32 nPathIndex = aParam.lastIndexOf( ';' );
544  sal_Int32 nFilterIndex = aParam.indexOf( ':' );
545  sal_Int32 nImgFilterIndex = aParam.lastIndexOf( '|' );
546  if( nPathIndex < nFilterIndex )
547  nFilterIndex = -1;
548 
549  OUString aFilterOut;
550  OUString aImgOut;
551  OUString aFilter;
552  OUString aFilterExt;
553  bool bGuess = false;
554 
555  if( nFilterIndex >= 0 )
556  {
557  aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
558  aFilterExt = aParam.copy( 0, nFilterIndex );
559  }
560  else
561  {
562  // Guess
563  bGuess = true;
564  aFilterExt = aParam.copy( 0, nPathIndex );
565  }
566 
567  if( nImgFilterIndex >= 0 )
568  {
569  aImgOut = aParam.copy( nImgFilterIndex+1 );
570  aFilterOut = aParam.copy( nPathIndex+1, nImgFilterIndex-nPathIndex-1 );
571  }
572  else
573  aFilterOut = aParam.copy( nPathIndex+1 );
574 
575  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
576  INetURLObject aOutFilename(aFilterOut);
577  aOutFilename.Append(aObj.getName(INetURLObject::LAST_SEGMENT, true,
579  aOutFilename.SetExtension(aFilterExt);
580  OUString aOutFile
582 
583  std::unique_ptr<utl::TempFile> fileForCat;
584  if( aDispatchRequest.aRequestType == REQUEST_CAT )
585  {
586  fileForCat = std::make_unique<utl::TempFile>();
587  if (fileForCat->IsValid())
588  fileForCat->EnableKillingFile();
589  else
590  std::cerr << "Error: Cannot create temporary file..." << std::endl ;
591  aOutFile = fileForCat->GetURL();
592  }
593 
594  if ( bGuess )
595  {
596  OUString aDocService;
597  Reference< XModel > xModel( xDoc, UNO_QUERY );
598  if ( xModel.is() )
599  {
600  utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
601  aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
602  }
603  aFilter = impl_GuessFilter( aOutFile, aDocService );
604  }
605 
606  if (aFilter.isEmpty())
607  {
608  std::cerr << "Error: no export filter" << std::endl;
609  }
610  else
611  {
612  sal_Int32 nFilterOptionsIndex = aFilter.indexOf(':');
613  sal_Int32 nProps = ( 0 < nFilterOptionsIndex ) ? 3 : 2;
614 
615  if ( !aImgOut.isEmpty() )
616  nProps +=1;
617  Sequence<PropertyValue> conversionProperties( nProps );
618  conversionProperties[0].Name = "Overwrite";
619  conversionProperties[0].Value <<= true;
620 
621  conversionProperties[1].Name = "FilterName";
622  if( 0 < nFilterOptionsIndex )
623  {
624  conversionProperties[1].Value <<= aFilter.copy(0, nFilterOptionsIndex);
625 
626  conversionProperties[2].Name = "FilterOptions";
627  conversionProperties[2].Value <<= aFilter.copy(nFilterOptionsIndex + 1);
628  }
629  else
630  {
631  conversionProperties[1].Value <<= aFilter;
632  }
633 
634  if ( !aImgOut.isEmpty() )
635  {
636  conversionProperties[nProps-1].Name = "ImageFilter";
637  conversionProperties[nProps-1].Value <<= aImgOut;
638  }
639 
640  OUString aTempName;
641  FileBase::getSystemPathFromFileURL(aName, aTempName);
642  OString aSource8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
643  FileBase::getSystemPathFromFileURL(aOutFile, aTempName);
644  OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
645  if (aDispatchRequest.aRequestType != REQUEST_CAT)
646  {
647  std::cout << "convert " << aSource8 << " -> " << aTargetURL8;
648  std::cout << " using filter : " << OUStringToOString(aFilter, osl_getThreadTextEncoding()) << std::endl;
649  if (FStatHelper::IsDocument(aOutFile))
650  std::cout << "Overwriting: " << OUStringToOString(aTempName, osl_getThreadTextEncoding()) << std::endl ;
651  }
652  try
653  {
654  xStorable->storeToURL(aOutFile, conversionProperties);
655  }
656  catch (const Exception& rException)
657  {
658  std::cerr << "Error: Please verify input parameters...";
659  if (!rException.Message.isEmpty())
660  std::cerr << " (" << rException.Message << ")";
661  std::cerr << std::endl;
662  }
663 
664  if (fileForCat && fileForCat->IsValid())
665  {
666  SvStream* aStream = fileForCat->GetStream(StreamMode::STD_READ);
667  while (aStream->good())
668  {
669  OString aStr;
670  aStream->ReadLine(aStr, SAL_MAX_INT32);
671  for (sal_Int32 i = 0; i < aStr.getLength(); ++i)
672  {
673  std::cout << aStr[i];
674  }
675  std::cout << std::endl;
676  }
677  }
678  }
679  }
680  }
681  else if ( aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
682  {
683  Reference< XModel > xModel( xDoc, UNO_QUERY );
684  if( xModel.is() )
685  scriptCat( xModel );
686  }
687  else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT )
688  {
689  batchPrint( aDispatchRequest.aPrinterName, xDoc, aObj, aName );
690  }
691  else
692  {
693  if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
694  {
695  // create the printer
696  Sequence < PropertyValue > aPrinterArgs( 1 );
697  aPrinterArgs[0].Name = "Name";
698  aPrinterArgs[0].Value <<= aDispatchRequest.aPrinterName;
699  xDoc->setPrinter( aPrinterArgs );
700  }
701 
702  // print ( also without user interaction )
703  Sequence < PropertyValue > aPrinterArgs( 1 );
704  aPrinterArgs[0].Name = "Wait";
705  aPrinterArgs[0].Value <<= true;
706  xDoc->print( aPrinterArgs );
707  }
708  }
709  else
710  {
711  std::cerr << "Error: source file could not be loaded" << std::endl;
712  }
713 
714  // remove the document
715  try
716  {
717  Reference < XCloseable > xClose( xDoc, UNO_QUERY );
718  if ( xClose.is() )
719  xClose->close( true );
720  else
721  {
722  Reference < XComponent > xComp( xDoc, UNO_QUERY );
723  if ( xComp.is() )
724  xComp->dispose();
725  }
726  }
727  catch (const css::util::CloseVetoException&)
728  {
729  }
730 
731  // request is completed
733  }
734  }
735  }
736 
737  if ( !aDispatches.empty() )
738  {
739  // Execute all asynchronous dispatches now after we placed them into our request container!
740  Sequence < PropertyValue > aArgs( 2 );
741  aArgs[0].Name = "Referer";
742  aArgs[0].Value <<= OUString("private:OpenEvent");
743  aArgs[1].Name = "SynchronMode";
744  aArgs[1].Value <<= true;
745 
746  for (const DispatchHolder & aDispatche : aDispatches)
747  {
748  Reference< XDispatch > xDispatch = aDispatche.xDispatch;
749  Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );
750  if ( xDisp.is() )
751  xDisp->dispatchWithNotification( aDispatche.aURL, aArgs, this );
752  else
753  {
754  {
755  osl::MutexGuard aGuard(m_mutex);
756  m_nRequestCount--;
757  }
758  xDispatch->dispatch( aDispatche.aURL, aArgs );
759  }
760  }
761  }
762 
763  ::osl::ClearableMutexGuard aGuard(m_mutex);
764  bool bEmpty = (m_nRequestCount == 0);
765  aGuard.clear();
766 
767  // No more asynchronous requests?
768  // The requests are removed from the request container after they called back to this
769  // implementation via statusChanged!!
770  if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ )
771  {
772  // We have to check if we have an open task otherwise we have to shutdown the office.
773  Reference< XElementAccess > xList = xDesktop->getFrames();
774 
775  if ( !xList->hasElements() )
776  {
777  // We don't have any task open so we have to shutdown ourself!!
778  return xDesktop->terminate();
779  }
780  }
781 
782  return false;
783 }
784 
785 
786 void SAL_CALL DispatchWatcher::disposing( const css::lang::EventObject& )
787 {
788 }
789 
790 
791 void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& )
792 {
793  osl::ClearableMutexGuard aGuard(m_mutex);
794  sal_Int16 nCount = --m_nRequestCount;
795  aGuard.clear();
797  if ( !nCount && !RequestHandler::AreRequestsPending() )
798  {
799  // We have to check if we have an open task otherwise we have to shutdown the office.
800  Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
801  Reference< XElementAccess > xList = xDesktop->getFrames();
802 
803  if ( !xList->hasElements() )
804  {
805  // We don't have any task open so we have to shutdown ourself!!
806  xDesktop->terminate();
807  }
808  }
809 }
810 
811 } // namespace desktop
812 
813 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SVL_DLLPUBLIC bool IsDocument(const OUString &rURL)
URL aURL
#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)
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)
OUString GetURL_Impl(const OUString &rName, o3tl::optional< OUString > const &cwdUrl)
Definition: app.cxx:2211
#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
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:2087
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)