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