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