merge the formfield patch from ooo-build
[ooovba.git] / framework / source / jobs / job.cxx
blob2609a57734731e4bb097739f38453939239dbff5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: job.cxx,v $
10 * $Revision: 1.12.82.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //________________________________
35 // my own includes
36 #include <jobs/job.hxx>
37 #include <threadhelp/readguard.hxx>
38 #include <threadhelp/writeguard.hxx>
39 #include <general.h>
40 #include <services.h>
42 //________________________________
43 // interface includes
44 #include <com/sun/star/task/XJob.hpp>
45 #include <com/sun/star/task/XAsyncJob.hpp>
46 #include <com/sun/star/util/XCloseBroadcaster.hpp>
47 #include <com/sun/star/util/XCloseable.hpp>
48 #include <com/sun/star/lang/DisposedException.hpp>
50 //________________________________
51 // includes of other projects
52 #include <rtl/ustrbuf.hxx>
53 #include <vcl/svapp.hxx>
54 #include <comphelper/uieventslogger.hxx>
56 //________________________________
57 // namespace
59 namespace framework{
61 //________________________________
62 // non exported const
64 //________________________________
65 // non exported definitions
67 //________________________________
68 // declarations
70 DEFINE_XINTERFACE_4( Job ,
71 OWeakObject ,
72 DIRECT_INTERFACE(css::lang::XTypeProvider ),
73 DIRECT_INTERFACE(css::task::XJobListener ),
74 DIRECT_INTERFACE(css::frame::XTerminateListener),
75 DIRECT_INTERFACE(css::util::XCloseListener )
78 DEFINE_XTYPEPROVIDER_4( Job ,
79 css::lang::XTypeProvider ,
80 css::task::XJobListener ,
81 css::frame::XTerminateListener,
82 css::util::XCloseListener
85 //________________________________
86 /**
87 @short standard ctor
88 @descr It initialize this new instance. But it set some generic parameters here only.
89 Specialized informations (e.g. the alias or service name ofthis job) will be set
90 later using the method setJobData().
92 @param xSMGR
93 reference to the uno service manager
95 @param xFrame
96 reference to the frame, in which environment we run
97 (May be null!)
99 Job::Job( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
100 /*IN*/ const css::uno::Reference< css::frame::XFrame >& xFrame )
101 : ThreadHelpBase (&Application::GetSolarMutex())
102 , ::cppu::OWeakObject ( )
103 , m_aJobCfg (xSMGR )
104 , m_xSMGR (xSMGR )
105 , m_xFrame (xFrame )
106 , m_bListenOnDesktop (sal_False )
107 , m_bListenOnFrame (sal_False )
108 , m_bListenOnModel (sal_False )
109 , m_bPendingCloseFrame (sal_False )
110 , m_bPendingCloseModel (sal_False )
111 , m_eRunState (E_NEW )
115 //________________________________
117 @short standard ctor
118 @descr It initialize this new instance. But it set some generic parameters here only.
119 Specialized informations (e.g. the alias or service name ofthis job) will be set
120 later using the method setJobData().
122 @param xSMGR
123 reference to the uno service manager
125 @param xModel
126 reference to the model, in which environment we run
127 (May be null!)
129 Job::Job( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
130 /*IN*/ const css::uno::Reference< css::frame::XModel >& xModel )
131 : ThreadHelpBase (&Application::GetSolarMutex())
132 , ::cppu::OWeakObject ( )
133 , m_aJobCfg (xSMGR )
134 , m_xSMGR (xSMGR )
135 , m_xModel (xModel )
136 , m_bListenOnDesktop (sal_False )
137 , m_bListenOnFrame (sal_False )
138 , m_bListenOnModel (sal_False )
139 , m_bPendingCloseFrame (sal_False )
140 , m_bPendingCloseModel (sal_False )
141 , m_eRunState (E_NEW )
145 //________________________________
147 @short superflous!
148 @descr Releasing of memory and reference must be done inside die() call.
149 Otherwhise it's a bug.
151 Job::~Job()
155 //________________________________
157 @short set (or delete) a listener for sending dispatch result events
158 @descr Because this object is used in a wrapped mode ... the original listener
159 for such events can't be registered here directly. Because the
160 listener expect to get the original object given as source of the event.
161 That's why we get this source here too, to fake(!) it at sending time!
163 @param xListener
164 the original listener for dispatch result events
166 @param xSourceFake
167 our user, which got the registration request for this listener
169 void Job::setDispatchResultFake( /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ,
170 /*IN*/ const css::uno::Reference< css::uno::XInterface >& xSourceFake )
172 /* SAFE { */
173 WriteGuard aWriteLock(m_aLock);
175 // reject dangerous calls
176 if (m_eRunState != E_NEW)
178 LOG_WARNING("Job::setJobData()", "job may still running or already finished")
179 return;
182 m_xResultListener = xListener ;
183 m_xResultSourceFake = xSourceFake;
184 aWriteLock.unlock();
185 /* } SAFE */
188 void Job::setJobData( const JobData& aData )
190 /* SAFE { */
191 WriteGuard aWriteLock(m_aLock);
193 // reject dangerous calls
194 if (m_eRunState != E_NEW)
196 LOG_WARNING("Job::setJobData()", "job may still running or already finished")
197 return;
200 m_aJobCfg = aData;
201 aWriteLock.unlock();
202 /* } SAFE */
205 //________________________________
207 @short runs the job
208 @descr It doesn't matter, if the job is an asynchronous or
209 synchronous one. This method returns only if it was finished
210 or cancelled.
212 @param lDynamicArgs
213 optional arguments for job execution
214 In case the represented job is a configured one (which uses static
215 arguments too) all informations will be merged!
217 void Job::execute( /*IN*/ const css::uno::Sequence< css::beans::NamedValue >& lDynamicArgs )
219 /* SAFE { */
220 WriteGuard aWriteLock(m_aLock);
222 // reject dangerous calls
223 if (m_eRunState != E_NEW)
225 LOG_WARNING("Job::execute()", "job may still running or already finished")
226 return;
229 // create the environment and mark this job as running ...
230 m_eRunState = E_RUNNING;
231 impl_startListening();
233 css::uno::Reference< css::task::XAsyncJob > xAJob;
234 css::uno::Reference< css::task::XJob > xSJob;
235 css::uno::Sequence< css::beans::NamedValue > lJobArgs = impl_generateJobArgs(lDynamicArgs);
237 // It's neccessary to hold us self alive!
238 // Otherwhise we might die by ref count ...
239 css::uno::Reference< css::task::XJobListener > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
241 if ( ::comphelper::UiEventsLogger::isEnabled() )
244 // create the job
245 // We must check for the supported interface on demand!
246 // But we preferr the synchronous one ...
247 m_xJob = m_xSMGR->createInstance(m_aJobCfg.getService());
248 xSJob = css::uno::Reference< css::task::XJob >(m_xJob, css::uno::UNO_QUERY);
249 if (!xSJob.is())
250 xAJob = css::uno::Reference< css::task::XAsyncJob >(m_xJob, css::uno::UNO_QUERY);
252 // execute it asynchron
253 if (xAJob.is())
255 m_aAsyncWait.reset();
256 aWriteLock.unlock();
257 /* } SAFE */
258 xAJob->executeAsync(lJobArgs, xThis);
259 // wait for finishing this job - so this method
260 // does the same for synchronous and asynchronous jobs!
261 m_aAsyncWait.wait();
262 aWriteLock.lock();
263 /* SAFE { */
264 // Note: Result handling was already done inside the callback!
266 // execute it synchron
267 else if (xSJob.is())
269 aWriteLock.unlock();
270 /* } SAFE */
271 css::uno::Any aResult = xSJob->execute(lJobArgs);
272 aWriteLock.lock();
273 /* SAFE { */
274 impl_reactForJobResult(aResult);
277 #if OSL_DEBUG_LEVEL > 0
278 catch(const css::uno::Exception& ex)
280 ::rtl::OUStringBuffer sMsg(256);
281 sMsg.appendAscii("Got exception during job execution. Original Message was:\n\"");
282 sMsg.append (ex.Message);
283 sMsg.appendAscii("\"");
284 LOG_WARNING("Job::execute()", U2B(sMsg.makeStringAndClear()).getStr())
286 #else
287 catch(const css::uno::Exception&)
289 #endif
291 // deinitialize the environment and mark this job as finished ...
292 // but don't overwrite any informations about STOPPED or might DISPOSED jobs!
293 impl_stopListening();
294 if (m_eRunState == E_RUNNING)
295 m_eRunState = E_STOPPED_OR_FINISHED;
297 // If we got a close request from our frame or model ...
298 // but we disagreed wit that by throwing a veto exception...
299 // and got the ownership ...
300 // we have to close the resource frame or model now -
301 // and to disable ourself!
302 if (m_bPendingCloseFrame)
304 m_bPendingCloseFrame = sal_False;
305 css::uno::Reference< css::util::XCloseable > xClose(m_xFrame, css::uno::UNO_QUERY);
306 if (xClose.is())
310 xClose->close(sal_True);
312 catch(const css::util::CloseVetoException&) {}
316 if (m_bPendingCloseModel)
318 m_bPendingCloseModel = sal_False;
319 css::uno::Reference< css::util::XCloseable > xClose(m_xModel, css::uno::UNO_QUERY);
320 if (xClose.is())
324 xClose->close(sal_True);
326 catch(const css::util::CloseVetoException&) {}
330 aWriteLock.unlock();
331 /* SAFE { */
333 // release this instance ...
334 die();
337 //________________________________
339 @short kill this job
340 @descr It doesn't matter if this request is called from inside or
341 from outside. We release our internal structures and stop
342 avary activity. After doing so - this instance will not be
343 useable any longer! Of course we try to handle further requests
344 carefully. May somehwere else hold a reference to us ...
346 void Job::die()
348 /* SAFE { */
349 WriteGuard aWriteLock(m_aLock);
351 impl_stopListening();
353 if (m_eRunState != E_DISPOSED)
357 css::uno::Reference< css::lang::XComponent > xDispose(m_xJob, css::uno::UNO_QUERY);
358 if (xDispose.is())
360 xDispose->dispose();
361 m_eRunState = E_DISPOSED;
364 catch(const css::lang::DisposedException&)
366 m_eRunState = E_DISPOSED;
370 m_xJob = css::uno::Reference< css::uno::XInterface >();
371 m_xFrame = css::uno::Reference< css::frame::XFrame >();
372 m_xModel = css::uno::Reference< css::frame::XModel >();
373 m_xDesktop = css::uno::Reference< css::frame::XDesktop >();
374 m_xResultListener = css::uno::Reference< css::frame::XDispatchResultListener >();
375 m_xResultSourceFake = css::uno::Reference< css::uno::XInterface >();
376 m_bPendingCloseFrame = sal_False;
377 m_bPendingCloseModel = sal_False;
379 aWriteLock.unlock();
380 /* SAFE { */
383 //________________________________
385 @short generates list of arguments for job execute
386 @descr There exist a set of informations, which can be needed by a job.
387 a) it's static configuration data (Equals for all jobs. )
388 b) it's specific configuration data (Different for every job.)
389 c) some environment values (e.g. the frame, for which this job was started)
390 d) any other dynamic data (e.g. parameters of a dispatch() request)
391 We collect all these informations and generate one list which include all others.
393 @param lDynamicArgs
394 list of dynamic arguments (given by a corresponding dispatch() call)
395 Can be empty too.
397 @return A list which includes all mentioned sub lists.
399 css::uno::Sequence< css::beans::NamedValue > Job::impl_generateJobArgs( /*IN*/ const css::uno::Sequence< css::beans::NamedValue >& lDynamicArgs )
401 css::uno::Sequence< css::beans::NamedValue > lAllArgs;
403 /* SAFE { */
404 ReadGuard aReadLock(m_aLock);
406 // the real structure of the returned list depends from the environment of this job!
407 JobData::EMode eMode = m_aJobCfg.getMode();
409 // Create list of environment variables. This list must be part of the
410 // returned structure everytimes ... but some of its members are opetional!
411 css::uno::Sequence< css::beans::NamedValue > lEnvArgs(1);
412 lEnvArgs[0].Name = ::rtl::OUString::createFromAscii(JobData::PROP_ENVTYPE);
413 lEnvArgs[0].Value <<= m_aJobCfg.getEnvironmentDescriptor();
415 if (m_xFrame.is())
417 sal_Int32 c = lEnvArgs.getLength();
418 lEnvArgs.realloc(c+1);
419 lEnvArgs[c].Name = ::rtl::OUString::createFromAscii(JobData::PROP_FRAME);
420 lEnvArgs[c].Value <<= m_xFrame;
422 if (m_xModel.is())
424 sal_Int32 c = lEnvArgs.getLength();
425 lEnvArgs.realloc(c+1);
426 lEnvArgs[c].Name = ::rtl::OUString::createFromAscii(JobData::PROP_MODEL);
427 lEnvArgs[c].Value <<= m_xModel;
429 if (eMode==JobData::E_EVENT)
431 sal_Int32 c = lEnvArgs.getLength();
432 lEnvArgs.realloc(c+1);
433 lEnvArgs[c].Name = ::rtl::OUString::createFromAscii(JobData::PROP_EVENTNAME);
434 lEnvArgs[c].Value <<= m_aJobCfg.getEvent();
437 // get the configuration data from the job data container ... if possible
438 // Means: if this job has any configuration data. Note: only realy
439 // filled lists will be set to the return structure at the end of this method.
440 css::uno::Sequence< css::beans::NamedValue > lConfigArgs ;
441 css::uno::Sequence< css::beans::NamedValue > lJobConfigArgs;
442 if (eMode==JobData::E_ALIAS || eMode==JobData::E_EVENT)
444 lConfigArgs = m_aJobCfg.getConfig();
445 lJobConfigArgs = m_aJobCfg.getJobConfig();
448 aReadLock.unlock();
449 /* } SAFE */
451 // Add all valid (not empty) lists to the return list
452 if (lConfigArgs.getLength()>0)
454 sal_Int32 nLength = lAllArgs.getLength();
455 lAllArgs.realloc(nLength+1);
456 lAllArgs[nLength].Name = ::rtl::OUString::createFromAscii(JobData::PROPSET_CONFIG);
457 lAllArgs[nLength].Value <<= lConfigArgs;
459 if (lJobConfigArgs.getLength()>0)
461 sal_Int32 nLength = lAllArgs.getLength();
462 lAllArgs.realloc(nLength+1);
463 lAllArgs[nLength].Name = ::rtl::OUString::createFromAscii(JobData::PROPSET_OWNCONFIG);
464 lAllArgs[nLength].Value <<= lJobConfigArgs;
466 if (lEnvArgs.getLength()>0)
468 sal_Int32 nLength = lAllArgs.getLength();
469 lAllArgs.realloc(nLength+1);
470 lAllArgs[nLength].Name = ::rtl::OUString::createFromAscii(JobData::PROPSET_ENVIRONMENT);
471 lAllArgs[nLength].Value <<= lEnvArgs;
473 if (lDynamicArgs.getLength()>0)
475 sal_Int32 nLength = lAllArgs.getLength();
476 lAllArgs.realloc(nLength+1);
477 lAllArgs[nLength].Name = ::rtl::OUString::createFromAscii(JobData::PROPSET_DYNAMICDATA);
478 lAllArgs[nLength].Value <<= lDynamicArgs;
481 return lAllArgs;
484 //________________________________
486 @short analyze the given job result and change the job configuration
487 @descr Note: Some results can be handled only, if this job has a valid configuration!
488 For "not configured jobs" (means pure services) they can be ignored.
489 But these cases are handled by our JobData member. We can call it everytime.
490 It does the right things automaticly. E.g. if the job has no configuration ...
491 it does nothing during setJobConfig()!
493 @param aResult
494 the job result for analyzing
496 void Job::impl_reactForJobResult( /*IN*/ const css::uno::Any& aResult )
498 /* SAFE { */
499 WriteGuard aWriteLock(m_aLock);
501 // analyze the result set ...
502 JobResult aAnalyzedResult(aResult);
504 // some of the following operations will be supported for different environments
505 // or different type of jobs only.
506 JobData::EEnvironment eEnvironment = m_aJobCfg.getEnvironment();
508 // write back the job specific configuration data ...
509 // If the environment allow it and if this job has a configuration!
510 if (
511 (m_aJobCfg.hasConfig() ) &&
512 (aAnalyzedResult.existPart(JobResult::E_ARGUMENTS))
515 m_aJobCfg.setJobConfig(aAnalyzedResult.getArguments());
518 // disable a job for further executions.
519 // Note: this option is available inside the environment EXECUTOR only
520 if (
521 // (eEnvironment == JobData::E_EXECUTION ) &&
522 (m_aJobCfg.hasConfig() ) &&
523 (aAnalyzedResult.existPart(JobResult::E_DEACTIVATE))
526 m_aJobCfg.disableJob();
529 // notify any interested listener with the may given result state.
530 // Note: this option is available inside the environment DISPATCH only
531 if (
532 (eEnvironment == JobData::E_DISPATCH ) &&
533 (m_xResultListener.is() ) &&
534 (aAnalyzedResult.existPart(JobResult::E_DISPATCHRESULT))
537 m_aJobCfg.setResult(aAnalyzedResult);
538 // Attention: Because the listener expect that the original object send this event ...
539 // and we nor the job are the right ones ...
540 // our user has set itself before. So we can fake this source address!
541 css::frame::DispatchResultEvent aEvent = aAnalyzedResult.getDispatchResult();
542 aEvent.Source = m_xResultSourceFake;
543 m_xResultListener->dispatchFinished(aEvent);
546 aWriteLock.unlock();
547 /* SAFE { */
550 //________________________________
552 @short starts listening for office shutdown and closing of our
553 given target frame (if its a valid reference)
554 @descr We will reghister ourself as terminate listener
555 at the global desktop instance. That will hold us
556 alive and additional we get the information, if the
557 office whish to shutdown. If then an internal job
558 is running we will have the chance to supress that
559 by throwing a veto exception. If our internal wrapped
560 job finished his work, we can release this listener
561 connection.
563 Further we are listener for closing of the (possible valid)
564 given frame. We must be shure, that this ressource won't be gone
565 if our internal job is still running.
567 void Job::impl_startListening()
569 /* SAFE { */
570 WriteGuard aWriteLock(m_aLock);
572 // listening for office shutdown
573 if (!m_xDesktop.is() && !m_bListenOnDesktop)
577 m_xDesktop = css::uno::Reference< css::frame::XDesktop >(m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
578 css::uno::Reference< css::frame::XTerminateListener > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
579 if (m_xDesktop.is())
581 m_xDesktop->addTerminateListener(xThis);
582 m_bListenOnDesktop = sal_True;
585 catch(css::uno::Exception&)
587 m_xDesktop = css::uno::Reference< css::frame::XDesktop >();
591 // listening for frame closing
592 if (m_xFrame.is() && !m_bListenOnFrame)
596 css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xFrame , css::uno::UNO_QUERY);
597 css::uno::Reference< css::util::XCloseListener > xThis (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
598 if (xCloseable.is())
600 xCloseable->addCloseListener(xThis);
601 m_bListenOnFrame = sal_True;
604 catch(css::uno::Exception&)
606 m_bListenOnFrame = sal_False;
610 // listening for model closing
611 if (m_xModel.is() && !m_bListenOnModel)
615 css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xModel , css::uno::UNO_QUERY);
616 css::uno::Reference< css::util::XCloseListener > xThis (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
617 if (xCloseable.is())
619 xCloseable->addCloseListener(xThis);
620 m_bListenOnModel = sal_True;
623 catch(css::uno::Exception&)
625 m_bListenOnModel = sal_False;
629 aWriteLock.unlock();
630 /* } SAFE */
633 //________________________________
635 @short release listener connection for office shutdown
636 @descr see description of impl_startListening()
638 void Job::impl_stopListening()
640 /* SAFE { */
641 WriteGuard aWriteLock(m_aLock);
643 // stop listening for office shutdown
644 if (m_xDesktop.is() && m_bListenOnDesktop)
648 css::uno::Reference< css::frame::XTerminateListener > xThis(static_cast< ::cppu::OWeakObject* >(this) , css::uno::UNO_QUERY);
649 m_xDesktop->removeTerminateListener(xThis);
650 m_xDesktop = css::uno::Reference< css::frame::XDesktop >();
651 m_bListenOnDesktop = sal_False;
653 catch(css::uno::Exception&)
658 // stop listening for frame closing
659 if (m_xFrame.is() && m_bListenOnFrame)
663 css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xFrame , css::uno::UNO_QUERY);
664 css::uno::Reference< css::util::XCloseListener > xThis (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
665 if (xCloseable.is())
667 xCloseable->removeCloseListener(xThis);
668 m_bListenOnFrame = sal_False;
671 catch(css::uno::Exception&)
676 // stop listening for model closing
677 if (m_xModel.is() && m_bListenOnModel)
681 css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xModel , css::uno::UNO_QUERY);
682 css::uno::Reference< css::util::XCloseListener > xThis (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
683 if (xCloseable.is())
685 xCloseable->removeCloseListener(xThis);
686 m_bListenOnModel = sal_False;
689 catch(css::uno::Exception&)
694 aWriteLock.unlock();
695 /* } SAFE */
698 //________________________________
700 @short callback from any asynchronous executed job
702 @descr Our execute() method waits for this callback.
703 We have to react for the possible results here,
704 to kill the running job and disable the blocked condition
705 so execute() can be finished too.
707 @param xJob
708 the job, which was running and inform us now
710 @param aResult
711 it's results
713 void SAL_CALL Job::jobFinished( /*IN*/ const css::uno::Reference< css::task::XAsyncJob >& xJob ,
714 /*IN*/ const css::uno::Any& aResult ) throw(css::uno::RuntimeException)
716 /* SAFE { */
717 WriteGuard aWriteLock(m_aLock);
719 // It's neccessary to check this.
720 // May this job was cancelled by any other reason
721 // some milliseconds before. :-)
722 if (m_xJob.is() && m_xJob==xJob)
724 // react for his results
725 // (means enable/disable it for further requests
726 // or save arguments or notify listener ...)
727 impl_reactForJobResult(aResult);
729 // Let the job die!
730 m_xJob = css::uno::Reference< css::uno::XInterface >();
733 // And let the start method "execute()" finishing it's job.
734 // But do it everytime. So any outside blocking code can finish
735 // his work too.
736 m_aAsyncWait.set();
738 aWriteLock.unlock();
739 /* } SAFE */
742 //________________________________
744 @short prevent internal wrapped job against office termination
745 @descr This event is broadcasted by the desktop instance and ask for an office termination.
746 If the internal wrapped job is still in progress, we disagree with that by throwing the
747 right veto exception. If not - we agree. But then we must be aware, that another event
748 notifyTermination() can follow. Then we have no chance to do the same. Then we have to
749 accept that and stop our work instandly.
751 @param aEvent
752 describes the broadcaster and must be the desktop instance
754 @throw TerminateVetoException
755 if our internal wrapped job is still running.
757 void SAL_CALL Job::queryTermination( /*IN*/ const css::lang::EventObject& ) throw(css::frame::TerminationVetoException,
758 css::uno::RuntimeException )
760 /* SAFE { */
761 ReadGuard aReadLock(m_aLock);
763 // don't disagree with this request if job was already stopped or finished it's work
764 // if (m_eRunState != E_RUNNING)
765 // return;
767 // Otherwhise try to close() it
768 css::uno::Reference< css::util::XCloseable > xClose(m_xJob, css::uno::UNO_QUERY);
769 if (xClose.is())
773 xClose->close(sal_False);
774 m_eRunState = E_STOPPED_OR_FINISHED;
776 catch(const css::util::CloseVetoException&) {}
779 if (m_eRunState != E_STOPPED_OR_FINISHED)
781 css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
782 throw css::frame::TerminationVetoException(DECLARE_ASCII("job still in progress"), xThis);
785 aReadLock.unlock();
786 /* } SAFE */
790 //________________________________
792 @short inform us about office termination
793 @descr Instead of the method queryTermination(), here is no chance to disagree with that.
794 We have to accept it and cancel all current processes inside.
795 It can occure only, if job was not already started if queryTermination() was called here ..
796 Then we had not throwed a veto exception. But now we must agree with this situation and break
797 all our internal processes. Its not a good idea to mark this instance as non startable any longer
798 inside queryTermination() if no job was unning too. Because that would disable this job and may
799 the office does not realy shutdownm, because another listener has thrown the suitable exception.
801 @param aEvent
802 describes the broadcaster and must be the desktop instance
804 void SAL_CALL Job::notifyTermination( /*IN*/ const css::lang::EventObject& ) throw(css::uno::RuntimeException)
806 die();
807 // Do nothing else here. Our internal ressources was released ...
810 //________________________________
812 @short prevent internal wrapped job against frame closing
813 @descr This event is broadcasted by the frame instance and ask for closing.
814 If the internal wrapped job is still in progress, we disagree with that by throwing the
815 right veto exception. If not - we agree. But then we must be aware, that another event
816 notifyClosing() can follow. Then we have no chance to do the same. Then we have to
817 accept that and stop our work instandly.
819 @param aEvent
820 describes the broadcaster and must be the frame instance
822 @param bGetsOwnerShip
823 If it's set to <TRUE> and we throw the right veto excepion, we have to close this frame later
824 if our internal processes will be finished. If it's set to <FALSE/> we can ignore it.
826 @throw CloseVetoException
827 if our internal wrapped job is still running.
829 void SAL_CALL Job::queryClosing( const css::lang::EventObject& aEvent ,
830 sal_Bool bGetsOwnership ) throw(css::util::CloseVetoException,
831 css::uno::RuntimeException )
833 /* SAFE { */
834 WriteGuard aWriteLock(m_aLock);
836 // do nothing, if no internal job is still running ...
837 // The frame or model can be closed then successfully.
838 if (m_eRunState != E_RUNNING)
839 return;
841 // try close() first at the job.
842 // The job can agree or disagree with this request.
843 css::uno::Reference< css::util::XCloseable > xClose(m_xJob, css::uno::UNO_QUERY);
844 if (xClose.is())
846 xClose->close(bGetsOwnership);
847 // Here we can say: "this job was stopped successfully". Because
848 // no veto exception was thrown!
849 m_eRunState = E_STOPPED_OR_FINISHED;
850 return;
853 // try dispose() then
854 // Here the job has no chance for a veto.
855 // But we must be aware of an "already disposed exception"...
858 css::uno::Reference< css::lang::XComponent > xDispose(m_xJob, css::uno::UNO_QUERY);
859 if (xDispose.is())
861 xDispose->dispose();
862 m_eRunState = E_DISPOSED;
865 catch(const css::lang::DisposedException&)
867 // the job was already disposed by any other mechanism !?
868 // But it's not interesting for us. For us this job is stopped now.
869 m_eRunState = E_DISPOSED;
872 if (m_eRunState != E_DISPOSED)
874 // analyze event source - to find out, which resource called queryClosing() at this
875 // job wrapper. We must bind a "pending close" request to this resource.
876 // Closing of the corresponding resource will be done if our internal job finish it's work.
877 m_bPendingCloseFrame = (m_xFrame.is() && aEvent.Source == m_xFrame);
878 m_bPendingCloseModel = (m_xModel.is() && aEvent.Source == m_xModel);
880 // throw suitable veto exception - because the internal job could not be cancelled.
881 css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
882 throw css::util::CloseVetoException(DECLARE_ASCII("job still in progress"), xThis);
885 // No veto ...
886 // But don't call die() here or free our internal member.
887 // This must be done inside notifyClosing() only. Otherwhise the
888 // might stopped job has no chance to return it's results or
889 // call us back. We must give him the chance to finish it's work successfully.
891 aWriteLock.unlock();
892 /* } SAFE */
895 //________________________________
897 @short inform us about frame closing
898 @descr Instead of the method queryClosing(), here is no chance to disagree with that.
899 We have to accept it and cancel all current processes inside.
901 @param aEvent
902 describes the broadcaster and must be the frame or model instance we know
904 void SAL_CALL Job::notifyClosing( const css::lang::EventObject& ) throw(css::uno::RuntimeException)
906 die();
907 // Do nothing else here. Our internal ressources was released ...
910 //________________________________
912 @short shouldn't be called normaly
913 @descr But it doesn't matter, who called it. We have to kill our internal
914 running processes hardly.
916 @param aEvent
917 describe the broadcaster
919 void SAL_CALL Job::disposing( const css::lang::EventObject& aEvent ) throw(css::uno::RuntimeException)
921 /* SAFE { */
922 WriteGuard aWriteLock(m_aLock);
924 if (m_xDesktop.is() && aEvent.Source == m_xDesktop)
926 m_xDesktop = css::uno::Reference< css::frame::XDesktop >();
927 m_bListenOnDesktop = sal_False;
929 else
930 if (m_xFrame.is() && aEvent.Source == m_xFrame)
932 m_xFrame = css::uno::Reference< css::frame::XFrame >();
933 m_bListenOnFrame = sal_False;
935 else
936 if (m_xModel.is() && aEvent.Source == m_xModel)
938 m_xModel = css::uno::Reference< css::frame::XModel >();
939 m_bListenOnModel = sal_False;
942 aWriteLock.unlock();
943 /* } SAFE */
945 die();
946 // Do nothing else here. Our internal ressources was released ...
949 } // namespace framework