LCOV - code coverage report
Current view: top level - include/comphelper - accessiblecontexthelper.hxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 33 33 100.0 %
Date: 2014-11-03 Functions: 14 14 100.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             : #ifndef INCLUDED_COMPHELPER_ACCESSIBLECONTEXTHELPER_HXX
      21             : #define INCLUDED_COMPHELPER_ACCESSIBLECONTEXTHELPER_HXX
      22             : 
      23             : #include <cppuhelper/compbase2.hxx>
      24             : #include <com/sun/star/accessibility/XAccessibleContext.hpp>
      25             : #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
      26             : #include <com/sun/star/lang/DisposedException.hpp>
      27             : #include <comphelper/broadcasthelper.hxx>
      28             : #include <comphelper/comphelperdllapi.h>
      29             : 
      30             : 
      31             : namespace comphelper
      32             : {
      33             : 
      34             : 
      35             : 
      36             :     //= IMutex
      37             : 
      38             : 
      39             :     // This whole thingie here (own mutex classes and such) is a HACK. I hate the SolarMutex.
      40             :     // See below for more explanations ....
      41             : 
      42             :     /** abstract interface for implementing a mutex
      43             :     */
      44        5514 :     class COMPHELPER_DLLPUBLIC IMutex
      45             :     {
      46             :     public:
      47             :         virtual ~IMutex();
      48             :         virtual void acquire() = 0;
      49             :         virtual void release() = 0;
      50             :     };
      51             : 
      52             : 
      53             :     //= OMutexGuard
      54             : 
      55             : 
      56             :     class OMutexGuard
      57             :     {
      58             :         IMutex* m_pMutex;
      59             :     public:
      60       97676 :         inline OMutexGuard( IMutex* _pMutex )
      61       97676 :             :m_pMutex( _pMutex )
      62             :         {
      63       97676 :             if ( m_pMutex )
      64       97676 :                 m_pMutex->acquire();
      65       97676 :         }
      66             : 
      67       97676 :         inline ~OMutexGuard( )
      68             :         {
      69       97676 :             if ( m_pMutex )
      70       97676 :                 m_pMutex->release();
      71       97676 :         }
      72             :     };
      73             : 
      74             : 
      75             :     //= OAccessibleContextHelper
      76             : 
      77             : 
      78             :     class OContextHelper_Impl;
      79             :     typedef ::cppu::WeakAggComponentImplHelper2 <   ::com::sun::star::accessibility::XAccessibleContext,
      80             :                                                     ::com::sun::star::accessibility::XAccessibleEventBroadcaster
      81             :                                                 >   OAccessibleContextHelper_Base;
      82             : 
      83             :     /** helper class for implementing an AccessibleContext
      84             :     */
      85             :     class COMPHELPER_DLLPUBLIC OAccessibleContextHelper
      86             :                 :public ::comphelper::OBaseMutex
      87             :                 ,public OAccessibleContextHelper_Base
      88             :     {
      89             :     private:
      90             :         OContextHelper_Impl*    m_pImpl;
      91             : 
      92             :     protected:
      93             :         virtual ~OAccessibleContextHelper( );
      94             : 
      95             :         /** ctor
      96             : 
      97             :             <p>If you need additional object safety for your class, and want to ensure that your own
      98             :             mutex is locked before the mutex this class provides is, than use this ctor.</p>
      99             : 
     100             :             <p>Beware that this is a hack. Unfortunately, OpenOffice.org has two different mutex hierarchies,
     101             :             which are not compatible. In addition, wide parts of the code (especially VCL) is not thread-safe,
     102             :             but instead relies on a <em>single global mutex</em>. As a consequence, components using
     103             :             directly or indirectly such code need to care for this global mutex. Yes, this is as ugly as
     104             :             anything.</p>
     105             : 
     106             :             <p>Note that the external lock is used as additional lock, not as the only one. The own mutex of the
     107             :             instance is used for internal actions, and every action which potentially involves external code
     108             :             (for instance every call to a virtual method overridden by derivees) is <em>additionally</em> and
     109             :             <em>first</em> guarded by with the external lock.</p>
     110             : 
     111             :             <p>Beware of the lifetime of the lock - you must ensure that the lock exists at least as long as
     112             :             the context does. A good approach to implement the lock may be to derive you own context
     113             :             not only from OAccessibleContextHelper, but also from IMutex.</p>
     114             : 
     115             :             <p>One more note. This lock is definitely not used once the dtor is reached. Means whatever
     116             :             the dtor implementation does, it does <em>not</em> guard the external lock. See this as a contract.
     117             :             <br/>You should ensure the same thing for own derivees which do not supply the lock themself,
     118             :             but get them from yet another derivee.</p>
     119             :             @see forgetExternalLock
     120             :         */
     121             :         OAccessibleContextHelper( IMutex* _pExternalLock );
     122             : 
     123             :         /** late construction
     124             :         @param _rxAccessible
     125             :             the Accessible object which created this context.
     126             :             <p>If your derived implementation implements the XAccessible (and does not follow the proposed
     127             :             separation of XAccessible from XAccessibleContext), you may pass <code>this</code> here.</p>
     128             : 
     129             :             <p>The object is hold weak, so its life time is not affected.</p>
     130             : 
     131             :             <p>The object is needed for performance reasons: for <method>getAccessibleIndexInParent</method>,
     132             :             all children (which are XAccessible's theirself) of our parent have to be asked. If we know our
     133             :             XAccessible, we can compare it with all the children, instead of asking all children for their
     134             :             context and comparing this context with ourself.</p>
     135             :         */
     136             :         void    lateInit( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxAccessible );
     137             : 
     138             :         /** retrieves the creator previously set with <method>lateInit</method>
     139             :         */
     140             :         ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
     141             :                 getAccessibleCreator( ) const;
     142             : 
     143             :     private:
     144             :         /** forgets the reference to the external lock, if present.
     145             : 
     146             :             <p>This means any further locking will not be guard the external lock anymore, never.</p>
     147             : 
     148             :             <p>To be used in derived classes which do not supply the external lock themself, but instead get
     149             :             them passed from own derivees (or clients).</p>
     150             :         */
     151             :         void    forgetExternalLock();
     152             : 
     153             :     public:
     154             :         // XAccessibleEventBroadcaster
     155             :         virtual void SAL_CALL addAccessibleEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     156             :         virtual void SAL_CALL removeAccessibleEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     157             : 
     158             :         // XAccessibleContext - still waiting to be overwritten
     159             :         virtual sal_Int32 SAL_CALL getAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     160             :         virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     161             :         virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     162             :         virtual sal_Int16 SAL_CALL getAccessibleRole(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     163             :         virtual OUString SAL_CALL getAccessibleDescription(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     164             :         virtual OUString SAL_CALL getAccessibleName(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     165             :         virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     166             :         virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0;
     167             : 
     168             :         // XAccessibleContext - default implementations
     169             :         /** default implementation for retrieving the index of this object within the parent
     170             :             <p>This basic implementation here returns the index <code>i</code> of the child for which
     171             :                 <code>&lt;parent&gt;.getAccessibleChild( i )</code> equals our creator.</p>
     172             :         */
     173             :         virtual sal_Int32 SAL_CALL getAccessibleIndexInParent(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     174             :         /** default implementation for retrieving the locale
     175             :             <p>This basic implementation returns the locale of the parent context,
     176             :             as retrieved via getAccessibleParent()->getAccessibleContext.</p>
     177             :         */
     178             :         virtual ::com::sun::star::lang::Locale SAL_CALL getLocale(  ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     179             : 
     180             :     public:
     181             :         // helper struct for granting selective access rights
     182             :         struct OAccessControl
     183             :         {
     184             :             friend class OContextEntryGuard;
     185             :             friend class OContextHelper_Impl;
     186             :             friend class OExternalLockGuard;
     187             :         private:
     188      279062 :             OAccessControl() { }
     189             :         };
     190             : 
     191             :         // ensures that the object is alive
     192             :         inline  void            ensureAlive( const OAccessControl& ) const;
     193             :         inline  IMutex*         getExternalLock( const OAccessControl& );
     194             :         inline  ::osl::Mutex&   GetMutex( const OAccessControl& );
     195             : 
     196             :     protected:
     197             :         // OComponentHelper
     198             :         virtual void SAL_CALL disposing() SAL_OVERRIDE;
     199             : 
     200             :     protected:
     201             :         // helper
     202             :         /** notifies all AccessibleEventListeners of a certain event
     203             : 
     204             :         @precond    not to be called with our mutex locked
     205             :         @param  _nEventId
     206             :             the id of the event. See AccessibleEventType
     207             :         @param  _rOldValue
     208             :             the old value to be notified
     209             :         @param  _rNewValue
     210             :             the new value to be notified
     211             :         */
     212             :         void NotifyAccessibleEvent(
     213             :                     const sal_Int16 _nEventId,
     214             :                     const ::com::sun::star::uno::Any& _rOldValue,
     215             :                     const ::com::sun::star::uno::Any& _rNewValue
     216             :                 );
     217             : 
     218             :         // life time control
     219             :         /// checks whether the object is alive (returns <TRUE/> then) or disposed
     220             :         bool    isAlive() const;
     221             :         /// checks for being alive. If the object is already disposed (i.e. not alive), an exception is thrown.
     222             :         void        ensureAlive() const;
     223             : 
     224             :         /** ensures that the object is disposed.
     225             :         @precond
     226             :             to be called from within the destructor of your derived class only!
     227             :         */
     228             :         void        ensureDisposed( );
     229             : 
     230             :         /** shortcut for retrieving the context of the parent (returned by getAccessibleParent)
     231             :         */
     232             :         ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
     233             :                     implGetParentContext();
     234             : 
     235             :         // access to the base class' broadcast helper/mutex
     236        6092 :         ::cppu::OBroadcastHelper&       GetBroadcastHelper()        { return rBHelper; }
     237      187662 :         const ::cppu::OBroadcastHelper& GetBroadcastHelper() const  { return rBHelper; }
     238      100436 :         ::osl::Mutex&                   GetMutex()                  { return m_aMutex; }
     239             :         IMutex*                         getExternalLock( );
     240             :     };
     241             : 
     242             : 
     243       93550 :     inline  void OAccessibleContextHelper::ensureAlive( const OAccessControl& ) const
     244             :     {
     245       93550 :         ensureAlive();
     246       93550 :     }
     247             : 
     248             : 
     249       91962 :     inline  IMutex* OAccessibleContextHelper::getExternalLock( const OAccessControl& )
     250             :     {
     251       91962 :         return getExternalLock();
     252             :     }
     253             : 
     254             : 
     255       93550 :     inline  ::osl::Mutex& OAccessibleContextHelper::GetMutex( const OAccessControl& )
     256             :     {
     257       93550 :         return GetMutex();
     258             :     }
     259             : 
     260             : 
     261             :     //= OContextEntryGuard
     262             : 
     263             :     typedef ::osl::ClearableMutexGuard  OContextEntryGuard_Base;
     264             :     /** helper class for guarding the entry into OAccessibleContextHelper methods.
     265             : 
     266             :         <p>The class has two responsibilities:
     267             :         <ul><li>it locks the mutex of an OAccessibleContextHelper instance, as long as the guard lives</li>
     268             :             <li>it checks if an given OAccessibleContextHelper instance is alive, else an exception is thrown
     269             :                 our of the constructor of the guard</li>
     270             :         </ul>
     271             :         <br/>
     272             :         This makes it your first choice (hopefully :) for guarding any interface method implementations of
     273             :         you derived class.
     274             :         </p>
     275             :     */
     276             :     class OContextEntryGuard : public OContextEntryGuard_Base
     277             :     {
     278             :     public:
     279             :         /** constructs the guard
     280             : 
     281             :             <p>The given context (it's mutex, respectively) is locked, and an exception is thrown if the context
     282             :             is not alive anymore. In the latter case, of course, the mutex is freed, again.</p>
     283             : 
     284             :         @param _pContext
     285             :             the context which shall be guarded
     286             :         @precond <arg>_pContext</arg> != NULL
     287             :         */
     288             :         inline OContextEntryGuard( OAccessibleContextHelper* _pContext );
     289             : 
     290             :         /** destructs the guard.
     291             :             <p>The context (it's mutex, respectively) is unlocked.</p>
     292             :         */
     293             :         inline ~OContextEntryGuard();
     294             :     };
     295             : 
     296             : 
     297       93550 :     inline OContextEntryGuard::OContextEntryGuard( OAccessibleContextHelper* _pContext  )
     298       93550 :         :OContextEntryGuard_Base( _pContext->GetMutex( OAccessibleContextHelper::OAccessControl() ) )
     299             :     {
     300       93550 :         _pContext->ensureAlive( OAccessibleContextHelper::OAccessControl() );
     301       93550 :     }
     302             : 
     303             : 
     304       93550 :     inline OContextEntryGuard::~OContextEntryGuard()
     305             :     {
     306       93550 :     }
     307             : 
     308             : 
     309             :     //= OExternalLockGuard
     310             : 
     311             :     class OExternalLockGuard
     312             :             :public OMutexGuard
     313             :             ,public OContextEntryGuard
     314             :     {
     315             :     public:
     316             :         inline OExternalLockGuard( OAccessibleContextHelper* _pContext );
     317             :         inline ~OExternalLockGuard( );
     318             :     };
     319             : 
     320             : 
     321       91962 :     inline OExternalLockGuard::OExternalLockGuard( OAccessibleContextHelper* _pContext )
     322             :         :OMutexGuard( _pContext->getExternalLock( OAccessibleContextHelper::OAccessControl() ) )
     323       91962 :         ,OContextEntryGuard( _pContext )
     324             :     {
     325             :         // #102438#
     326             :         // Only lock the external mutex,
     327             :         // release the ::osl::Mutex of the OAccessibleContextHelper instance.
     328             :         // If you call into another UNO object with locked ::osl::Mutex,
     329             :         // this may lead to dead locks.
     330       91962 :         clear();
     331       91962 :     }
     332             : 
     333             : 
     334       91962 :     inline OExternalLockGuard::~OExternalLockGuard( )
     335             :     {
     336       91962 :     }
     337             : 
     338             : 
     339             : }   // namespace comphelper
     340             : 
     341             : 
     342             : #endif // INCLUDED_COMPHELPER_ACCESSIBLECONTEXTHELPER_HXX
     343             : 
     344             : 
     345             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10