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>
26 #include <com/sun/star/frame/DispatchResultEvent.hpp>
27 #include <com/sun/star/frame/DispatchResultState.hpp>
28 #include <com/sun/star/frame/ModuleManager.hpp>
29 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
30 #include <com/sun/star/frame/XDispatch.hpp>
31 #include <com/sun/star/frame/XStatusListener.hpp>
32 #include <com/sun/star/frame/XDispatchResultListener.hpp>
33 #include <com/sun/star/frame/XDispatchProvider.hpp>
34 #include <com/sun/star/lang/XInitialization.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
37 #include <cppuhelper/supportsservice.hxx>
38 #include <cppuhelper/implbase4.hxx>
39 #include <rtl/ref.hxx>
40 #include <rtl/ustrbuf.hxx>
41 #include <unotools/configpaths.hxx>
42 #include <vcl/svapp.hxx>
44 using namespace framework
;
49 @short implements a dispatch object for jobs
50 @descr Such dispatch object will be used by the generic dispatch mechanism if
51 an URL "vnd.sun.star.job:alias=<name>" occurs.
52 Then an instance of this class will be created and used.
53 This new instance will be called within his method
54 dispatch() or dispatchWithNotification() for executing the
55 real job. We do it, control the life cycle of this internal
56 wrapped job and inform any interested listener if it finish.
58 class JobDispatch
: public ::cppu::WeakImplHelper4
<
59 css::lang::XServiceInfo
60 , css::lang::XInitialization
61 , css::frame::XDispatchProvider
62 , css::frame::XNotifyingDispatch
> // => XDispatch
66 /** reference to the uno service manager */
67 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
69 /** reference to the frame, inside which this dispatch is used */
70 css::uno::Reference
< css::frame::XFrame
> m_xFrame
;
72 /** name of module (writer, impress etc.) the frame is for */
73 OUString m_sModuleIdentifier
;
75 // native interface methods
79 JobDispatch( const css::uno::Reference
< css::uno::XComponentContext
>& xContext
);
80 virtual ~JobDispatch();
82 void impl_dispatchEvent ( const OUString
& sEvent
,
83 const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
84 const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
);
85 void impl_dispatchService( const OUString
& sService
,
86 const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
87 const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
);
88 void impl_dispatchAlias ( const OUString
& sAlias
,
89 const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
90 const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
);
93 virtual OUString SAL_CALL
getImplementationName()
94 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
96 return OUString("com.sun.star.comp.framework.jobs.JobDispatch");
99 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
)
100 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
102 return cppu::supportsService(this, ServiceName
);
105 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames()
106 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
108 css::uno::Sequence
< OUString
> aSeq(1);
109 aSeq
[0] = "com.sun.star.frame.ProtocolHandler";
114 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& lArguments
) throw(css::uno::Exception
,
115 css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
118 virtual css::uno::Reference
< css::frame::XDispatch
> SAL_CALL
queryDispatch ( const css::util::URL
& aURL
,
119 const OUString
& sTargetFrameName
,
120 sal_Int32 nSearchFlags
) throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
121 virtual css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > SAL_CALL
queryDispatches( const css::uno::Sequence
< css::frame::DispatchDescriptor
>& lDescriptor
) throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
123 // XNotifyingDispatch
124 virtual void SAL_CALL
dispatchWithNotification( const css::util::URL
& aURL
,
125 const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
126 const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
) throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
129 virtual void SAL_CALL
dispatch ( const css::util::URL
& aURL
,
130 const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
) throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
131 virtual void SAL_CALL
addStatusListener ( const css::uno::Reference
< css::frame::XStatusListener
>& xListener
,
132 const css::util::URL
& aURL
) throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
133 virtual void SAL_CALL
removeStatusListener( const css::uno::Reference
< css::frame::XStatusListener
>& xListener
,
134 const css::util::URL
& aURL
) throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
139 @descr It initialize this new instance.
142 reference to the uno service manager
144 JobDispatch::JobDispatch( /*IN*/ const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
145 : m_xContext (xContext
)
150 @short let this instance die
151 @descr We have to release all used resources and free used memory.
153 JobDispatch::~JobDispatch()
155 // release all used resources
161 @short implementation of XInitalization
162 @descr A protocol handler can provide this functionality, if it wish to get additional information
163 about the context it runs. In this case the frame reference would be given by the outside code.
166 the list of initialization arguments
167 First parameter should be the frame reference we need.
169 void SAL_CALL
JobDispatch::initialize( const css::uno::Sequence
< css::uno::Any
>& lArguments
) throw(css::uno::Exception
,
170 css::uno::RuntimeException
, std::exception
)
174 for (int a
=0; a
<lArguments
.getLength(); ++a
)
178 lArguments
[a
] >>= m_xFrame
;
180 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager
=
181 css::frame::ModuleManager::create(m_xContext
);
184 m_sModuleIdentifier
= xModuleManager
->identify( m_xFrame
);
186 catch( const css::uno::Exception
& )
193 @short implementation of XDispatchProvider::queryDispatches()
194 @descr Every protocol handler will be asked for his agreement, if an URL was queried
195 for which this handler is registered. It's the chance for this handler to validate
196 the given URL and return a dispatch object (may be itself) or not.
199 the queried URL, which should be checked
201 @param sTargetFrameName
202 describes the target frame, in which context this handler will be used
203 Is mostly set to "", "_self", "_blank", "_default" or a non special one
204 using SELF/CREATE as search flags.
207 Can be SELF or CREATE only and are set only if sTargetFrameName isn't a special target
209 css::uno::Reference
< css::frame::XDispatch
> SAL_CALL
JobDispatch::queryDispatch( /*IN*/ const css::util::URL
& aURL
,
210 /*IN*/ const OUString
& /*sTargetFrameName*/ ,
211 /*IN*/ sal_Int32
/*nSearchFlags*/ ) throw(css::uno::RuntimeException
, std::exception
)
213 css::uno::Reference
< css::frame::XDispatch
> xDispatch
;
215 JobURL
aAnalyzedURL(aURL
.Complete
);
216 if (aAnalyzedURL
.isValid())
217 xDispatch
= css::uno::Reference
< css::frame::XDispatch
>( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
223 @short implementation of XDispatchProvider::queryDispatches()
224 @descr It's an optimized access for remote, so you can ask for
225 multiple dispatch objects at the same time.
228 a list of queryDispatch() parameter
230 @return A list of corresponding dispatch objects.
231 NULL references are not skipped. Every result
232 match to one given descriptor item.
234 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > SAL_CALL
JobDispatch::queryDispatches( const css::uno::Sequence
< css::frame::DispatchDescriptor
>& lDescriptor
) throw(css::uno::RuntimeException
, std::exception
)
236 // don't pack resulting list!
237 sal_Int32 nCount
= lDescriptor
.getLength();
238 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > lDispatches(nCount
);
240 for (sal_Int32 i
=0; i
<nCount
; ++i
)
241 lDispatches
[i
] = queryDispatch( lDescriptor
[i
].FeatureURL
,
242 lDescriptor
[i
].FrameName
,
243 lDescriptor
[i
].SearchFlags
);
248 @short implementation of XNotifyingDispatch::dispatchWithNotification()
249 @descr It creates the job service implementation and call execute on it.
250 Further it starts the life time control of it. (important for async job)
251 For synchonrous job we react for the returned result directly ... for asynchronous
252 ones we do it later inside our callback method. But we use the same impl method
253 doing that to share the code. (see impl_finishJob())
255 If a job is already running, (it can only occur for asynchronous jobs)
256 don't start the same job a second time. Queue in the given dispatch parameter
257 and return immediately. If the current running job call us back, we will start this
258 new dispatch request.
259 If no job is running - queue the parameter too! But then start the new job immediately.
260 We have to queue it every time - because it hold us alive by ref count!
263 describe the job(s), which should be started
266 optional arguments for this request
269 an interested listener for possible results of this operation
271 void SAL_CALL
JobDispatch::dispatchWithNotification( /*IN*/ const css::util::URL
& aURL
,
272 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
273 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
) throw(css::uno::RuntimeException
, std::exception
)
275 JobURL
aAnalyzedURL(aURL
.Complete
);
276 if (aAnalyzedURL
.isValid())
279 if (aAnalyzedURL
.getEvent(sRequest
))
280 impl_dispatchEvent(sRequest
, lArgs
, xListener
);
282 if (aAnalyzedURL
.getService(sRequest
))
283 impl_dispatchService(sRequest
, lArgs
, xListener
);
285 if (aAnalyzedURL
.getAlias(sRequest
))
286 impl_dispatchAlias(sRequest
, lArgs
, xListener
);
291 @short dispatch an event
292 @descr We search all registered jobs for this event and execute it.
293 After doing so, we inform the given listener about the results.
294 (There will be one notify for every executed job!)
297 the event, for which jobs can be registered
300 optional arguments for this request
304 an interested listener for possible results of this operation
306 void JobDispatch::impl_dispatchEvent( /*IN*/ const OUString
& sEvent
,
307 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
308 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
)
310 // get list of all enabled jobs
311 // The called static helper methods read it from the configuration and
312 // filter disabled jobs using it's time stamp values.
314 SolarMutexResettableGuard aReadLock
;
315 css::uno::Sequence
< OUString
> lJobs
= JobData::getEnabledJobsForEvent(m_xContext
, sEvent
);
319 css::uno::Reference
< css::frame::XDispatchResultListener
> xThis( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
321 // no jobs ... no execution
322 // But a may given listener will know something ...
323 // I think this operaton was finished successfully.
324 // It's not really an error, if no registered jobs could be located.
325 // Step over all found jobs and execute it
327 for (int j
=0; j
<lJobs
.getLength(); ++j
)
332 JobData
aCfg(m_xContext
);
333 aCfg
.setEvent(sEvent
, lJobs
[j
]);
334 aCfg
.setEnvironment(JobData::E_DISPATCH
);
335 const bool bIsEnabled
=aCfg
.hasCorrectContext(m_sModuleIdentifier
);
338 Jobs implements interfaces and dies by ref count!
339 And freeing of such uno object is done by uno itself.
340 So we have to use dynamic memory everytimes.
342 Job
* pJob
= new Job(m_xContext
, m_xFrame
);
343 css::uno::Reference
< css::uno::XInterface
> xJob(static_cast< ::cppu::OWeakObject
* >(pJob
), css::uno::UNO_QUERY
);
344 pJob
->setJobData(aCfg
);
352 // Special mode for listener.
353 // We dont notify it directly here. We delegate that
354 // to the job implementation. But we must set ourself there too.
355 // Because this job must fake the source address of the event.
356 // Otherwise the listener may ignore it.
358 pJob
->setDispatchResultFake(xListener
, xThis
);
359 pJob
->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs
));
363 if (nExecutedJobs
<1 && xListener
.is())
365 css::frame::DispatchResultEvent aEvent
;
366 aEvent
.Source
= xThis
;
367 aEvent
.State
= css::frame::DispatchResultState::SUCCESS
;
368 xListener
->dispatchFinished(aEvent
);
373 @short dispatch a service
374 @descr We use the given name only to create and if possible to initialize
375 it as an uno service. It can be useful for creating (caching?)
376 of e.g. one instance services.
379 the uno implementation or service name of the job, which should be instantiated
382 optional arguments for this request
386 an interested listener for possible results of this operation
388 void JobDispatch::impl_dispatchService( /*IN*/ const OUString
& sService
,
389 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
390 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
)
393 SolarMutexClearableGuard aReadLock
;
395 JobData
aCfg(m_xContext
);
396 aCfg
.setService(sService
);
397 aCfg
.setEnvironment(JobData::E_DISPATCH
);
400 Jobs implements interfaces and dies by ref count!
401 And freeing of such uno object is done by uno itself.
402 So we have to use dynamic memory everytimes.
404 Job
* pJob
= new Job(m_xContext
, m_xFrame
);
405 css::uno::Reference
< css::uno::XInterface
> xJob(static_cast< ::cppu::OWeakObject
* >(pJob
), css::uno::UNO_QUERY
);
406 pJob
->setJobData(aCfg
);
411 css::uno::Reference
< css::frame::XDispatchResultListener
> xThis( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
413 // Special mode for listener.
414 // We dont notify it directly here. We delegate that
415 // to the job implementation. But we must set ourself there too.
416 // Because this job must fake the source address of the event.
417 // Otherwise the listener may ignore it.
419 pJob
->setDispatchResultFake(xListener
, xThis
);
420 pJob
->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs
));
424 @short dispatch an alias
425 @descr We use this alias to locate a job inside the configuration
426 and execute it. Further we inform the given listener about the results.
429 the alias name of the configured job
432 optional arguments for this request
436 an interested listener for possible results of this operation
438 void JobDispatch::impl_dispatchAlias( /*IN*/ const OUString
& sAlias
,
439 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
440 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
)
443 SolarMutexClearableGuard aReadLock
;
445 JobData
aCfg(m_xContext
);
446 aCfg
.setAlias(sAlias
);
447 aCfg
.setEnvironment(JobData::E_DISPATCH
);
450 Jobs implements interfaces and dies by ref count!
451 And freeing of such uno object is done by uno itself.
452 So we have to use dynamic memory everytimes.
454 Job
* pJob
= new Job(m_xContext
, m_xFrame
);
455 css::uno::Reference
< css::uno::XInterface
> xJob(static_cast< ::cppu::OWeakObject
* >(pJob
), css::uno::UNO_QUERY
);
456 pJob
->setJobData(aCfg
);
461 css::uno::Reference
< css::frame::XDispatchResultListener
> xThis( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
463 // Special mode for listener.
464 // We dont notify it directly here. We delegate that
465 // to the job implementation. But we must set ourself there too.
466 // Because this job must fake the source address of the event.
467 // Otherwise the listener may ignore it.
469 pJob
->setDispatchResultFake(xListener
, xThis
);
470 pJob
->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs
));
474 @short implementation of XDispatch::dispatch()
475 @descr Because the methods dispatch() and dispatchWithNotification() are different in her parameters
476 only, we can forward this request to dispatchWithNotification() by using an empty listener!
479 describe the job(s), which should be started
482 optional arguments for this request
484 @see dispatchWithNotification()
486 void SAL_CALL
JobDispatch::dispatch( /*IN*/ const css::util::URL
& aURL
,
487 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
) throw(css::uno::RuntimeException
, std::exception
)
489 dispatchWithNotification(aURL
, lArgs
, css::uno::Reference
< css::frame::XDispatchResultListener
>());
495 void SAL_CALL
JobDispatch::addStatusListener( /*IN*/ const css::uno::Reference
< css::frame::XStatusListener
>&,
496 /*IN*/ const css::util::URL
& ) throw(css::uno::RuntimeException
, std::exception
)
503 void SAL_CALL
JobDispatch::removeStatusListener( /*IN*/ const css::uno::Reference
< css::frame::XStatusListener
>&,
504 /*IN*/ const css::util::URL
& ) throw(css::uno::RuntimeException
, std::exception
)
510 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
511 com_sun_star_comp_framework_jobs_JobDispatch_get_implementation(
512 css::uno::XComponentContext
*context
,
513 css::uno::Sequence
<css::uno::Any
> const &)
515 return cppu::acquire(new JobDispatch(context
));
518 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */