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/job.hxx>
21 #include <threadhelp/readguard.hxx>
22 #include <threadhelp/writeguard.hxx>
26 #include <com/sun/star/frame/Desktop.hpp>
27 #include <com/sun/star/task/XJob.hpp>
28 #include <com/sun/star/task/XAsyncJob.hpp>
29 #include <com/sun/star/util/XCloseBroadcaster.hpp>
30 #include <com/sun/star/util/XCloseable.hpp>
31 #include <com/sun/star/lang/DisposedException.hpp>
33 #include <comphelper/processfactory.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <vcl/svapp.hxx>
39 DEFINE_XINTERFACE_4( Job
,
41 DIRECT_INTERFACE(css::lang::XTypeProvider
),
42 DIRECT_INTERFACE(css::task::XJobListener
),
43 DIRECT_INTERFACE(css::frame::XTerminateListener
),
44 DIRECT_INTERFACE(css::util::XCloseListener
)
47 DEFINE_XTYPEPROVIDER_4( Job
,
48 css::lang::XTypeProvider
,
49 css::task::XJobListener
,
50 css::frame::XTerminateListener
,
51 css::util::XCloseListener
54 //________________________________
57 @descr It initialize this new instance. But it set some generic parameters here only.
58 Specialized information (e.g. the alias or service name ofthis job) will be set
59 later using the method setJobData().
62 reference to the uno service manager
65 reference to the frame, in which environment we run
68 Job::Job( /*IN*/ const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
,
69 /*IN*/ const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
70 : ThreadHelpBase (&Application::GetSolarMutex())
71 , ::cppu::OWeakObject ( )
72 , m_aJobCfg (comphelper::getComponentContext(xSMGR
))
75 , m_bListenOnDesktop (sal_False
)
76 , m_bListenOnFrame (sal_False
)
77 , m_bListenOnModel (sal_False
)
78 , m_bPendingCloseFrame (sal_False
)
79 , m_bPendingCloseModel (sal_False
)
80 , m_eRunState (E_NEW
)
84 //________________________________
87 @descr It initialize this new instance. But it set some generic parameters here only.
88 Specialized information (e.g. the alias or service name ofthis job) will be set
89 later using the method setJobData().
92 reference to the uno service manager
95 reference to the model, in which environment we run
98 Job::Job( /*IN*/ const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
,
99 /*IN*/ const css::uno::Reference
< css::frame::XModel
>& xModel
)
100 : ThreadHelpBase (&Application::GetSolarMutex())
101 , ::cppu::OWeakObject ( )
102 , m_aJobCfg (comphelper::getComponentContext(xSMGR
))
105 , m_bListenOnDesktop (sal_False
)
106 , m_bListenOnFrame (sal_False
)
107 , m_bListenOnModel (sal_False
)
108 , m_bPendingCloseFrame (sal_False
)
109 , m_bPendingCloseModel (sal_False
)
110 , m_eRunState (E_NEW
)
114 //________________________________
117 @descr Releasing of memory and reference must be done inside die() call.
118 Otherwhise it's a bug.
124 //________________________________
126 @short set (or delete) a listener for sending dispatch result events
127 @descr Because this object is used in a wrapped mode ... the original listener
128 for such events can't be registered here directly. Because the
129 listener expect to get the original object given as source of the event.
130 That's why we get this source here too, to fake(!) it at sending time!
133 the original listener for dispatch result events
136 our user, which got the registration request for this listener
138 void Job::setDispatchResultFake( /*IN*/ const css::uno::Reference
< css::frame::XDispatchResultListener
>& xListener
,
139 /*IN*/ const css::uno::Reference
< css::uno::XInterface
>& xSourceFake
)
142 WriteGuard
aWriteLock(m_aLock
);
144 // reject dangerous calls
145 if (m_eRunState
!= E_NEW
)
147 LOG_WARNING("Job::setJobData()", "job may still running or already finished")
151 m_xResultListener
= xListener
;
152 m_xResultSourceFake
= xSourceFake
;
157 void Job::setJobData( const JobData
& aData
)
160 WriteGuard
aWriteLock(m_aLock
);
162 // reject dangerous calls
163 if (m_eRunState
!= E_NEW
)
165 LOG_WARNING("Job::setJobData()", "job may still running or already finished")
174 //________________________________
177 @descr It doesn't matter, if the job is an asynchronous or
178 synchronous one. This method returns only if it was finished
182 optional arguments for job execution
183 In case the represented job is a configured one (which uses static
184 arguments too) all information will be merged!
186 void Job::execute( /*IN*/ const css::uno::Sequence
< css::beans::NamedValue
>& lDynamicArgs
)
189 WriteGuard
aWriteLock(m_aLock
);
191 // reject dangerous calls
192 if (m_eRunState
!= E_NEW
)
194 LOG_WARNING("Job::execute()", "job may still running or already finished")
198 // create the environment and mark this job as running ...
199 m_eRunState
= E_RUNNING
;
200 impl_startListening();
202 css::uno::Reference
< css::task::XAsyncJob
> xAJob
;
203 css::uno::Reference
< css::task::XJob
> xSJob
;
204 css::uno::Sequence
< css::beans::NamedValue
> lJobArgs
= impl_generateJobArgs(lDynamicArgs
);
206 // It's necessary to hold us self alive!
207 // Otherwhise we might die by ref count ...
208 css::uno::Reference
< css::task::XJobListener
> xThis(static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
213 // We must check for the supported interface on demand!
214 // But we preferr the synchronous one ...
215 m_xJob
= m_xSMGR
->createInstance(m_aJobCfg
.getService());
216 xSJob
= css::uno::Reference
< css::task::XJob
>(m_xJob
, css::uno::UNO_QUERY
);
218 xAJob
= css::uno::Reference
< css::task::XAsyncJob
>(m_xJob
, css::uno::UNO_QUERY
);
220 // execute it asynchron
223 m_aAsyncWait
.reset();
226 xAJob
->executeAsync(lJobArgs
, xThis
);
227 // wait for finishing this job - so this method
228 // does the same for synchronous and asynchronous jobs!
232 // Note: Result handling was already done inside the callback!
234 // execute it synchron
239 css::uno::Any aResult
= xSJob
->execute(lJobArgs
);
242 impl_reactForJobResult(aResult
);
245 #if OSL_DEBUG_LEVEL > 0
246 catch(const css::uno::Exception
& ex
)
248 OUStringBuffer
sMsg(256);
249 sMsg
.appendAscii("Got exception during job execution. Original Message was:\n\"");
250 sMsg
.append (ex
.Message
);
251 sMsg
.appendAscii("\"");
252 LOG_WARNING("Job::execute()", U2B(sMsg
.makeStringAndClear()).getStr())
255 catch(const css::uno::Exception
&)
259 // deinitialize the environment and mark this job as finished ...
260 // but don't overwrite any information about STOPPED or might DISPOSED jobs!
261 impl_stopListening();
262 if (m_eRunState
== E_RUNNING
)
263 m_eRunState
= E_STOPPED_OR_FINISHED
;
265 // If we got a close request from our frame or model ...
266 // but we disagreed wit that by throwing a veto exception...
267 // and got the ownership ...
268 // we have to close the resource frame or model now -
269 // and to disable ourself!
270 if (m_bPendingCloseFrame
)
272 m_bPendingCloseFrame
= sal_False
;
273 css::uno::Reference
< css::util::XCloseable
> xClose(m_xFrame
, css::uno::UNO_QUERY
);
278 xClose
->close(sal_True
);
280 catch(const css::util::CloseVetoException
&) {}
284 if (m_bPendingCloseModel
)
286 m_bPendingCloseModel
= sal_False
;
287 css::uno::Reference
< css::util::XCloseable
> xClose(m_xModel
, css::uno::UNO_QUERY
);
292 xClose
->close(sal_True
);
294 catch(const css::util::CloseVetoException
&) {}
301 // release this instance ...
305 //________________________________
308 @descr It doesn't matter if this request is called from inside or
309 from outside. We release our internal structures and stop
310 avary activity. After doing so - this instance will not be
311 useable any longer! Of course we try to handle further requests
312 carefully. May somehwere else hold a reference to us ...
317 WriteGuard
aWriteLock(m_aLock
);
319 impl_stopListening();
321 if (m_eRunState
!= E_DISPOSED
)
325 css::uno::Reference
< css::lang::XComponent
> xDispose(m_xJob
, css::uno::UNO_QUERY
);
329 m_eRunState
= E_DISPOSED
;
332 catch(const css::lang::DisposedException
&)
334 m_eRunState
= E_DISPOSED
;
338 m_xJob
= css::uno::Reference
< css::uno::XInterface
>();
339 m_xFrame
= css::uno::Reference
< css::frame::XFrame
>();
340 m_xModel
= css::uno::Reference
< css::frame::XModel
>();
341 m_xDesktop
= css::uno::Reference
< css::frame::XDesktop2
>();
342 m_xResultListener
= css::uno::Reference
< css::frame::XDispatchResultListener
>();
343 m_xResultSourceFake
= css::uno::Reference
< css::uno::XInterface
>();
344 m_bPendingCloseFrame
= sal_False
;
345 m_bPendingCloseModel
= sal_False
;
351 //________________________________
353 @short generates list of arguments for job execute
354 @descr There exist a set of information, which can be needed by a job.
355 a) it's static configuration data (Equals for all jobs. )
356 b) it's specific configuration data (Different for every job.)
357 c) some environment values (e.g. the frame, for which this job was started)
358 d) any other dynamic data (e.g. parameters of a dispatch() request)
359 We collect all these information and generate one list which include all others.
362 list of dynamic arguments (given by a corresponding dispatch() call)
365 @return A list which includes all mentioned sub lists.
367 css::uno::Sequence
< css::beans::NamedValue
> Job::impl_generateJobArgs( /*IN*/ const css::uno::Sequence
< css::beans::NamedValue
>& lDynamicArgs
)
369 css::uno::Sequence
< css::beans::NamedValue
> lAllArgs
;
372 ReadGuard
aReadLock(m_aLock
);
374 // the real structure of the returned list depends from the environment of this job!
375 JobData::EMode eMode
= m_aJobCfg
.getMode();
377 // Create list of environment variables. This list must be part of the
378 // returned structure everytimes ... but some of its members are opetional!
379 css::uno::Sequence
< css::beans::NamedValue
> lEnvArgs(1);
380 lEnvArgs
[0].Name
= OUString::createFromAscii(JobData::PROP_ENVTYPE
);
381 lEnvArgs
[0].Value
<<= m_aJobCfg
.getEnvironmentDescriptor();
385 sal_Int32 c
= lEnvArgs
.getLength();
386 lEnvArgs
.realloc(c
+1);
387 lEnvArgs
[c
].Name
= OUString::createFromAscii(JobData::PROP_FRAME
);
388 lEnvArgs
[c
].Value
<<= m_xFrame
;
392 sal_Int32 c
= lEnvArgs
.getLength();
393 lEnvArgs
.realloc(c
+1);
394 lEnvArgs
[c
].Name
= OUString::createFromAscii(JobData::PROP_MODEL
);
395 lEnvArgs
[c
].Value
<<= m_xModel
;
397 if (eMode
==JobData::E_EVENT
)
399 sal_Int32 c
= lEnvArgs
.getLength();
400 lEnvArgs
.realloc(c
+1);
401 lEnvArgs
[c
].Name
= OUString::createFromAscii(JobData::PROP_EVENTNAME
);
402 lEnvArgs
[c
].Value
<<= m_aJobCfg
.getEvent();
405 // get the configuration data from the job data container ... if possible
406 // Means: if this job has any configuration data. Note: only realy
407 // filled lists will be set to the return structure at the end of this method.
408 css::uno::Sequence
< css::beans::NamedValue
> lConfigArgs
;
409 css::uno::Sequence
< css::beans::NamedValue
> lJobConfigArgs
;
410 if (eMode
==JobData::E_ALIAS
|| eMode
==JobData::E_EVENT
)
412 lConfigArgs
= m_aJobCfg
.getConfig();
413 lJobConfigArgs
= m_aJobCfg
.getJobConfig();
419 // Add all valid (not empty) lists to the return list
420 if (lConfigArgs
.getLength()>0)
422 sal_Int32 nLength
= lAllArgs
.getLength();
423 lAllArgs
.realloc(nLength
+1);
424 lAllArgs
[nLength
].Name
= OUString::createFromAscii(JobData::PROPSET_CONFIG
);
425 lAllArgs
[nLength
].Value
<<= lConfigArgs
;
427 if (lJobConfigArgs
.getLength()>0)
429 sal_Int32 nLength
= lAllArgs
.getLength();
430 lAllArgs
.realloc(nLength
+1);
431 lAllArgs
[nLength
].Name
= OUString::createFromAscii(JobData::PROPSET_OWNCONFIG
);
432 lAllArgs
[nLength
].Value
<<= lJobConfigArgs
;
434 if (lEnvArgs
.getLength()>0)
436 sal_Int32 nLength
= lAllArgs
.getLength();
437 lAllArgs
.realloc(nLength
+1);
438 lAllArgs
[nLength
].Name
= OUString::createFromAscii(JobData::PROPSET_ENVIRONMENT
);
439 lAllArgs
[nLength
].Value
<<= lEnvArgs
;
441 if (lDynamicArgs
.getLength()>0)
443 sal_Int32 nLength
= lAllArgs
.getLength();
444 lAllArgs
.realloc(nLength
+1);
445 lAllArgs
[nLength
].Name
= OUString::createFromAscii(JobData::PROPSET_DYNAMICDATA
);
446 lAllArgs
[nLength
].Value
<<= lDynamicArgs
;
452 //________________________________
454 @short analyze the given job result and change the job configuration
455 @descr Note: Some results can be handled only, if this job has a valid configuration!
456 For "not configured jobs" (means pure services) they can be ignored.
457 But these cases are handled by our JobData member. We can call it everytime.
458 It does the right things automaticly. E.g. if the job has no configuration ...
459 it does nothing during setJobConfig()!
462 the job result for analyzing
464 void Job::impl_reactForJobResult( /*IN*/ const css::uno::Any
& aResult
)
467 WriteGuard
aWriteLock(m_aLock
);
469 // analyze the result set ...
470 JobResult
aAnalyzedResult(aResult
);
472 // some of the following operations will be supported for different environments
473 // or different type of jobs only.
474 JobData::EEnvironment eEnvironment
= m_aJobCfg
.getEnvironment();
476 // write back the job specific configuration data ...
477 // If the environment allow it and if this job has a configuration!
479 (m_aJobCfg
.hasConfig() ) &&
480 (aAnalyzedResult
.existPart(JobResult::E_ARGUMENTS
))
483 m_aJobCfg
.setJobConfig(aAnalyzedResult
.getArguments());
486 // disable a job for further executions.
487 // Note: this option is available inside the environment EXECUTOR only
489 // (eEnvironment == JobData::E_EXECUTION ) &&
490 (m_aJobCfg
.hasConfig() ) &&
491 (aAnalyzedResult
.existPart(JobResult::E_DEACTIVATE
))
494 m_aJobCfg
.disableJob();
497 // notify any interested listener with the may given result state.
498 // Note: this option is available inside the environment DISPATCH only
500 (eEnvironment
== JobData::E_DISPATCH
) &&
501 (m_xResultListener
.is() ) &&
502 (aAnalyzedResult
.existPart(JobResult::E_DISPATCHRESULT
))
505 m_aJobCfg
.setResult(aAnalyzedResult
);
506 // Attention: Because the listener expect that the original object send this event ...
507 // and we nor the job are the right ones ...
508 // our user has set itself before. So we can fake this source address!
509 css::frame::DispatchResultEvent aEvent
= aAnalyzedResult
.getDispatchResult();
510 aEvent
.Source
= m_xResultSourceFake
;
511 m_xResultListener
->dispatchFinished(aEvent
);
518 //________________________________
520 @short starts listening for office shutdown and closing of our
521 given target frame (if its a valid reference)
522 @descr We will reghister ourself as terminate listener
523 at the global desktop instance. That will hold us
524 alive and additional we get the information, if the
525 office whish to shutdown. If then an internal job
526 is running we will have the chance to supress that
527 by throwing a veto exception. If our internal wrapped
528 job finished his work, we can release this listener
531 Further we are listener for closing of the (possible valid)
532 given frame. We must be shure, that this resource won't be gone
533 if our internal job is still running.
535 void Job::impl_startListening()
538 WriteGuard
aWriteLock(m_aLock
);
540 // listening for office shutdown
541 if (!m_xDesktop
.is() && !m_bListenOnDesktop
)
545 m_xDesktop
= css::frame::Desktop::create( comphelper::getComponentContext(m_xSMGR
) );
546 css::uno::Reference
< css::frame::XTerminateListener
> xThis(static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
547 m_xDesktop
->addTerminateListener(xThis
);
548 m_bListenOnDesktop
= sal_True
;
550 catch(const css::uno::Exception
&)
556 // listening for frame closing
557 if (m_xFrame
.is() && !m_bListenOnFrame
)
561 css::uno::Reference
< css::util::XCloseBroadcaster
> xCloseable(m_xFrame
, css::uno::UNO_QUERY
);
562 css::uno::Reference
< css::util::XCloseListener
> xThis (static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
565 xCloseable
->addCloseListener(xThis
);
566 m_bListenOnFrame
= sal_True
;
569 catch(const css::uno::Exception
&)
571 m_bListenOnFrame
= sal_False
;
575 // listening for model closing
576 if (m_xModel
.is() && !m_bListenOnModel
)
580 css::uno::Reference
< css::util::XCloseBroadcaster
> xCloseable(m_xModel
, css::uno::UNO_QUERY
);
581 css::uno::Reference
< css::util::XCloseListener
> xThis (static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
584 xCloseable
->addCloseListener(xThis
);
585 m_bListenOnModel
= sal_True
;
588 catch(const css::uno::Exception
&)
590 m_bListenOnModel
= sal_False
;
598 //________________________________
600 @short release listener connection for office shutdown
601 @descr see description of impl_startListening()
603 void Job::impl_stopListening()
606 WriteGuard
aWriteLock(m_aLock
);
608 // stop listening for office shutdown
609 if (m_xDesktop
.is() && m_bListenOnDesktop
)
613 css::uno::Reference
< css::frame::XTerminateListener
> xThis(static_cast< ::cppu::OWeakObject
* >(this) , css::uno::UNO_QUERY
);
614 m_xDesktop
->removeTerminateListener(xThis
);
616 m_bListenOnDesktop
= sal_False
;
618 catch(const css::uno::Exception
&)
623 // stop listening for frame closing
624 if (m_xFrame
.is() && m_bListenOnFrame
)
628 css::uno::Reference
< css::util::XCloseBroadcaster
> xCloseable(m_xFrame
, css::uno::UNO_QUERY
);
629 css::uno::Reference
< css::util::XCloseListener
> xThis (static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
632 xCloseable
->removeCloseListener(xThis
);
633 m_bListenOnFrame
= sal_False
;
636 catch(const css::uno::Exception
&)
641 // stop listening for model closing
642 if (m_xModel
.is() && m_bListenOnModel
)
646 css::uno::Reference
< css::util::XCloseBroadcaster
> xCloseable(m_xModel
, css::uno::UNO_QUERY
);
647 css::uno::Reference
< css::util::XCloseListener
> xThis (static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
650 xCloseable
->removeCloseListener(xThis
);
651 m_bListenOnModel
= sal_False
;
654 catch(const css::uno::Exception
&)
663 //________________________________
665 @short callback from any asynchronous executed job
667 @descr Our execute() method waits for this callback.
668 We have to react for the possible results here,
669 to kill the running job and disable the blocked condition
670 so execute() can be finished too.
673 the job, which was running and inform us now
678 void SAL_CALL
Job::jobFinished( /*IN*/ const css::uno::Reference
< css::task::XAsyncJob
>& xJob
,
679 /*IN*/ const css::uno::Any
& aResult
) throw(css::uno::RuntimeException
)
682 WriteGuard
aWriteLock(m_aLock
);
684 // It's necessary to check this.
685 // May this job was cancelled by any other reason
686 // some milliseconds before. :-)
687 if (m_xJob
.is() && m_xJob
==xJob
)
689 // react for his results
690 // (means enable/disable it for further requests
691 // or save arguments or notify listener ...)
692 impl_reactForJobResult(aResult
);
695 m_xJob
= css::uno::Reference
< css::uno::XInterface
>();
698 // And let the start method "execute()" finishing it's job.
699 // But do it everytime. So any outside blocking code can finish
707 //________________________________
709 @short prevent internal wrapped job against office termination
710 @descr This event is broadcasted by the desktop instance and ask for an office termination.
711 If the internal wrapped job is still in progress, we disagree with that by throwing the
712 right veto exception. If not - we agree. But then we must be aware, that another event
713 notifyTermination() can follow. Then we have no chance to do the same. Then we have to
714 accept that and stop our work instandly.
717 describes the broadcaster and must be the desktop instance
719 @throw TerminateVetoException
720 if our internal wrapped job is still running.
722 void SAL_CALL
Job::queryTermination( /*IN*/ const css::lang::EventObject
& ) throw(css::frame::TerminationVetoException
,
723 css::uno::RuntimeException
)
726 ReadGuard
aReadLock(m_aLock
);
729 // Otherwhise try to close() it
730 css::uno::Reference
< css::util::XCloseable
> xClose(m_xJob
, css::uno::UNO_QUERY
);
735 xClose
->close(sal_False
);
736 m_eRunState
= E_STOPPED_OR_FINISHED
;
738 catch(const css::util::CloseVetoException
&) {}
741 if (m_eRunState
!= E_STOPPED_OR_FINISHED
)
743 css::uno::Reference
< css::uno::XInterface
> xThis(static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
744 throw css::frame::TerminationVetoException(DECLARE_ASCII("job still in progress"), xThis
);
752 //________________________________
754 @short inform us about office termination
755 @descr Instead of the method queryTermination(), here is no chance to disagree with that.
756 We have to accept it and cancel all current processes inside.
757 It can occure only, if job was not already started if queryTermination() was called here ..
758 Then we had not throwed a veto exception. But now we must agree with this situation and break
759 all our internal processes. Its not a good idea to mark this instance as non startable any longer
760 inside queryTermination() if no job was unning too. Because that would disable this job and may
761 the office does not realy shutdownm, because another listener has thrown the suitable exception.
764 describes the broadcaster and must be the desktop instance
766 void SAL_CALL
Job::notifyTermination( /*IN*/ const css::lang::EventObject
& ) throw(css::uno::RuntimeException
)
769 // Do nothing else here. Our internal resources was released ...
772 //________________________________
774 @short prevent internal wrapped job against frame closing
775 @descr This event is broadcasted by the frame instance and ask for closing.
776 If the internal wrapped job is still in progress, we disagree with that by throwing the
777 right veto exception. If not - we agree. But then we must be aware, that another event
778 notifyClosing() can follow. Then we have no chance to do the same. Then we have to
779 accept that and stop our work instandly.
782 describes the broadcaster and must be the frame instance
784 @param bGetsOwnership
785 If it's set to <sal_True> and we throw the right veto excepion, we have to close this frame later
786 if our internal processes will be finished. If it's set to <FALSE/> we can ignore it.
788 @throw CloseVetoException
789 if our internal wrapped job is still running.
791 void SAL_CALL
Job::queryClosing( const css::lang::EventObject
& aEvent
,
792 sal_Bool bGetsOwnership
) throw(css::util::CloseVetoException
,
793 css::uno::RuntimeException
)
796 WriteGuard
aWriteLock(m_aLock
);
798 // do nothing, if no internal job is still running ...
799 // The frame or model can be closed then successfully.
800 if (m_eRunState
!= E_RUNNING
)
803 // try close() first at the job.
804 // The job can agree or disagree with this request.
805 css::uno::Reference
< css::util::XCloseable
> xClose(m_xJob
, css::uno::UNO_QUERY
);
808 xClose
->close(bGetsOwnership
);
809 // Here we can say: "this job was stopped successfully". Because
810 // no veto exception was thrown!
811 m_eRunState
= E_STOPPED_OR_FINISHED
;
815 // try dispose() then
816 // Here the job has no chance for a veto.
817 // But we must be aware of an "already disposed exception"...
820 css::uno::Reference
< css::lang::XComponent
> xDispose(m_xJob
, css::uno::UNO_QUERY
);
824 m_eRunState
= E_DISPOSED
;
827 catch(const css::lang::DisposedException
&)
829 // the job was already disposed by any other mechanism !?
830 // But it's not interesting for us. For us this job is stopped now.
831 m_eRunState
= E_DISPOSED
;
834 if (m_eRunState
!= E_DISPOSED
)
836 // analyze event source - to find out, which resource called queryClosing() at this
837 // job wrapper. We must bind a "pending close" request to this resource.
838 // Closing of the corresponding resource will be done if our internal job finish it's work.
839 m_bPendingCloseFrame
= (m_xFrame
.is() && aEvent
.Source
== m_xFrame
);
840 m_bPendingCloseModel
= (m_xModel
.is() && aEvent
.Source
== m_xModel
);
842 // throw suitable veto exception - because the internal job could not be cancelled.
843 css::uno::Reference
< css::uno::XInterface
> xThis(static_cast< ::cppu::OWeakObject
* >(this), css::uno::UNO_QUERY
);
844 throw css::util::CloseVetoException(DECLARE_ASCII("job still in progress"), xThis
);
848 // But don't call die() here or free our internal member.
849 // This must be done inside notifyClosing() only. Otherwhise the
850 // might stopped job has no chance to return it's results or
851 // call us back. We must give him the chance to finish it's work successfully.
857 //________________________________
859 @short inform us about frame closing
860 @descr Instead of the method queryClosing(), here is no chance to disagree with that.
861 We have to accept it and cancel all current processes inside.
864 describes the broadcaster and must be the frame or model instance we know
866 void SAL_CALL
Job::notifyClosing( const css::lang::EventObject
& ) throw(css::uno::RuntimeException
)
869 // Do nothing else here. Our internal resources was released ...
872 //________________________________
874 @short shouldn't be called normaly
875 @descr But it doesn't matter, who called it. We have to kill our internal
876 running processes hardly.
879 describe the broadcaster
881 void SAL_CALL
Job::disposing( const css::lang::EventObject
& aEvent
) throw(css::uno::RuntimeException
)
884 WriteGuard
aWriteLock(m_aLock
);
886 if (m_xDesktop
.is() && aEvent
.Source
== m_xDesktop
)
889 m_bListenOnDesktop
= sal_False
;
891 else if (m_xFrame
.is() && aEvent
.Source
== m_xFrame
)
893 m_xFrame
= css::uno::Reference
< css::frame::XFrame
>();
894 m_bListenOnFrame
= sal_False
;
896 else if (m_xModel
.is() && aEvent
.Source
== m_xModel
)
898 m_xModel
= css::uno::Reference
< css::frame::XModel
>();
899 m_bListenOnModel
= sal_False
;
906 // Do nothing else here. Our internal resources was released ...
909 } // namespace framework
911 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */