bump product version to 4.1.6.2
[LibreOffice.git] / framework / source / jobs / jobdispatch.cxx
blobd66feca76179e0fae3d86b01f0255bef63bac8a7
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/jobdispatch.hxx>
21 #include <jobs/joburl.hxx>
22 #include <jobs/job.hxx>
23 #include <threadhelp/readguard.hxx>
24 #include <threadhelp/writeguard.hxx>
25 #include <threadhelp/resetableguard.hxx>
26 #include <classes/converter.hxx>
27 #include <general.h>
28 #include <services.h>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/frame/DispatchResultState.hpp>
32 #include <com/sun/star/frame/ModuleManager.hpp>
34 #include <rtl/ustrbuf.hxx>
35 #include <vcl/svapp.hxx>
37 namespace framework{
39 DEFINE_XINTERFACE_6( JobDispatch ,
40 OWeakObject ,
41 DIRECT_INTERFACE(css::lang::XTypeProvider ),
42 DIRECT_INTERFACE(css::frame::XDispatchProvider ),
43 DIRECT_INTERFACE(css::lang::XInitialization ),
44 DIRECT_INTERFACE(css::lang::XServiceInfo),
45 DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
46 DIRECT_INTERFACE(css::frame::XDispatch )
49 DEFINE_XTYPEPROVIDER_6( JobDispatch ,
50 css::lang::XTypeProvider ,
51 css::frame::XDispatchProvider ,
52 css::frame::XNotifyingDispatch,
53 css::lang::XInitialization,
54 css::lang::XServiceInfo,
55 css::frame::XDispatch
58 DEFINE_XSERVICEINFO_MULTISERVICE( JobDispatch ,
59 ::cppu::OWeakObject ,
60 SERVICENAME_PROTOCOLHANDLER ,
61 IMPLEMENTATIONNAME_JOBDISPATCH
64 DEFINE_INIT_SERVICE( JobDispatch,
66 /*Attention
67 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
68 to create a new instance of this class by our own supported service factory.
69 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further information!
74 //________________________________
75 /**
76 @short standard ctor
77 @descr It initialize this new instance.
79 @param xSMGR
80 reference to the uno service manager
82 JobDispatch::JobDispatch( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
83 : ThreadHelpBase(&Application::GetSolarMutex())
84 , OWeakObject ( )
85 , m_xSMGR (xSMGR )
89 //________________________________
90 /**
91 @short let this instance die
92 @descr We have to release all used resources and free used memory.
94 JobDispatch::~JobDispatch()
96 // release all used resources
97 m_xSMGR = css::uno::Reference< css::lang::XMultiServiceFactory >();
98 m_xFrame = css::uno::Reference< css::frame::XFrame >();
101 //________________________________
103 @short implementation of XInitalization
104 @descr A protocol handler can provide this functionality, if it wish to get additional information
105 about the context it runs. In this case the frame reference would be given by the outside code.
107 @param lArguments
108 the list of initialization arguments
109 First parameter should be the frame reference we need.
111 void SAL_CALL JobDispatch::initialize( const css::uno::Sequence< css::uno::Any >& lArguments ) throw(css::uno::Exception ,
112 css::uno::RuntimeException)
114 /* SAFE { */
115 WriteGuard aWriteLock(m_aLock);
117 for (int a=0; a<lArguments.getLength(); ++a)
119 if (a==0)
121 lArguments[a] >>= m_xFrame;
123 css::uno::Reference< css::frame::XModuleManager2 > xModuleManager =
124 css::frame::ModuleManager::create(comphelper::getComponentContext(m_xSMGR));
127 m_sModuleIdentifier = xModuleManager->identify( m_xFrame );
129 catch( const css::uno::Exception& )
134 aWriteLock.unlock();
135 /* } SAFE */
138 //________________________________
140 @short implementation of XDispatchProvider::queryDispatches()
141 @descr Every protocol handler will be asked for his agreement, if an URL was queried
142 for which this handler is registered. It's the chance for this handler to validate
143 the given URL and return a dispatch object (may be itself) or not.
145 @param aURL
146 the queried URL, which should be checked
148 @param sTargetFrameName
149 describes the target frame, in which context this handler will be used
150 Is mostly set to "", "_self", "_blank", "_default" or a non special one
151 using SELF/CREATE as search flags.
153 @param nSearchFlags
154 Can be SELF or CREATE only and are set only if sTargetFrameName isn't a special target
156 css::uno::Reference< css::frame::XDispatch > SAL_CALL JobDispatch::queryDispatch( /*IN*/ const css::util::URL& aURL ,
157 /*IN*/ const OUString& /*sTargetFrameName*/ ,
158 /*IN*/ sal_Int32 /*nSearchFlags*/ ) throw(css::uno::RuntimeException)
160 css::uno::Reference< css::frame::XDispatch > xDispatch;
162 JobURL aAnalyzedURL(aURL.Complete);
163 if (aAnalyzedURL.isValid())
164 xDispatch = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
166 return xDispatch;
169 //________________________________
171 @short implementation of XDispatchProvider::queryDispatches()
172 @descr It's an optimized access for remote, so you can ask for
173 multiple dispatch objects at the same time.
175 @param lDescriptor
176 a list of queryDispatch() parameter
178 @return A list of corresponding dispatch objects.
179 NULL references are not skipped. Every result
180 match to one given descriptor item.
182 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)
184 // don't pack resulting list!
185 sal_Int32 nCount = lDescriptor.getLength();
186 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatches(nCount);
188 for (sal_Int32 i=0; i<nCount; ++i)
189 lDispatches[i] = queryDispatch( lDescriptor[i].FeatureURL ,
190 lDescriptor[i].FrameName ,
191 lDescriptor[i].SearchFlags );
192 return lDispatches;
195 //________________________________
197 @short implementation of XNotifyingDispatch::dispatchWithNotification()
198 @descr It creates the job service implementation and call execute on it.
199 Further it starts the life time control of it. (important for async job)
200 For synchonrous job we react for the returned result directly ... for asynchronous
201 ones we do it later inside our callback method. But we use the same impl method
202 doing that to share the code. (see impl_finishJob())
204 If a job is already running, (it can only occure for asynchronous jobs)
205 don't start the same job a second time. Queue in the given dispatch parameter
206 and return immediately. If the current running job call us back, we will start this
207 new dispatch request.
208 If no job is running - queue the parameter too! But then start the new job immediately.
209 We have to queue it every time - because it hold us alive by ref count!
211 @param aURL
212 describe the job(s), which should be started
214 @param lArgs
215 optional arguments for this request
217 @param xListener
218 an interested listener for possible results of this operation
220 void SAL_CALL JobDispatch::dispatchWithNotification( /*IN*/ const css::util::URL& aURL ,
221 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
222 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw(css::uno::RuntimeException)
224 JobURL aAnalyzedURL(aURL.Complete);
225 if (aAnalyzedURL.isValid())
227 OUString sRequest;
228 if (aAnalyzedURL.getEvent(sRequest))
229 impl_dispatchEvent(sRequest, lArgs, xListener);
230 else
231 if (aAnalyzedURL.getService(sRequest))
232 impl_dispatchService(sRequest, lArgs, xListener);
233 else
234 if (aAnalyzedURL.getAlias(sRequest))
235 impl_dispatchAlias(sRequest, lArgs, xListener);
239 //________________________________
241 @short dispatch an event
242 @descr We search all registered jobs for this event and execute it.
243 After doing so, we inform the given listener about the results.
244 (There will be one notify for every executed job!)
246 @param sEvent
247 the event, for which jobs can be registered
249 @param lArgs
250 optional arguments for this request
251 Currently not used!
253 @param xListener
254 an interested listener for possible results of this operation
256 void JobDispatch::impl_dispatchEvent( /*IN*/ const OUString& sEvent ,
257 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
258 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
260 // get list of all enabled jobs
261 // The called static helper methods read it from the configuration and
262 // filter disabled jobs using it's time stamp values.
263 /* SAFE { */
264 ReadGuard aReadLock(m_aLock);
265 css::uno::Sequence< OUString > lJobs = JobData::getEnabledJobsForEvent(comphelper::getComponentContext(m_xSMGR), sEvent);
266 aReadLock.unlock();
267 /* } SAFE */
269 css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
271 // no jobs ... no execution
272 // But a may given listener will know something ...
273 // I think this operaton was finished successfully.
274 // It's not realy an error, if no registered jobs could be located.
275 // Step over all found jobs and execute it
276 int nExecutedJobs=0;
277 for (int j=0; j<lJobs.getLength(); ++j)
279 /* SAFE { */
280 aReadLock.lock();
282 JobData aCfg(comphelper::getComponentContext(m_xSMGR));
283 aCfg.setEvent(sEvent, lJobs[j]);
284 aCfg.setEnvironment(JobData::E_DISPATCH);
285 const bool bIsEnabled=aCfg.hasCorrectContext(m_sModuleIdentifier);
287 /*Attention!
288 Jobs implements interfaces and dies by ref count!
289 And freeing of such uno object is done by uno itself.
290 So we have to use dynamic memory everytimes.
292 Job* pJob = new Job(m_xSMGR, m_xFrame);
293 css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
294 pJob->setJobData(aCfg);
296 aReadLock.unlock();
297 /* } SAFE */
299 if (!bIsEnabled)
300 continue;
302 // Special mode for listener.
303 // We dont notify it directly here. We delegate that
304 // to the job implementation. But we must set ourself there too.
305 // Because this job must fake the source address of the event.
306 // Otherwise the listener may ignore it.
307 if (xListener.is())
308 pJob->setDispatchResultFake(xListener, xThis);
309 pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
310 ++nExecutedJobs;
313 if (nExecutedJobs<1 && xListener.is())
315 css::frame::DispatchResultEvent aEvent;
316 aEvent.Source = xThis;
317 aEvent.State = css::frame::DispatchResultState::SUCCESS;
318 xListener->dispatchFinished(aEvent);
322 //________________________________
324 @short dispatch a service
325 @descr We use the given name only to create and if possible to initialize
326 it as an uno service. It can be useful for creating (caching?)
327 of e.g. one instance services.
329 @param sService
330 the uno implementation or service name of the job, which should be instanciated
332 @param lArgs
333 optional arguments for this request
334 Currently not used!
336 @param xListener
337 an interested listener for possible results of this operation
339 void JobDispatch::impl_dispatchService( /*IN*/ const OUString& sService ,
340 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
341 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
343 /* SAFE { */
344 ReadGuard aReadLock(m_aLock);
346 JobData aCfg(comphelper::getComponentContext(m_xSMGR));
347 aCfg.setService(sService);
348 aCfg.setEnvironment(JobData::E_DISPATCH);
350 /*Attention!
351 Jobs implements interfaces and dies by ref count!
352 And freeing of such uno object is done by uno itself.
353 So we have to use dynamic memory everytimes.
355 Job* pJob = new Job(m_xSMGR, m_xFrame);
356 css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
357 pJob->setJobData(aCfg);
359 aReadLock.unlock();
360 /* } SAFE */
362 css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
364 // Special mode for listener.
365 // We dont notify it directly here. We delegate that
366 // to the job implementation. But we must set ourself there too.
367 // Because this job must fake the source address of the event.
368 // Otherwise the listener may ignore it.
369 if (xListener.is())
370 pJob->setDispatchResultFake(xListener, xThis);
371 pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
374 //________________________________
376 @short dispatch an alias
377 @descr We use this alias to locate a job inside the configuration
378 and execute it. Further we inform the given listener about the results.
380 @param sAlias
381 the alias name of the configured job
383 @param lArgs
384 optional arguments for this request
385 Currently not used!
387 @param xListener
388 an interested listener for possible results of this operation
390 void JobDispatch::impl_dispatchAlias( /*IN*/ const OUString& sAlias ,
391 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
392 /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
394 /* SAFE { */
395 ReadGuard aReadLock(m_aLock);
397 JobData aCfg(comphelper::getComponentContext(m_xSMGR));
398 aCfg.setAlias(sAlias);
399 aCfg.setEnvironment(JobData::E_DISPATCH);
401 /*Attention!
402 Jobs implements interfaces and dies by ref count!
403 And freeing of such uno object is done by uno itself.
404 So we have to use dynamic memory everytimes.
406 Job* pJob = new Job(m_xSMGR, m_xFrame);
407 css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
408 pJob->setJobData(aCfg);
410 aReadLock.unlock();
411 /* } SAFE */
413 css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
415 // Special mode for listener.
416 // We dont notify it directly here. We delegate that
417 // to the job implementation. But we must set ourself there too.
418 // Because this job must fake the source address of the event.
419 // Otherwise the listener may ignore it.
420 if (xListener.is())
421 pJob->setDispatchResultFake(xListener, xThis);
422 pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
425 //________________________________
427 @short implementation of XDispatch::dispatch()
428 @descr Because the methods dispatch() and dispatchWithNotification() are different in her parameters
429 only, we can forward this request to dispatchWithNotification() by using an empty listener!
431 @param aURL
432 describe the job(s), which should be started
434 @param lArgs
435 optional arguments for this request
437 @see dispatchWithNotification()
439 void SAL_CALL JobDispatch::dispatch( /*IN*/ const css::util::URL& aURL ,
440 /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ) throw(css::uno::RuntimeException)
442 dispatchWithNotification(aURL, lArgs, css::uno::Reference< css::frame::XDispatchResultListener >());
445 //________________________________
447 @short not supported
449 void SAL_CALL JobDispatch::addStatusListener( /*IN*/ const css::uno::Reference< css::frame::XStatusListener >&,
450 /*IN*/ const css::util::URL& ) throw(css::uno::RuntimeException)
454 //________________________________
456 @short not supported
458 void SAL_CALL JobDispatch::removeStatusListener( /*IN*/ const css::uno::Reference< css::frame::XStatusListener >&,
459 /*IN*/ const css::util::URL& ) throw(css::uno::RuntimeException)
463 } // namespace framework
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */