LCOV - code coverage report
Current view: top level - libreoffice/framework/source/jobs - job.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 278 0.0 %
Date: 2012-12-17 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10