LCOV - code coverage report
Current view: top level - comphelper/source/misc - instancelocker.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 8 199 4.0 %
Date: 2014-11-03 Functions: 3 24 12.5 %
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             : 
      21             : #include "comphelper_module.hxx"
      22             : #include "comphelper_services.hxx"
      23             : #include <cppuhelper/supportsservice.hxx>
      24             : 
      25             : #include <com/sun/star/util/XCloseBroadcaster.hpp>
      26             : #include <com/sun/star/util/XCloseable.hpp>
      27             : #include <com/sun/star/lang/DisposedException.hpp>
      28             : #include <com/sun/star/lang/IllegalArgumentException.hpp>
      29             : #include <com/sun/star/frame/XDesktop.hpp>
      30             : #include <com/sun/star/frame/DoubleInitializationException.hpp>
      31             : #include <com/sun/star/beans/XPropertySet.hpp>
      32             : 
      33             : #include "instancelocker.hxx"
      34             : 
      35             : using namespace ::com::sun::star;
      36             : 
      37             : 
      38             : 
      39             : // OInstanceLocker
      40             : 
      41             : 
      42             : 
      43           0 : OInstanceLocker::OInstanceLocker( const uno::Reference< uno::XComponentContext >& xContext )
      44             : : m_xContext( xContext )
      45             : , m_pLockListener( NULL )
      46             : , m_pListenersContainer( NULL )
      47             : , m_bDisposed( false )
      48           0 : , m_bInitialized( false )
      49             : {
      50           0 : }
      51             : 
      52             : 
      53           0 : OInstanceLocker::~OInstanceLocker()
      54             : {
      55           0 :     if ( !m_bDisposed )
      56             :     {
      57           0 :         m_refCount++; // to call dispose
      58             :         try {
      59           0 :             dispose();
      60             :         }
      61           0 :         catch ( uno::RuntimeException& )
      62             :         {}
      63             :     }
      64             : 
      65           0 :     if ( m_pListenersContainer )
      66             :     {
      67           0 :         delete m_pListenersContainer;
      68           0 :         m_pListenersContainer = NULL;
      69             :     }
      70           0 : }
      71             : 
      72             : // XComponent
      73             : 
      74           0 : void SAL_CALL OInstanceLocker::dispose()
      75             :     throw (uno::RuntimeException, std::exception)
      76             : {
      77           0 :     ::osl::MutexGuard aGuard( m_aMutex );
      78             : 
      79           0 :     if ( m_bDisposed )
      80           0 :         throw lang::DisposedException();
      81             : 
      82           0 :        lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
      83           0 :     if ( m_pListenersContainer )
      84           0 :         m_pListenersContainer->disposeAndClear( aSource );
      85             : 
      86           0 :     if ( m_xLockListener.is() )
      87             :     {
      88           0 :         if ( m_pLockListener )
      89             :         {
      90           0 :             m_pLockListener->Dispose();
      91           0 :             m_pLockListener = NULL;
      92             :         }
      93           0 :         m_xLockListener = uno::Reference< uno::XInterface >();
      94             :     }
      95             : 
      96           0 :     m_bDisposed = true;
      97           0 : }
      98             : 
      99             : 
     100           0 : void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
     101             :     throw (uno::RuntimeException, std::exception)
     102             : {
     103           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     104           0 :     if ( m_bDisposed )
     105           0 :         throw lang::DisposedException(); // TODO
     106             : 
     107           0 :     if ( !m_pListenersContainer )
     108           0 :         m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
     109             : 
     110           0 :     m_pListenersContainer->addInterface( xListener );
     111           0 : }
     112             : 
     113             : 
     114           0 : void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
     115             :     throw (uno::RuntimeException, std::exception)
     116             : {
     117           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     118           0 :     if ( m_pListenersContainer )
     119           0 :         m_pListenersContainer->removeInterface( xListener );
     120           0 : }
     121             : 
     122             : // XInitialization
     123             : 
     124           0 : void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments )
     125             :     throw (uno::Exception, uno::RuntimeException, std::exception)
     126             : {
     127           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     128           0 :     if ( m_bInitialized )
     129           0 :         throw frame::DoubleInitializationException();
     130             : 
     131           0 :     if ( m_bDisposed )
     132           0 :         throw lang::DisposedException(); // TODO
     133             : 
     134           0 :     if ( !m_refCount )
     135           0 :         throw uno::RuntimeException(); // the object must be refcounted already!
     136             : 
     137           0 :     uno::Reference< uno::XInterface > xInstance;
     138           0 :     uno::Reference< embed::XActionsApproval > xApproval;
     139           0 :     sal_Int32 nModes = 0;
     140             : 
     141             :     try
     142             :     {
     143           0 :         sal_Int32 nLen = aArguments.getLength();
     144           0 :         if ( nLen < 2 || nLen > 3 )
     145             :             throw lang::IllegalArgumentException(
     146             :                             OUString( "Wrong count of parameters!" ),
     147             :                             uno::Reference< uno::XInterface >(),
     148           0 :                             0 );
     149             : 
     150           0 :         if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() )
     151             :             throw lang::IllegalArgumentException(
     152             :                     OUString( "Nonempty reference is expected as the first argument!" ),
     153             :                     uno::Reference< uno::XInterface >(),
     154           0 :                     0 );
     155             : 
     156           0 :         if (
     157           0 :             !( aArguments[1] >>= nModes ) ||
     158             :             (
     159           0 :               !( nModes & embed::Actions::PREVENT_CLOSE ) &&
     160           0 :               !( nModes & embed::Actions::PREVENT_TERMINATION )
     161             :             )
     162             :            )
     163             :         {
     164             :             throw lang::IllegalArgumentException(
     165             :                     OUString("The correct modes set is expected as the second argument!"),
     166             :                     uno::Reference< uno::XInterface >(),
     167           0 :                     0 );
     168             :         }
     169             : 
     170           0 :         if ( nLen == 3 && !( aArguments[2] >>= xApproval ) )
     171             :             throw lang::IllegalArgumentException(
     172             :                     OUString( "If the third argument is provided, it must be XActionsApproval implementation!" ),
     173             :                     uno::Reference< uno::XInterface >(),
     174           0 :                     0 );
     175             : 
     176             :         m_pLockListener = new OLockListener( uno::Reference< lang::XComponent > ( static_cast< lang::XComponent* >( this ) ),
     177             :                                             xInstance,
     178             :                                             nModes,
     179           0 :                                             xApproval );
     180           0 :         m_xLockListener = uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( m_pLockListener ) );
     181           0 :         m_pLockListener->Init();
     182             :     }
     183           0 :     catch( uno::Exception& )
     184             :     {
     185           0 :         dispose();
     186           0 :         throw;
     187             :     }
     188             : 
     189           0 :     m_bInitialized = true;
     190           0 : }
     191             : 
     192             : // XServiceInfo
     193           0 : OUString SAL_CALL OInstanceLocker::getImplementationName(  )
     194             :     throw (uno::RuntimeException, std::exception)
     195             : {
     196           0 :     return getImplementationName_static();
     197             : }
     198             : 
     199           0 : sal_Bool SAL_CALL OInstanceLocker::supportsService( const OUString& ServiceName )
     200             :     throw (uno::RuntimeException, std::exception)
     201             : {
     202           0 :     return cppu::supportsService(this, ServiceName);
     203             : }
     204             : 
     205           0 : uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames()
     206             :     throw (uno::RuntimeException, std::exception)
     207             : {
     208           0 :     return getSupportedServiceNames_static();
     209             : }
     210             : 
     211             : // Static methods
     212             : 
     213         284 : uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames_static()
     214             : {
     215         284 :     const OUString aServiceName( "com.sun.star.embed.InstanceLocker" );
     216         284 :     return uno::Sequence< OUString >( &aServiceName, 1 );
     217             : }
     218             : 
     219             : 
     220         284 : OUString SAL_CALL OInstanceLocker::getImplementationName_static()
     221             : {
     222         284 :     return OUString( "com.sun.star.comp.embed.InstanceLocker" );
     223             : }
     224             : 
     225             : 
     226           0 : uno::Reference< uno::XInterface > SAL_CALL OInstanceLocker::Create(
     227             :                                 const uno::Reference< uno::XComponentContext >& rxContext )
     228             : {
     229           0 :     return static_cast< cppu::OWeakObject * >( new OInstanceLocker( rxContext ) );
     230             : }
     231             : 
     232             : 
     233             : 
     234             : 
     235             : // OLockListener
     236             : 
     237             : 
     238             : 
     239           0 : OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper,
     240             :                     const uno::Reference< uno::XInterface >& xInstance,
     241             :                     sal_Int32 nMode,
     242             :                     const uno::Reference< embed::XActionsApproval > xApproval )
     243             : : m_xInstance( xInstance )
     244             : , m_xApproval( xApproval )
     245             : , m_xWrapper( xWrapper )
     246             : , m_bDisposed( false )
     247             : , m_bInitialized( false )
     248           0 : , m_nMode( nMode )
     249             : {
     250           0 : }
     251             : 
     252             : 
     253           0 : OLockListener::~OLockListener()
     254             : {
     255           0 : }
     256             : 
     257             : 
     258           0 : void OLockListener::Dispose()
     259             : {
     260           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
     261             : 
     262           0 :     if ( m_bDisposed )
     263           0 :         return;
     264             : 
     265           0 :     if ( m_nMode & embed::Actions::PREVENT_CLOSE )
     266             :     {
     267             :         try
     268             :         {
     269           0 :             uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY );
     270           0 :             if ( xCloseBroadcaster.is() )
     271           0 :                 xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
     272             : 
     273           0 :             uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY );
     274           0 :             if ( xCloseable.is() )
     275           0 :                 xCloseable->close( sal_True );
     276             :         }
     277           0 :         catch( uno::Exception& )
     278             :         {}
     279             :     }
     280             : 
     281           0 :     if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
     282             :     {
     283             :         try
     284             :         {
     285           0 :             uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
     286           0 :             xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
     287             :         }
     288           0 :         catch( uno::Exception& )
     289             :         {}
     290             :     }
     291             : 
     292           0 :     m_xInstance = uno::Reference< uno::XInterface >();
     293           0 :     m_bDisposed = true;
     294             : }
     295             : 
     296             : // XEventListener
     297             : 
     298           0 : void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent )
     299             :     throw (uno::RuntimeException, std::exception)
     300             : {
     301           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
     302             : 
     303             :     // object is disposed
     304           0 :     if ( aEvent.Source == m_xInstance )
     305             :     {
     306             :         // the object does not listen for anything any more
     307           0 :         m_nMode = 0;
     308             : 
     309             :         // dispose the wrapper;
     310           0 :         uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
     311           0 :         aGuard.clear();
     312           0 :         if ( xComponent.is() )
     313             :         {
     314           0 :             try { xComponent->dispose(); }
     315           0 :             catch( uno::Exception& ){}
     316           0 :         }
     317           0 :     }
     318           0 : }
     319             : 
     320             : 
     321             : // XCloseListener
     322             : 
     323           0 : void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool )
     324             :     throw (util::CloseVetoException, uno::RuntimeException, std::exception)
     325             : {
     326             :     // GetsOwnership parameter is always ignored, the user of the service must close the object always
     327           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
     328           0 :     if ( !m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE ) )
     329             :     {
     330             :         try
     331             :         {
     332           0 :             uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
     333             : 
     334             :             // unlock the mutex here
     335           0 :             aGuard.clear();
     336             : 
     337           0 :             if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) )
     338           0 :                 throw util::CloseVetoException();
     339             :         }
     340           0 :         catch( util::CloseVetoException& )
     341             :         {
     342             :             // rethrow this exception
     343           0 :             throw;
     344             :         }
     345           0 :         catch( uno::Exception& )
     346             :         {
     347             :             // no action should be done
     348             :         }
     349           0 :     }
     350           0 : }
     351             : 
     352             : 
     353           0 : void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent )
     354             :     throw (uno::RuntimeException, std::exception)
     355             : {
     356           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
     357             : 
     358             :     // object is closed, no reason to listen
     359           0 :     if ( aEvent.Source == m_xInstance )
     360             :     {
     361           0 :         uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( aEvent.Source, uno::UNO_QUERY );
     362           0 :         if ( xCloseBroadcaster.is() )
     363             :         {
     364           0 :             xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) );
     365           0 :             m_nMode &= ~embed::Actions::PREVENT_CLOSE;
     366           0 :             if ( !m_nMode )
     367             :             {
     368             :                 // dispose the wrapper;
     369           0 :                 uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
     370           0 :                 aGuard.clear();
     371           0 :                 if ( xComponent.is() )
     372             :                 {
     373           0 :                     try { xComponent->dispose(); }
     374           0 :                     catch( uno::Exception& ){}
     375           0 :                 }
     376             :             }
     377           0 :         }
     378           0 :     }
     379           0 : }
     380             : 
     381             : 
     382             : // XTerminateListener
     383             : 
     384           0 : void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent )
     385             :     throw (frame::TerminationVetoException, uno::RuntimeException, std::exception)
     386             : {
     387           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
     388           0 :     if ( aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION ) )
     389             :     {
     390             :         try
     391             :         {
     392           0 :             uno::Reference< embed::XActionsApproval > xApprove = m_xApproval;
     393             : 
     394             :             // unlock the mutex here
     395           0 :             aGuard.clear();
     396             : 
     397           0 :             if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) )
     398           0 :                 throw frame::TerminationVetoException();
     399             :         }
     400           0 :         catch( frame::TerminationVetoException& )
     401             :         {
     402             :             // rethrow this exception
     403           0 :             throw;
     404             :         }
     405           0 :         catch( uno::Exception& )
     406             :         {
     407             :             // no action should be done
     408             :         }
     409           0 :     }
     410           0 : }
     411             : 
     412             : 
     413           0 : void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent )
     414             :     throw (uno::RuntimeException, std::exception)
     415             : {
     416           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
     417             : 
     418             :     // object is terminated, no reason to listen
     419           0 :     if ( aEvent.Source == m_xInstance )
     420             :     {
     421           0 :         uno::Reference< frame::XDesktop > xDesktop( aEvent.Source, uno::UNO_QUERY );
     422           0 :         if ( xDesktop.is() )
     423             :         {
     424             :             try
     425             :             {
     426           0 :                 xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
     427           0 :                 m_nMode &= ~embed::Actions::PREVENT_TERMINATION;
     428           0 :                 if ( !m_nMode )
     429             :                 {
     430             :                     // dispose the wrapper;
     431           0 :                     uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
     432           0 :                     aGuard.clear();
     433           0 :                     if ( xComponent.is() )
     434             :                     {
     435           0 :                         try { xComponent->dispose(); }
     436           0 :                         catch( uno::Exception& ){}
     437           0 :                     }
     438             :                 }
     439             :             }
     440           0 :             catch( uno::Exception& )
     441             :             {}
     442           0 :         }
     443           0 :     }
     444           0 : }
     445             : 
     446             : 
     447             : // XInitialization
     448             : 
     449           0 : bool OLockListener::Init()
     450             : {
     451           0 :     ::osl::ResettableMutexGuard aGuard( m_aMutex );
     452             : 
     453           0 :     if ( m_bDisposed || m_bInitialized )
     454           0 :         return false;
     455             : 
     456             :     try
     457             :     {
     458           0 :         if ( m_nMode & embed::Actions::PREVENT_CLOSE )
     459             :         {
     460           0 :             uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY_THROW );
     461           0 :             xCloseBroadcaster->addCloseListener( static_cast< util::XCloseListener* >( this ) );
     462             :         }
     463             : 
     464           0 :         if ( m_nMode & embed::Actions::PREVENT_TERMINATION )
     465             :         {
     466           0 :             uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW );
     467           0 :             xDesktop->addTerminateListener( static_cast< frame::XTerminateListener* >( this ) );
     468             :         }
     469             :     }
     470           0 :     catch( uno::Exception& )
     471             :     {
     472             :         // dispose the wrapper;
     473           0 :         uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY );
     474           0 :         aGuard.clear();
     475           0 :         if ( xComponent.is() )
     476             :         {
     477           0 :             try { xComponent->dispose(); }
     478           0 :             catch( uno::Exception& ){}
     479             :         }
     480             : 
     481           0 :         throw;
     482             :     }
     483             : 
     484           0 :     m_bInitialized = true;
     485             : 
     486           0 :     return true;
     487             : }
     488             : 
     489         284 : void createRegistryInfo_OInstanceLocker()
     490             : {
     491         284 :     static ::comphelper::module::OAutoRegistration< OInstanceLocker > aAutoRegistration;
     492         284 : }
     493             : 
     494             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10