xref: /aoo42x/main/framework/source/jobs/job.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_framework.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir //________________________________
32*cdf0e10cSrcweir //	my own includes
33*cdf0e10cSrcweir #include <jobs/job.hxx>
34*cdf0e10cSrcweir #include <threadhelp/readguard.hxx>
35*cdf0e10cSrcweir #include <threadhelp/writeguard.hxx>
36*cdf0e10cSrcweir #include <general.h>
37*cdf0e10cSrcweir #include <services.h>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir //________________________________
40*cdf0e10cSrcweir //	interface includes
41*cdf0e10cSrcweir #include <com/sun/star/task/XJob.hpp>
42*cdf0e10cSrcweir #include <com/sun/star/task/XAsyncJob.hpp>
43*cdf0e10cSrcweir #include <com/sun/star/util/XCloseBroadcaster.hpp>
44*cdf0e10cSrcweir #include <com/sun/star/util/XCloseable.hpp>
45*cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp>
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir //________________________________
48*cdf0e10cSrcweir //	includes of other projects
49*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
50*cdf0e10cSrcweir #include <vcl/svapp.hxx>
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir //________________________________
53*cdf0e10cSrcweir //	namespace
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir namespace framework{
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir //________________________________
58*cdf0e10cSrcweir //	non exported const
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir //________________________________
61*cdf0e10cSrcweir //	non exported definitions
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir //________________________________
64*cdf0e10cSrcweir //	declarations
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir DEFINE_XINTERFACE_4( Job                                             ,
67*cdf0e10cSrcweir                      OWeakObject                                     ,
68*cdf0e10cSrcweir                      DIRECT_INTERFACE(css::lang::XTypeProvider      ),
69*cdf0e10cSrcweir                      DIRECT_INTERFACE(css::task::XJobListener       ),
70*cdf0e10cSrcweir                      DIRECT_INTERFACE(css::frame::XTerminateListener),
71*cdf0e10cSrcweir                      DIRECT_INTERFACE(css::util::XCloseListener     )
72*cdf0e10cSrcweir                    )
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir DEFINE_XTYPEPROVIDER_4( Job                           ,
75*cdf0e10cSrcweir                         css::lang::XTypeProvider      ,
76*cdf0e10cSrcweir                         css::task::XJobListener       ,
77*cdf0e10cSrcweir                         css::frame::XTerminateListener,
78*cdf0e10cSrcweir                         css::util::XCloseListener
79*cdf0e10cSrcweir                       )
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir //________________________________
82*cdf0e10cSrcweir /**
83*cdf0e10cSrcweir     @short      standard ctor
84*cdf0e10cSrcweir     @descr      It initialize this new instance. But it set some generic parameters here only.
85*cdf0e10cSrcweir                 Specialized informations (e.g. the alias or service name ofthis job) will be set
86*cdf0e10cSrcweir                 later using the method setJobData().
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir     @param      xSMGR
89*cdf0e10cSrcweir                 reference to the uno service manager
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir     @param      xFrame
92*cdf0e10cSrcweir                 reference to the frame, in which environment we run
93*cdf0e10cSrcweir                 (May be null!)
94*cdf0e10cSrcweir */
95*cdf0e10cSrcweir Job::Job( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR  ,
96*cdf0e10cSrcweir           /*IN*/ const css::uno::Reference< css::frame::XFrame >&              xFrame )
97*cdf0e10cSrcweir     : ThreadHelpBase       (&Application::GetSolarMutex())
98*cdf0e10cSrcweir     , ::cppu::OWeakObject  (                             )
99*cdf0e10cSrcweir     , m_aJobCfg            (xSMGR                        )
100*cdf0e10cSrcweir     , m_xSMGR              (xSMGR                        )
101*cdf0e10cSrcweir     , m_xFrame             (xFrame                       )
102*cdf0e10cSrcweir     , m_bListenOnDesktop   (sal_False                    )
103*cdf0e10cSrcweir     , m_bListenOnFrame     (sal_False                    )
104*cdf0e10cSrcweir     , m_bListenOnModel     (sal_False                    )
105*cdf0e10cSrcweir     , m_bPendingCloseFrame (sal_False                    )
106*cdf0e10cSrcweir     , m_bPendingCloseModel (sal_False                    )
107*cdf0e10cSrcweir     , m_eRunState          (E_NEW                        )
108*cdf0e10cSrcweir {
109*cdf0e10cSrcweir }
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir //________________________________
112*cdf0e10cSrcweir /**
113*cdf0e10cSrcweir     @short      standard ctor
114*cdf0e10cSrcweir     @descr      It initialize this new instance. But it set some generic parameters here only.
115*cdf0e10cSrcweir                 Specialized informations (e.g. the alias or service name ofthis job) will be set
116*cdf0e10cSrcweir                 later using the method setJobData().
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir     @param      xSMGR
119*cdf0e10cSrcweir                 reference to the uno service manager
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir     @param      xModel
122*cdf0e10cSrcweir                 reference to the model, in which environment we run
123*cdf0e10cSrcweir                 (May be null!)
124*cdf0e10cSrcweir */
125*cdf0e10cSrcweir Job::Job( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR  ,
126*cdf0e10cSrcweir           /*IN*/ const css::uno::Reference< css::frame::XModel >&              xModel )
127*cdf0e10cSrcweir     : ThreadHelpBase       (&Application::GetSolarMutex())
128*cdf0e10cSrcweir     , ::cppu::OWeakObject  (                             )
129*cdf0e10cSrcweir     , m_aJobCfg            (xSMGR                        )
130*cdf0e10cSrcweir     , m_xSMGR              (xSMGR                        )
131*cdf0e10cSrcweir     , m_xModel             (xModel                       )
132*cdf0e10cSrcweir     , m_bListenOnDesktop   (sal_False                    )
133*cdf0e10cSrcweir     , m_bListenOnFrame     (sal_False                    )
134*cdf0e10cSrcweir     , m_bListenOnModel     (sal_False                    )
135*cdf0e10cSrcweir     , m_bPendingCloseFrame (sal_False                    )
136*cdf0e10cSrcweir     , m_bPendingCloseModel (sal_False                    )
137*cdf0e10cSrcweir     , m_eRunState          (E_NEW                        )
138*cdf0e10cSrcweir {
139*cdf0e10cSrcweir }
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir //________________________________
142*cdf0e10cSrcweir /**
143*cdf0e10cSrcweir     @short  superflous!
144*cdf0e10cSrcweir     @descr  Releasing of memory and reference must be done inside die() call.
145*cdf0e10cSrcweir             Otherwhise it's a bug.
146*cdf0e10cSrcweir */
147*cdf0e10cSrcweir Job::~Job()
148*cdf0e10cSrcweir {
149*cdf0e10cSrcweir }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir //________________________________
152*cdf0e10cSrcweir /**
153*cdf0e10cSrcweir     @short  set (or delete) a listener for sending dispatch result events
154*cdf0e10cSrcweir     @descr  Because this object is used in a wrapped mode ... the original listener
155*cdf0e10cSrcweir             for such events can't be registered here directly. Because the
156*cdf0e10cSrcweir             listener expect to get the original object given as source of the event.
157*cdf0e10cSrcweir             That's why we get this source here too, to fake(!) it at sending time!
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir     @param  xListener
160*cdf0e10cSrcweir                 the original listener for dispatch result events
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir     @param  xSourceFake
163*cdf0e10cSrcweir                 our user, which got the registration request for this listener
164*cdf0e10cSrcweir */
165*cdf0e10cSrcweir void Job::setDispatchResultFake( /*IN*/ const css::uno::Reference< css::frame::XDispatchResultListener >& xListener   ,
166*cdf0e10cSrcweir                                  /*IN*/ const css::uno::Reference< css::uno::XInterface >&                xSourceFake )
167*cdf0e10cSrcweir {
168*cdf0e10cSrcweir     /* SAFE { */
169*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
170*cdf0e10cSrcweir 
171*cdf0e10cSrcweir     // reject dangerous calls
172*cdf0e10cSrcweir     if (m_eRunState != E_NEW)
173*cdf0e10cSrcweir     {
174*cdf0e10cSrcweir         LOG_WARNING("Job::setJobData()", "job may still running or already finished")
175*cdf0e10cSrcweir         return;
176*cdf0e10cSrcweir     }
177*cdf0e10cSrcweir 
178*cdf0e10cSrcweir     m_xResultListener   = xListener  ;
179*cdf0e10cSrcweir     m_xResultSourceFake = xSourceFake;
180*cdf0e10cSrcweir     aWriteLock.unlock();
181*cdf0e10cSrcweir     /* } SAFE */
182*cdf0e10cSrcweir }
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir void Job::setJobData( const JobData& aData )
185*cdf0e10cSrcweir {
186*cdf0e10cSrcweir     /* SAFE { */
187*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir     // reject dangerous calls
190*cdf0e10cSrcweir     if (m_eRunState != E_NEW)
191*cdf0e10cSrcweir     {
192*cdf0e10cSrcweir         LOG_WARNING("Job::setJobData()", "job may still running or already finished")
193*cdf0e10cSrcweir         return;
194*cdf0e10cSrcweir     }
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir     m_aJobCfg = aData;
197*cdf0e10cSrcweir     aWriteLock.unlock();
198*cdf0e10cSrcweir     /* } SAFE */
199*cdf0e10cSrcweir }
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir //________________________________
202*cdf0e10cSrcweir /**
203*cdf0e10cSrcweir     @short  runs the job
204*cdf0e10cSrcweir     @descr  It doesn't matter, if the job is an asynchronous or
205*cdf0e10cSrcweir             synchronous one. This method returns only if it was finished
206*cdf0e10cSrcweir             or cancelled.
207*cdf0e10cSrcweir 
208*cdf0e10cSrcweir     @param  lDynamicArgs
209*cdf0e10cSrcweir                 optional arguments for job execution
210*cdf0e10cSrcweir                 In case the represented job is a configured one (which uses static
211*cdf0e10cSrcweir                 arguments too) all informations will be merged!
212*cdf0e10cSrcweir */
213*cdf0e10cSrcweir void Job::execute( /*IN*/ const css::uno::Sequence< css::beans::NamedValue >& lDynamicArgs )
214*cdf0e10cSrcweir {
215*cdf0e10cSrcweir     /* SAFE { */
216*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir     // reject dangerous calls
219*cdf0e10cSrcweir     if (m_eRunState != E_NEW)
220*cdf0e10cSrcweir     {
221*cdf0e10cSrcweir         LOG_WARNING("Job::execute()", "job may still running or already finished")
222*cdf0e10cSrcweir         return;
223*cdf0e10cSrcweir     }
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir     // create the environment and mark this job as running ...
226*cdf0e10cSrcweir     m_eRunState = E_RUNNING;
227*cdf0e10cSrcweir     impl_startListening();
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir     css::uno::Reference< css::task::XAsyncJob >  xAJob;
230*cdf0e10cSrcweir     css::uno::Reference< css::task::XJob >       xSJob;
231*cdf0e10cSrcweir     css::uno::Sequence< css::beans::NamedValue > lJobArgs = impl_generateJobArgs(lDynamicArgs);
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir     // It's neccessary to hold us self alive!
234*cdf0e10cSrcweir     // Otherwhise we might die by ref count ...
235*cdf0e10cSrcweir     css::uno::Reference< css::task::XJobListener > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
236*cdf0e10cSrcweir 
237*cdf0e10cSrcweir     try
238*cdf0e10cSrcweir     {
239*cdf0e10cSrcweir         // create the job
240*cdf0e10cSrcweir         // We must check for the supported interface on demand!
241*cdf0e10cSrcweir         // But we preferr the synchronous one ...
242*cdf0e10cSrcweir         m_xJob = m_xSMGR->createInstance(m_aJobCfg.getService());
243*cdf0e10cSrcweir         xSJob  = css::uno::Reference< css::task::XJob >(m_xJob, css::uno::UNO_QUERY);
244*cdf0e10cSrcweir         if (!xSJob.is())
245*cdf0e10cSrcweir             xAJob = css::uno::Reference< css::task::XAsyncJob >(m_xJob, css::uno::UNO_QUERY);
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir         // execute it asynchron
248*cdf0e10cSrcweir         if (xAJob.is())
249*cdf0e10cSrcweir         {
250*cdf0e10cSrcweir             m_aAsyncWait.reset();
251*cdf0e10cSrcweir             aWriteLock.unlock();
252*cdf0e10cSrcweir             /* } SAFE */
253*cdf0e10cSrcweir             xAJob->executeAsync(lJobArgs, xThis);
254*cdf0e10cSrcweir             // wait for finishing this job - so this method
255*cdf0e10cSrcweir             // does the same for synchronous and asynchronous jobs!
256*cdf0e10cSrcweir             m_aAsyncWait.wait();
257*cdf0e10cSrcweir             aWriteLock.lock();
258*cdf0e10cSrcweir             /* SAFE { */
259*cdf0e10cSrcweir             // Note: Result handling was already done inside the callback!
260*cdf0e10cSrcweir         }
261*cdf0e10cSrcweir         // execute it synchron
262*cdf0e10cSrcweir         else if (xSJob.is())
263*cdf0e10cSrcweir         {
264*cdf0e10cSrcweir             aWriteLock.unlock();
265*cdf0e10cSrcweir             /* } SAFE */
266*cdf0e10cSrcweir             css::uno::Any aResult = xSJob->execute(lJobArgs);
267*cdf0e10cSrcweir             aWriteLock.lock();
268*cdf0e10cSrcweir             /* SAFE { */
269*cdf0e10cSrcweir             impl_reactForJobResult(aResult);
270*cdf0e10cSrcweir         }
271*cdf0e10cSrcweir     }
272*cdf0e10cSrcweir     #if OSL_DEBUG_LEVEL > 0
273*cdf0e10cSrcweir     catch(const css::uno::Exception& ex)
274*cdf0e10cSrcweir     {
275*cdf0e10cSrcweir         ::rtl::OUStringBuffer sMsg(256);
276*cdf0e10cSrcweir         sMsg.appendAscii("Got exception during job execution. Original Message was:\n\"");
277*cdf0e10cSrcweir         sMsg.append     (ex.Message);
278*cdf0e10cSrcweir         sMsg.appendAscii("\"");
279*cdf0e10cSrcweir         LOG_WARNING("Job::execute()", U2B(sMsg.makeStringAndClear()).getStr())
280*cdf0e10cSrcweir     }
281*cdf0e10cSrcweir     #else
282*cdf0e10cSrcweir     catch(const css::uno::Exception&)
283*cdf0e10cSrcweir         {}
284*cdf0e10cSrcweir     #endif
285*cdf0e10cSrcweir 
286*cdf0e10cSrcweir     // deinitialize the environment and mark this job as finished ...
287*cdf0e10cSrcweir     // but don't overwrite any informations about STOPPED or might DISPOSED jobs!
288*cdf0e10cSrcweir     impl_stopListening();
289*cdf0e10cSrcweir     if (m_eRunState == E_RUNNING)
290*cdf0e10cSrcweir         m_eRunState = E_STOPPED_OR_FINISHED;
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir     // If we got a close request from our frame or model ...
293*cdf0e10cSrcweir     // but we disagreed wit that by throwing a veto exception...
294*cdf0e10cSrcweir     // and got the ownership ...
295*cdf0e10cSrcweir     // we have to close the resource frame or model now -
296*cdf0e10cSrcweir     // and to disable ourself!
297*cdf0e10cSrcweir     if (m_bPendingCloseFrame)
298*cdf0e10cSrcweir     {
299*cdf0e10cSrcweir         m_bPendingCloseFrame = sal_False;
300*cdf0e10cSrcweir         css::uno::Reference< css::util::XCloseable > xClose(m_xFrame, css::uno::UNO_QUERY);
301*cdf0e10cSrcweir         if (xClose.is())
302*cdf0e10cSrcweir         {
303*cdf0e10cSrcweir             try
304*cdf0e10cSrcweir             {
305*cdf0e10cSrcweir                 xClose->close(sal_True);
306*cdf0e10cSrcweir             }
307*cdf0e10cSrcweir             catch(const css::util::CloseVetoException&) {}
308*cdf0e10cSrcweir         }
309*cdf0e10cSrcweir     }
310*cdf0e10cSrcweir 
311*cdf0e10cSrcweir     if (m_bPendingCloseModel)
312*cdf0e10cSrcweir     {
313*cdf0e10cSrcweir         m_bPendingCloseModel = sal_False;
314*cdf0e10cSrcweir         css::uno::Reference< css::util::XCloseable > xClose(m_xModel, css::uno::UNO_QUERY);
315*cdf0e10cSrcweir         if (xClose.is())
316*cdf0e10cSrcweir         {
317*cdf0e10cSrcweir             try
318*cdf0e10cSrcweir             {
319*cdf0e10cSrcweir                 xClose->close(sal_True);
320*cdf0e10cSrcweir             }
321*cdf0e10cSrcweir             catch(const css::util::CloseVetoException&) {}
322*cdf0e10cSrcweir         }
323*cdf0e10cSrcweir     }
324*cdf0e10cSrcweir 
325*cdf0e10cSrcweir     aWriteLock.unlock();
326*cdf0e10cSrcweir     /* SAFE { */
327*cdf0e10cSrcweir 
328*cdf0e10cSrcweir     // release this instance ...
329*cdf0e10cSrcweir     die();
330*cdf0e10cSrcweir }
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir //________________________________
333*cdf0e10cSrcweir /**
334*cdf0e10cSrcweir     @short  kill this job
335*cdf0e10cSrcweir     @descr  It doesn't matter if this request is called from inside or
336*cdf0e10cSrcweir             from outside. We release our internal structures and stop
337*cdf0e10cSrcweir             avary activity. After doing so - this instance will not be
338*cdf0e10cSrcweir             useable any longer! Of course we try to handle further requests
339*cdf0e10cSrcweir             carefully. May somehwere else hold a reference to us ...
340*cdf0e10cSrcweir */
341*cdf0e10cSrcweir void Job::die()
342*cdf0e10cSrcweir {
343*cdf0e10cSrcweir     /* SAFE { */
344*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
345*cdf0e10cSrcweir 
346*cdf0e10cSrcweir     impl_stopListening();
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir     if (m_eRunState != E_DISPOSED)
349*cdf0e10cSrcweir     {
350*cdf0e10cSrcweir         try
351*cdf0e10cSrcweir         {
352*cdf0e10cSrcweir             css::uno::Reference< css::lang::XComponent > xDispose(m_xJob, css::uno::UNO_QUERY);
353*cdf0e10cSrcweir             if (xDispose.is())
354*cdf0e10cSrcweir             {
355*cdf0e10cSrcweir                 xDispose->dispose();
356*cdf0e10cSrcweir                 m_eRunState = E_DISPOSED;
357*cdf0e10cSrcweir             }
358*cdf0e10cSrcweir         }
359*cdf0e10cSrcweir         catch(const css::lang::DisposedException&)
360*cdf0e10cSrcweir         {
361*cdf0e10cSrcweir             m_eRunState = E_DISPOSED;
362*cdf0e10cSrcweir         }
363*cdf0e10cSrcweir     }
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir     m_xJob               = css::uno::Reference< css::uno::XInterface >();
366*cdf0e10cSrcweir     m_xFrame             = css::uno::Reference< css::frame::XFrame >();
367*cdf0e10cSrcweir     m_xModel             = css::uno::Reference< css::frame::XModel >();
368*cdf0e10cSrcweir     m_xDesktop           = css::uno::Reference< css::frame::XDesktop >();
369*cdf0e10cSrcweir     m_xResultListener    = css::uno::Reference< css::frame::XDispatchResultListener >();
370*cdf0e10cSrcweir     m_xResultSourceFake  = css::uno::Reference< css::uno::XInterface >();
371*cdf0e10cSrcweir     m_bPendingCloseFrame = sal_False;
372*cdf0e10cSrcweir     m_bPendingCloseModel = sal_False;
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir     aWriteLock.unlock();
375*cdf0e10cSrcweir     /* SAFE { */
376*cdf0e10cSrcweir }
377*cdf0e10cSrcweir 
378*cdf0e10cSrcweir //________________________________
379*cdf0e10cSrcweir /**
380*cdf0e10cSrcweir     @short  generates list of arguments for job execute
381*cdf0e10cSrcweir     @descr  There exist a set of informations, which can be needed by a job.
382*cdf0e10cSrcweir                 a) it's static configuration data   (Equals for all jobs.    )
383*cdf0e10cSrcweir                 b) it's specific configuration data (Different for every job.)
384*cdf0e10cSrcweir                 c) some environment values          (e.g. the frame, for which this job was started)
385*cdf0e10cSrcweir                 d) any other dynamic data           (e.g. parameters of a dispatch() request)
386*cdf0e10cSrcweir             We collect all these informations and generate one list which include all others.
387*cdf0e10cSrcweir 
388*cdf0e10cSrcweir     @param  lDynamicArgs
389*cdf0e10cSrcweir                 list of dynamic arguments (given by a corresponding dispatch() call)
390*cdf0e10cSrcweir                 Can be empty too.
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir     @return A list which includes all mentioned sub lists.
393*cdf0e10cSrcweir */
394*cdf0e10cSrcweir css::uno::Sequence< css::beans::NamedValue > Job::impl_generateJobArgs( /*IN*/ const css::uno::Sequence< css::beans::NamedValue >& lDynamicArgs )
395*cdf0e10cSrcweir {
396*cdf0e10cSrcweir     css::uno::Sequence< css::beans::NamedValue > lAllArgs;
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir     /* SAFE { */
399*cdf0e10cSrcweir     ReadGuard aReadLock(m_aLock);
400*cdf0e10cSrcweir 
401*cdf0e10cSrcweir     // the real structure of the returned list depends from the environment of this job!
402*cdf0e10cSrcweir     JobData::EMode eMode = m_aJobCfg.getMode();
403*cdf0e10cSrcweir 
404*cdf0e10cSrcweir     // Create list of environment variables. This list must be part of the
405*cdf0e10cSrcweir     // returned structure everytimes ... but some of its members are opetional!
406*cdf0e10cSrcweir     css::uno::Sequence< css::beans::NamedValue > lEnvArgs(1);
407*cdf0e10cSrcweir     lEnvArgs[0].Name    = ::rtl::OUString::createFromAscii(JobData::PROP_ENVTYPE);
408*cdf0e10cSrcweir     lEnvArgs[0].Value <<= m_aJobCfg.getEnvironmentDescriptor();
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir     if (m_xFrame.is())
411*cdf0e10cSrcweir     {
412*cdf0e10cSrcweir         sal_Int32 c = lEnvArgs.getLength();
413*cdf0e10cSrcweir         lEnvArgs.realloc(c+1);
414*cdf0e10cSrcweir         lEnvArgs[c].Name    = ::rtl::OUString::createFromAscii(JobData::PROP_FRAME);
415*cdf0e10cSrcweir         lEnvArgs[c].Value <<= m_xFrame;
416*cdf0e10cSrcweir     }
417*cdf0e10cSrcweir     if (m_xModel.is())
418*cdf0e10cSrcweir     {
419*cdf0e10cSrcweir         sal_Int32 c = lEnvArgs.getLength();
420*cdf0e10cSrcweir         lEnvArgs.realloc(c+1);
421*cdf0e10cSrcweir         lEnvArgs[c].Name    = ::rtl::OUString::createFromAscii(JobData::PROP_MODEL);
422*cdf0e10cSrcweir         lEnvArgs[c].Value <<= m_xModel;
423*cdf0e10cSrcweir     }
424*cdf0e10cSrcweir     if (eMode==JobData::E_EVENT)
425*cdf0e10cSrcweir     {
426*cdf0e10cSrcweir         sal_Int32 c = lEnvArgs.getLength();
427*cdf0e10cSrcweir         lEnvArgs.realloc(c+1);
428*cdf0e10cSrcweir         lEnvArgs[c].Name    = ::rtl::OUString::createFromAscii(JobData::PROP_EVENTNAME);
429*cdf0e10cSrcweir         lEnvArgs[c].Value <<= m_aJobCfg.getEvent();
430*cdf0e10cSrcweir     }
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir     // get the configuration data from the job data container ... if possible
433*cdf0e10cSrcweir     // Means: if this job has any configuration data. Note: only realy
434*cdf0e10cSrcweir     // filled lists will be set to the return structure at the end of this method.
435*cdf0e10cSrcweir     css::uno::Sequence< css::beans::NamedValue > lConfigArgs   ;
436*cdf0e10cSrcweir     css::uno::Sequence< css::beans::NamedValue > lJobConfigArgs;
437*cdf0e10cSrcweir     if (eMode==JobData::E_ALIAS || eMode==JobData::E_EVENT)
438*cdf0e10cSrcweir     {
439*cdf0e10cSrcweir         lConfigArgs    = m_aJobCfg.getConfig();
440*cdf0e10cSrcweir         lJobConfigArgs = m_aJobCfg.getJobConfig();
441*cdf0e10cSrcweir     }
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir     aReadLock.unlock();
444*cdf0e10cSrcweir     /* } SAFE */
445*cdf0e10cSrcweir 
446*cdf0e10cSrcweir     // Add all valid (not empty) lists to the return list
447*cdf0e10cSrcweir     if (lConfigArgs.getLength()>0)
448*cdf0e10cSrcweir     {
449*cdf0e10cSrcweir         sal_Int32 nLength = lAllArgs.getLength();
450*cdf0e10cSrcweir         lAllArgs.realloc(nLength+1);
451*cdf0e10cSrcweir         lAllArgs[nLength].Name    = ::rtl::OUString::createFromAscii(JobData::PROPSET_CONFIG);
452*cdf0e10cSrcweir         lAllArgs[nLength].Value <<= lConfigArgs;
453*cdf0e10cSrcweir     }
454*cdf0e10cSrcweir     if (lJobConfigArgs.getLength()>0)
455*cdf0e10cSrcweir     {
456*cdf0e10cSrcweir         sal_Int32 nLength = lAllArgs.getLength();
457*cdf0e10cSrcweir         lAllArgs.realloc(nLength+1);
458*cdf0e10cSrcweir         lAllArgs[nLength].Name    = ::rtl::OUString::createFromAscii(JobData::PROPSET_OWNCONFIG);
459*cdf0e10cSrcweir         lAllArgs[nLength].Value <<= lJobConfigArgs;
460*cdf0e10cSrcweir     }
461*cdf0e10cSrcweir     if (lEnvArgs.getLength()>0)
462*cdf0e10cSrcweir     {
463*cdf0e10cSrcweir         sal_Int32 nLength = lAllArgs.getLength();
464*cdf0e10cSrcweir         lAllArgs.realloc(nLength+1);
465*cdf0e10cSrcweir         lAllArgs[nLength].Name    = ::rtl::OUString::createFromAscii(JobData::PROPSET_ENVIRONMENT);
466*cdf0e10cSrcweir         lAllArgs[nLength].Value <<= lEnvArgs;
467*cdf0e10cSrcweir     }
468*cdf0e10cSrcweir     if (lDynamicArgs.getLength()>0)
469*cdf0e10cSrcweir     {
470*cdf0e10cSrcweir         sal_Int32 nLength = lAllArgs.getLength();
471*cdf0e10cSrcweir         lAllArgs.realloc(nLength+1);
472*cdf0e10cSrcweir         lAllArgs[nLength].Name    = ::rtl::OUString::createFromAscii(JobData::PROPSET_DYNAMICDATA);
473*cdf0e10cSrcweir         lAllArgs[nLength].Value <<= lDynamicArgs;
474*cdf0e10cSrcweir     }
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir     return lAllArgs;
477*cdf0e10cSrcweir }
478*cdf0e10cSrcweir 
479*cdf0e10cSrcweir //________________________________
480*cdf0e10cSrcweir /**
481*cdf0e10cSrcweir     @short  analyze the given job result and change the job configuration
482*cdf0e10cSrcweir     @descr  Note: Some results can be handled only, if this job has a valid configuration!
483*cdf0e10cSrcweir             For "not configured jobs" (means pure services) they can be ignored.
484*cdf0e10cSrcweir             But these cases are handled by our JobData member. We can call it everytime.
485*cdf0e10cSrcweir             It does the right things automaticly. E.g. if the job has no configuration ...
486*cdf0e10cSrcweir             it does nothing during setJobConfig()!
487*cdf0e10cSrcweir 
488*cdf0e10cSrcweir     @param  aResult
489*cdf0e10cSrcweir                 the job result for analyzing
490*cdf0e10cSrcweir */
491*cdf0e10cSrcweir void Job::impl_reactForJobResult( /*IN*/ const css::uno::Any& aResult )
492*cdf0e10cSrcweir {
493*cdf0e10cSrcweir     /* SAFE { */
494*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
495*cdf0e10cSrcweir 
496*cdf0e10cSrcweir     // analyze the result set ...
497*cdf0e10cSrcweir     JobResult aAnalyzedResult(aResult);
498*cdf0e10cSrcweir 
499*cdf0e10cSrcweir     // some of the following operations will be supported for different environments
500*cdf0e10cSrcweir     // or different type of jobs only.
501*cdf0e10cSrcweir     JobData::EEnvironment eEnvironment = m_aJobCfg.getEnvironment();
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir     // write back the job specific configuration data ...
504*cdf0e10cSrcweir     // If the environment allow it and if this job has a configuration!
505*cdf0e10cSrcweir     if (
506*cdf0e10cSrcweir         (m_aJobCfg.hasConfig()                            ) &&
507*cdf0e10cSrcweir         (aAnalyzedResult.existPart(JobResult::E_ARGUMENTS))
508*cdf0e10cSrcweir        )
509*cdf0e10cSrcweir     {
510*cdf0e10cSrcweir         m_aJobCfg.setJobConfig(aAnalyzedResult.getArguments());
511*cdf0e10cSrcweir     }
512*cdf0e10cSrcweir 
513*cdf0e10cSrcweir     // disable a job for further executions.
514*cdf0e10cSrcweir     // Note: this option is available inside the environment EXECUTOR only
515*cdf0e10cSrcweir     if (
516*cdf0e10cSrcweir //        (eEnvironment == JobData::E_EXECUTION              ) &&
517*cdf0e10cSrcweir         (m_aJobCfg.hasConfig()                             ) &&
518*cdf0e10cSrcweir         (aAnalyzedResult.existPart(JobResult::E_DEACTIVATE))
519*cdf0e10cSrcweir        )
520*cdf0e10cSrcweir     {
521*cdf0e10cSrcweir         m_aJobCfg.disableJob();
522*cdf0e10cSrcweir     }
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir     // notify any interested listener with the may given result state.
525*cdf0e10cSrcweir     // Note: this option is available inside the environment DISPATCH only
526*cdf0e10cSrcweir     if (
527*cdf0e10cSrcweir         (eEnvironment == JobData::E_DISPATCH                   ) &&
528*cdf0e10cSrcweir         (m_xResultListener.is()                                ) &&
529*cdf0e10cSrcweir         (aAnalyzedResult.existPart(JobResult::E_DISPATCHRESULT))
530*cdf0e10cSrcweir        )
531*cdf0e10cSrcweir     {
532*cdf0e10cSrcweir         m_aJobCfg.setResult(aAnalyzedResult);
533*cdf0e10cSrcweir         // Attention: Because the listener expect that the original object send this event ...
534*cdf0e10cSrcweir         // and we nor the job are the right ones ...
535*cdf0e10cSrcweir         // our user has set itself before. So we can fake this source address!
536*cdf0e10cSrcweir         css::frame::DispatchResultEvent aEvent        = aAnalyzedResult.getDispatchResult();
537*cdf0e10cSrcweir                                         aEvent.Source = m_xResultSourceFake;
538*cdf0e10cSrcweir         m_xResultListener->dispatchFinished(aEvent);
539*cdf0e10cSrcweir     }
540*cdf0e10cSrcweir 
541*cdf0e10cSrcweir     aWriteLock.unlock();
542*cdf0e10cSrcweir     /* SAFE { */
543*cdf0e10cSrcweir }
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir //________________________________
546*cdf0e10cSrcweir /**
547*cdf0e10cSrcweir     @short  starts listening for office shutdown and closing of our
548*cdf0e10cSrcweir             given target frame (if its a valid reference)
549*cdf0e10cSrcweir     @descr  We will reghister ourself as terminate listener
550*cdf0e10cSrcweir             at the global desktop instance. That will hold us
551*cdf0e10cSrcweir             alive and additional we get the information, if the
552*cdf0e10cSrcweir             office whish to shutdown. If then an internal job
553*cdf0e10cSrcweir             is running we will have the chance to supress that
554*cdf0e10cSrcweir             by throwing a veto exception. If our internal wrapped
555*cdf0e10cSrcweir             job finished his work, we can release this listener
556*cdf0e10cSrcweir             connection.
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir             Further we are listener for closing of the (possible valid)
559*cdf0e10cSrcweir             given frame. We must be shure, that this ressource won't be gone
560*cdf0e10cSrcweir             if our internal job is still running.
561*cdf0e10cSrcweir */
562*cdf0e10cSrcweir void Job::impl_startListening()
563*cdf0e10cSrcweir {
564*cdf0e10cSrcweir     /* SAFE { */
565*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir     // listening for office shutdown
568*cdf0e10cSrcweir     if (!m_xDesktop.is() && !m_bListenOnDesktop)
569*cdf0e10cSrcweir     {
570*cdf0e10cSrcweir         try
571*cdf0e10cSrcweir         {
572*cdf0e10cSrcweir             m_xDesktop = css::uno::Reference< css::frame::XDesktop >(m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY);
573*cdf0e10cSrcweir             css::uno::Reference< css::frame::XTerminateListener > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
574*cdf0e10cSrcweir             if (m_xDesktop.is())
575*cdf0e10cSrcweir             {
576*cdf0e10cSrcweir                 m_xDesktop->addTerminateListener(xThis);
577*cdf0e10cSrcweir                 m_bListenOnDesktop = sal_True;
578*cdf0e10cSrcweir             }
579*cdf0e10cSrcweir         }
580*cdf0e10cSrcweir         catch(css::uno::Exception&)
581*cdf0e10cSrcweir         {
582*cdf0e10cSrcweir             m_xDesktop = css::uno::Reference< css::frame::XDesktop >();
583*cdf0e10cSrcweir         }
584*cdf0e10cSrcweir     }
585*cdf0e10cSrcweir 
586*cdf0e10cSrcweir     // listening for frame closing
587*cdf0e10cSrcweir     if (m_xFrame.is() && !m_bListenOnFrame)
588*cdf0e10cSrcweir     {
589*cdf0e10cSrcweir         try
590*cdf0e10cSrcweir         {
591*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xFrame                                 , css::uno::UNO_QUERY);
592*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseListener >    xThis     (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
593*cdf0e10cSrcweir             if (xCloseable.is())
594*cdf0e10cSrcweir             {
595*cdf0e10cSrcweir                 xCloseable->addCloseListener(xThis);
596*cdf0e10cSrcweir                 m_bListenOnFrame = sal_True;
597*cdf0e10cSrcweir             }
598*cdf0e10cSrcweir         }
599*cdf0e10cSrcweir         catch(css::uno::Exception&)
600*cdf0e10cSrcweir         {
601*cdf0e10cSrcweir             m_bListenOnFrame = sal_False;
602*cdf0e10cSrcweir         }
603*cdf0e10cSrcweir     }
604*cdf0e10cSrcweir 
605*cdf0e10cSrcweir     // listening for model closing
606*cdf0e10cSrcweir     if (m_xModel.is() && !m_bListenOnModel)
607*cdf0e10cSrcweir     {
608*cdf0e10cSrcweir         try
609*cdf0e10cSrcweir         {
610*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xModel                                 , css::uno::UNO_QUERY);
611*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseListener >    xThis     (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
612*cdf0e10cSrcweir             if (xCloseable.is())
613*cdf0e10cSrcweir             {
614*cdf0e10cSrcweir                 xCloseable->addCloseListener(xThis);
615*cdf0e10cSrcweir                 m_bListenOnModel = sal_True;
616*cdf0e10cSrcweir             }
617*cdf0e10cSrcweir         }
618*cdf0e10cSrcweir         catch(css::uno::Exception&)
619*cdf0e10cSrcweir         {
620*cdf0e10cSrcweir             m_bListenOnModel = sal_False;
621*cdf0e10cSrcweir         }
622*cdf0e10cSrcweir     }
623*cdf0e10cSrcweir 
624*cdf0e10cSrcweir     aWriteLock.unlock();
625*cdf0e10cSrcweir     /* } SAFE */
626*cdf0e10cSrcweir }
627*cdf0e10cSrcweir 
628*cdf0e10cSrcweir //________________________________
629*cdf0e10cSrcweir /**
630*cdf0e10cSrcweir     @short  release listener connection for office shutdown
631*cdf0e10cSrcweir     @descr  see description of impl_startListening()
632*cdf0e10cSrcweir */
633*cdf0e10cSrcweir void Job::impl_stopListening()
634*cdf0e10cSrcweir {
635*cdf0e10cSrcweir     /* SAFE { */
636*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
637*cdf0e10cSrcweir 
638*cdf0e10cSrcweir     // stop listening for office shutdown
639*cdf0e10cSrcweir     if (m_xDesktop.is() && m_bListenOnDesktop)
640*cdf0e10cSrcweir     {
641*cdf0e10cSrcweir         try
642*cdf0e10cSrcweir         {
643*cdf0e10cSrcweir             css::uno::Reference< css::frame::XTerminateListener > xThis(static_cast< ::cppu::OWeakObject* >(this)   , css::uno::UNO_QUERY);
644*cdf0e10cSrcweir             m_xDesktop->removeTerminateListener(xThis);
645*cdf0e10cSrcweir             m_xDesktop = css::uno::Reference< css::frame::XDesktop >();
646*cdf0e10cSrcweir             m_bListenOnDesktop = sal_False;
647*cdf0e10cSrcweir         }
648*cdf0e10cSrcweir         catch(css::uno::Exception&)
649*cdf0e10cSrcweir         {
650*cdf0e10cSrcweir         }
651*cdf0e10cSrcweir     }
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir     // stop listening for frame closing
654*cdf0e10cSrcweir     if (m_xFrame.is() && m_bListenOnFrame)
655*cdf0e10cSrcweir     {
656*cdf0e10cSrcweir         try
657*cdf0e10cSrcweir         {
658*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xFrame                                 , css::uno::UNO_QUERY);
659*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseListener >    xThis     (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
660*cdf0e10cSrcweir             if (xCloseable.is())
661*cdf0e10cSrcweir             {
662*cdf0e10cSrcweir                 xCloseable->removeCloseListener(xThis);
663*cdf0e10cSrcweir                 m_bListenOnFrame = sal_False;
664*cdf0e10cSrcweir             }
665*cdf0e10cSrcweir         }
666*cdf0e10cSrcweir         catch(css::uno::Exception&)
667*cdf0e10cSrcweir         {
668*cdf0e10cSrcweir         }
669*cdf0e10cSrcweir     }
670*cdf0e10cSrcweir 
671*cdf0e10cSrcweir     // stop listening for model closing
672*cdf0e10cSrcweir     if (m_xModel.is() && m_bListenOnModel)
673*cdf0e10cSrcweir     {
674*cdf0e10cSrcweir         try
675*cdf0e10cSrcweir         {
676*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseBroadcaster > xCloseable(m_xModel                                 , css::uno::UNO_QUERY);
677*cdf0e10cSrcweir             css::uno::Reference< css::util::XCloseListener >    xThis     (static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
678*cdf0e10cSrcweir             if (xCloseable.is())
679*cdf0e10cSrcweir             {
680*cdf0e10cSrcweir                 xCloseable->removeCloseListener(xThis);
681*cdf0e10cSrcweir                 m_bListenOnModel = sal_False;
682*cdf0e10cSrcweir             }
683*cdf0e10cSrcweir         }
684*cdf0e10cSrcweir         catch(css::uno::Exception&)
685*cdf0e10cSrcweir         {
686*cdf0e10cSrcweir         }
687*cdf0e10cSrcweir     }
688*cdf0e10cSrcweir 
689*cdf0e10cSrcweir     aWriteLock.unlock();
690*cdf0e10cSrcweir     /* } SAFE */
691*cdf0e10cSrcweir }
692*cdf0e10cSrcweir 
693*cdf0e10cSrcweir //________________________________
694*cdf0e10cSrcweir /**
695*cdf0e10cSrcweir     @short  callback from any asynchronous executed job
696*cdf0e10cSrcweir 
697*cdf0e10cSrcweir     @descr  Our execute() method waits for this callback.
698*cdf0e10cSrcweir             We have to react for the possible results here,
699*cdf0e10cSrcweir             to kill the running job and disable the blocked condition
700*cdf0e10cSrcweir             so execute() can be finished too.
701*cdf0e10cSrcweir 
702*cdf0e10cSrcweir     @param  xJob
703*cdf0e10cSrcweir                 the job, which was running and inform us now
704*cdf0e10cSrcweir 
705*cdf0e10cSrcweir     @param  aResult
706*cdf0e10cSrcweir                 it's results
707*cdf0e10cSrcweir */
708*cdf0e10cSrcweir void SAL_CALL Job::jobFinished( /*IN*/ const css::uno::Reference< css::task::XAsyncJob >& xJob    ,
709*cdf0e10cSrcweir                                 /*IN*/ const css::uno::Any&                               aResult ) throw(css::uno::RuntimeException)
710*cdf0e10cSrcweir {
711*cdf0e10cSrcweir     /* SAFE { */
712*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
713*cdf0e10cSrcweir 
714*cdf0e10cSrcweir     // It's neccessary to check this.
715*cdf0e10cSrcweir     // May this job was cancelled by any other reason
716*cdf0e10cSrcweir     // some milliseconds before. :-)
717*cdf0e10cSrcweir     if (m_xJob.is() && m_xJob==xJob)
718*cdf0e10cSrcweir     {
719*cdf0e10cSrcweir         // react for his results
720*cdf0e10cSrcweir         // (means enable/disable it for further requests
721*cdf0e10cSrcweir         // or save arguments or notify listener ...)
722*cdf0e10cSrcweir         impl_reactForJobResult(aResult);
723*cdf0e10cSrcweir 
724*cdf0e10cSrcweir         // Let the job die!
725*cdf0e10cSrcweir         m_xJob = css::uno::Reference< css::uno::XInterface >();
726*cdf0e10cSrcweir     }
727*cdf0e10cSrcweir 
728*cdf0e10cSrcweir     // And let the start method "execute()" finishing it's job.
729*cdf0e10cSrcweir     // But do it everytime. So any outside blocking code can finish
730*cdf0e10cSrcweir     // his work too.
731*cdf0e10cSrcweir     m_aAsyncWait.set();
732*cdf0e10cSrcweir 
733*cdf0e10cSrcweir     aWriteLock.unlock();
734*cdf0e10cSrcweir     /* } SAFE */
735*cdf0e10cSrcweir }
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir //________________________________
738*cdf0e10cSrcweir /**
739*cdf0e10cSrcweir     @short  prevent internal wrapped job against office termination
740*cdf0e10cSrcweir     @descr  This event is broadcasted by the desktop instance and ask for an office termination.
741*cdf0e10cSrcweir             If the internal wrapped job is still in progress, we disagree with that by throwing the
742*cdf0e10cSrcweir             right veto exception. If not - we agree. But then we must be aware, that another event
743*cdf0e10cSrcweir             notifyTermination() can follow. Then we have no chance to do the same. Then we have to
744*cdf0e10cSrcweir             accept that and stop our work instandly.
745*cdf0e10cSrcweir 
746*cdf0e10cSrcweir     @param  aEvent
747*cdf0e10cSrcweir                 describes the broadcaster and must be the desktop instance
748*cdf0e10cSrcweir 
749*cdf0e10cSrcweir     @throw  TerminateVetoException
750*cdf0e10cSrcweir                 if our internal wrapped job is still running.
751*cdf0e10cSrcweir  */
752*cdf0e10cSrcweir void SAL_CALL Job::queryTermination( /*IN*/ const css::lang::EventObject& ) throw(css::frame::TerminationVetoException,
753*cdf0e10cSrcweir                                                                                          css::uno::RuntimeException          )
754*cdf0e10cSrcweir {
755*cdf0e10cSrcweir     /* SAFE { */
756*cdf0e10cSrcweir     ReadGuard aReadLock(m_aLock);
757*cdf0e10cSrcweir 
758*cdf0e10cSrcweir     // don't disagree with this request if job was already stopped or finished it's work
759*cdf0e10cSrcweir     // if (m_eRunState != E_RUNNING)
760*cdf0e10cSrcweir     //    return;
761*cdf0e10cSrcweir 
762*cdf0e10cSrcweir     // Otherwhise try to close() it
763*cdf0e10cSrcweir     css::uno::Reference< css::util::XCloseable > xClose(m_xJob, css::uno::UNO_QUERY);
764*cdf0e10cSrcweir     if (xClose.is())
765*cdf0e10cSrcweir     {
766*cdf0e10cSrcweir         try
767*cdf0e10cSrcweir         {
768*cdf0e10cSrcweir             xClose->close(sal_False);
769*cdf0e10cSrcweir             m_eRunState = E_STOPPED_OR_FINISHED;
770*cdf0e10cSrcweir         }
771*cdf0e10cSrcweir         catch(const css::util::CloseVetoException&) {}
772*cdf0e10cSrcweir     }
773*cdf0e10cSrcweir 
774*cdf0e10cSrcweir     if (m_eRunState != E_STOPPED_OR_FINISHED)
775*cdf0e10cSrcweir     {
776*cdf0e10cSrcweir         css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
777*cdf0e10cSrcweir         throw css::frame::TerminationVetoException(DECLARE_ASCII("job still in progress"), xThis);
778*cdf0e10cSrcweir     }
779*cdf0e10cSrcweir 
780*cdf0e10cSrcweir     aReadLock.unlock();
781*cdf0e10cSrcweir     /* } SAFE */
782*cdf0e10cSrcweir }
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir 
785*cdf0e10cSrcweir //________________________________
786*cdf0e10cSrcweir /**
787*cdf0e10cSrcweir     @short  inform us about office termination
788*cdf0e10cSrcweir     @descr  Instead of the method queryTermination(), here is no chance to disagree with that.
789*cdf0e10cSrcweir             We have to accept it and cancel all current processes inside.
790*cdf0e10cSrcweir             It can occure only, if job was not already started if queryTermination() was called here ..
791*cdf0e10cSrcweir             Then we had not throwed a veto exception. But now we must agree with this situation and break
792*cdf0e10cSrcweir             all our internal processes. Its not a good idea to mark this instance as non startable any longer
793*cdf0e10cSrcweir             inside queryTermination() if no job was unning too. Because that would disable this job and may
794*cdf0e10cSrcweir             the office does not realy shutdownm, because another listener has thrown the suitable exception.
795*cdf0e10cSrcweir 
796*cdf0e10cSrcweir     @param  aEvent
797*cdf0e10cSrcweir                 describes the broadcaster and must be the desktop instance
798*cdf0e10cSrcweir  */
799*cdf0e10cSrcweir void SAL_CALL Job::notifyTermination( /*IN*/ const css::lang::EventObject& ) throw(css::uno::RuntimeException)
800*cdf0e10cSrcweir {
801*cdf0e10cSrcweir     die();
802*cdf0e10cSrcweir     // Do nothing else here. Our internal ressources was released ...
803*cdf0e10cSrcweir }
804*cdf0e10cSrcweir 
805*cdf0e10cSrcweir //________________________________
806*cdf0e10cSrcweir /**
807*cdf0e10cSrcweir     @short  prevent internal wrapped job against frame closing
808*cdf0e10cSrcweir     @descr  This event is broadcasted by the frame instance and ask for closing.
809*cdf0e10cSrcweir             If the internal wrapped job is still in progress, we disagree with that by throwing the
810*cdf0e10cSrcweir             right veto exception. If not - we agree. But then we must be aware, that another event
811*cdf0e10cSrcweir             notifyClosing() can follow. Then we have no chance to do the same. Then we have to
812*cdf0e10cSrcweir             accept that and stop our work instandly.
813*cdf0e10cSrcweir 
814*cdf0e10cSrcweir     @param  aEvent
815*cdf0e10cSrcweir                 describes the broadcaster and must be the frame instance
816*cdf0e10cSrcweir 
817*cdf0e10cSrcweir     @param  bGetsOwnerShip
818*cdf0e10cSrcweir                 If it's set to <sal_True> and we throw the right veto excepion, we have to close this frame later
819*cdf0e10cSrcweir                 if our internal processes will be finished. If it's set to <FALSE/> we can ignore it.
820*cdf0e10cSrcweir 
821*cdf0e10cSrcweir     @throw  CloseVetoException
822*cdf0e10cSrcweir                 if our internal wrapped job is still running.
823*cdf0e10cSrcweir  */
824*cdf0e10cSrcweir void SAL_CALL Job::queryClosing( const css::lang::EventObject& aEvent         ,
825*cdf0e10cSrcweir                                        sal_Bool                bGetsOwnership ) throw(css::util::CloseVetoException,
826*cdf0e10cSrcweir                                                                                       css::uno::RuntimeException   )
827*cdf0e10cSrcweir {
828*cdf0e10cSrcweir     /* SAFE { */
829*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
830*cdf0e10cSrcweir 
831*cdf0e10cSrcweir     // do nothing, if no internal job is still running ...
832*cdf0e10cSrcweir     // The frame or model can be closed then successfully.
833*cdf0e10cSrcweir     if (m_eRunState != E_RUNNING)
834*cdf0e10cSrcweir         return;
835*cdf0e10cSrcweir 
836*cdf0e10cSrcweir     // try close() first at the job.
837*cdf0e10cSrcweir     // The job can agree or disagree with this request.
838*cdf0e10cSrcweir     css::uno::Reference< css::util::XCloseable > xClose(m_xJob, css::uno::UNO_QUERY);
839*cdf0e10cSrcweir     if (xClose.is())
840*cdf0e10cSrcweir     {
841*cdf0e10cSrcweir         xClose->close(bGetsOwnership);
842*cdf0e10cSrcweir         // Here we can say: "this job was stopped successfully". Because
843*cdf0e10cSrcweir         // no veto exception was thrown!
844*cdf0e10cSrcweir         m_eRunState = E_STOPPED_OR_FINISHED;
845*cdf0e10cSrcweir         return;
846*cdf0e10cSrcweir     }
847*cdf0e10cSrcweir 
848*cdf0e10cSrcweir     // try dispose() then
849*cdf0e10cSrcweir     // Here the job has no chance for a veto.
850*cdf0e10cSrcweir     // But we must be aware of an "already disposed exception"...
851*cdf0e10cSrcweir     try
852*cdf0e10cSrcweir     {
853*cdf0e10cSrcweir         css::uno::Reference< css::lang::XComponent > xDispose(m_xJob, css::uno::UNO_QUERY);
854*cdf0e10cSrcweir         if (xDispose.is())
855*cdf0e10cSrcweir         {
856*cdf0e10cSrcweir             xDispose->dispose();
857*cdf0e10cSrcweir             m_eRunState = E_DISPOSED;
858*cdf0e10cSrcweir         }
859*cdf0e10cSrcweir     }
860*cdf0e10cSrcweir     catch(const css::lang::DisposedException&)
861*cdf0e10cSrcweir     {
862*cdf0e10cSrcweir         // the job was already disposed by any other mechanism !?
863*cdf0e10cSrcweir         // But it's not interesting for us. For us this job is stopped now.
864*cdf0e10cSrcweir         m_eRunState = E_DISPOSED;
865*cdf0e10cSrcweir     }
866*cdf0e10cSrcweir 
867*cdf0e10cSrcweir     if (m_eRunState != E_DISPOSED)
868*cdf0e10cSrcweir     {
869*cdf0e10cSrcweir         // analyze event source - to find out, which resource called queryClosing() at this
870*cdf0e10cSrcweir         // job wrapper. We must bind a "pending close" request to this resource.
871*cdf0e10cSrcweir         // Closing of the corresponding resource will be done if our internal job finish it's work.
872*cdf0e10cSrcweir         m_bPendingCloseFrame = (m_xFrame.is() && aEvent.Source == m_xFrame);
873*cdf0e10cSrcweir         m_bPendingCloseModel = (m_xModel.is() && aEvent.Source == m_xModel);
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir         // throw suitable veto exception - because the internal job could not be cancelled.
876*cdf0e10cSrcweir         css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
877*cdf0e10cSrcweir         throw css::util::CloseVetoException(DECLARE_ASCII("job still in progress"), xThis);
878*cdf0e10cSrcweir     }
879*cdf0e10cSrcweir 
880*cdf0e10cSrcweir     // No veto ...
881*cdf0e10cSrcweir     // But don't call die() here or free our internal member.
882*cdf0e10cSrcweir     // This must be done inside notifyClosing() only. Otherwhise the
883*cdf0e10cSrcweir     // might stopped job has no chance to return it's results or
884*cdf0e10cSrcweir     // call us back. We must give him the chance to finish it's work successfully.
885*cdf0e10cSrcweir 
886*cdf0e10cSrcweir     aWriteLock.unlock();
887*cdf0e10cSrcweir     /* } SAFE */
888*cdf0e10cSrcweir }
889*cdf0e10cSrcweir 
890*cdf0e10cSrcweir //________________________________
891*cdf0e10cSrcweir /**
892*cdf0e10cSrcweir     @short  inform us about frame closing
893*cdf0e10cSrcweir     @descr  Instead of the method queryClosing(), here is no chance to disagree with that.
894*cdf0e10cSrcweir             We have to accept it and cancel all current processes inside.
895*cdf0e10cSrcweir 
896*cdf0e10cSrcweir     @param  aEvent
897*cdf0e10cSrcweir             describes the broadcaster and must be the frame or model instance we know
898*cdf0e10cSrcweir  */
899*cdf0e10cSrcweir void SAL_CALL Job::notifyClosing( const css::lang::EventObject& ) throw(css::uno::RuntimeException)
900*cdf0e10cSrcweir {
901*cdf0e10cSrcweir     die();
902*cdf0e10cSrcweir     // Do nothing else here. Our internal ressources was released ...
903*cdf0e10cSrcweir }
904*cdf0e10cSrcweir 
905*cdf0e10cSrcweir //________________________________
906*cdf0e10cSrcweir /**
907*cdf0e10cSrcweir     @short      shouldn't be called normaly
908*cdf0e10cSrcweir     @descr      But it doesn't matter, who called it. We have to kill our internal
909*cdf0e10cSrcweir                 running processes hardly.
910*cdf0e10cSrcweir 
911*cdf0e10cSrcweir     @param      aEvent
912*cdf0e10cSrcweir                 describe the broadcaster
913*cdf0e10cSrcweir */
914*cdf0e10cSrcweir void SAL_CALL Job::disposing( const css::lang::EventObject& aEvent ) throw(css::uno::RuntimeException)
915*cdf0e10cSrcweir {
916*cdf0e10cSrcweir     /* SAFE { */
917*cdf0e10cSrcweir     WriteGuard aWriteLock(m_aLock);
918*cdf0e10cSrcweir 
919*cdf0e10cSrcweir     if (m_xDesktop.is() && aEvent.Source == m_xDesktop)
920*cdf0e10cSrcweir     {
921*cdf0e10cSrcweir         m_xDesktop = css::uno::Reference< css::frame::XDesktop >();
922*cdf0e10cSrcweir         m_bListenOnDesktop = sal_False;
923*cdf0e10cSrcweir     }
924*cdf0e10cSrcweir     else
925*cdf0e10cSrcweir     if (m_xFrame.is() && aEvent.Source == m_xFrame)
926*cdf0e10cSrcweir     {
927*cdf0e10cSrcweir         m_xFrame = css::uno::Reference< css::frame::XFrame >();
928*cdf0e10cSrcweir         m_bListenOnFrame = sal_False;
929*cdf0e10cSrcweir     }
930*cdf0e10cSrcweir     else
931*cdf0e10cSrcweir     if (m_xModel.is() && aEvent.Source == m_xModel)
932*cdf0e10cSrcweir     {
933*cdf0e10cSrcweir         m_xModel = css::uno::Reference< css::frame::XModel >();
934*cdf0e10cSrcweir         m_bListenOnModel = sal_False;
935*cdf0e10cSrcweir     }
936*cdf0e10cSrcweir 
937*cdf0e10cSrcweir     aWriteLock.unlock();
938*cdf0e10cSrcweir     /* } SAFE */
939*cdf0e10cSrcweir 
940*cdf0e10cSrcweir     die();
941*cdf0e10cSrcweir     // Do nothing else here. Our internal ressources was released ...
942*cdf0e10cSrcweir }
943*cdf0e10cSrcweir 
944*cdf0e10cSrcweir } // namespace framework
945