Branch data 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 <tools/debug.hxx>
23 : : #include <comphelper/stl_types.hxx>
24 : : #include <uno/data.h>
25 : : #include <algorithm>
26 : :
27 : : #ifdef DBG_UTIL
28 : : #include <rtl/strbuf.hxx>
29 : : #endif
30 : :
31 : : //.........................................................................
32 : : namespace utl
33 : : {
34 : : //.........................................................................
35 : :
36 : : using namespace ::com::sun::star::uno;
37 : : using namespace ::com::sun::star::lang;
38 : :
39 : : //=====================================================================
40 : : //= NodeValueAccessor
41 : : //=====================================================================
42 : : enum LocationType
43 : : {
44 : : ltSimplyObjectInstance,
45 : : ltAnyInstance,
46 : :
47 : : ltUnbound
48 : : };
49 : :
50 : 0 : struct NodeValueAccessor
51 : : {
52 : : private:
53 : : ::rtl::OUString sRelativePath; // the relative path of the node
54 : : LocationType eLocationType; // the type of location where the value is stored
55 : : void* pLocation; // the pointer to the location
56 : : Type aDataType; // the type object pointed to by pLocation
57 : :
58 : : public:
59 : : NodeValueAccessor( const ::rtl::OUString& _rNodePath );
60 : :
61 : : void bind( void* _pLocation, const Type& _rType );
62 : :
63 : : bool isBound( ) const { return ( ltUnbound != eLocationType ) && ( NULL != pLocation ); }
64 : 0 : const ::rtl::OUString& getPath( ) const { return sRelativePath; }
65 : 0 : LocationType getLocType( ) const { return eLocationType; }
66 : 0 : void* getLocation( ) const { return pLocation; }
67 : 0 : const Type& getDataType( ) const { return aDataType; }
68 : :
69 : : bool operator == ( const NodeValueAccessor& rhs ) const;
70 : : bool operator != ( const NodeValueAccessor& rhs ) const { return !operator == ( rhs ); }
71 : : };
72 : :
73 : 0 : NodeValueAccessor::NodeValueAccessor( const ::rtl::OUString& _rNodePath )
74 : : :sRelativePath( _rNodePath )
75 : : ,eLocationType( ltUnbound )
76 : 0 : ,pLocation( NULL )
77 : : {
78 : 0 : }
79 : :
80 : 0 : bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const
81 : : {
82 : 0 : return ( sRelativePath == rhs.sRelativePath )
83 : : && ( eLocationType == rhs.eLocationType )
84 [ # # ][ # # ]: 0 : && ( pLocation == rhs.pLocation );
[ # # ]
85 : : }
86 : :
87 : 0 : void NodeValueAccessor::bind( void* _pLocation, const Type& _rType )
88 : : {
89 : : DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
90 : :
91 : 0 : eLocationType = ltSimplyObjectInstance;
92 : 0 : pLocation = _pLocation;
93 : 0 : aDataType = _rType;
94 : 0 : }
95 : :
96 : : #ifndef UNX
97 : : static
98 : : #endif
99 : 0 : void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex )
100 : : {
101 [ # # ]: 0 : ::osl::MutexGuard aGuard( _rMutex );
102 : :
103 : : DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
104 [ # # # ]: 0 : switch ( _rAccessor.getLocType() )
105 : : {
106 : : case ltSimplyObjectInstance:
107 : : {
108 [ # # ]: 0 : if ( _rData.hasValue() )
109 : : {
110 : : #ifdef DBG_UTIL
111 : : sal_Bool bSuccess =
112 : : #endif
113 : : // assign the value
114 : : uno_type_assignData(
115 : 0 : _rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(),
116 : 0 : const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(),
117 : : (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release
118 : 0 : );
119 : : #ifdef DBG_UTIL
120 : : rtl::OStringBuffer aBuf( 256 );
121 : : aBuf.append("::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: ");
122 : : aBuf.append( rtl::OUStringToOString( _rAccessor.getPath(), RTL_TEXTENCODING_ASCII_US ) );
123 : : aBuf.append( " !" );
124 : : DBG_ASSERT( bSuccess, aBuf.getStr() );
125 : : #endif
126 : : }
127 : : else {
128 : : DBG_WARNING( "::utl::lcl_copyData: NULL value lost!" );
129 : : }
130 : : }
131 : 0 : break;
132 : : case ltAnyInstance:
133 : : // a simple assignment of an Any ...
134 : 0 : *static_cast< Any* >( _rAccessor.getLocation() ) = _rData;
135 : 0 : break;
136 : : default:
137 : 0 : break;
138 [ # # ]: 0 : }
139 : 0 : }
140 : :
141 : : #ifndef UNX
142 : : static
143 : : #endif
144 : 0 : void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex )
145 : : {
146 [ # # ]: 0 : ::osl::MutexGuard aGuard( _rMutex );
147 : :
148 : : DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
149 [ # # # ]: 0 : switch ( _rAccessor.getLocType() )
150 : : {
151 : : case ltSimplyObjectInstance:
152 : : // a simple setValue ....
153 : 0 : _rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() );
154 : 0 : break;
155 : :
156 : : case ltAnyInstance:
157 : : // a simple assignment of an Any ...
158 : 0 : _rData = *static_cast< Any* >( _rAccessor.getLocation() );
159 : 0 : break;
160 : : default:
161 : 0 : break;
162 [ # # ]: 0 : }
163 : 0 : }
164 : :
165 : : //=====================================================================
166 : : //= functors on NodeValueAccessor instances
167 : : //=====================================================================
168 : :
169 : : /// base class for functors syncronizing between exchange locations and config sub nodes
170 : : struct SubNodeAccess : public ::std::unary_function< NodeValueAccessor, void >
171 : : {
172 : : protected:
173 : : const OConfigurationNode& m_rRootNode;
174 : : ::osl::Mutex& m_rMutex;
175 : :
176 : : public:
177 : 0 : SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex )
178 : : :m_rRootNode( _rRootNode )
179 : 0 : ,m_rMutex( _rMutex )
180 : : {
181 : 0 : }
182 : : };
183 : :
184 : : struct UpdateFromConfig : public SubNodeAccess
185 : : {
186 : : public:
187 : 0 : UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
188 : :
189 : 0 : void operator() ( NodeValueAccessor& _rAccessor )
190 : : {
191 [ # # ]: 0 : ::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex );
192 : 0 : }
193 : : };
194 : :
195 : : struct UpdateToConfig : public SubNodeAccess
196 : : {
197 : : public:
198 : 0 : UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
199 : :
200 : 0 : void operator() ( NodeValueAccessor& _rAccessor )
201 : : {
202 : 0 : Any aNewValue;
203 [ # # ]: 0 : lcl_copyData( aNewValue, _rAccessor, m_rMutex );
204 : 0 : m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue );
205 : 0 : }
206 : : };
207 : :
208 : : DECLARE_STL_VECTOR( NodeValueAccessor, NodeValueAccessors );
209 : :
210 : : //=====================================================================
211 : : //= OConfigurationValueContainerImpl
212 : : //=====================================================================
213 [ # # ]: 0 : struct OConfigurationValueContainerImpl
214 : : {
215 : : Reference< XMultiServiceFactory > xORB; // the service factory
216 : : ::osl::Mutex& rMutex; // the mutex for accessing the data containers
217 : : OConfigurationTreeRoot aConfigRoot; // the configuration node we're accessing
218 : :
219 : : NodeValueAccessors aAccessors; // the accessors to the node values
220 : :
221 : 0 : OConfigurationValueContainerImpl( const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rMutex )
222 : : :xORB( _rxORB )
223 [ # # ][ # # ]: 0 : ,rMutex( _rMutex )
224 : : {
225 : 0 : }
226 : : };
227 : :
228 : : //=====================================================================
229 : : //= OConfigurationValueContainer
230 : : //=====================================================================
231 : :
232 : 0 : OConfigurationValueContainer::OConfigurationValueContainer(
233 : : const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety,
234 : : const sal_Char* _pConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
235 [ # # ]: 0 : :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
236 : : {
237 [ # # ]: 0 : implConstruct( ::rtl::OUString::createFromAscii( _pConfigLocation ), _nAccessFlags, _nLevels );
238 : 0 : }
239 : :
240 : 0 : OConfigurationValueContainer::~OConfigurationValueContainer()
241 : : {
242 [ # # ]: 0 : delete m_pImpl;
243 : 0 : }
244 : :
245 : 0 : void OConfigurationValueContainer::implConstruct( const ::rtl::OUString& _rConfigLocation,
246 : : const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
247 : : {
248 : : DBG_ASSERT( !m_pImpl->aConfigRoot.isValid(), "OConfigurationValueContainer::implConstruct: already initialized!" );
249 : :
250 : : // .................................
251 : : // create the configuration node we're about to work with
252 : : m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithServiceFactory(
253 : : m_pImpl->xORB,
254 : : _rConfigLocation,
255 : : _nLevels,
256 : : ( _nAccessFlags & CVC_UPDATE_ACCESS ) ? OConfigurationTreeRoot::CM_UPDATABLE : OConfigurationTreeRoot::CM_READONLY,
257 : : ( _nAccessFlags & CVC_IMMEDIATE_UPDATE ) ? sal_False : sal_True
258 [ # # ]: 0 : );
259 : : #ifdef DBG_UTIL
260 : : rtl::OStringBuffer aBuf(256);
261 : : aBuf.append("Could not access the configuration node located at ");
262 : : aBuf.append( rtl::OUStringToOString( _rConfigLocation, RTL_TEXTENCODING_ASCII_US ) );
263 : : aBuf.append( " !" );
264 : : DBG_ASSERT( m_pImpl->aConfigRoot.isValid(), aBuf.getStr() );
265 : : #endif
266 : 0 : }
267 : :
268 : 0 : void OConfigurationValueContainer::registerExchangeLocation( const sal_Char* _pRelativePath,
269 : : void* _pContainer, const Type& _rValueType )
270 : : {
271 : : // checks ....
272 : : DBG_ASSERT( _pContainer, "OConfigurationValueContainer::registerExchangeLocation: invalid container location!" );
273 : : DBG_ASSERT( ( TypeClass_CHAR == _rValueType.getTypeClass( ) )
274 : : || ( TypeClass_BOOLEAN == _rValueType.getTypeClass( ) )
275 : : || ( TypeClass_BYTE == _rValueType.getTypeClass( ) )
276 : : || ( TypeClass_SHORT == _rValueType.getTypeClass( ) )
277 : : || ( TypeClass_LONG == _rValueType.getTypeClass( ) )
278 : : || ( TypeClass_DOUBLE == _rValueType.getTypeClass( ) )
279 : : || ( TypeClass_STRING == _rValueType.getTypeClass( ) )
280 : : || ( TypeClass_SEQUENCE == _rValueType.getTypeClass( ) ),
281 : : "OConfigurationValueContainer::registerExchangeLocation: invalid type!" );
282 : :
283 : : // build an accessor for this container
284 : 0 : NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) );
285 : 0 : aNewAccessor.bind( _pContainer, _rValueType );
286 : :
287 : : // insert it into our structure
288 [ # # ]: 0 : implRegisterExchangeLocation( aNewAccessor );
289 : 0 : }
290 : :
291 : 0 : void OConfigurationValueContainer::read( )
292 : : {
293 : : std::for_each(
294 : : m_pImpl->aAccessors.begin(),
295 : : m_pImpl->aAccessors.end(),
296 : : UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
297 [ # # ]: 0 : );
298 : 0 : }
299 : :
300 : 0 : void OConfigurationValueContainer::write( sal_Bool _bCommit )
301 : : {
302 : : // collect the current values in the exchange locations
303 : : std::for_each(
304 : : m_pImpl->aAccessors.begin(),
305 : : m_pImpl->aAccessors.end(),
306 : : UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
307 [ # # ]: 0 : );
308 : :
309 : : // commit the changes done (if requested)
310 [ # # ]: 0 : if ( _bCommit )
311 : 0 : commit( sal_False );
312 : 0 : }
313 : :
314 : 0 : void OConfigurationValueContainer::commit( sal_Bool _bWrite )
315 : : {
316 : : // write the current values in the exchange locations (if requested)
317 [ # # ]: 0 : if ( _bWrite )
318 : 0 : write( sal_False );
319 : :
320 : : // commit the changes done
321 : 0 : m_pImpl->aConfigRoot.commit( );
322 : 0 : }
323 : :
324 : 0 : void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor )
325 : : {
326 : : // some checks
327 : : DBG_ASSERT( !m_pImpl->aConfigRoot.isValid() || m_pImpl->aConfigRoot.hasByHierarchicalName( _rAccessor.getPath() ),
328 : : "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" );
329 : :
330 : : #ifdef DBG_UTIL
331 : : // another check (should be the first container for this node)
332 : : ConstNodeValueAccessorsIterator aExistent = ::std::find(
333 : : m_pImpl->aAccessors.begin(),
334 : : m_pImpl->aAccessors.end(),
335 : : _rAccessor
336 : : );
337 : : DBG_ASSERT( m_pImpl->aAccessors.end() == aExistent, "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" );
338 : : #endif
339 : :
340 : : // remember the accessor
341 : 0 : m_pImpl->aAccessors.push_back( _rAccessor );
342 : :
343 : : // and initially fill the value
344 [ # # ]: 0 : lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex );
345 : 0 : }
346 : :
347 : : //.........................................................................
348 : : } // namespace utl
349 : : //.........................................................................
350 : :
351 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|