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