7b87afa899
Change-Id: Ifa67ab7198f5d3b06171869f57703acdaa959f7d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135128 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
304 lines
11 KiB
C++
304 lines
11 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <sal/config.h>
|
|
|
|
#include <sal/log.hxx>
|
|
#include <unotools/configvaluecontainer.hxx>
|
|
#include <unotools/confignode.hxx>
|
|
#include <uno/data.h>
|
|
#include <algorithm>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace utl
|
|
{
|
|
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::lang;
|
|
|
|
//= NodeValueAccessor
|
|
|
|
namespace {
|
|
|
|
enum class LocationType
|
|
{
|
|
SimplyObjectInstance,
|
|
Unbound
|
|
};
|
|
|
|
}
|
|
|
|
struct NodeValueAccessor
|
|
{
|
|
private:
|
|
OUString sRelativePath; // the relative path of the node
|
|
LocationType eLocationType; // the type of location where the value is stored
|
|
void* pLocation; // the pointer to the location
|
|
Type aDataType; // the type object pointed to by pLocation
|
|
|
|
public:
|
|
explicit NodeValueAccessor( OUString _aNodePath );
|
|
|
|
void bind( void* _pLocation, const Type& _rType );
|
|
|
|
bool isBound( ) const { return ( LocationType::Unbound != eLocationType ) && ( nullptr != pLocation ); }
|
|
const OUString& getPath( ) const { return sRelativePath; }
|
|
LocationType getLocType( ) const { return eLocationType; }
|
|
void* getLocation( ) const { return pLocation; }
|
|
const Type& getDataType( ) const { return aDataType; }
|
|
|
|
bool operator == ( const NodeValueAccessor& rhs ) const;
|
|
};
|
|
|
|
NodeValueAccessor::NodeValueAccessor( OUString _aNodePath )
|
|
:sRelativePath(std::move( _aNodePath ))
|
|
,eLocationType( LocationType::Unbound )
|
|
,pLocation( nullptr )
|
|
{
|
|
}
|
|
|
|
bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const
|
|
{
|
|
return ( sRelativePath == rhs.sRelativePath )
|
|
&& ( eLocationType == rhs.eLocationType )
|
|
&& ( pLocation == rhs.pLocation );
|
|
}
|
|
|
|
void NodeValueAccessor::bind( void* _pLocation, const Type& _rType )
|
|
{
|
|
SAL_WARN_IF(isBound(), "unotools.config", "NodeValueAccessor::bind: already bound!");
|
|
|
|
eLocationType = LocationType::SimplyObjectInstance;
|
|
pLocation = _pLocation;
|
|
aDataType = _rType;
|
|
}
|
|
|
|
static
|
|
void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex )
|
|
{
|
|
::osl::MutexGuard aGuard( _rMutex );
|
|
|
|
SAL_WARN_IF(!_rAccessor.isBound(), "unotools.config", "::utl::lcl_copyData: invalid accessor!");
|
|
switch ( _rAccessor.getLocType() )
|
|
{
|
|
case LocationType::SimplyObjectInstance:
|
|
{
|
|
if ( _rData.hasValue() )
|
|
{
|
|
// assign the value
|
|
bool bSuccess = uno_type_assignData(
|
|
_rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(),
|
|
const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(),
|
|
cpp_queryInterface, cpp_acquire, cpp_release
|
|
);
|
|
SAL_WARN_IF(!bSuccess, "unotools.config",
|
|
"::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: \"" << _rAccessor.getPath() << "\"");
|
|
}
|
|
else {
|
|
SAL_INFO("unotools.config", "::utl::lcl_copyData: NULL value lost!");
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static
|
|
void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex )
|
|
{
|
|
::osl::MutexGuard aGuard( _rMutex );
|
|
|
|
SAL_WARN_IF(!_rAccessor.isBound(), "unotools.config", "::utl::lcl_copyData: invalid accessor!" );
|
|
switch ( _rAccessor.getLocType() )
|
|
{
|
|
case LocationType::SimplyObjectInstance:
|
|
// a simple setValue...
|
|
_rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//= functors on NodeValueAccessor instances
|
|
|
|
namespace {
|
|
|
|
/// base class for functors synchronizing between exchange locations and config sub nodes
|
|
struct SubNodeAccess
|
|
{
|
|
protected:
|
|
const OConfigurationNode& m_rRootNode;
|
|
::osl::Mutex& m_rMutex;
|
|
|
|
public:
|
|
SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex )
|
|
:m_rRootNode( _rRootNode )
|
|
,m_rMutex( _rMutex )
|
|
{
|
|
}
|
|
};
|
|
|
|
struct UpdateFromConfig : public SubNodeAccess
|
|
{
|
|
public:
|
|
UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
|
|
|
|
void operator() ( NodeValueAccessor const & _rAccessor )
|
|
{
|
|
::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex );
|
|
}
|
|
};
|
|
|
|
struct UpdateToConfig : public SubNodeAccess
|
|
{
|
|
public:
|
|
UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
|
|
|
|
void operator() ( NodeValueAccessor const & _rAccessor )
|
|
{
|
|
Any aNewValue;
|
|
lcl_copyData( aNewValue, _rAccessor, m_rMutex );
|
|
m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue );
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
//= OConfigurationValueContainerImpl
|
|
|
|
struct OConfigurationValueContainerImpl
|
|
{
|
|
Reference< XComponentContext > xORB; // the service factory
|
|
::osl::Mutex& rMutex; // the mutex for accessing the data containers
|
|
OConfigurationTreeRoot aConfigRoot; // the configuration node we're accessing
|
|
|
|
std::vector<NodeValueAccessor> aAccessors; // the accessors to the node values
|
|
|
|
OConfigurationValueContainerImpl( const Reference< XComponentContext >& _rxORB, ::osl::Mutex& _rMutex )
|
|
:xORB( _rxORB )
|
|
,rMutex( _rMutex )
|
|
{
|
|
}
|
|
};
|
|
|
|
//= OConfigurationValueContainer
|
|
|
|
OConfigurationValueContainer::OConfigurationValueContainer(
|
|
const Reference< XComponentContext >& _rxORB, ::osl::Mutex& _rAccessSafety,
|
|
const char* _pConfigLocation, const sal_Int32 _nLevels )
|
|
:m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
|
|
{
|
|
implConstruct( OUString::createFromAscii( _pConfigLocation ), _nLevels );
|
|
}
|
|
|
|
OConfigurationValueContainer::~OConfigurationValueContainer()
|
|
{
|
|
}
|
|
|
|
void OConfigurationValueContainer::implConstruct( const OUString& _rConfigLocation,
|
|
const sal_Int32 _nLevels )
|
|
{
|
|
SAL_WARN_IF(m_pImpl->aConfigRoot.isValid(), "unotools.config", "OConfigurationValueContainer::implConstruct: already initialized!");
|
|
|
|
// create the configuration node we're about to work with
|
|
m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithComponentContext(
|
|
m_pImpl->xORB,
|
|
_rConfigLocation,
|
|
_nLevels
|
|
);
|
|
SAL_WARN_IF(!m_pImpl->aConfigRoot.isValid(), "unotools.config",
|
|
"Could not access the configuration node located at " << _rConfigLocation);
|
|
}
|
|
|
|
void OConfigurationValueContainer::registerExchangeLocation( const char* _pRelativePath,
|
|
void* _pContainer, const Type& _rValueType )
|
|
{
|
|
// checks...
|
|
SAL_WARN_IF(!_pContainer, "unotools.config",
|
|
"OConfigurationValueContainer::registerExchangeLocation: invalid container location!");
|
|
SAL_WARN_IF(!( (TypeClass_CHAR == _rValueType.getTypeClass( ) )
|
|
|| ( TypeClass_BOOLEAN == _rValueType.getTypeClass( ) )
|
|
|| ( TypeClass_BYTE == _rValueType.getTypeClass( ) )
|
|
|| ( TypeClass_SHORT == _rValueType.getTypeClass( ) )
|
|
|| ( TypeClass_LONG == _rValueType.getTypeClass( ) )
|
|
|| ( TypeClass_DOUBLE == _rValueType.getTypeClass( ) )
|
|
|| ( TypeClass_STRING == _rValueType.getTypeClass( ) )
|
|
|| ( TypeClass_SEQUENCE == _rValueType.getTypeClass( ) )),
|
|
"unotools.config",
|
|
"OConfigurationValueContainer::registerExchangeLocation: invalid type!" );
|
|
|
|
// build an accessor for this container
|
|
NodeValueAccessor aNewAccessor( OUString::createFromAscii( _pRelativePath ) );
|
|
aNewAccessor.bind( _pContainer, _rValueType );
|
|
|
|
// insert it into our structure
|
|
implRegisterExchangeLocation( aNewAccessor );
|
|
}
|
|
|
|
void OConfigurationValueContainer::read( )
|
|
{
|
|
std::for_each(
|
|
m_pImpl->aAccessors.begin(),
|
|
m_pImpl->aAccessors.end(),
|
|
UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
|
|
);
|
|
}
|
|
|
|
void OConfigurationValueContainer::commit()
|
|
{
|
|
// write the current values in the exchange locations
|
|
std::for_each(
|
|
m_pImpl->aAccessors.begin(),
|
|
m_pImpl->aAccessors.end(),
|
|
UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
|
|
);
|
|
|
|
// commit the changes done
|
|
m_pImpl->aConfigRoot.commit( );
|
|
}
|
|
|
|
void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor )
|
|
{
|
|
// some checks
|
|
SAL_WARN_IF(m_pImpl->aConfigRoot.isValid() && !m_pImpl->aConfigRoot.hasByHierarchicalName(_rAccessor.getPath()),
|
|
"unotools.config",
|
|
"OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" );
|
|
|
|
// another check (should be the first container for this node)
|
|
SAL_WARN_IF(!(m_pImpl->aAccessors.end() == ::std::find(
|
|
m_pImpl->aAccessors.begin(),
|
|
m_pImpl->aAccessors.end(),
|
|
_rAccessor)),
|
|
"unotools.config",
|
|
"OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" );
|
|
|
|
// remember the accessor
|
|
m_pImpl->aAccessors.push_back( _rAccessor );
|
|
|
|
// and initially fill the value
|
|
lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex );
|
|
}
|
|
|
|
} // namespace utl
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|