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