Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <jobs/jobdispatch.hxx>
30 : : #include <jobs/joburl.hxx>
31 : : #include <jobs/job.hxx>
32 : : #include <threadhelp/readguard.hxx>
33 : : #include <threadhelp/writeguard.hxx>
34 : : #include <threadhelp/resetableguard.hxx>
35 : : #include <classes/converter.hxx>
36 : : #include <general.h>
37 : : #include <services.h>
38 : :
39 : : #include <com/sun/star/beans/XPropertySet.hpp>
40 : : #include <com/sun/star/frame/DispatchResultState.hpp>
41 : : #include <com/sun/star/frame/XModuleManager.hpp>
42 : :
43 : : #include <rtl/ustrbuf.hxx>
44 : : #include <vcl/svapp.hxx>
45 : :
46 : : namespace framework{
47 : :
48 [ # # ][ # # ]: 0 : DEFINE_XINTERFACE_6( JobDispatch ,
49 : : OWeakObject ,
50 : : DIRECT_INTERFACE(css::lang::XTypeProvider ),
51 : : DIRECT_INTERFACE(css::frame::XDispatchProvider ),
52 : : DIRECT_INTERFACE(css::lang::XInitialization ),
53 : : DIRECT_INTERFACE(css::lang::XServiceInfo),
54 : : DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
55 : : DIRECT_INTERFACE(css::frame::XDispatch )
56 : : )
57 : :
58 [ # # ][ # # ]: 0 : DEFINE_XTYPEPROVIDER_6( JobDispatch ,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
59 : : css::lang::XTypeProvider ,
60 : : css::frame::XDispatchProvider ,
61 : : css::frame::XNotifyingDispatch,
62 : : css::lang::XInitialization,
63 : : css::lang::XServiceInfo,
64 : : css::frame::XDispatch
65 : : )
66 : :
67 [ # # ][ # # ]: 2650 : DEFINE_XSERVICEINFO_MULTISERVICE( JobDispatch ,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
68 : : ::cppu::OWeakObject ,
69 : : SERVICENAME_PROTOCOLHANDLER ,
70 : : IMPLEMENTATIONNAME_JOBDISPATCH
71 : : )
72 : :
73 : 0 : DEFINE_INIT_SERVICE( JobDispatch,
74 : : {
75 : : /*Attention
76 : : I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
77 : : to create a new instance of this class by our own supported service factory.
78 : : see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
79 : : */
80 : : }
81 : : )
82 : :
83 : : //________________________________
84 : : /**
85 : : @short standard ctor
86 : : @descr It initialize this new instance.
87 : :
88 : : @param xSMGR
89 : : reference to the uno service manager
90 : : */
91 : 0 : JobDispatch::JobDispatch( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
92 [ # # ]: 0 : : ThreadHelpBase(&Application::GetSolarMutex())
93 : : , OWeakObject ( )
94 [ # # ]: 0 : , m_xSMGR (xSMGR )
95 : : {
96 : 0 : }
97 : :
98 : : //________________________________
99 : : /**
100 : : @short let this instance die
101 : : @descr We have to release all used resources and free used memory.
102 : : */
103 [ # # ][ # # ]: 0 : JobDispatch::~JobDispatch()
104 : : {
105 : : // release all used resources
106 [ # # ]: 0 : m_xSMGR = css::uno::Reference< css::lang::XMultiServiceFactory >();
107 [ # # ]: 0 : m_xFrame = css::uno::Reference< css::frame::XFrame >();
108 [ # # ]: 0 : }
109 : :
110 : : //________________________________
111 : : /**
112 : : @short implementation of XInitalization
113 : : @descr A protocol handler can provide this functionality, if it wish to get additional informations
114 : : about the context it runs. In this case the frame reference would be given by the outside code.
115 : :
116 : : @param lArguments
117 : : the list of initialization arguments
118 : : First parameter should be the frame reference we need.
119 : : */
120 : 0 : void SAL_CALL JobDispatch::initialize( const css::uno::Sequence< css::uno::Any >& lArguments ) throw(css::uno::Exception ,
121 : : css::uno::RuntimeException)
122 : : {
123 : : /* SAFE { */
124 [ # # ]: 0 : WriteGuard aWriteLock(m_aLock);
125 : :
126 [ # # ]: 0 : for (int a=0; a<lArguments.getLength(); ++a)
127 : : {
128 [ # # ]: 0 : if (a==0)
129 : : {
130 [ # # ]: 0 : lArguments[a] >>= m_xFrame;
131 : :
132 : : css::uno::Reference< css::frame::XModuleManager > xModuleManager(
133 [ # # ]: 0 : m_xSMGR->createInstance(
134 : 0 : SERVICENAME_MODULEMANAGER ),
135 [ # # ][ # # ]: 0 : css::uno::UNO_QUERY_THROW );
[ # # ][ # # ]
136 : : try
137 : : {
138 [ # # ][ # # ]: 0 : m_sModuleIdentifier = xModuleManager->identify( m_xFrame );
139 : : }
140 [ # # ]: 0 : catch( const css::uno::Exception& )
141 : 0 : {}
142 : : }
143 : : }
144 : :
145 [ # # ][ # # ]: 0 : aWriteLock.unlock();
146 : : /* } SAFE */
147 : 0 : }
148 : :
149 : : //________________________________
150 : : /**
151 : : @short implementation of XDispatchProvider::queryDispatches()
152 : : @descr Every protocol handler will be asked for his agreement, if an URL was queried
153 : : for which this handler is registered. It's the chance for this handler to validate
154 : : the given URL and return a dispatch object (may be itself) or not.
155 : :
156 : : @param aURL
157 : : the queried URL, which should be checked
158 : :
159 : : @param sTargetFrameName
160 : : describes the target frame, in which context this handler will be used
161 : : Is mostly set to "", "_self", "_blank", "_default" or a non special one
162 : : using SELF/CREATE as search flags.
163 : :
164 : : @param nSearchFlags
165 : : Can be SELF or CREATE only and are set only if sTargetFrameName isn't a special target
166 : : */
167 : 0 : css::uno::Reference< css::frame::XDispatch > SAL_CALL JobDispatch::queryDispatch( /*IN*/ const css::util::URL& aURL ,
168 : : /*IN*/ const ::rtl::OUString& /*sTargetFrameName*/ ,
169 : : /*IN*/ sal_Int32 /*nSearchFlags*/ ) throw(css::uno::RuntimeException)
170 : : {
171 : 0 : css::uno::Reference< css::frame::XDispatch > xDispatch;
172 : :
173 [ # # ]: 0 : JobURL aAnalyzedURL(aURL.Complete);
174 [ # # ][ # # ]: 0 : if (aAnalyzedURL.isValid())
175 [ # # ][ # # ]: 0 : xDispatch = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
176 : :
177 [ # # ]: 0 : return xDispatch;
178 : : }
179 : :
180 : : //________________________________
181 : : /**
182 : : @short implementation of XDispatchProvider::queryDispatches()
183 : : @descr It's an optimized access for remote, so you can ask for
184 : : multiple dispatch objects at the same time.
185 : :
186 : : @param lDescriptor
187 : : a list of queryDispatch() parameter
188 : :
189 : : @return A list of corresponding dispatch objects.
190 : : NULL references are not skipped. Every result
191 : : match to one given descriptor item.
192 : : */
193 : 0 : 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)
194 : : {
195 : : // don't pack resulting list!
196 : 0 : sal_Int32 nCount = lDescriptor.getLength();
197 : 0 : css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatches(nCount);
198 : :
199 [ # # ]: 0 : for (sal_Int32 i=0; i<nCount; ++i)
200 [ # # ]: 0 : lDispatches[i] = queryDispatch( lDescriptor[i].FeatureURL ,
201 : 0 : lDescriptor[i].FrameName ,
202 [ # # ][ # # ]: 0 : lDescriptor[i].SearchFlags );
203 : 0 : return lDispatches;
204 : : }
205 : :
206 : : //________________________________
207 : : /**
208 : : @short implementation of XNotifyingDispatch::dispatchWithNotification()
209 : : @descr It creates the job service implementation and call execute on it.
210 : : Further it starts the life time control of it. (important for async job)
211 : : For synchonrous job we react for the returned result directly ... for asynchronous
212 : : ones we do it later inside our callback method. But we use the same impl method
213 : : doing that to share the code. (see impl_finishJob())
214 : :
215 : : If a job is already running, (it can only occure for asynchronous jobs)
216 : : don't start the same job a second time. Queue in the given dispatch parameter
217 : : and return immediatly. If the current running job call us back, we will start this
218 : : new dispatch request.
219 : : If no job is running - queue the parameter too! But then start the new job immediatly.
220 : : We have to queue it every time - because it hold us alive by ref count!
221 : :
222 : : @param aURL
223 : : describe the job(s), which should be started
224 : :
225 : : @param lArgs
226 : : optional arguments for this request
227 : :
228 : : @param xListener
229 : : an interested listener for possible results of this operation
230 : : */
231 : 0 : void SAL_CALL JobDispatch::dispatchWithNotification( /*IN*/ const css::util::URL& aURL ,
232 : : /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
233 : : /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw(css::uno::RuntimeException)
234 : : {
235 [ # # ]: 0 : JobURL aAnalyzedURL(aURL.Complete);
236 [ # # ][ # # ]: 0 : if (aAnalyzedURL.isValid())
237 : : {
238 : 0 : ::rtl::OUString sRequest;
239 [ # # ][ # # ]: 0 : if (aAnalyzedURL.getEvent(sRequest))
240 [ # # ]: 0 : impl_dispatchEvent(sRequest, lArgs, xListener);
241 : : else
242 [ # # ][ # # ]: 0 : if (aAnalyzedURL.getService(sRequest))
243 [ # # ]: 0 : impl_dispatchService(sRequest, lArgs, xListener);
244 : : else
245 [ # # ][ # # ]: 0 : if (aAnalyzedURL.getAlias(sRequest))
246 [ # # ]: 0 : impl_dispatchAlias(sRequest, lArgs, xListener);
247 [ # # ]: 0 : }
248 : 0 : }
249 : :
250 : : //________________________________
251 : : /**
252 : : @short dispatch an event
253 : : @descr We search all registered jobs for this event and execute it.
254 : : After doing so, we inform the given listener about the results.
255 : : (There will be one notify for every executed job!)
256 : :
257 : : @param sEvent
258 : : the event, for which jobs can be registered
259 : :
260 : : @param lArgs
261 : : optional arguments for this request
262 : : Currently not used!
263 : :
264 : : @param xListener
265 : : an interested listener for possible results of this operation
266 : : */
267 : 0 : void JobDispatch::impl_dispatchEvent( /*IN*/ const ::rtl::OUString& sEvent ,
268 : : /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
269 : : /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
270 : : {
271 : : // get list of all enabled jobs
272 : : // The called static helper methods read it from the configuration and
273 : : // filter disabled jobs using it's time stamp values.
274 : : /* SAFE { */
275 [ # # ]: 0 : ReadGuard aReadLock(m_aLock);
276 [ # # ]: 0 : css::uno::Sequence< ::rtl::OUString > lJobs = JobData::getEnabledJobsForEvent(m_xSMGR, sEvent);
277 [ # # ]: 0 : aReadLock.unlock();
278 : : /* } SAFE */
279 : :
280 [ # # ]: 0 : css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
281 : :
282 : : // no jobs ... no execution
283 : : // But a may given listener will know something ...
284 : : // I think this operaton was finished successfully.
285 : : // It's not realy an error, if no registered jobs could be located.
286 : : // Step over all found jobs and execute it
287 : 0 : int nExecutedJobs=0;
288 [ # # ]: 0 : for (int j=0; j<lJobs.getLength(); ++j)
289 : : {
290 : : /* SAFE { */
291 [ # # ]: 0 : aReadLock.lock();
292 : :
293 [ # # ]: 0 : JobData aCfg(m_xSMGR);
294 [ # # ][ # # ]: 0 : aCfg.setEvent(sEvent, lJobs[j]);
295 [ # # ]: 0 : aCfg.setEnvironment(JobData::E_DISPATCH);
296 [ # # ]: 0 : const bool bIsEnabled=aCfg.hasCorrectContext(m_sModuleIdentifier);
297 : :
298 : : /*Attention!
299 : : Jobs implements interfaces and dies by ref count!
300 : : And freeing of such uno object is done by uno itself.
301 : : So we have to use dynamic memory everytimes.
302 : : */
303 [ # # ]: 0 : Job* pJob = new Job(m_xSMGR, m_xFrame);
304 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
305 [ # # ]: 0 : pJob->setJobData(aCfg);
306 : :
307 [ # # ]: 0 : aReadLock.unlock();
308 : : /* } SAFE */
309 : :
310 [ # # ]: 0 : if (!bIsEnabled)
311 : 0 : continue;
312 : :
313 : : // Special mode for listener.
314 : : // We dont notify it directly here. We delegate that
315 : : // to the job implementation. But we must set ourself there too.
316 : : // Because this job must fake the source address of the event.
317 : : // Otherwise the listener may ignore it.
318 [ # # ]: 0 : if (xListener.is())
319 [ # # ]: 0 : pJob->setDispatchResultFake(xListener, xThis);
320 [ # # ][ # # ]: 0 : pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
[ # # ]
321 [ # # ]: 0 : ++nExecutedJobs;
322 [ # # ][ # # ]: 0 : }
323 : :
324 [ # # ][ # # ]: 0 : if (nExecutedJobs<1 && xListener.is())
[ # # ]
325 : : {
326 [ # # ]: 0 : css::frame::DispatchResultEvent aEvent;
327 [ # # ]: 0 : aEvent.Source = xThis;
328 : 0 : aEvent.State = css::frame::DispatchResultState::SUCCESS;
329 [ # # ][ # # ]: 0 : xListener->dispatchFinished(aEvent);
[ # # ]
330 [ # # ][ # # ]: 0 : }
331 : 0 : }
332 : :
333 : : //________________________________
334 : : /**
335 : : @short dispatch a service
336 : : @descr We use the given name only to create and if possible to initialize
337 : : it as an uno service. It can be usefully for creating (caching?)
338 : : of e.g. one instance services.
339 : :
340 : : @param sService
341 : : the uno implementation or service name of the job, which should be instanciated
342 : :
343 : : @param lArgs
344 : : optional arguments for this request
345 : : Currently not used!
346 : :
347 : : @param xListener
348 : : an interested listener for possible results of this operation
349 : : */
350 : 0 : void JobDispatch::impl_dispatchService( /*IN*/ const ::rtl::OUString& sService ,
351 : : /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
352 : : /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
353 : : {
354 : : /* SAFE { */
355 [ # # ]: 0 : ReadGuard aReadLock(m_aLock);
356 : :
357 [ # # ]: 0 : JobData aCfg(m_xSMGR);
358 [ # # ]: 0 : aCfg.setService(sService);
359 [ # # ]: 0 : aCfg.setEnvironment(JobData::E_DISPATCH);
360 : :
361 : : /*Attention!
362 : : Jobs implements interfaces and dies by ref count!
363 : : And freeing of such uno object is done by uno itself.
364 : : So we have to use dynamic memory everytimes.
365 : : */
366 [ # # ]: 0 : Job* pJob = new Job(m_xSMGR, m_xFrame);
367 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
368 [ # # ]: 0 : pJob->setJobData(aCfg);
369 : :
370 [ # # ]: 0 : aReadLock.unlock();
371 : : /* } SAFE */
372 : :
373 [ # # ]: 0 : css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
374 : :
375 : : // Special mode for listener.
376 : : // We dont notify it directly here. We delegate that
377 : : // to the job implementation. But we must set ourself there too.
378 : : // Because this job must fake the source address of the event.
379 : : // Otherwise the listener may ignore it.
380 [ # # ]: 0 : if (xListener.is())
381 [ # # ]: 0 : pJob->setDispatchResultFake(xListener, xThis);
382 [ # # ][ # # ]: 0 : pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
[ # # ][ # # ]
[ # # ]
383 : 0 : }
384 : :
385 : : //________________________________
386 : : /**
387 : : @short dispatch an alias
388 : : @descr We use this alias to locate a job inside the configuration
389 : : and execute it. Further we inform the given listener about the results.
390 : :
391 : : @param sAlias
392 : : the alias name of the configured job
393 : :
394 : : @param lArgs
395 : : optional arguments for this request
396 : : Currently not used!
397 : :
398 : : @param xListener
399 : : an interested listener for possible results of this operation
400 : : */
401 : 0 : void JobDispatch::impl_dispatchAlias( /*IN*/ const ::rtl::OUString& sAlias ,
402 : : /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ,
403 : : /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
404 : : {
405 : : /* SAFE { */
406 [ # # ]: 0 : ReadGuard aReadLock(m_aLock);
407 : :
408 [ # # ]: 0 : JobData aCfg(m_xSMGR);
409 [ # # ]: 0 : aCfg.setAlias(sAlias);
410 [ # # ]: 0 : aCfg.setEnvironment(JobData::E_DISPATCH);
411 : :
412 : : /*Attention!
413 : : Jobs implements interfaces and dies by ref count!
414 : : And freeing of such uno object is done by uno itself.
415 : : So we have to use dynamic memory everytimes.
416 : : */
417 [ # # ]: 0 : Job* pJob = new Job(m_xSMGR, m_xFrame);
418 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
419 [ # # ]: 0 : pJob->setJobData(aCfg);
420 : :
421 [ # # ]: 0 : aReadLock.unlock();
422 : : /* } SAFE */
423 : :
424 [ # # ]: 0 : css::uno::Reference< css::frame::XDispatchResultListener > xThis( static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY );
425 : :
426 : : // Special mode for listener.
427 : : // We dont notify it directly here. We delegate that
428 : : // to the job implementation. But we must set ourself there too.
429 : : // Because this job must fake the source address of the event.
430 : : // Otherwise the listener may ignore it.
431 [ # # ]: 0 : if (xListener.is())
432 [ # # ]: 0 : pJob->setDispatchResultFake(xListener, xThis);
433 [ # # ][ # # ]: 0 : pJob->execute(Converter::convert_seqPropVal2seqNamedVal(lArgs));
[ # # ][ # # ]
[ # # ]
434 : 0 : }
435 : :
436 : : //________________________________
437 : : /**
438 : : @short implementation of XDispatch::dispatch()
439 : : @descr Because the methods dispatch() and dispatchWithNotification() are different in her parameters
440 : : only, we can forward this request to dispatchWithNotification() by using an empty listener!
441 : :
442 : : @param aURL
443 : : describe the job(s), which should be started
444 : :
445 : : @param lArgs
446 : : optional arguments for this request
447 : :
448 : : @see dispatchWithNotification()
449 : : */
450 : 0 : void SAL_CALL JobDispatch::dispatch( /*IN*/ const css::util::URL& aURL ,
451 : : /*IN*/ const css::uno::Sequence< css::beans::PropertyValue >& lArgs ) throw(css::uno::RuntimeException)
452 : : {
453 [ # # ]: 0 : dispatchWithNotification(aURL, lArgs, css::uno::Reference< css::frame::XDispatchResultListener >());
454 : 0 : }
455 : :
456 : : //________________________________
457 : : /**
458 : : @short not supported
459 : : */
460 : 0 : void SAL_CALL JobDispatch::addStatusListener( /*IN*/ const css::uno::Reference< css::frame::XStatusListener >&,
461 : : /*IN*/ const css::util::URL& ) throw(css::uno::RuntimeException)
462 : : {
463 : 0 : }
464 : :
465 : : //________________________________
466 : : /**
467 : : @short not supported
468 : : */
469 : 0 : void SAL_CALL JobDispatch::removeStatusListener( /*IN*/ const css::uno::Reference< css::frame::XStatusListener >&,
470 : : /*IN*/ const css::util::URL& ) throw(css::uno::RuntimeException)
471 : : {
472 : 0 : }
473 : :
474 : : } // namespace framework
475 : :
476 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|