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

Generated by: LCOV version 1.10