LCOV - code coverage report
Current view: top level - ucb/source/ucp/hierarchy - hierarchydatasource.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 101 255 39.6 %
Date: 2015-06-13 12:38:46 Functions: 25 57 43.9 %
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             : /**************************************************************************
      22             :                                 TODO
      23             :  **************************************************************************
      24             : 
      25             :  Note: Configuration Management classes do not support XAggregation.
      26             :        So I have to wrap the interesting interfaces manually.
      27             : 
      28             :  *************************************************************************/
      29             : #include "hierarchydatasource.hxx"
      30             : #include <osl/diagnose.h>
      31             : 
      32             : #include "osl/doublecheckedlocking.h"
      33             : #include <comphelper/processfactory.hxx>
      34             : #include <cppuhelper/interfacecontainer.hxx>
      35             : #include <com/sun/star/beans/PropertyValue.hpp>
      36             : #include <com/sun/star/configuration/theDefaultProvider.hpp>
      37             : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
      38             : #include <com/sun/star/container/XNameContainer.hpp>
      39             : #include <com/sun/star/util/XChangesBatch.hpp>
      40             : #include <com/sun/star/util/XChangesNotifier.hpp>
      41             : 
      42             : using namespace com::sun::star;
      43             : using namespace hierarchy_ucp;
      44             : 
      45             : 
      46             : 
      47             : // describe path of cfg entry
      48             : #define CFGPROPERTY_NODEPATH    "nodepath"
      49             : // true->async. update; false->sync. update
      50             : #define CFGPROPERTY_LAZYWRITE   "lazywrite"
      51             : 
      52             : #define READ_SERVICE_NAME      "com.sun.star.ucb.HierarchyDataReadAccess"
      53             : #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
      54             : 
      55             : #define CONFIG_READ_SERVICE_NAME      \
      56             :                         "com.sun.star.configuration.ConfigurationAccess"
      57             : #define CONFIG_READWRITE_SERVICE_NAME \
      58             :                         "com.sun.star.configuration.ConfigurationUpdateAccess"
      59             : #define CONFIG_DATA_ROOT_KEY          \
      60             :                         "/org.openoffice.ucb.Hierarchy/Root"
      61             : 
      62             : 
      63             : 
      64             : namespace hcp_impl
      65             : {
      66             : 
      67             : 
      68             : 
      69             : // HierarchyDataReadAccess Implementation.
      70             : 
      71             : 
      72             : 
      73             : class HierarchyDataAccess : public cppu::OWeakObject,
      74             :                             public lang::XServiceInfo,
      75             :                             public lang::XTypeProvider,
      76             :                             public lang::XComponent,
      77             :                             public lang::XSingleServiceFactory,
      78             :                             public container::XHierarchicalNameAccess,
      79             :                             public container::XNameContainer,
      80             :                             public util::XChangesNotifier,
      81             :                             public util::XChangesBatch
      82             : {
      83             :     osl::Mutex m_aMutex;
      84             :     uno::Reference< uno::XInterface > m_xConfigAccess;
      85             :     uno::Reference< lang::XComponent >                   m_xCfgC;
      86             :     uno::Reference< lang::XSingleServiceFactory >        m_xCfgSSF;
      87             :     uno::Reference< container::XHierarchicalNameAccess > m_xCfgHNA;
      88             :     uno::Reference< container::XNameContainer >          m_xCfgNC;
      89             :     uno::Reference< container::XNameReplace >            m_xCfgNR;
      90             :     uno::Reference< container::XNameAccess >             m_xCfgNA;
      91             :     uno::Reference< container::XElementAccess >          m_xCfgEA;
      92             :     uno::Reference< util::XChangesNotifier >             m_xCfgCN;
      93             :     uno::Reference< util::XChangesBatch >                m_xCfgCB;
      94             :     bool m_bReadOnly;
      95             : 
      96             : public:
      97             :     HierarchyDataAccess( const uno::Reference<
      98             :                                         uno::XInterface > & xConfigAccess,
      99             :                          bool bReadOnly );
     100             :     virtual ~HierarchyDataAccess();
     101             : 
     102             :     // XInterface
     103             :     virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType )
     104             :         throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     105             :     virtual void SAL_CALL acquire()
     106             :         throw() SAL_OVERRIDE;
     107             :     virtual void SAL_CALL release()
     108             :         throw() SAL_OVERRIDE;
     109             : 
     110             :     // XServiceInfo
     111             :     virtual OUString SAL_CALL getImplementationName()
     112             :         throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     113             :     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName )
     114             :         throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     115             :     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
     116             :         throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     117             : 
     118             :     static OUString getImplementationName_Static();
     119             :     static css::uno::Sequence< OUString > getSupportedServiceNames_Static();
     120             : 
     121             :     // XTypeProvider
     122             :     virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId()
     123             :         throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     124             :     virtual css::uno::Sequence< com::sun::star::uno::Type > SAL_CALL getTypes()
     125             :         throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     126             : 
     127             :     // XComponent
     128             :     virtual void SAL_CALL
     129             :     dispose()
     130             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     131             :     virtual void SAL_CALL
     132             :     addEventListener( const uno::Reference< lang::XEventListener > & xListener )
     133             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     134             :     virtual void SAL_CALL
     135             :     removeEventListener( const uno::Reference<
     136             :                             lang::XEventListener > & aListener )
     137             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     138             : 
     139             :     // XSingleServiceFactory
     140             :     virtual uno::Reference< uno::XInterface > SAL_CALL
     141             :     createInstance()
     142             :         throw ( uno::Exception, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     143             :     virtual uno::Reference< uno::XInterface > SAL_CALL
     144             :     createInstanceWithArguments( const uno::Sequence< uno::Any > & aArguments )
     145             :         throw ( uno::Exception, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     146             : 
     147             :     // XHierarchicalNameAccess
     148             :     virtual uno::Any SAL_CALL
     149             :     getByHierarchicalName( const OUString & aName )
     150             :         throw ( container::NoSuchElementException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     151             :     virtual sal_Bool SAL_CALL
     152             :     hasByHierarchicalName( const OUString & aName )
     153             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     154             : 
     155             :     // XNameContainer
     156             :     virtual void SAL_CALL
     157             :     insertByName( const OUString & aName, const uno::Any & aElement )
     158             :         throw ( lang::IllegalArgumentException,
     159             :                 container::ElementExistException,
     160             :                 lang::WrappedTargetException,
     161             :                 uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     162             :     virtual void SAL_CALL
     163             :     removeByName( const OUString & Name )
     164             :         throw ( container::NoSuchElementException,
     165             :                 lang::WrappedTargetException,
     166             :                 uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     167             : 
     168             :     // XNameReplace ( base of XNameContainer )
     169             :     virtual void SAL_CALL
     170             :     replaceByName( const OUString & aName, const uno::Any & aElement )
     171             :         throw ( lang::IllegalArgumentException,
     172             :                 container::NoSuchElementException,
     173             :                 lang::WrappedTargetException,
     174             :                 uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     175             : 
     176             :     // XNameAccess ( base of XNameReplace )
     177             :     virtual uno::Any SAL_CALL
     178             :     getByName( const OUString & aName )
     179             :         throw ( container::NoSuchElementException,
     180             :                 lang::WrappedTargetException,
     181             :                 uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     182             :     virtual uno::Sequence< OUString > SAL_CALL
     183             :     getElementNames()
     184             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     185             :     virtual sal_Bool SAL_CALL
     186             :     hasByName( const OUString & aName )
     187             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     188             : 
     189             :     // XElementAccess ( base of XNameAccess )
     190             :     virtual uno::Type SAL_CALL
     191             :     getElementType()
     192             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     193             :     virtual sal_Bool SAL_CALL
     194             :     hasElements()
     195             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     196             : 
     197             :     // XChangesNotifier
     198             :     virtual void SAL_CALL
     199             :     addChangesListener( const uno::Reference<
     200             :                             util::XChangesListener > & aListener )
     201             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     202             :     virtual void SAL_CALL
     203             :     removeChangesListener( const uno::Reference<
     204             :                             util::XChangesListener > & aListener )
     205             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     206             : 
     207             :     // XChangesBatch
     208             :     virtual void SAL_CALL
     209             :     commitChanges()
     210             :         throw ( lang::WrappedTargetException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     211             :     virtual sal_Bool SAL_CALL
     212             :     hasPendingChanges()
     213             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     214             :     virtual uno::Sequence< util::ElementChange > SAL_CALL
     215             :     getPendingChanges()
     216             :         throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
     217             : };
     218             : 
     219             : } // namespace hcp_impl
     220             : 
     221             : using namespace hcp_impl;
     222             : 
     223             : 
     224             : 
     225             : 
     226             : // HierarchyDataSource Implementation.
     227             : 
     228             : 
     229             : 
     230             : 
     231           2 : HierarchyDataSource::HierarchyDataSource(
     232             :         const uno::Reference< uno::XComponentContext > & rxContext )
     233             : : m_xContext( rxContext ),
     234           2 :   m_pDisposeEventListeners( 0 )
     235             : {
     236           2 : }
     237             : 
     238             : 
     239             : // virtual
     240           6 : HierarchyDataSource::~HierarchyDataSource()
     241             : {
     242           2 :     delete m_pDisposeEventListeners;
     243           4 : }
     244             : 
     245             : 
     246             : 
     247             : // XInterface methods.
     248          36 : void SAL_CALL HierarchyDataSource::acquire()
     249             :     throw()
     250             : {
     251          36 :     OWeakObject::acquire();
     252          36 : }
     253             : 
     254          36 : void SAL_CALL HierarchyDataSource::release()
     255             :     throw()
     256             : {
     257          36 :     OWeakObject::release();
     258          36 : }
     259             : 
     260          11 : css::uno::Any SAL_CALL HierarchyDataSource::queryInterface( const css::uno::Type & rType )
     261             :     throw( css::uno::RuntimeException, std::exception )
     262             : {
     263             :     css::uno::Any aRet = cppu::queryInterface( rType,
     264             :                                                (static_cast< lang::XTypeProvider* >(this)),
     265             :                                                (static_cast< lang::XServiceInfo* >(this)),
     266             :                                                (static_cast< lang::XComponent* >(this)),
     267             :                                                (static_cast< lang::XMultiServiceFactory* >(this))
     268          11 :                                                );
     269          11 :     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
     270             : }
     271             : 
     272             : // XTypeProvider methods.
     273             : 
     274             : 
     275             : 
     276           0 : XTYPEPROVIDER_IMPL_4( HierarchyDataSource,
     277             :                       lang::XTypeProvider,
     278             :                       lang::XServiceInfo,
     279             :                       lang::XComponent,
     280             :                       lang::XMultiServiceFactory );
     281             : 
     282             : 
     283             : 
     284             : // XServiceInfo methods.
     285             : 
     286             : 
     287             : 
     288          12 : XSERVICEINFO_IMPL_0_CTX( HierarchyDataSource,
     289             :                      OUString( "com.sun.star.comp.ucb.HierarchyDataSource" ) )
     290             : {
     291           3 :     uno::Sequence< OUString > aSNS( 2 );
     292           3 :     aSNS[ 0 ] = "com.sun.star.ucb.DefaultHierarchyDataSource";
     293           3 :     aSNS[ 1 ] = "com.sun.star.ucb.HierarchyDataSource";
     294           3 :     return aSNS;
     295             : }
     296             : 
     297           2 : ONE_INSTANCE_SERVICE_FACTORY_IMPL( HierarchyDataSource );
     298             : 
     299             : 
     300             : 
     301             : // XComponent methods.
     302             : 
     303             : 
     304             : 
     305             : // virtual
     306           4 : void SAL_CALL HierarchyDataSource::dispose()
     307             :     throw( uno::RuntimeException, std::exception )
     308             : {
     309           4 :     osl::Guard< osl::Mutex > aGuard( m_aMutex );
     310             : 
     311           4 :     if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
     312             :     {
     313           1 :         lang::EventObject aEvt;
     314           1 :         aEvt.Source = static_cast< lang::XComponent * >( this );
     315           1 :         m_pDisposeEventListeners->disposeAndClear( aEvt );
     316           4 :     }
     317           4 : }
     318             : 
     319             : 
     320             : // virtual
     321           2 : void SAL_CALL HierarchyDataSource::addEventListener(
     322             :                     const uno::Reference< lang::XEventListener > & Listener )
     323             :     throw( uno::RuntimeException, std::exception )
     324             : {
     325           2 :     osl::Guard< osl::Mutex > aGuard( m_aMutex );
     326             : 
     327           2 :     if ( !m_pDisposeEventListeners )
     328             :         m_pDisposeEventListeners
     329           1 :             = new cppu::OInterfaceContainerHelper( m_aMutex );
     330             : 
     331           2 :     m_pDisposeEventListeners->addInterface( Listener );
     332           2 : }
     333             : 
     334             : 
     335             : // virtual
     336           1 : void SAL_CALL HierarchyDataSource::removeEventListener(
     337             :                     const uno::Reference< lang::XEventListener > & Listener )
     338             :     throw( uno::RuntimeException, std::exception )
     339             : {
     340           1 :     osl::Guard< osl::Mutex > aGuard( m_aMutex );
     341             : 
     342           1 :     if ( m_pDisposeEventListeners )
     343           1 :         m_pDisposeEventListeners->removeInterface( Listener );
     344           1 : }
     345             : 
     346             : 
     347             : 
     348             : // XMultiServiceFactory methods.
     349             : 
     350             : 
     351             : 
     352             : // virtual
     353             : uno::Reference< uno::XInterface > SAL_CALL
     354           2 : HierarchyDataSource::createInstance( const OUString & aServiceSpecifier )
     355             :     throw ( uno::Exception, uno::RuntimeException, std::exception )
     356             : {
     357             :     // Create view to root node.
     358             : 
     359           2 :     beans::PropertyValue aProp;
     360           2 :     aProp.Name = CFGPROPERTY_NODEPATH;
     361           2 :     aProp.Value <<= OUString( CONFIG_DATA_ROOT_KEY  );
     362             : 
     363           4 :     uno::Sequence< uno::Any > aArguments( 1 );
     364           2 :     aArguments[ 0 ] <<= aProp;
     365             : 
     366           4 :     return createInstanceWithArguments( aServiceSpecifier, aArguments, false );
     367             : }
     368             : 
     369             : 
     370             : // virtual
     371             : uno::Reference< uno::XInterface > SAL_CALL
     372           0 : HierarchyDataSource::createInstanceWithArguments(
     373             :                                 const OUString & ServiceSpecifier,
     374             :                                 const uno::Sequence< uno::Any > & Arguments )
     375             :     throw ( uno::Exception, uno::RuntimeException, std::exception )
     376             : {
     377           0 :     return createInstanceWithArguments( ServiceSpecifier, Arguments, true );
     378             : }
     379             : 
     380             : 
     381             : // virtual
     382             : uno::Sequence< OUString > SAL_CALL
     383           1 : HierarchyDataSource::getAvailableServiceNames()
     384             :     throw ( uno::RuntimeException, std::exception )
     385             : {
     386           1 :     uno::Sequence< OUString > aNames( 2 );
     387           1 :     aNames[ 0 ] = READ_SERVICE_NAME;
     388           1 :     aNames[ 1 ] = READWRITE_SERVICE_NAME;
     389           1 :     return aNames;
     390             : }
     391             : 
     392             : 
     393             : 
     394             : // Non-interface methods
     395             : 
     396             : 
     397             : 
     398             : uno::Reference< uno::XInterface > SAL_CALL
     399           2 : HierarchyDataSource::createInstanceWithArguments(
     400             :                                 const OUString & ServiceSpecifier,
     401             :                                 const uno::Sequence< uno::Any > & Arguments,
     402             :                                 bool bCheckArgs )
     403             :     throw ( uno::Exception, uno::RuntimeException )
     404             : {
     405           2 :     osl::Guard< osl::Mutex > aGuard( m_aMutex );
     406             : 
     407             :     // Check service specifier.
     408           2 :     bool bReadOnly  = ServiceSpecifier == READ_SERVICE_NAME;
     409           2 :     bool bReadWrite = !bReadOnly && ServiceSpecifier == READWRITE_SERVICE_NAME;
     410             : 
     411           2 :     if ( !bReadOnly && !bReadWrite )
     412             :     {
     413             :         OSL_FAIL( "HierarchyDataSource::createInstanceWithArguments - "
     414             :                     "Unsupported service specifier!" );
     415           0 :         return uno::Reference< uno::XInterface >();
     416             :     }
     417             : 
     418           4 :     uno::Sequence< uno::Any > aNewArgs( Arguments );
     419             : 
     420           2 :     bool bHasLazyWriteProp = bReadOnly; // property must be added only if
     421             :                                         // a writable view is requested.
     422           2 :     if ( bCheckArgs )
     423             :     {
     424             :         // Check arguments.
     425           0 :         bool bHasNodePath = false;
     426           0 :         sal_Int32 nCount = Arguments.getLength();
     427           0 :         for ( sal_Int32 n = 0; n < nCount; ++n )
     428             :         {
     429           0 :             beans::PropertyValue aProp;
     430           0 :             if ( Arguments[ n ] >>= aProp )
     431             :             {
     432           0 :                 if ( aProp.Name == CFGPROPERTY_NODEPATH )
     433             :                 {
     434           0 :                     OUString aPath;
     435           0 :                     if ( aProp.Value >>= aPath )
     436             :                     {
     437           0 :                         bHasNodePath = true;
     438             : 
     439             :                         // Create path to data inside the configuration.
     440           0 :                         OUString aConfigPath;
     441           0 :                         if ( !createConfigPath( aPath, aConfigPath ) )
     442             :                         {
     443             :                             OSL_FAIL( "HierarchyDataSource::"
     444             :                                 "createInstanceWithArguments - "
     445             :                                 "Invalid node path!" );
     446           0 :                             return uno::Reference< uno::XInterface >();
     447             :                         }
     448             : 
     449           0 :                         aProp.Value <<= aConfigPath;
     450             : 
     451             :                         // Set new path in arguments.
     452           0 :                         aNewArgs[ n ] <<= aProp;
     453             : 
     454           0 :                         if ( bHasLazyWriteProp )
     455           0 :                             break;
     456             :                     }
     457             :                     else
     458             :                     {
     459             :                         OSL_FAIL( "HierarchyDataSource::createInstanceWithArguments - "
     460             :                             "Invalid type for property 'nodepath'!" );
     461           0 :                         return uno::Reference< uno::XInterface >();
     462           0 :                     }
     463             :                 }
     464           0 :                 else if ( aProp.Name == CFGPROPERTY_LAZYWRITE )
     465             :                 {
     466           0 :                     if ( aProp.Value.getValueType() == cppu::UnoType<bool>::get() )
     467             :                     {
     468           0 :                         bHasLazyWriteProp = true;
     469             : 
     470           0 :                         if ( bHasNodePath )
     471           0 :                             break;
     472             :                     }
     473             :                     else
     474             :                     {
     475             :                         OSL_FAIL( "HierarchyDataSource::createInstanceWithArguments - "
     476             :                             "Invalid type for property 'lazywrite'!" );
     477           0 :                         return uno::Reference< uno::XInterface >();
     478             :                     }
     479             :                 }
     480             :             }
     481           0 :         }
     482             : 
     483           0 :         if ( !bHasNodePath )
     484             :         {
     485             :             OSL_FAIL( "HierarchyDataSource::createInstanceWithArguments - "
     486             :                         "No 'nodepath' property!" );
     487           0 :             return uno::Reference< uno::XInterface >();
     488             :         }
     489             :     }
     490             : 
     491             :     // Create Configuration Provider.
     492           4 :     uno::Reference< lang::XMultiServiceFactory > xProv = getConfigProvider();
     493           2 :     if ( !xProv.is() )
     494           0 :         return uno::Reference< uno::XInterface >();
     495             : 
     496           4 :     uno::Reference< uno::XInterface > xConfigAccess;
     497             :     try
     498             :     {
     499           2 :         if ( bReadOnly )
     500             :         {
     501             :             // Create configuration read-only access object.
     502           3 :             xConfigAccess = xProv->createInstanceWithArguments(
     503             :                                 OUString( CONFIG_READ_SERVICE_NAME  ),
     504           2 :                                 aNewArgs );
     505             :         }
     506             :         else
     507             :         {
     508             :             // Append 'lazywrite' property value, if not already present.
     509           1 :             if ( !bHasLazyWriteProp )
     510             :             {
     511           1 :                 sal_Int32 nLen = aNewArgs.getLength();
     512           1 :                 aNewArgs.realloc( nLen + 1 );
     513             : 
     514           1 :                 beans::PropertyValue aProp;
     515           1 :                 aProp.Name = CFGPROPERTY_LAZYWRITE;
     516           1 :                 aProp.Value <<= sal_True;
     517           1 :                 aNewArgs[ nLen ] <<= aProp;
     518             :             }
     519             : 
     520             :             // Create configuration read-write access object.
     521           3 :             xConfigAccess = xProv->createInstanceWithArguments(
     522             :                                 OUString( CONFIG_READWRITE_SERVICE_NAME  ),
     523           2 :                                 aNewArgs );
     524             :         }
     525             :     }
     526           0 :     catch ( uno::Exception const & )
     527             :     {
     528             :         OSL_FAIL( "HierarchyDataSource::createInstanceWithArguments - "
     529             :                     "Cannot instanciate configuration access!" );
     530           0 :         throw;
     531             :     }
     532             : 
     533           2 :     if ( !xConfigAccess.is() )
     534             :     {
     535             :         OSL_FAIL( "HierarchyDataSource::createInstanceWithArguments - "
     536             :                     "Cannot instanciate configuration access!" );
     537           0 :         return xConfigAccess;
     538             :     }
     539             : 
     540             :     return uno::Reference< uno::XInterface >(
     541             :                 static_cast< cppu::OWeakObject * >(
     542           4 :                     new HierarchyDataAccess( xConfigAccess, bReadOnly ) ) );
     543             : }
     544             : 
     545             : 
     546             : uno::Reference< lang::XMultiServiceFactory >
     547           2 : HierarchyDataSource::getConfigProvider()
     548             : {
     549           2 :     if ( !m_xConfigProvider.is() )
     550             :     {
     551           1 :         osl::Guard< osl::Mutex > aGuard( m_aMutex );
     552           1 :         if ( !m_xConfigProvider.is() )
     553             :         {
     554             :             try
     555             :             {
     556           1 :                 m_xConfigProvider = configuration::theDefaultProvider::get( m_xContext );
     557             :             }
     558           0 :             catch ( uno::Exception const & )
     559             :             {
     560             :                 OSL_FAIL( "HierarchyDataSource::getConfigProvider - "
     561             :                                "caught exception!" );
     562             :             }
     563           1 :         }
     564             :     }
     565             : 
     566           2 :     return m_xConfigProvider;
     567             : }
     568             : 
     569             : 
     570           0 : bool HierarchyDataSource::createConfigPath(
     571             :                 const OUString & rInPath, OUString & rOutPath )
     572             : {
     573           0 :     if ( !rInPath.isEmpty() )
     574             :     {
     575           0 :         if ( rInPath.startsWith( "/" ) )
     576             :         {
     577             :             OSL_FAIL( "HierarchyDataSource::createConfigPath - "
     578             :                         "Leading slash in node path!" );
     579           0 :             return false;
     580             :         }
     581             : 
     582           0 :         if ( rInPath.endsWith( "/" ) )
     583             :         {
     584             :             OSL_FAIL( "HierarchyDataSource::createConfigPath - "
     585             :                         "Trailing slash in node path!" );
     586           0 :             return false;
     587             :         }
     588             : 
     589           0 :         rOutPath = CONFIG_DATA_ROOT_KEY "/" + rInPath;
     590             :     }
     591             :     else
     592             :     {
     593           0 :         rOutPath = CONFIG_DATA_ROOT_KEY;
     594             :     }
     595             : 
     596           0 :     return true;
     597             : }
     598             : 
     599             : 
     600             : 
     601             : 
     602             : // HierarchyDataAccess Implementation.
     603             : 
     604             : 
     605             : 
     606             : 
     607             : #define ENSURE_ORIG_INTERFACE( interface_name, member_name )    \
     608             :     m_xCfg##member_name;                                        \
     609             :     if ( !m_xCfg##member_name.is() )                            \
     610             :     {                                                           \
     611             :         osl::Guard< osl::Mutex > aGuard( m_aMutex );            \
     612             :         if ( !m_xCfg##member_name.is() )                        \
     613             :             m_xCfg##member_name                                 \
     614             :                 = uno::Reference< interface_name >(             \
     615             :                     m_xConfigAccess, uno::UNO_QUERY );          \
     616             :         xOrig = m_xCfg##member_name;                            \
     617             :     }
     618             : 
     619             : 
     620           2 : HierarchyDataAccess::HierarchyDataAccess( const uno::Reference<
     621             :                                             uno::XInterface > & xConfigAccess,
     622             :                                           bool bReadOnly )
     623             : : m_xConfigAccess( xConfigAccess ),
     624           2 :   m_bReadOnly( bReadOnly )
     625             : {
     626           2 : }
     627             : 
     628             : 
     629             : // virtual
     630           4 : HierarchyDataAccess::~HierarchyDataAccess()
     631             : {
     632           4 : }
     633             : 
     634             : 
     635             : 
     636             : // XInterface methods.
     637           8 : void SAL_CALL HierarchyDataAccess::acquire()
     638             :     throw()
     639             : {
     640           8 :     OWeakObject::acquire();
     641           8 : }
     642             : 
     643           8 : void SAL_CALL HierarchyDataAccess::release()
     644             :     throw()
     645             : {
     646           8 :     OWeakObject::release();
     647           8 : }
     648             : 
     649             : // virtual
     650           2 : uno::Any SAL_CALL HierarchyDataAccess::queryInterface( const uno::Type & aType )
     651             :     throw ( uno::RuntimeException, std::exception )
     652             : {
     653             :     // Interfaces supported in read-only and read-write mode.
     654             :     uno::Any aRet = cppu::queryInterface( aType,
     655             :                 static_cast< lang::XTypeProvider * >( this ),
     656             :                 static_cast< lang::XServiceInfo * >( this ),
     657             :                 static_cast< lang::XComponent * >( this ),
     658             :                 static_cast< container::XHierarchicalNameAccess * >( this ),
     659             :                 static_cast< container::XNameAccess * >( this ),
     660             :                 static_cast< container::XElementAccess * >( this ),
     661           2 :                 static_cast< util::XChangesNotifier * >( this ) );
     662             : 
     663             :     // Interfaces supported only in read-write mode.
     664           2 :     if ( !aRet.hasValue() && !m_bReadOnly )
     665             :     {
     666           2 :         aRet = cppu::queryInterface( aType,
     667             :                 static_cast< lang::XSingleServiceFactory * >( this ),
     668             :                 static_cast< container::XNameContainer * >( this ),
     669             :                 static_cast< container::XNameReplace * >( this ),
     670           1 :                 static_cast< util::XChangesBatch * >( this ) );
     671             :     }
     672             : 
     673           2 :     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( aType );
     674             : }
     675             : 
     676             : 
     677             : 
     678             : // XTypeProvider methods.
     679             : 
     680             : 
     681             : 
     682           0 : XTYPEPROVIDER_COMMON_IMPL( HierarchyDataAccess );
     683             : 
     684             : 
     685             : // virtual
     686           0 : uno::Sequence< uno::Type > SAL_CALL HierarchyDataAccess::getTypes()
     687             :     throw( uno::RuntimeException, std::exception )
     688             : {
     689           0 :     cppu::OTypeCollection * pCollection = 0;
     690             : 
     691           0 :     if ( m_bReadOnly )
     692             :     {
     693             :         static cppu::OTypeCollection* pReadOnlyTypes = 0;
     694             : 
     695           0 :         pCollection = pReadOnlyTypes;
     696           0 :         if ( !pCollection )
     697             :         {
     698           0 :             osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
     699             : 
     700           0 :             pCollection = pReadOnlyTypes;
     701           0 :             if ( !pCollection )
     702             :             {
     703             :                 static cppu::OTypeCollection aCollection(
     704           0 :                     CPPU_TYPE_REF( lang::XTypeProvider ),
     705           0 :                     CPPU_TYPE_REF( lang::XServiceInfo ),
     706           0 :                     CPPU_TYPE_REF( lang::XComponent ),
     707           0 :                     CPPU_TYPE_REF( container::XHierarchicalNameAccess ),
     708           0 :                     CPPU_TYPE_REF( container::XNameAccess ),
     709           0 :                     CPPU_TYPE_REF( util::XChangesNotifier ) );
     710           0 :                 pCollection = &aCollection;
     711             :                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     712           0 :                 pReadOnlyTypes = pCollection;
     713           0 :             }
     714             :         }
     715             :         else {
     716             :             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     717             :         }
     718             :     }
     719             :     else
     720             :     {
     721             :         static cppu::OTypeCollection* pReadWriteTypes = 0;
     722             : 
     723           0 :         pCollection = pReadWriteTypes;
     724           0 :         if ( !pCollection )
     725             :         {
     726           0 :             osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
     727             : 
     728           0 :             pCollection = pReadWriteTypes;
     729           0 :             if ( !pCollection )
     730             :             {
     731             :                 static cppu::OTypeCollection aCollection(
     732           0 :                     CPPU_TYPE_REF( lang::XTypeProvider ),
     733           0 :                     CPPU_TYPE_REF( lang::XServiceInfo ),
     734           0 :                     CPPU_TYPE_REF( lang::XComponent ),
     735           0 :                     CPPU_TYPE_REF( lang::XSingleServiceFactory ),
     736           0 :                     CPPU_TYPE_REF( container::XHierarchicalNameAccess ),
     737           0 :                     CPPU_TYPE_REF( container::XNameContainer ),
     738           0 :                     CPPU_TYPE_REF( util::XChangesBatch ),
     739           0 :                     CPPU_TYPE_REF( util::XChangesNotifier ) );
     740           0 :                 pCollection = &aCollection;
     741             :                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     742           0 :                 pReadWriteTypes = pCollection;
     743           0 :             }
     744             :         }
     745             :         else {
     746             :             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     747             :         }
     748             :     }
     749             : 
     750           0 :     return (*pCollection).getTypes();
     751             : }
     752             : 
     753             : 
     754             : 
     755             : // XServiceInfo methods.
     756             : 
     757             : 
     758             : 
     759           0 : XSERVICEINFO_NOFACTORY_IMPL_0(
     760             :         HierarchyDataAccess,
     761             :         OUString( "com.sun.star.comp.ucb.HierarchyDataAccess"  ) )
     762             : {
     763           0 :     uno::Sequence< OUString > aSNS( 2 );
     764           0 :     aSNS[ 0 ] = READ_SERVICE_NAME;
     765           0 :     aSNS[ 1 ] = READWRITE_SERVICE_NAME;
     766           0 :     return aSNS;
     767             : }
     768             : 
     769             : 
     770             : 
     771             : // XComponent methods.
     772             : 
     773             : 
     774             : 
     775             : // virtual
     776           0 : void SAL_CALL HierarchyDataAccess::dispose()
     777             :     throw ( uno::RuntimeException, std::exception )
     778             : {
     779             :     uno::Reference< lang::XComponent > xOrig
     780           0 :         = ENSURE_ORIG_INTERFACE( lang::XComponent, C );
     781             : 
     782             :     OSL_ENSURE( xOrig.is(),
     783             :                 "HierarchyDataAccess : Data source is not an XComponent!" );
     784           0 :     xOrig->dispose();
     785           0 : }
     786             : 
     787             : 
     788             : // virtual
     789           0 : void SAL_CALL HierarchyDataAccess::addEventListener(
     790             :                     const uno::Reference< lang::XEventListener > & xListener )
     791             :     throw ( uno::RuntimeException, std::exception )
     792             : {
     793             :     uno::Reference< lang::XComponent > xOrig
     794           0 :         = ENSURE_ORIG_INTERFACE( lang::XComponent, C );
     795             : 
     796             :     OSL_ENSURE( xOrig.is(),
     797             :                 "HierarchyDataAccess : Data source is not an XComponent!" );
     798           0 :     xOrig->addEventListener( xListener );
     799           0 : }
     800             : 
     801             : 
     802             : // virtual
     803           0 : void SAL_CALL HierarchyDataAccess::removeEventListener(
     804             :                     const uno::Reference< lang::XEventListener > & aListener )
     805             :     throw ( uno::RuntimeException, std::exception )
     806             : {
     807             :     uno::Reference< lang::XComponent > xOrig
     808           0 :         = ENSURE_ORIG_INTERFACE( lang::XComponent, C );
     809             : 
     810             :     OSL_ENSURE( xOrig.is(),
     811             :                 "HierarchyDataAccess : Data source is not an XComponent!" );
     812           0 :     xOrig->removeEventListener( aListener );
     813           0 : }
     814             : 
     815             : 
     816             : 
     817             : // XHierarchicalNameAccess methods.
     818             : 
     819             : 
     820             : 
     821             : // virtual
     822           0 : uno::Any SAL_CALL HierarchyDataAccess::getByHierarchicalName(
     823             :                                                 const OUString & aName )
     824             :     throw ( container::NoSuchElementException, uno::RuntimeException, std::exception )
     825             : {
     826             :     uno::Reference< container::XHierarchicalNameAccess > xOrig
     827           0 :         = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA );
     828             : 
     829             :     OSL_ENSURE( xOrig.is(),
     830             :                 "HierarchyDataAccess : "
     831             :                 "Data source is not an XHierarchicalNameAccess!" );
     832           0 :     return xOrig->getByHierarchicalName( aName );
     833             : }
     834             : 
     835             : 
     836             : // virtual
     837           0 : sal_Bool SAL_CALL HierarchyDataAccess::hasByHierarchicalName(
     838             :                                                 const OUString & aName )
     839             :     throw ( uno::RuntimeException, std::exception )
     840             : {
     841             :     uno::Reference< container::XHierarchicalNameAccess > xOrig
     842           0 :         = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA );
     843             : 
     844             :     OSL_ENSURE( xOrig.is(),
     845             :                 "HierarchyDataAccess : "
     846             :                 "Data source is not an XHierarchicalNameAccess!" );
     847           0 :     return xOrig->hasByHierarchicalName( aName );
     848             : }
     849             : 
     850             : 
     851             : 
     852             : // XNameAccess methods.
     853             : 
     854             : 
     855             : 
     856             : // virtual
     857           0 : uno::Any SAL_CALL HierarchyDataAccess::getByName( const OUString & aName )
     858             :     throw ( container::NoSuchElementException,
     859             :             lang::WrappedTargetException,
     860             :             uno::RuntimeException, std::exception )
     861             : {
     862             :     uno::Reference< container::XNameAccess > xOrig
     863           0 :         = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA );
     864             : 
     865             :     OSL_ENSURE( xOrig.is(),
     866             :                 "HierarchyDataAccess : Data source is not an XNameAccess!" );
     867           0 :     return xOrig->getByName( aName );
     868             : }
     869             : 
     870             : 
     871             : // virtual
     872           0 : uno::Sequence< OUString > SAL_CALL HierarchyDataAccess::getElementNames()
     873             :     throw ( uno::RuntimeException, std::exception )
     874             : {
     875             :     uno::Reference< container::XNameAccess > xOrig
     876           0 :         = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA );
     877             : 
     878             :     OSL_ENSURE( xOrig.is(),
     879             :                 "HierarchyDataAccess : Data source is not an XNameAccess!" );
     880           0 :     return xOrig->getElementNames();
     881             : }
     882             : 
     883             : 
     884             : // virtual
     885           0 : sal_Bool SAL_CALL HierarchyDataAccess::hasByName( const OUString & aName )
     886             :     throw ( uno::RuntimeException, std::exception )
     887             : {
     888             :     uno::Reference< container::XNameAccess > xOrig
     889           0 :         = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA );
     890             : 
     891             :     OSL_ENSURE( xOrig.is(),
     892             :                 "HierarchyDataAccess : Data source is not an XNameAccess!" );
     893           0 :     return xOrig->hasByName( aName );
     894             : }
     895             : 
     896             : 
     897             : 
     898             : // XElementAccess methods.
     899             : 
     900             : 
     901             : 
     902             : // virtual
     903           0 : uno::Type SAL_CALL HierarchyDataAccess::getElementType()
     904             :     throw ( uno::RuntimeException, std::exception )
     905             : {
     906             :     uno::Reference< container::XElementAccess > xOrig
     907           0 :         = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA );
     908             : 
     909             :     OSL_ENSURE( xOrig.is(),
     910             :                 "HierarchyDataAccess : Data source is not an XElementAccess!" );
     911           0 :     return xOrig->getElementType();
     912             : }
     913             : 
     914             : 
     915             : // virtual
     916           0 : sal_Bool SAL_CALL HierarchyDataAccess::hasElements()
     917             :     throw ( uno::RuntimeException, std::exception )
     918             : {
     919             :     uno::Reference< container::XElementAccess > xOrig
     920           0 :         = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA );
     921             : 
     922             :     OSL_ENSURE( xOrig.is(),
     923             :                 "HierarchyDataAccess : Data source is not an XElementAccess!" );
     924           0 :     return xOrig->hasElements();
     925             : }
     926             : 
     927             : 
     928             : 
     929             : // XChangesNotifier methods.
     930             : 
     931             : 
     932             : 
     933             : // virtual
     934           0 : void SAL_CALL HierarchyDataAccess::addChangesListener(
     935             :                 const uno::Reference< util::XChangesListener > & aListener )
     936             :     throw ( uno::RuntimeException, std::exception )
     937             : {
     938             :     uno::Reference< util::XChangesNotifier > xOrig
     939           0 :         = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN );
     940             : 
     941             :     OSL_ENSURE( xOrig.is(),
     942             :             "HierarchyDataAccess : Data source is not an XChangesNotifier!" );
     943           0 :     xOrig->addChangesListener( aListener );
     944           0 : }
     945             : 
     946             : 
     947             : // virtual
     948           0 : void SAL_CALL HierarchyDataAccess::removeChangesListener(
     949             :                 const uno::Reference< util::XChangesListener > & aListener )
     950             :     throw ( uno::RuntimeException, std::exception )
     951             : {
     952             :     uno::Reference< util::XChangesNotifier > xOrig
     953           0 :         = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN );
     954             : 
     955             :     OSL_ENSURE( xOrig.is(),
     956             :             "HierarchyDataAccess : Data source is not an XChangesNotifier!" );
     957           0 :     xOrig->removeChangesListener( aListener );
     958           0 : }
     959             : 
     960             : 
     961             : 
     962             : // XSingleServiceFactory methods.
     963             : 
     964             : 
     965             : 
     966             : // virtual
     967           0 : uno::Reference< uno::XInterface > SAL_CALL HierarchyDataAccess::createInstance()
     968             :     throw ( uno::Exception, uno::RuntimeException, std::exception )
     969             : {
     970             :     uno::Reference< lang::XSingleServiceFactory > xOrig
     971           0 :         = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF );
     972             : 
     973             :     OSL_ENSURE( xOrig.is(),
     974             :         "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" );
     975           0 :     return xOrig->createInstance();
     976             : }
     977             : 
     978             : 
     979             : // virtual
     980             : uno::Reference< uno::XInterface > SAL_CALL
     981           0 : HierarchyDataAccess::createInstanceWithArguments(
     982             :                             const uno::Sequence< uno::Any > & aArguments )
     983             :     throw ( uno::Exception, uno::RuntimeException, std::exception )
     984             : {
     985             :     uno::Reference< lang::XSingleServiceFactory > xOrig
     986           0 :         = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF );
     987             : 
     988             :     OSL_ENSURE( xOrig.is(),
     989             :         "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" );
     990           0 :     return xOrig->createInstanceWithArguments( aArguments );
     991             : }
     992             : 
     993             : 
     994             : 
     995             : // XNameContainer methods.
     996             : 
     997             : 
     998             : 
     999             : // virtual
    1000             : void SAL_CALL
    1001           0 : HierarchyDataAccess::insertByName( const OUString & aName,
    1002             :                                    const uno::Any & aElement )
    1003             :     throw ( lang::IllegalArgumentException,
    1004             :             container::ElementExistException,
    1005             :             lang::WrappedTargetException,
    1006             :             uno::RuntimeException, std::exception )
    1007             : {
    1008             :     uno::Reference< container::XNameContainer > xOrig
    1009           0 :         = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC );
    1010             : 
    1011             :     OSL_ENSURE( xOrig.is(),
    1012             :         "HierarchyDataAccess : Data source is not an XNameContainer!" );
    1013           0 :     xOrig->insertByName( aName, aElement );
    1014           0 : }
    1015             : 
    1016             : 
    1017             : // virtual
    1018             : void SAL_CALL
    1019           0 : HierarchyDataAccess::removeByName( const OUString & Name )
    1020             :     throw ( container::NoSuchElementException,
    1021             :             lang::WrappedTargetException,
    1022             :             uno::RuntimeException, std::exception )
    1023             : {
    1024             :     uno::Reference< container::XNameContainer > xOrig
    1025           0 :         = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC );
    1026             : 
    1027             :     OSL_ENSURE( xOrig.is(),
    1028             :         "HierarchyDataAccess : Data source is not an XNameContainer!" );
    1029           0 :     xOrig->removeByName( Name );
    1030           0 : }
    1031             : 
    1032             : 
    1033             : 
    1034             : // XNameReplace methods.
    1035             : 
    1036             : 
    1037             : 
    1038             : // virtual
    1039           0 : void SAL_CALL HierarchyDataAccess::replaceByName( const OUString & aName,
    1040             :                                                   const uno::Any & aElement )
    1041             :     throw ( lang::IllegalArgumentException,
    1042             :             container::NoSuchElementException,
    1043             :             lang::WrappedTargetException,
    1044             :             uno::RuntimeException, std::exception )
    1045             : {
    1046             :     uno::Reference< container::XNameReplace > xOrig
    1047           0 :         = ENSURE_ORIG_INTERFACE( container::XNameReplace, NR );
    1048             : 
    1049             :     OSL_ENSURE( xOrig.is(),
    1050             :         "HierarchyDataAccess : Data source is not an XNameReplace!" );
    1051           0 :     xOrig->replaceByName( aName, aElement );
    1052           0 : }
    1053             : 
    1054             : 
    1055             : 
    1056             : // XChangesBatch methods.
    1057             : 
    1058             : 
    1059             : 
    1060             : // virtual
    1061           0 : void SAL_CALL HierarchyDataAccess::commitChanges()
    1062             :     throw ( lang::WrappedTargetException, uno::RuntimeException, std::exception )
    1063             : {
    1064             :     uno::Reference< util::XChangesBatch > xOrig
    1065           0 :         = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB );
    1066             : 
    1067             :     OSL_ENSURE( xOrig.is(),
    1068             :         "HierarchyDataAccess : Data source is not an XChangesBatch!" );
    1069           0 :     xOrig->commitChanges();
    1070           0 : }
    1071             : 
    1072             : 
    1073             : // virtual
    1074           0 : sal_Bool SAL_CALL HierarchyDataAccess::hasPendingChanges()
    1075             :     throw ( uno::RuntimeException, std::exception )
    1076             : {
    1077             :     uno::Reference< util::XChangesBatch > xOrig
    1078           0 :         = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB );
    1079             : 
    1080             :     OSL_ENSURE( xOrig.is(),
    1081             :         "HierarchyDataAccess : Data source is not an XChangesBatch!" );
    1082           0 :     return xOrig->hasPendingChanges();
    1083             : }
    1084             : 
    1085             : 
    1086             : // virtual
    1087             : uno::Sequence< util::ElementChange > SAL_CALL
    1088           0 : HierarchyDataAccess::getPendingChanges()
    1089             :     throw ( uno::RuntimeException, std::exception )
    1090             : {
    1091             :     uno::Reference< util::XChangesBatch > xOrig
    1092           0 :         = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB );
    1093             : 
    1094             :     OSL_ENSURE( xOrig.is(),
    1095             :         "HierarchyDataAccess : Data source is not an XChangesBatch!" );
    1096           0 :     return xOrig->getPendingChanges();
    1097             : }
    1098             : 
    1099             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11