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: */
|