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

Generated by: LCOV version 1.11