Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <unotools/configvaluecontainer.hxx>
21 : #include <unotools/confignode.hxx>
22 : #include <uno/data.h>
23 : #include <algorithm>
24 : #include <vector>
25 :
26 : namespace utl
27 : {
28 :
29 : using namespace ::com::sun::star::uno;
30 : using namespace ::com::sun::star::lang;
31 :
32 : //= NodeValueAccessor
33 :
34 : enum LocationType
35 : {
36 : ltSimplyObjectInstance,
37 : ltAnyInstance,
38 :
39 : ltUnbound
40 : };
41 :
42 0 : struct NodeValueAccessor
43 : {
44 : private:
45 : OUString sRelativePath; // the relative path of the node
46 : LocationType eLocationType; // the type of location where the value is stored
47 : void* pLocation; // the pointer to the location
48 : Type aDataType; // the type object pointed to by pLocation
49 :
50 : public:
51 : NodeValueAccessor( const OUString& _rNodePath );
52 :
53 : void bind( void* _pLocation, const Type& _rType );
54 :
55 : bool isBound( ) const { return ( ltUnbound != eLocationType ) && ( NULL != pLocation ); }
56 0 : const OUString& getPath( ) const { return sRelativePath; }
57 0 : LocationType getLocType( ) const { return eLocationType; }
58 0 : void* getLocation( ) const { return pLocation; }
59 0 : const Type& getDataType( ) const { return aDataType; }
60 :
61 : bool operator == ( const NodeValueAccessor& rhs ) const;
62 : };
63 :
64 0 : NodeValueAccessor::NodeValueAccessor( const OUString& _rNodePath )
65 : :sRelativePath( _rNodePath )
66 : ,eLocationType( ltUnbound )
67 0 : ,pLocation( NULL )
68 : {
69 0 : }
70 :
71 0 : bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const
72 : {
73 0 : return ( sRelativePath == rhs.sRelativePath )
74 0 : && ( eLocationType == rhs.eLocationType )
75 0 : && ( pLocation == rhs.pLocation );
76 : }
77 :
78 0 : void NodeValueAccessor::bind( void* _pLocation, const Type& _rType )
79 : {
80 : SAL_WARN_IF(isBound(), "unotools.config", "NodeValueAccessor::bind: already bound!");
81 :
82 0 : eLocationType = ltSimplyObjectInstance;
83 0 : pLocation = _pLocation;
84 0 : aDataType = _rType;
85 0 : }
86 :
87 : #ifndef UNX
88 : static
89 : #endif
90 0 : void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex )
91 : {
92 0 : ::osl::MutexGuard aGuard( _rMutex );
93 :
94 : SAL_WARN_IF(!_rAccessor.isBound(), "unotools.config", "::utl::lcl_copyData: invalid accessor!");
95 0 : switch ( _rAccessor.getLocType() )
96 : {
97 : case ltSimplyObjectInstance:
98 : {
99 0 : if ( _rData.hasValue() )
100 : {
101 : // assign the value
102 : bool bSuccess = uno_type_assignData(
103 0 : _rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(),
104 0 : const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(),
105 : (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release
106 0 : );
107 : SAL_WARN_IF(!bSuccess, "unotools.config",
108 : "::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: \"" << _rAccessor.getPath() << "\"");
109 : }
110 : else {
111 : SAL_INFO("unotools.config", "::utl::lcl_copyData: NULL value lost!");
112 : }
113 : }
114 0 : break;
115 : case ltAnyInstance:
116 : // a simple assignment of an Any ...
117 0 : *static_cast< Any* >( _rAccessor.getLocation() ) = _rData;
118 0 : break;
119 : default:
120 0 : break;
121 0 : }
122 0 : }
123 :
124 : #ifndef UNX
125 : static
126 : #endif
127 0 : void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex )
128 : {
129 0 : ::osl::MutexGuard aGuard( _rMutex );
130 :
131 : SAL_WARN_IF(!_rAccessor.isBound(), "unotools.config", "::utl::lcl_copyData: invalid accessor!" );
132 0 : switch ( _rAccessor.getLocType() )
133 : {
134 : case ltSimplyObjectInstance:
135 : // a simple setValue ....
136 0 : _rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() );
137 0 : break;
138 :
139 : case ltAnyInstance:
140 : // a simple assignment of an Any ...
141 0 : _rData = *static_cast< Any* >( _rAccessor.getLocation() );
142 0 : break;
143 : default:
144 0 : break;
145 0 : }
146 0 : }
147 :
148 : //= functors on NodeValueAccessor instances
149 :
150 : /// base class for functors syncronizing between exchange locations and config sub nodes
151 : struct SubNodeAccess : public ::std::unary_function< NodeValueAccessor, void >
152 : {
153 : protected:
154 : const OConfigurationNode& m_rRootNode;
155 : ::osl::Mutex& m_rMutex;
156 :
157 : public:
158 0 : SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex )
159 : :m_rRootNode( _rRootNode )
160 0 : ,m_rMutex( _rMutex )
161 : {
162 0 : }
163 : };
164 :
165 : struct UpdateFromConfig : public SubNodeAccess
166 : {
167 : public:
168 0 : UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
169 :
170 0 : void operator() ( NodeValueAccessor& _rAccessor )
171 : {
172 0 : ::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex );
173 0 : }
174 : };
175 :
176 : struct UpdateToConfig : public SubNodeAccess
177 : {
178 : public:
179 0 : UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
180 :
181 0 : void operator() ( NodeValueAccessor& _rAccessor )
182 : {
183 0 : Any aNewValue;
184 0 : lcl_copyData( aNewValue, _rAccessor, m_rMutex );
185 0 : m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue );
186 0 : }
187 : };
188 :
189 : typedef std::vector<NodeValueAccessor> NodeValueAccessors;
190 :
191 : //= OConfigurationValueContainerImpl
192 :
193 0 : struct OConfigurationValueContainerImpl
194 : {
195 : Reference< XComponentContext > xORB; // the service factory
196 : ::osl::Mutex& rMutex; // the mutex for accessing the data containers
197 : OConfigurationTreeRoot aConfigRoot; // the configuration node we're accessing
198 :
199 : NodeValueAccessors aAccessors; // the accessors to the node values
200 :
201 0 : OConfigurationValueContainerImpl( const Reference< XComponentContext >& _rxORB, ::osl::Mutex& _rMutex )
202 : :xORB( _rxORB )
203 0 : ,rMutex( _rMutex )
204 : {
205 0 : }
206 : };
207 :
208 : //= OConfigurationValueContainer
209 :
210 0 : OConfigurationValueContainer::OConfigurationValueContainer(
211 : const Reference< XComponentContext >& _rxORB, ::osl::Mutex& _rAccessSafety,
212 : const sal_Char* _pConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
213 0 : :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
214 : {
215 0 : implConstruct( OUString::createFromAscii( _pConfigLocation ), _nAccessFlags, _nLevels );
216 0 : }
217 :
218 0 : OConfigurationValueContainer::~OConfigurationValueContainer()
219 : {
220 0 : delete m_pImpl;
221 0 : }
222 :
223 0 : void OConfigurationValueContainer::implConstruct( const OUString& _rConfigLocation,
224 : const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
225 : {
226 : SAL_WARN_IF(m_pImpl->aConfigRoot.isValid(), "unotools.config", "OConfigurationValueContainer::implConstruct: already initialized!");
227 :
228 : // create the configuration node we're about to work with
229 0 : m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithComponentContext(
230 : m_pImpl->xORB,
231 : _rConfigLocation,
232 : _nLevels,
233 0 : ( _nAccessFlags & CVC_UPDATE_ACCESS ) ? OConfigurationTreeRoot::CM_UPDATABLE : OConfigurationTreeRoot::CM_READONLY,
234 0 : ( _nAccessFlags & CVC_IMMEDIATE_UPDATE ) ? sal_False : sal_True
235 0 : );
236 : SAL_WARN_IF(!m_pImpl->aConfigRoot.isValid(), "unotools.config",
237 : "Could not access the configuration node located at " << _rConfigLocation);
238 0 : }
239 :
240 0 : void OConfigurationValueContainer::registerExchangeLocation( const sal_Char* _pRelativePath,
241 : void* _pContainer, const Type& _rValueType )
242 : {
243 : // checks ....
244 : SAL_WARN_IF(!_pContainer, "unotools.config",
245 : "OConfigurationValueContainer::registerExchangeLocation: invalid container location!");
246 : SAL_WARN_IF(!( (TypeClass_CHAR == _rValueType.getTypeClass( ) )
247 : || ( TypeClass_BOOLEAN == _rValueType.getTypeClass( ) )
248 : || ( TypeClass_BYTE == _rValueType.getTypeClass( ) )
249 : || ( TypeClass_SHORT == _rValueType.getTypeClass( ) )
250 : || ( TypeClass_LONG == _rValueType.getTypeClass( ) )
251 : || ( TypeClass_DOUBLE == _rValueType.getTypeClass( ) )
252 : || ( TypeClass_STRING == _rValueType.getTypeClass( ) )
253 : || ( TypeClass_SEQUENCE == _rValueType.getTypeClass( ) )),
254 : "unotools.config",
255 : "OConfigurationValueContainer::registerExchangeLocation: invalid type!" );
256 :
257 : // build an accessor for this container
258 0 : NodeValueAccessor aNewAccessor( OUString::createFromAscii( _pRelativePath ) );
259 0 : aNewAccessor.bind( _pContainer, _rValueType );
260 :
261 : // insert it into our structure
262 0 : implRegisterExchangeLocation( aNewAccessor );
263 0 : }
264 :
265 0 : void OConfigurationValueContainer::read( )
266 : {
267 : std::for_each(
268 : m_pImpl->aAccessors.begin(),
269 : m_pImpl->aAccessors.end(),
270 : UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
271 0 : );
272 0 : }
273 :
274 0 : void OConfigurationValueContainer::write( bool _bCommit )
275 : {
276 : // collect the current values in the exchange locations
277 : std::for_each(
278 : m_pImpl->aAccessors.begin(),
279 : m_pImpl->aAccessors.end(),
280 : UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
281 0 : );
282 :
283 : // commit the changes done (if requested)
284 0 : if ( _bCommit )
285 0 : commit( false );
286 0 : }
287 :
288 0 : void OConfigurationValueContainer::commit( bool _bWrite )
289 : {
290 : // write the current values in the exchange locations (if requested)
291 0 : if ( _bWrite )
292 0 : write( false );
293 :
294 : // commit the changes done
295 0 : m_pImpl->aConfigRoot.commit( );
296 0 : }
297 :
298 0 : void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor )
299 : {
300 : // some checks
301 : SAL_WARN_IF(m_pImpl->aConfigRoot.isValid() && !m_pImpl->aConfigRoot.hasByHierarchicalName(_rAccessor.getPath()),
302 : "unotools.config",
303 : "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" );
304 :
305 : // another check (should be the first container for this node)
306 : SAL_WARN_IF(!(m_pImpl->aAccessors.end() == ::std::find(
307 : m_pImpl->aAccessors.begin(),
308 : m_pImpl->aAccessors.end(),
309 : _rAccessor)),
310 : "unotools.config",
311 : "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" );
312 :
313 : // remember the accessor
314 0 : m_pImpl->aAccessors.push_back( _rAccessor );
315 :
316 : // and initially fill the value
317 0 : lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex );
318 0 : }
319 :
320 : } // namespace utl
321 :
322 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|