xref: /trunk/main/unotools/source/config/configvaluecontainer.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_unotools.hxx"
30 #include <unotools/configvaluecontainer.hxx>
31 #include <unotools/confignode.hxx>
32 #include <tools/debug.hxx>
33 #include <comphelper/stl_types.hxx>
34 #include <uno/data.h>
35 #include <algorithm>
36 
37 #ifdef DBG_UTIL
38 #include <rtl/strbuf.hxx>
39 #endif
40 
41 //.........................................................................
42 namespace utl
43 {
44 //.........................................................................
45 
46     using namespace ::com::sun::star::uno;
47     using namespace ::com::sun::star::lang;
48 
49     //=====================================================================
50     //= NodeValueAccessor
51     //=====================================================================
52     enum LocationType
53     {
54         ltSimplyObjectInstance,
55         ltAnyInstance,
56 
57         ltUnbound
58     };
59 
60     struct NodeValueAccessor
61     {
62     private:
63         ::rtl::OUString     sRelativePath;      // the relative path of the node
64         LocationType        eLocationType;      // the type of location where the value is stored
65         void*               pLocation;          // the pointer to the location
66         Type                aDataType;          // the type object pointed to by pLocation
67 
68     public:
69         NodeValueAccessor( const ::rtl::OUString& _rNodePath );
70 
71         void bind( void* _pLocation, const Type& _rType );
72         void bind( Any* _pLocation );
73 
74         bool                    isBound( ) const        { return ( ltUnbound != eLocationType ) && ( NULL != pLocation ); }
75         const ::rtl::OUString&  getPath( ) const        { return sRelativePath; }
76         LocationType            getLocType( ) const     { return eLocationType; }
77         void*                   getLocation( ) const    { return pLocation; }
78         const Type&             getDataType( ) const    { return aDataType; }
79 
80         bool operator == ( const NodeValueAccessor& rhs ) const;
81         bool operator != ( const NodeValueAccessor& rhs ) const { return !operator == ( rhs ); }
82     };
83 
84     //---------------------------------------------------------------------
85     //--- 20.08.01 17:21:13 -----------------------------------------------
86 
87     NodeValueAccessor::NodeValueAccessor( const ::rtl::OUString& _rNodePath )
88         :sRelativePath( _rNodePath )
89         ,eLocationType( ltUnbound )
90         ,pLocation( NULL )
91     {
92     }
93 
94     //---------------------------------------------------------------------
95     //--- 20.08.01 17:06:36 -----------------------------------------------
96 
97     bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const
98     {
99         return  (   sRelativePath   ==  rhs.sRelativePath   )
100             &&  (   eLocationType   ==  rhs.eLocationType   )
101             &&  (   pLocation       ==  rhs.pLocation       );
102     }
103 
104     //---------------------------------------------------------------------
105     //--- 20.08.01 17:47:43 -----------------------------------------------
106 
107     void NodeValueAccessor::bind( void* _pLocation, const Type& _rType )
108     {
109         DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
110 
111         eLocationType = ltSimplyObjectInstance;
112         pLocation = _pLocation;
113         aDataType = _rType;
114     }
115 
116     //---------------------------------------------------------------------
117     //--- 20.08.01 17:48:47 -----------------------------------------------
118 
119     void NodeValueAccessor::bind( Any* _pLocation )
120     {
121         DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
122 
123         eLocationType = ltAnyInstance;
124         pLocation = _pLocation;
125         aDataType = ::getCppuType( _pLocation );
126     }
127 
128     //---------------------------------------------------------------------
129     //--- 20.08.01 17:42:17 -----------------------------------------------
130 
131     #ifndef UNX
132     static
133     #endif
134     void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex )
135     {
136         ::osl::MutexGuard aGuard( _rMutex );
137 
138         DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
139         switch ( _rAccessor.getLocType() )
140         {
141             case ltSimplyObjectInstance:
142             {
143                 if ( _rData.hasValue() )
144                 {
145 #ifdef DBG_UTIL
146                     sal_Bool bSuccess =
147 #endif
148                     // assign the value
149                     uno_type_assignData(
150                         _rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(),
151                         const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(),
152                         (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release
153                     );
154                     #ifdef DBG_UTIL
155                     rtl::OStringBuffer aBuf( 256 );
156                     aBuf.append("::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: ");
157                     aBuf.append( rtl::OUStringToOString( _rAccessor.getPath(), RTL_TEXTENCODING_ASCII_US ) );
158                     aBuf.append( " !" );
159                     DBG_ASSERT( bSuccess, aBuf.getStr() );
160                     #endif
161                 }
162                 else {
163                     DBG_WARNING( "::utl::lcl_copyData: NULL value lost!" );
164                 }
165             }
166             break;
167             case ltAnyInstance:
168                 // a simple assignment of an Any ...
169                 *static_cast< Any* >( _rAccessor.getLocation() ) = _rData;
170                 break;
171             default:
172                 break;
173         }
174     }
175 
176     //---------------------------------------------------------------------
177     //--- 21.08.01 12:06:43 -----------------------------------------------
178 
179     #ifndef UNX
180     static
181     #endif
182     void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex )
183     {
184         ::osl::MutexGuard aGuard( _rMutex );
185 
186         DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
187         switch ( _rAccessor.getLocType() )
188         {
189             case ltSimplyObjectInstance:
190                 // a simple setValue ....
191                 _rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() );
192                 break;
193 
194             case ltAnyInstance:
195                 // a simple assignment of an Any ...
196                 _rData = *static_cast< Any* >( _rAccessor.getLocation() );
197                 break;
198             default:
199                 break;
200         }
201     }
202 
203     //=====================================================================
204     //= functors on NodeValueAccessor instances
205     //=====================================================================
206 
207     //---------------------------------------------------------------------
208     //--- 21.08.01 12:01:16 -----------------------------------------------
209 
210     /// base class for functors syncronizing between exchange locations and config sub nodes
211     struct SubNodeAccess : public ::std::unary_function< NodeValueAccessor, void >
212     {
213     protected:
214         const OConfigurationNode&   m_rRootNode;
215         ::osl::Mutex&               m_rMutex;
216 
217     public:
218         SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex )
219             :m_rRootNode( _rRootNode )
220             ,m_rMutex( _rMutex )
221         {
222         }
223     };
224 
225     //---------------------------------------------------------------------
226     //--- 21.08.01 11:25:56 -----------------------------------------------
227 
228     struct UpdateFromConfig : public SubNodeAccess
229     {
230     public:
231         UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
232 
233         void operator() ( NodeValueAccessor& _rAccessor )
234         {
235             ::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex );
236         }
237     };
238 
239     //---------------------------------------------------------------------
240     //--- 21.08.01 11:25:56 -----------------------------------------------
241 
242     struct UpdateToConfig : public SubNodeAccess
243     {
244     public:
245         UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
246 
247         void operator() ( NodeValueAccessor& _rAccessor )
248         {
249             Any aNewValue;
250             lcl_copyData( aNewValue, _rAccessor, m_rMutex );
251             m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue );
252         }
253     };
254 
255     //---------------------------------------------------------------------
256     //--- 20.08.01 16:58:24 -----------------------------------------------
257 
258     DECLARE_STL_VECTOR( NodeValueAccessor, NodeValueAccessors );
259 
260     //=====================================================================
261     //= OConfigurationValueContainerImpl
262     //=====================================================================
263     struct OConfigurationValueContainerImpl
264     {
265         Reference< XMultiServiceFactory >       xORB;           // the service factory
266         ::osl::Mutex&                           rMutex;         // the mutex for accessing the data containers
267         OConfigurationTreeRoot                  aConfigRoot;    // the configuration node we're accessing
268 
269         NodeValueAccessors                      aAccessors;     // the accessors to the node values
270 
271         OConfigurationValueContainerImpl( const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rMutex )
272             :xORB( _rxORB )
273             ,rMutex( _rMutex )
274         {
275         }
276     };
277 
278     //=====================================================================
279     //= OConfigurationValueContainer
280     //=====================================================================
281 
282     //---------------------------------------------------------------------
283     //--- 20.08.01 15:53:35 -----------------------------------------------
284 
285     OConfigurationValueContainer::OConfigurationValueContainer(
286             const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety,
287             const sal_Char* _pConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
288         :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
289     {
290         implConstruct( ::rtl::OUString::createFromAscii( _pConfigLocation ), _nAccessFlags, _nLevels );
291     }
292 
293     //---------------------------------------------------------------------
294     //--- 20.08.01 15:55:20 -----------------------------------------------
295 
296     OConfigurationValueContainer::OConfigurationValueContainer(
297             const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety,
298             const ::rtl::OUString& _rConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
299         :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
300     {
301         implConstruct( _rConfigLocation, _nAccessFlags, _nLevels );
302     }
303 
304     //---------------------------------------------------------------------
305     //--- 20.08.01 16:01:29 -----------------------------------------------
306 
307     OConfigurationValueContainer::~OConfigurationValueContainer()
308     {
309         delete m_pImpl;
310     }
311 
312     //---------------------------------------------------------------------
313     //--- 20.08.01 15:59:13 -----------------------------------------------
314 
315     const Reference< XMultiServiceFactory >& OConfigurationValueContainer::getServiceFactory( ) const
316     {
317         return m_pImpl->xORB;
318     }
319 
320     //---------------------------------------------------------------------
321     //--- 20.08.01 16:02:07 -----------------------------------------------
322 
323     void OConfigurationValueContainer::implConstruct( const ::rtl::OUString& _rConfigLocation,
324         const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
325     {
326         DBG_ASSERT( !m_pImpl->aConfigRoot.isValid(), "OConfigurationValueContainer::implConstruct: already initialized!" );
327 
328         // .................................
329         // create the configuration node we're about to work with
330         m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithServiceFactory(
331             m_pImpl->xORB,
332             _rConfigLocation,
333             _nLevels,
334             ( _nAccessFlags & CVC_UPDATE_ACCESS ) ? OConfigurationTreeRoot::CM_UPDATABLE : OConfigurationTreeRoot::CM_READONLY,
335             ( _nAccessFlags & CVC_IMMEDIATE_UPDATE ) ? sal_False : sal_True
336         );
337         #ifdef DBG_UTIL
338         rtl::OStringBuffer aBuf(256);
339         aBuf.append("Could not access the configuration node located at ");
340         aBuf.append( rtl::OUStringToOString( _rConfigLocation, RTL_TEXTENCODING_ASCII_US ) );
341         aBuf.append( " !" );
342         DBG_ASSERT( m_pImpl->aConfigRoot.isValid(), aBuf.getStr() );
343         #endif
344     }
345 
346     //---------------------------------------------------------------------
347     //--- 20.08.01 16:39:05 -----------------------------------------------
348 
349     void OConfigurationValueContainer::registerExchangeLocation( const sal_Char* _pRelativePath,
350         void* _pContainer, const Type& _rValueType )
351     {
352         // checks ....
353         DBG_ASSERT( _pContainer, "OConfigurationValueContainer::registerExchangeLocation: invalid container location!" );
354         DBG_ASSERT( (   TypeClass_CHAR      ==  _rValueType.getTypeClass( ) )
355                 ||  (   TypeClass_BOOLEAN   ==  _rValueType.getTypeClass( ) )
356                 ||  (   TypeClass_BYTE      ==  _rValueType.getTypeClass( ) )
357                 ||  (   TypeClass_SHORT     ==  _rValueType.getTypeClass( ) )
358                 ||  (   TypeClass_LONG      ==  _rValueType.getTypeClass( ) )
359                 ||  (   TypeClass_DOUBLE    ==  _rValueType.getTypeClass( ) )
360                 ||  (   TypeClass_STRING    ==  _rValueType.getTypeClass( ) )
361                 ||  (   TypeClass_SEQUENCE  ==  _rValueType.getTypeClass( ) ),
362                 "OConfigurationValueContainer::registerExchangeLocation: invalid type!" );
363 
364         // build an accessor for this container
365         NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) );
366         aNewAccessor.bind( _pContainer, _rValueType );
367 
368         // insert it into our structure
369         implRegisterExchangeLocation( aNewAccessor );
370     }
371 
372     //---------------------------------------------------------------------
373     //--- 21.08.01 14:44:45 -----------------------------------------------
374 
375     void OConfigurationValueContainer::registerNullValueExchangeLocation( const sal_Char* _pRelativePath, Any* _pContainer )
376     {
377         // build an accessor for this container
378         NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) );
379         aNewAccessor.bind( _pContainer );
380 
381         // insert it into our structure
382         implRegisterExchangeLocation( aNewAccessor );
383     }
384 
385     //---------------------------------------------------------------------
386     //--- 21.08.01 10:23:34 -----------------------------------------------
387 
388     void OConfigurationValueContainer::read( )
389     {
390         for_each(
391             m_pImpl->aAccessors.begin(),
392             m_pImpl->aAccessors.end(),
393             UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
394         );
395     }
396 
397     //---------------------------------------------------------------------
398     //--- 21.08.01 12:04:48 -----------------------------------------------
399 
400     void OConfigurationValueContainer::write( sal_Bool _bCommit )
401     {
402         // collect the current values in the exchange locations
403         for_each(
404             m_pImpl->aAccessors.begin(),
405             m_pImpl->aAccessors.end(),
406             UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
407         );
408 
409         // commit the changes done (if requested)
410         if ( _bCommit )
411             commit( sal_False );
412     }
413 
414     //---------------------------------------------------------------------
415     //--- 21.08.01 12:09:45 -----------------------------------------------
416 
417     void OConfigurationValueContainer::commit( sal_Bool _bWrite )
418     {
419         // write the current values in the exchange locations (if requested)
420         if ( _bWrite )
421             write( sal_False );
422 
423         // commit the changes done
424         m_pImpl->aConfigRoot.commit( );
425     }
426 
427     //---------------------------------------------------------------------
428     //--- 20.08.01 17:29:27 -----------------------------------------------
429 
430     void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor )
431     {
432         // some checks
433         DBG_ASSERT( !m_pImpl->aConfigRoot.isValid() || m_pImpl->aConfigRoot.hasByHierarchicalName( _rAccessor.getPath() ),
434             "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" );
435 
436 #ifdef DBG_UTIL
437         // another check (should be the first container for this node)
438         ConstNodeValueAccessorsIterator aExistent = ::std::find(
439             m_pImpl->aAccessors.begin(),
440             m_pImpl->aAccessors.end(),
441             _rAccessor
442         );
443         DBG_ASSERT( m_pImpl->aAccessors.end() == aExistent, "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" );
444 #endif
445 
446         // remember the accessor
447         m_pImpl->aAccessors.push_back( _rAccessor );
448 
449         // and initially fill the value
450         lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex );
451     }
452 
453 //.........................................................................
454 }   // namespace utl
455 //.........................................................................
456 
457