xref: /aoo42x/main/framework/source/jobs/job.cxx (revision 6d739b60)
1*6d739b60SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*6d739b60SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*6d739b60SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*6d739b60SAndrew Rist  * distributed with this work for additional information
6*6d739b60SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*6d739b60SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*6d739b60SAndrew Rist  * "License"); you may not use this file except in compliance
9*6d739b60SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*6d739b60SAndrew Rist  *
11*6d739b60SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*6d739b60SAndrew Rist  *
13*6d739b60SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*6d739b60SAndrew Rist  * software distributed under the License is distributed on an
15*6d739b60SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*6d739b60SAndrew Rist  * KIND, either express or implied.  See the License for the
17*6d739b60SAndrew Rist  * specific language governing permissions and limitations
18*6d739b60SAndrew Rist  * under the License.
19*6d739b60SAndrew Rist  *
20*6d739b60SAndrew Rist  *************************************************************/
21*6d739b60SAndrew Rist 
22*6d739b60SAndrew 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 
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
80cdf0e10cSrcweir     @descr      It initialize this new instance. But it set some generic parameters here only.
81cdf0e10cSrcweir                 Specialized informations (e.g. the alias or service name ofthis 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
110cdf0e10cSrcweir     @descr      It initialize this new instance. But it set some generic parameters here only.
111cdf0e10cSrcweir                 Specialized informations (e.g. the alias or service name ofthis 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 */
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 /**
139cdf0e10cSrcweir     @short  superflous!
140cdf0e10cSrcweir     @descr  Releasing of memory and reference must be done inside die() call.
141cdf0e10cSrcweir             Otherwhise it's a bug.
142cdf0e10cSrcweir */
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 */
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 
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
202cdf0e10cSrcweir             or cancelled.
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 */
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 
229cdf0e10cSrcweir     // It's neccessary to hold us self alive!
230cdf0e10cSrcweir     // Otherwhise 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!
237cdf0e10cSrcweir         // But we preferr 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 
243cdf0e10cSrcweir         // execute it asynchron
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         }
257cdf0e10cSrcweir         // execute it synchron
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
333cdf0e10cSrcweir             avary activity. After doing so - this instance will not be
334cdf0e10cSrcweir             useable any longer! Of course we try to handle further requests
335cdf0e10cSrcweir             carefully. May somehwere else hold a reference to us ...
336cdf0e10cSrcweir */
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.
378cdf0e10cSrcweir                 a) it's static configuration data   (Equals for all jobs.    )
379cdf0e10cSrcweir                 b) it's 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 */
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
401cdf0e10cSrcweir     // returned structure everytimes ... but some of its members are opetional!
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
429cdf0e10cSrcweir     // Means: if this job has any configuration data. Note: only realy
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.
480cdf0e10cSrcweir             But these cases are handled by our JobData member. We can call it everytime.
481cdf0e10cSrcweir             It does the right things automaticly. 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 */
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)
545cdf0e10cSrcweir     @descr  We will reghister ourself as terminate listener
546cdf0e10cSrcweir             at the global desktop instance. That will hold us
547cdf0e10cSrcweir             alive and additional we get the information, if the
548cdf0e10cSrcweir             office whish to shutdown. If then an internal job
549cdf0e10cSrcweir             is running we will have the chance to supress 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)
555cdf0e10cSrcweir             given frame. We must be shure, that this ressource won't be gone
556cdf0e10cSrcweir             if our internal job is still running.
557cdf0e10cSrcweir */
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 */
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
702cdf0e10cSrcweir                 it's results
703cdf0e10cSrcweir */
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 
710cdf0e10cSrcweir     // It's neccessary to check this.
711cdf0e10cSrcweir     // May this job was cancelled 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 
724cdf0e10cSrcweir     // And let the start method "execute()" finishing it's job.
725cdf0e10cSrcweir     // But do it everytime. 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
740cdf0e10cSrcweir             accept that and stop our work instandly.
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  */
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 
754cdf0e10cSrcweir     // don't disagree with this request if job was already stopped or finished it's work
755cdf0e10cSrcweir     // if (m_eRunState != E_RUNNING)
756cdf0e10cSrcweir     //    return;
757cdf0e10cSrcweir 
758cdf0e10cSrcweir     // Otherwhise 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.
786cdf0e10cSrcweir             It can occure only, if job was not already started if queryTermination() was called here ..
787cdf0e10cSrcweir             Then we had not throwed 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
789cdf0e10cSrcweir             inside queryTermination() if no job was unning too. Because that would disable this job and may
790cdf0e10cSrcweir             the office does not realy shutdownm, because another listener has thrown the suitable exception.
791cdf0e10cSrcweir 
792cdf0e10cSrcweir     @param  aEvent
793cdf0e10cSrcweir                 describes the broadcaster and must be the desktop instance
794cdf0e10cSrcweir  */
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
808cdf0e10cSrcweir             accept that and stop our work instandly.
809cdf0e10cSrcweir 
810cdf0e10cSrcweir     @param  aEvent
811cdf0e10cSrcweir                 describes the broadcaster and must be the frame instance
812cdf0e10cSrcweir 
813cdf0e10cSrcweir     @param  bGetsOwnerShip
814cdf0e10cSrcweir                 If it's set to <sal_True> and we throw the right veto excepion, 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  */
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.
867cdf0e10cSrcweir         // Closing of the corresponding resource will be done if our internal job finish it's 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.
878cdf0e10cSrcweir     // This must be done inside notifyClosing() only. Otherwhise the
879cdf0e10cSrcweir     // might stopped job has no chance to return it's results or
880cdf0e10cSrcweir     // call us back. We must give him the chance to finish it's 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  */
895cdf0e10cSrcweir void SAL_CALL Job::notifyClosing( const css::lang::EventObject& ) throw(css::uno::RuntimeException)
896cdf0e10cSrcweir {
897cdf0e10cSrcweir     die();
898cdf0e10cSrcweir     // Do nothing else here. Our internal ressources was released ...
899cdf0e10cSrcweir }
900cdf0e10cSrcweir 
901cdf0e10cSrcweir //________________________________
902cdf0e10cSrcweir /**
903cdf0e10cSrcweir     @short      shouldn't be called normaly
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 */
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();
937cdf0e10cSrcweir     // Do nothing else here. Our internal ressources was released ...
938cdf0e10cSrcweir }
939cdf0e10cSrcweir 
940cdf0e10cSrcweir } // namespace framework
941