nss: upgrade to release 3.73
[LibreOffice.git] / framework / source / jobs / jobdispatch.cxx
blob6ec94cb3293cede2ff7e95a3e19afc5a357caec2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <jobs/configaccess.hxx>
21 #include <jobs/joburl.hxx>
22 #include <jobs/job.hxx>
23 #include <classes/converter.hxx>
25 #include <com/sun/star/frame/DispatchResultEvent.hpp>
26 #include <com/sun/star/frame/DispatchResultState.hpp>
27 #include <com/sun/star/frame/ModuleManager.hpp>
28 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
29 #include <com/sun/star/frame/XDispatch.hpp>
30 #include <com/sun/star/frame/XStatusListener.hpp>
31 #include <com/sun/star/frame/XDispatchResultListener.hpp>
32 #include <com/sun/star/frame/XDispatchProvider.hpp>
33 #include <com/sun/star/lang/XInitialization.hpp>
34 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <cppuhelper/supportsservice.hxx>
37 #include <cppuhelper/implbase.hxx>
38 #include <rtl/ref.hxx>
39 #include <vcl/svapp.hxx>
41 using namespace framework;
43 namespace {
45 /**
46 @short implements a dispatch object for jobs
47 @descr Such dispatch object will be used by the generic dispatch mechanism if
48 a URL "vnd.sun.star.job:alias=<name>" occurs.
49 Then an instance of this class will be created and used.
50 This new instance will be called within his method
51 dispatch() or dispatchWithNotification() for executing the
52 real job. We do it, control the life cycle of this internal
53 wrapped job and inform any interested listener if it finish.
55 class JobDispatch : public ::cppu::WeakImplHelper<
56 css::lang::XServiceInfo
57 , css::lang::XInitialization
58 , css::frame::XDispatchProvider
59 , css::frame::XNotifyingDispatch > // => XDispatch
61 private:
63 /** reference to the uno service manager */
64 css::uno::Reference< css::uno::XComponentContext > m_xContext;
66 /** reference to the frame, inside which this dispatch is used */
67 css::uno::Reference< css::frame::XFrame > m_xFrame;
69 /** name of module (writer, impress etc.) the frame is for */
70 OUString m_sModuleIdentifier;
72 // native interface methods
74 public:
76 explicit JobDispatch(const css::uno::Reference< css::uno::XComponentContext >& xContext);
77 virtual ~JobDispatch() override;
79 void impl_dispatchEvent ( const OUString& sEvent ,
80 const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
81 const css::uno::Reference< css::frame::XDispatchResultListener >& xListener );
82 void impl_dispatchService( const OUString& sService ,
83 const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
84 const css::uno::Reference< css::frame::XDispatchResultListener >& xListener );
85 void impl_dispatchAlias ( const OUString& sAlias ,
86 const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
87 const css::uno::Reference< css::frame::XDispatchResultListener >& xListener );
89 public:
90 virtual OUString SAL_CALL getImplementationName() override
92 return "com.sun.star.comp.framework.jobs.JobDispatch";
95 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
97 return cppu::supportsService(this, ServiceName);
100 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
102 css::uno::Sequence< OUString > aSeq { "com.sun.star.frame.ProtocolHandler" };
103 return aSeq;
106 // Xinitialization
107 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& lArguments ) override;
109 // XDispatchProvider
110 virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch ( const css::util::URL& aURL ,
111 const OUString& sTargetFrameName ,
112 sal_Int32 nSearchFlags ) override;
113 virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) override;
115 // XNotifyingDispatch
116 virtual void SAL_CALL dispatchWithNotification( const css::util::URL& aURL ,
117 const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
118 const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) override;
120 // XDispatch
121 virtual void SAL_CALL dispatch ( const css::util::URL& aURL ,
122 const css::uno::Sequence< css::beans::PropertyValue >& lArgs ) override;
123 virtual void SAL_CALL addStatusListener ( const css::uno::Reference< css::frame::XStatusListener >& xListener ,
124 const css::util::URL& aURL ) override;
125 virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener ,
126 const css::util::URL& aURL ) override;
130 @short standard ctor
131 @descr It initialize this new instance.
133 @param xContext
134 reference to the uno service manager
136 JobDispatch::JobDispatch( /*IN*/ const css::uno::Reference< css::uno::XComponentContext >& xContext )
137 : m_xContext (xContext )
142 @short let this instance die
143 @descr We have to release all used resources and free used memory.
145 JobDispatch::~JobDispatch()
147 // release all used resources
148 m_xContext.clear();
149 m_xFrame.clear();
153 @short implementation of XInitialization
154 @descr A protocol handler can provide this functionality, if it wish to get additional information
155 about the context it runs. In this case the frame reference would be given by the outside code.
157 @param lArguments
158 the list of initialization arguments
159 First parameter should be the frame reference we need.
161 void SAL_CALL JobDispatch::initialize( const css::uno::Sequence< css::uno::Any >& lArguments )
163 SolarMutexGuard g;
165 for (int a=0; a<lArguments.getLength(); ++a)
167 if (a==0)
169 lArguments[a] >>= m_xFrame;
171 css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
172 css::frame::ModuleManager::create(m_xContext);
175 m_sModuleIdentifier = xModuleManager->identify( m_xFrame );
177 catch( const css::uno::Exception& )
184 @short implementation of XDispatchProvider::queryDispatches()
185 @descr Every protocol handler will be asked for his agreement, if a URL was queried
186 for which this handler is registered. It's the chance for this handler to validate
187 the given URL and return a dispatch object (may be itself) or not.
189 @param aURL
190 the queried URL, which should be checked
192 @param sTargetFrameName
193 describes the target frame, in which context this handler will be used
194 Is mostly set to "", "_self", "_blank", "_default" or a non special one
195 using SELF/CREATE as search flags.
197 @param nSearchFlags
198 Can be SELF or CREATE only and are set only if sTargetFrameName isn't a special target
200 css::uno::Reference< css::frame::XDispatch > SAL_CALL JobDispatch::queryDispatch( /*IN*/ const css::util::URL& aURL ,
201 /*IN*/ const OUString& /*sTargetFrameName*/ ,
202 /*IN*/ sal_Int32 /*nSearchFlags*/ )
204 css::uno::Reference< css::frame::XDispatch > xDispatch;
206 JobURL aAnalyzedURL(aURL.Complete);
207 if (aAnalyzedURL.isValid())
208 xDispatch.set( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
210 return xDispatch;
214 @short implementation of XDispatchProvider::queryDispatches()
215 @descr It's an optimized access for remote, so you can ask for
216 multiple dispatch objects at the same time.
218 @param lDescriptor
219 a list of queryDispatch() parameter
221 @return A list of corresponding dispatch objects.
222 NULL references are not skipped. Every result
223 match to one given descriptor item.
225 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL JobDispatch::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
227 // don't pack resulting list!
228 sal_Int32 nCount = lDescriptor.getLength();
229 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatches(nCount);
231 for (sal_Int32 i=0; i<nCount; ++i)
232 lDispatches[i] = queryDispatch( lDescriptor[i].FeatureURL ,
233 lDescriptor[i].FrameName ,
234 lDescriptor[i].SearchFlags );
235 return lDispatches;
239 @short implementation of XNotifyingDispatch::dispatchWithNotification()
240 @descr It creates the job service implementation and call execute on it.
241 Further it starts the life time control of it. (important for async job)
242 For synchronous job we react for the returned result directly ... for asynchronous
243 ones we do it later inside our callback method. But we use the same impl method
244 doing that to share the code. (see impl_finishJob())
246 If a job is already running, (it can only occur for asynchronous jobs)
247 don't start the same job a second time. Queue in the given dispatch parameter
248 and return immediately. If the current running job call us back, we will start this
249 new dispatch request.
250 If no job is running - queue the parameter too! But then start the new job immediately.
251 We have to queue it every time - because it hold us alive by ref count!
253 @param aURL
254 describe the job(s), which should be started
256 @param lArgs
257 optional arguments for this request
259 @param xListener
260 an interested listener for possible results of this operation
262 void SAL_CALL JobDispatch::dispatchWithNotification( /*IN*/ const css::util::URL& aURL ,
263 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
264 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
266 JobURL aAnalyzedURL(aURL.Complete);
267 if (aAnalyzedURL.isValid())
269 OUString sRequest;
270 if (aAnalyzedURL.getEvent(sRequest))
271 impl_dispatchEvent(sRequest, lArgs, xListener);
272 else
273 if (aAnalyzedURL.getService(sRequest))
274 impl_dispatchService(sRequest, lArgs, xListener);
275 else
276 if (aAnalyzedURL.getAlias(sRequest))
277 impl_dispatchAlias(sRequest, lArgs, xListener);
282 @short dispatch an event
283 @descr We search all registered jobs for this event and execute it.
284 After doing so, we inform the given listener about the results.
285 (There will be one notify for every executed job!)
287 @param sEvent
288 the event, for which jobs can be registered
290 @param lArgs
291 optional arguments for this request
292 Currently not used!
294 @param xListener
295 an interested listener for possible results of this operation
297 void JobDispatch::impl_dispatchEvent( /*IN*/ const OUString& sEvent ,
298 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
299 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
301 // get list of all enabled jobs
302 // The called static helper methods read it from the configuration and
303 // filter disabled jobs using it's time stamp values.
304 /* SAFE { */
305 SolarMutexResettableGuard aReadLock;
306 std::vector< OUString > lJobs = JobData::getEnabledJobsForEvent(m_xContext, sEvent);
307 aReadLock.clear();
308 /* } SAFE */
310 css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
312 // no jobs... no execution
313 // But a may given listener will know something...
314 // I think this operation was finished successfully.
315 // It's not really an error, if no registered jobs could be located.
316 // Step over all found jobs and execute it
317 int nExecutedJobs=0;
318 for (const OUString & lJob : lJobs)
320 /* SAFE { */
321 aReadLock.reset();
323 JobData aCfg(m_xContext);
324 aCfg.setEvent(sEvent, lJob);
325 aCfg.setEnvironment(JobData::E_DISPATCH);
326 const bool bIsEnabled=aCfg.hasCorrectContext(m_sModuleIdentifier);
328 rtl::Reference<Job> pJob = new Job(m_xContext, m_xFrame);
329 pJob->setJobData(aCfg);
331 aReadLock.clear();
332 /* } SAFE */
334 if (!bIsEnabled)
335 continue;
337 // Special mode for listener.
338 // We don't notify it directly here. We delegate that
339 // to the job implementation. But we must set ourself there too.
340 // Because this job must fake the source address of the event.
341 // Otherwise the listener may ignore it.
342 if (xListener.is())
343 pJob->setDispatchResultFake(xListener, xThis);
344 pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
345 ++nExecutedJobs;
348 if (nExecutedJobs<1 && xListener.is())
350 css::frame::DispatchResultEvent aEvent;
351 aEvent.Source = xThis;
352 aEvent.State = css::frame::DispatchResultState::SUCCESS;
353 xListener->dispatchFinished(aEvent);
358 @short dispatch a service
359 @descr We use the given name only to create and if possible to initialize
360 it as a uno service. It can be useful for creating (caching?)
361 of e.g. one instance services.
363 @param sService
364 the uno implementation or service name of the job, which should be instantiated
366 @param lArgs
367 optional arguments for this request
368 Currently not used!
370 @param xListener
371 an interested listener for possible results of this operation
373 void JobDispatch::impl_dispatchService( /*IN*/ const OUString& sService ,
374 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
375 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
377 /* SAFE { */
378 SolarMutexClearableGuard aReadLock;
380 JobData aCfg(m_xContext);
381 aCfg.setService(sService);
382 aCfg.setEnvironment(JobData::E_DISPATCH);
384 /*Attention!
385 Jobs implements interfaces and dies by ref count!
386 And freeing of such uno object is done by uno itself.
387 So we have to use dynamic memory everytimes.
389 rtl::Reference<Job> pJob = new Job(m_xContext, m_xFrame);
390 pJob->setJobData(aCfg);
392 aReadLock.clear();
393 /* } SAFE */
395 css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
397 // Special mode for listener.
398 // We don't notify it directly here. We delegate that
399 // to the job implementation. But we must set ourself there too.
400 // Because this job must fake the source address of the event.
401 // Otherwise the listener may ignore it.
402 if (xListener.is())
403 pJob->setDispatchResultFake(xListener, xThis);
404 pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
408 @short dispatch an alias
409 @descr We use this alias to locate a job inside the configuration
410 and execute it. Further we inform the given listener about the results.
412 @param sAlias
413 the alias name of the configured job
415 @param lArgs
416 optional arguments for this request
417 Currently not used!
419 @param xListener
420 an interested listener for possible results of this operation
422 void JobDispatch::impl_dispatchAlias( /*IN*/ const OUString& sAlias ,
423 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
424 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
426 /* SAFE { */
427 SolarMutexClearableGuard aReadLock;
429 JobData aCfg(m_xContext);
430 aCfg.setAlias(sAlias);
431 aCfg.setEnvironment(JobData::E_DISPATCH);
433 rtl::Reference<Job> pJob = new Job(m_xContext, m_xFrame);
434 pJob->setJobData(aCfg);
436 aReadLock.clear();
437 /* } SAFE */
439 css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
441 // Special mode for listener.
442 // We don't notify it directly here. We delegate that
443 // to the job implementation. But we must set ourself there too.
444 // Because this job must fake the source address of the event.
445 // Otherwise the listener may ignore it.
446 if (xListener.is())
447 pJob->setDispatchResultFake(xListener, xThis);
448 pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
452 @short implementation of XDispatch::dispatch()
453 @descr Because the methods dispatch() and dispatchWithNotification() are different in her parameters
454 only, we can forward this request to dispatchWithNotification() by using an empty listener!
456 @param aURL
457 describe the job(s), which should be started
459 @param lArgs
460 optional arguments for this request
462 @see dispatchWithNotification()
464 void SAL_CALL JobDispatch::dispatch( /*IN*/ const css::util::URL& aURL ,
465 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs )
467 dispatchWithNotification(aURL, lArgs, css::uno::Reference< css::frame::XDispatchResultListener >());
471 @short not supported
473 void SAL_CALL JobDispatch::addStatusListener( /*IN*/ const css::uno::Reference< css::frame::XStatusListener >&,
474 /*IN*/ const css::util::URL& )
479 @short not supported
481 void SAL_CALL JobDispatch::removeStatusListener( /*IN*/ const css::uno::Reference< css::frame::XStatusListener >&,
482 /*IN*/ const css::util::URL& )
488 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
489 com_sun_star_comp_framework_jobs_JobDispatch_get_implementation(
490 css::uno::XComponentContext *context,
491 css::uno::Sequence<css::uno::Any> const &)
493 return cppu::acquire(new JobDispatch(context));
496 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */