1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
31 //________________________________
33 #include <jobs/jobdispatch.hxx>
34 #include <jobs/joburl.hxx>
35 #include <jobs/job.hxx>
36 #include <threadhelp/readguard.hxx>
37 #include <threadhelp/writeguard.hxx>
38 #include <threadhelp/resetableguard.hxx>
39 #include <classes/converter.hxx>
43 //________________________________
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/frame/DispatchResultState.hpp>
48 //________________________________
49 // includes of other projects
50 #include <rtl/ustrbuf.hxx>
51 #include <vcl/svapp.hxx>
53 //________________________________
58 //________________________________
61 //________________________________
62 // non exported definitions
64 //________________________________
67 DEFINE_XINTERFACE_6( JobDispatch
,
69 DIRECT_INTERFACE(css::lang::XTypeProvider
),
70 DIRECT_INTERFACE(css::frame::XDispatchProvider
),
71 DIRECT_INTERFACE(css::lang::XInitialization
),
72 DIRECT_INTERFACE(css::lang::XServiceInfo
),
73 DIRECT_INTERFACE(css::frame::XNotifyingDispatch
),
74 DIRECT_INTERFACE(css::frame::XDispatch
)
77 DEFINE_XTYPEPROVIDER_6( JobDispatch
,
78 css::lang::XTypeProvider
,
79 css::frame::XDispatchProvider
,
80 css::frame::XNotifyingDispatch
,
81 css::lang::XInitialization
,
82 css::lang::XServiceInfo
,
86 DEFINE_XSERVICEINFO_MULTISERVICE( JobDispatch
,
88 SERVICENAME_PROTOCOLHANDLER
,
89 IMPLEMENTATIONNAME_JOBDISPATCH
92 DEFINE_INIT_SERVICE( JobDispatch
,
95 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
96 to create a new instance of this class by our own supported service factory.
97 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
102 //________________________________
105 @descr It initialize this new instance.
108 reference to the uno service manager
110 JobDispatch::JobDispatch( /*IN*/ const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
111 : ThreadHelpBase(&Application::GetSolarMutex())
117 //________________________________
119 @short let this instance die
120 @descr We have to release all used ressources and free used memory.
122 JobDispatch::~JobDispatch()
124 // release all used ressources
125 m_xSMGR
= css::uno::Reference
< css::lang::XMultiServiceFactory
>();
126 m_xFrame
= css::uno::Reference
< css::frame::XFrame
>();
129 //________________________________
131 @short implementation of XInitalization
132 @descr A protocol handler can provide this functionality, if it wish to get additional informations
133 about the context it runs. In this case the frame reference would be given by the outside code.
136 the list of initialization arguments
137 First parameter should be the frame reference we need.
139 void SAL_CALL
JobDispatch::initialize( const css::uno::Sequence
< css::uno::Any
>& lArguments
) throw(css::uno::Exception
,
140 css::uno::RuntimeException
)
143 WriteGuard
aWriteLock(m_aLock
);
145 for (int a
=0; a
<lArguments
.getLength(); ++a
)
148 lArguments
[a
] >>= m_xFrame
;
155 //________________________________
157 @short implementation of XDispatchProvider::queryDispatches()
158 @descr Every protocol handler will be asked for his agreement, if an URL was queried
159 for which this handler is registered. It's the chance for this handler to validate
160 the given URL and return a dispatch object (may be itself) or not.
163 the queried URL, which should be checked
165 @param sTargetFrameName
166 describes the target frame, in which context this handler will be used
167 Is mostly set to "", "_self", "_blank", "_default" or a non special one
168 using SELF/CREATE as search flags.
171 Can be SELF or CREATE only and are set only if sTargetFrameName isn't a special target
173 css::uno::Reference
< css::frame::XDispatch
> SAL_CALL
JobDispatch::queryDispatch( /*IN*/ const css::util::URL
& aURL
,
174 /*IN*/ const ::rtl::OUString
& /*sTargetFrameName*/ ,
175 /*IN*/ sal_Int32
/*nSearchFlags*/ ) throw(css::uno::RuntimeException
)
177 css::uno::Reference
< css::frame::XDispatch
> xDispatch
;
179 JobURL
aAnalyzedURL(aURL
.Complete
);
180 if (aAnalyzedURL
.isValid())
181 xDispatch
= css::uno::Reference
< css::frame::XDispatch
>( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
186 //________________________________
188 @short implementation of XDispatchProvider::queryDispatches()
189 @descr It's an optimized access for remote, so you can ask for
190 multiple dispatch objects at the same time.
193 a list of queryDispatch() parameter
195 @return A list of corresponding dispatch objects.
196 NULL references are not skipped. Every result
197 match to one given descriptor item.
199 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
)
201 // don't pack resulting list!
202 sal_Int32 nCount
= lDescriptor
.getLength();
203 css::uno::Sequence
< css::uno::Reference
< css::frame::XDispatch
> > lDispatches(nCount
);
205 for (sal_Int32 i
=0; i
<nCount
; ++i
)
206 lDispatches
[i
] = queryDispatch( lDescriptor
[i
].FeatureURL
,
207 lDescriptor
[i
].FrameName
,
208 lDescriptor
[i
].SearchFlags
);
212 //________________________________
214 @short implementation of XNotifyingDispatch::dispatchWithNotification()
215 @descr It creates the job service implementation and call execute on it.
216 Further it starts the life time control of it. (important for async job)
217 For synchonrous job we react for the returned result directly ... for asynchronous
218 ones we do it later inside our callback method. But we use the same impl method
219 doing that to share the code. (see impl_finishJob())
221 If a job is already running, (it can only occure for asynchronous jobs)
222 don't start the same job a second time. Queue in the given dispatch parameter
223 and return immediatly. If the current running job call us back, we will start this
224 new dispatch request.
225 If no job is running - queue the parameter too! But then start the new job immediatly.
226 We have to queue it every time - because it hold us alive by ref count!
229 describe the job(s), which should be started
232 optional arguments for this request
235 an interested listener for possible results of this operation
237 void SAL_CALL
JobDispatch::dispatchWithNotification( /*IN*/ const css::util::URL
& aURL
,
238 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
239 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
) throw(css::uno::RuntimeException
)
241 JobURL
aAnalyzedURL(aURL
.Complete
);
242 if (aAnalyzedURL
.isValid())
244 ::rtl::OUString sRequest
;
245 if (aAnalyzedURL
.getEvent(sRequest
))
246 impl_dispatchEvent(sRequest
, lArgs
, xListener
);
248 if (aAnalyzedURL
.getService(sRequest
))
249 impl_dispatchService(sRequest
, lArgs
, xListener
);
251 if (aAnalyzedURL
.getAlias(sRequest
))
252 impl_dispatchAlias(sRequest
, lArgs
, xListener
);
256 //________________________________
258 @short dispatch an event
259 @descr We search all registered jobs for this event and execute it.
260 After doing so, we inform the given listener about the results.
261 (There will be one notify for every executed job!)
264 the event, for which jobs can be registered
267 optional arguments for this request
271 an interested listener for possible results of this operation
273 void JobDispatch::impl_dispatchEvent( /*IN*/ const ::rtl::OUString
& sEvent
,
274 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
275 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
)
277 // get list of all enabled jobs
278 // The called static helper methods read it from the configuration and
279 // filter disabled jobs using it's time stamp values.
281 ReadGuard
aReadLock(m_aLock
);
282 css::uno::Sequence
< ::rtl::OUString
> lJobs
= JobData::getEnabledJobsForEvent(m_xSMGR
, sEvent
);
286 css::uno::Reference
< css::frame::XDispatchResultListener
> xThis( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
288 // no jobs ... no execution
289 // But a may given listener will know something ...
290 // I think this operaton was finished successfully.
291 // It's not realy an error, if no registered jobs could be located.
292 if (lJobs
.getLength()<1 && xListener
.is())
294 css::frame::DispatchResultEvent aEvent
;
295 aEvent
.Source
= xThis
;
296 aEvent
.State
= css::frame::DispatchResultState::SUCCESS
;
297 xListener
->dispatchFinished(aEvent
);
301 // Step over all found jobs and execute it
302 for (int j
=0; j
<lJobs
.getLength(); ++j
)
307 JobData
aCfg(m_xSMGR
);
308 aCfg
.setEvent(sEvent
, lJobs
[j
]);
309 aCfg
.setEnvironment(JobData::E_DISPATCH
);
312 Jobs implements interfaces and dies by ref count!
313 And freeing of such uno object is done by uno itself.
314 So we have to use dynamic memory everytimes.
316 Job
* pJob
= new Job(m_xSMGR
, m_xFrame
);
317 css::uno::Reference
< css::uno::XInterface
> xJob(static_cast< ::cppu::OWeakObject
* >(pJob
), css::uno::UNO_QUERY
);
318 pJob
->setJobData(aCfg
);
323 // Special mode for listener.
324 // We dont notify it directly here. We delegate that
325 // to the job implementation. But we must set ourself there too.
326 // Because this job must fake the source adress of the event.
327 // Otherwhise the listener may will ignore it.
329 pJob
->setDispatchResultFake(xListener
, xThis
);
330 pJob
->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs
));
334 //________________________________
336 @short dispatch a service
337 @descr We use the given name only to create and if possible to initialize
338 it as an uno service. It can be usefully for creating (caching?)
339 of e.g. one instance services.
342 the uno implementation or service name of the job, which should be instanciated
345 optional arguments for this request
349 an interested listener for possible results of this operation
351 void JobDispatch::impl_dispatchService( /*IN*/ const ::rtl::OUString
& sService
,
352 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
353 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
)
356 ReadGuard
aReadLock(m_aLock
);
358 JobData
aCfg(m_xSMGR
);
359 aCfg
.setService(sService
);
360 aCfg
.setEnvironment(JobData::E_DISPATCH
);
363 Jobs implements interfaces and dies by ref count!
364 And freeing of such uno object is done by uno itself.
365 So we have to use dynamic memory everytimes.
367 Job
* pJob
= new Job(m_xSMGR
, m_xFrame
);
368 css::uno::Reference
< css::uno::XInterface
> xJob(static_cast< ::cppu::OWeakObject
* >(pJob
), css::uno::UNO_QUERY
);
369 pJob
->setJobData(aCfg
);
374 css::uno::Reference
< css::frame::XDispatchResultListener
> xThis( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
376 // Special mode for listener.
377 // We dont notify it directly here. We delegate that
378 // to the job implementation. But we must set ourself there too.
379 // Because this job must fake the source adress of the event.
380 // Otherwhise the listener may will ignore it.
382 pJob
->setDispatchResultFake(xListener
, xThis
);
383 pJob
->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs
));
386 //________________________________
388 @short dispatch an alias
389 @descr We use this alias to locate a job inside the configuration
390 and execute it. Further we inform the given listener about the results.
393 the alias name of the configured job
396 optional arguments for this request
400 an interested listener for possible results of this operation
402 void JobDispatch::impl_dispatchAlias( /*IN*/ const ::rtl::OUString
& sAlias
,
403 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
,
404 /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
)
407 ReadGuard
aReadLock(m_aLock
);
409 JobData
aCfg(m_xSMGR
);
410 aCfg
.setAlias(sAlias
);
411 aCfg
.setEnvironment(JobData::E_DISPATCH
);
414 Jobs implements interfaces and dies by ref count!
415 And freeing of such uno object is done by uno itself.
416 So we have to use dynamic memory everytimes.
418 Job
* pJob
= new Job(m_xSMGR
, m_xFrame
);
419 css::uno::Reference
< css::uno::XInterface
> xJob(static_cast< ::cppu::OWeakObject
* >(pJob
), css::uno::UNO_QUERY
);
420 pJob
->setJobData(aCfg
);
425 css::uno::Reference
< css::frame::XDispatchResultListener
> xThis( static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
427 // Special mode for listener.
428 // We dont notify it directly here. We delegate that
429 // to the job implementation. But we must set ourself there too.
430 // Because this job must fake the source adress of the event.
431 // Otherwhise the listener may will ignore it.
433 pJob
->setDispatchResultFake(xListener
, xThis
);
434 pJob
->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs
));
437 //________________________________
439 @short implementation of XDispatch::dispatch()
440 @descr Because the methods dispatch() and dispatchWithNotification() are different in her parameters
441 only, we can forward this request to dispatchWithNotification() by using an empty listener!
444 describe the job(s), which should be started
447 optional arguments for this request
449 @see dispatchWithNotification()
451 void SAL_CALL
JobDispatch::dispatch( /*IN*/ const css::util::URL
& aURL
,
452 /*IN*/ const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
) throw(css::uno::RuntimeException
)
454 dispatchWithNotification(aURL
, lArgs
, css::uno::Reference
< css::frame::XDispatchResultListener
>());
457 //________________________________
461 void SAL_CALL
JobDispatch::addStatusListener( /*IN*/ const css::uno::Reference
< css::frame::XStatusListener
>&,
462 /*IN*/ const css::util::URL
& ) throw(css::uno::RuntimeException
)
466 //________________________________
470 void SAL_CALL
JobDispatch::removeStatusListener( /*IN*/ const css::uno::Reference
< css::frame::XStatusListener
>&,
471 /*IN*/ const css::util::URL
& ) throw(css::uno::RuntimeException
)
475 } // namespace framework