1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
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
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
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
);
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" };
107 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& lArguments
) override
;
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
;
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
;
131 @descr It initialize this new instance.
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
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.
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
)
165 for (int a
=0; a
<lArguments
.getLength(); ++a
)
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.
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.
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
);
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.
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
);
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!
254 describe the job(s), which should be started
257 optional arguments for this request
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())
270 if (aAnalyzedURL
.getEvent(sRequest
))
271 impl_dispatchEvent(sRequest
, lArgs
, xListener
);
273 if (aAnalyzedURL
.getService(sRequest
))
274 impl_dispatchService(sRequest
, lArgs
, xListener
);
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!)
288 the event, for which jobs can be registered
291 optional arguments for this request
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.
305 SolarMutexResettableGuard aReadLock
;
306 std::vector
< OUString
> lJobs
= JobData::getEnabledJobsForEvent(m_xContext
, sEvent
);
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
318 for (const OUString
& lJob
: lJobs
)
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
);
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.
343 pJob
->setDispatchResultFake(xListener
, xThis
);
344 pJob
->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs
));
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.
364 the uno implementation or service name of the job, which should be instantiated
367 optional arguments for this request
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
)
378 SolarMutexClearableGuard aReadLock
;
380 JobData
aCfg(m_xContext
);
381 aCfg
.setService(sService
);
382 aCfg
.setEnvironment(JobData::E_DISPATCH
);
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
);
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.
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.
413 the alias name of the configured job
416 optional arguments for this request
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
)
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
);
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.
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!
457 describe the job(s), which should be started
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
>());
473 void SAL_CALL
JobDispatch::addStatusListener( /*IN*/ const css::uno::Reference
< css::frame::XStatusListener
>&,
474 /*IN*/ const css::util::URL
& )
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: */