1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: configvaluecontainer.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_unotools.hxx"
33 #include <unotools/configvaluecontainer.hxx>
34 #include <unotools/confignode.hxx>
35 #include <tools/debug.hxx>
36 #include <comphelper/stl_types.hxx>
41 #include <rtl/strbuf.hxx>
44 //.........................................................................
47 //.........................................................................
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::lang
;
52 //=====================================================================
54 //=====================================================================
57 ltSimplyObjectInstance
,
63 struct NodeValueAccessor
66 ::rtl::OUString sRelativePath
; // the relative path of the node
67 LocationType eLocationType
; // the type of location where the value is stored
68 void* pLocation
; // the pointer to the location
69 Type aDataType
; // the type object pointed to by pLocation
72 NodeValueAccessor( const ::rtl::OUString
& _rNodePath
);
74 void bind( void* _pLocation
, const Type
& _rType
);
75 void bind( Any
* _pLocation
);
77 bool isBound( ) const { return ( ltUnbound
!= eLocationType
) && ( NULL
!= pLocation
); }
78 const ::rtl::OUString
& getPath( ) const { return sRelativePath
; }
79 LocationType
getLocType( ) const { return eLocationType
; }
80 void* getLocation( ) const { return pLocation
; }
81 const Type
& getDataType( ) const { return aDataType
; }
83 bool operator == ( const NodeValueAccessor
& rhs
) const;
84 bool operator != ( const NodeValueAccessor
& rhs
) const { return !operator == ( rhs
); }
87 //---------------------------------------------------------------------
88 //--- 20.08.01 17:21:13 -----------------------------------------------
90 NodeValueAccessor::NodeValueAccessor( const ::rtl::OUString
& _rNodePath
)
91 :sRelativePath( _rNodePath
)
92 ,eLocationType( ltUnbound
)
97 //---------------------------------------------------------------------
98 //--- 20.08.01 17:06:36 -----------------------------------------------
100 bool NodeValueAccessor::operator == ( const NodeValueAccessor
& rhs
) const
102 return ( sRelativePath
== rhs
.sRelativePath
)
103 && ( eLocationType
== rhs
.eLocationType
)
104 && ( pLocation
== rhs
.pLocation
);
107 //---------------------------------------------------------------------
108 //--- 20.08.01 17:47:43 -----------------------------------------------
110 void NodeValueAccessor::bind( void* _pLocation
, const Type
& _rType
)
112 DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
114 eLocationType
= ltSimplyObjectInstance
;
115 pLocation
= _pLocation
;
119 //---------------------------------------------------------------------
120 //--- 20.08.01 17:48:47 -----------------------------------------------
122 void NodeValueAccessor::bind( Any
* _pLocation
)
124 DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
126 eLocationType
= ltAnyInstance
;
127 pLocation
= _pLocation
;
128 aDataType
= ::getCppuType( _pLocation
);
131 //---------------------------------------------------------------------
132 //--- 20.08.01 17:42:17 -----------------------------------------------
137 void lcl_copyData( const NodeValueAccessor
& _rAccessor
, const Any
& _rData
, ::osl::Mutex
& _rMutex
)
139 ::osl::MutexGuard
aGuard( _rMutex
);
141 DBG_ASSERT( _rAccessor
.isBound(), "::utl::lcl_copyData: invalid accessor!" );
142 switch ( _rAccessor
.getLocType() )
144 case ltSimplyObjectInstance
:
146 if ( _rData
.hasValue() )
153 _rAccessor
.getLocation(), _rAccessor
.getDataType().getTypeLibType(),
154 const_cast< void* >( _rData
.getValue() ), _rData
.getValueType().getTypeLibType(),
155 (uno_QueryInterfaceFunc
)cpp_queryInterface
, (uno_AcquireFunc
)cpp_acquire
, (uno_ReleaseFunc
)cpp_release
158 rtl::OStringBuffer
aBuf( 256 );
159 aBuf
.append("::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: ");
160 aBuf
.append( rtl::OUStringToOString( _rAccessor
.getPath(), RTL_TEXTENCODING_ASCII_US
) );
162 DBG_ASSERT( bSuccess
, aBuf
.getStr() );
166 DBG_WARNING( "::utl::lcl_copyData: NULL value lost!" );
171 // a simple assignment of an Any ...
172 *static_cast< Any
* >( _rAccessor
.getLocation() ) = _rData
;
179 //---------------------------------------------------------------------
180 //--- 21.08.01 12:06:43 -----------------------------------------------
185 void lcl_copyData( Any
& _rData
, const NodeValueAccessor
& _rAccessor
, ::osl::Mutex
& _rMutex
)
187 ::osl::MutexGuard
aGuard( _rMutex
);
189 DBG_ASSERT( _rAccessor
.isBound(), "::utl::lcl_copyData: invalid accessor!" );
190 switch ( _rAccessor
.getLocType() )
192 case ltSimplyObjectInstance
:
193 // a simple setValue ....
194 _rData
.setValue( _rAccessor
.getLocation(), _rAccessor
.getDataType() );
198 // a simple assignment of an Any ...
199 _rData
= *static_cast< Any
* >( _rAccessor
.getLocation() );
206 //=====================================================================
207 //= functors on NodeValueAccessor instances
208 //=====================================================================
210 //---------------------------------------------------------------------
211 //--- 21.08.01 12:01:16 -----------------------------------------------
213 /// base class for functors syncronizing between exchange locations and config sub nodes
214 struct SubNodeAccess
: public ::std::unary_function
< NodeValueAccessor
, void >
217 const OConfigurationNode
& m_rRootNode
;
218 ::osl::Mutex
& m_rMutex
;
221 SubNodeAccess( const OConfigurationNode
& _rRootNode
, ::osl::Mutex
& _rMutex
)
222 :m_rRootNode( _rRootNode
)
228 //---------------------------------------------------------------------
229 //--- 21.08.01 11:25:56 -----------------------------------------------
231 struct UpdateFromConfig
: public SubNodeAccess
234 UpdateFromConfig( const OConfigurationNode
& _rRootNode
, ::osl::Mutex
& _rMutex
) : SubNodeAccess( _rRootNode
, _rMutex
) { }
236 void operator() ( NodeValueAccessor
& _rAccessor
)
238 ::utl::lcl_copyData( _rAccessor
, m_rRootNode
.getNodeValue( _rAccessor
.getPath( ) ), m_rMutex
);
242 //---------------------------------------------------------------------
243 //--- 21.08.01 11:25:56 -----------------------------------------------
245 struct UpdateToConfig
: public SubNodeAccess
248 UpdateToConfig( const OConfigurationNode
& _rRootNode
, ::osl::Mutex
& _rMutex
) : SubNodeAccess( _rRootNode
, _rMutex
) { }
250 void operator() ( NodeValueAccessor
& _rAccessor
)
253 lcl_copyData( aNewValue
, _rAccessor
, m_rMutex
);
254 m_rRootNode
.setNodeValue( _rAccessor
.getPath( ), aNewValue
);
258 //---------------------------------------------------------------------
259 //--- 20.08.01 16:58:24 -----------------------------------------------
261 DECLARE_STL_VECTOR( NodeValueAccessor
, NodeValueAccessors
);
263 //=====================================================================
264 //= OConfigurationValueContainerImpl
265 //=====================================================================
266 struct OConfigurationValueContainerImpl
268 Reference
< XMultiServiceFactory
> xORB
; // the service factory
269 ::osl::Mutex
& rMutex
; // the mutex for accessing the data containers
270 OConfigurationTreeRoot aConfigRoot
; // the configuration node we're accessing
272 NodeValueAccessors aAccessors
; // the accessors to the node values
274 OConfigurationValueContainerImpl( const Reference
< XMultiServiceFactory
>& _rxORB
, ::osl::Mutex
& _rMutex
)
281 //=====================================================================
282 //= OConfigurationValueContainer
283 //=====================================================================
285 //---------------------------------------------------------------------
286 //--- 20.08.01 15:53:35 -----------------------------------------------
288 OConfigurationValueContainer::OConfigurationValueContainer(
289 const Reference
< XMultiServiceFactory
>& _rxORB
, ::osl::Mutex
& _rAccessSafety
,
290 const sal_Char
* _pConfigLocation
, const sal_uInt16 _nAccessFlags
, const sal_Int32 _nLevels
)
291 :m_pImpl( new OConfigurationValueContainerImpl( _rxORB
, _rAccessSafety
) )
293 implConstruct( ::rtl::OUString::createFromAscii( _pConfigLocation
), _nAccessFlags
, _nLevels
);
296 //---------------------------------------------------------------------
297 //--- 20.08.01 15:55:20 -----------------------------------------------
299 OConfigurationValueContainer::OConfigurationValueContainer(
300 const Reference
< XMultiServiceFactory
>& _rxORB
, ::osl::Mutex
& _rAccessSafety
,
301 const ::rtl::OUString
& _rConfigLocation
, const sal_uInt16 _nAccessFlags
, const sal_Int32 _nLevels
)
302 :m_pImpl( new OConfigurationValueContainerImpl( _rxORB
, _rAccessSafety
) )
304 implConstruct( _rConfigLocation
, _nAccessFlags
, _nLevels
);
307 //---------------------------------------------------------------------
308 //--- 20.08.01 16:01:29 -----------------------------------------------
310 OConfigurationValueContainer::~OConfigurationValueContainer()
315 //---------------------------------------------------------------------
316 //--- 20.08.01 15:59:13 -----------------------------------------------
318 const Reference
< XMultiServiceFactory
>& OConfigurationValueContainer::getServiceFactory( ) const
320 return m_pImpl
->xORB
;
323 //---------------------------------------------------------------------
324 //--- 20.08.01 16:02:07 -----------------------------------------------
326 void OConfigurationValueContainer::implConstruct( const ::rtl::OUString
& _rConfigLocation
,
327 const sal_uInt16 _nAccessFlags
, const sal_Int32 _nLevels
)
329 DBG_ASSERT( !m_pImpl
->aConfigRoot
.isValid(), "OConfigurationValueContainer::implConstruct: already initialized!" );
331 // .................................
332 // create the configuration node we're about to work with
333 m_pImpl
->aConfigRoot
= OConfigurationTreeRoot::createWithServiceFactory(
337 ( _nAccessFlags
& CVC_UPDATE_ACCESS
) ? OConfigurationTreeRoot::CM_PREFER_UPDATABLE
: OConfigurationTreeRoot::CM_READONLY
,
338 ( _nAccessFlags
& CVC_IMMEDIATE_UPDATE
) ? sal_False
: sal_True
341 rtl::OStringBuffer
aBuf(256);
342 aBuf
.append("Could not access the configuration node located at ");
343 aBuf
.append( rtl::OUStringToOString( _rConfigLocation
, RTL_TEXTENCODING_ASCII_US
) );
345 DBG_ASSERT( m_pImpl
->aConfigRoot
.isValid(), aBuf
.getStr() );
349 //---------------------------------------------------------------------
350 //--- 20.08.01 16:39:05 -----------------------------------------------
352 void OConfigurationValueContainer::registerExchangeLocation( const sal_Char
* _pRelativePath
,
353 void* _pContainer
, const Type
& _rValueType
)
356 DBG_ASSERT( _pContainer
, "OConfigurationValueContainer::registerExchangeLocation: invalid container location!" );
357 DBG_ASSERT( ( TypeClass_CHAR
== _rValueType
.getTypeClass( ) )
358 || ( TypeClass_BOOLEAN
== _rValueType
.getTypeClass( ) )
359 || ( TypeClass_BYTE
== _rValueType
.getTypeClass( ) )
360 || ( TypeClass_SHORT
== _rValueType
.getTypeClass( ) )
361 || ( TypeClass_LONG
== _rValueType
.getTypeClass( ) )
362 || ( TypeClass_DOUBLE
== _rValueType
.getTypeClass( ) )
363 || ( TypeClass_STRING
== _rValueType
.getTypeClass( ) )
364 || ( TypeClass_SEQUENCE
== _rValueType
.getTypeClass( ) ),
365 "OConfigurationValueContainer::registerExchangeLocation: invalid type!" );
367 // build an accessor for this container
368 NodeValueAccessor
aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath
) );
369 aNewAccessor
.bind( _pContainer
, _rValueType
);
371 // insert it into our structure
372 implRegisterExchangeLocation( aNewAccessor
);
375 //---------------------------------------------------------------------
376 //--- 21.08.01 14:44:45 -----------------------------------------------
378 void OConfigurationValueContainer::registerNullValueExchangeLocation( const sal_Char
* _pRelativePath
, Any
* _pContainer
)
380 // build an accessor for this container
381 NodeValueAccessor
aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath
) );
382 aNewAccessor
.bind( _pContainer
);
384 // insert it into our structure
385 implRegisterExchangeLocation( aNewAccessor
);
388 //---------------------------------------------------------------------
389 //--- 21.08.01 10:23:34 -----------------------------------------------
391 void OConfigurationValueContainer::read( )
394 m_pImpl
->aAccessors
.begin(),
395 m_pImpl
->aAccessors
.end(),
396 UpdateFromConfig( m_pImpl
->aConfigRoot
, m_pImpl
->rMutex
)
400 //---------------------------------------------------------------------
401 //--- 21.08.01 12:04:48 -----------------------------------------------
403 void OConfigurationValueContainer::write( sal_Bool _bCommit
)
405 // collect the current values in the exchange locations
407 m_pImpl
->aAccessors
.begin(),
408 m_pImpl
->aAccessors
.end(),
409 UpdateToConfig( m_pImpl
->aConfigRoot
, m_pImpl
->rMutex
)
412 // commit the changes done (if requested)
417 //---------------------------------------------------------------------
418 //--- 21.08.01 12:09:45 -----------------------------------------------
420 void OConfigurationValueContainer::commit( sal_Bool _bWrite
)
422 // write the current values in the exchange locations (if requested)
426 // commit the changes done
427 m_pImpl
->aConfigRoot
.commit( );
430 //---------------------------------------------------------------------
431 //--- 20.08.01 17:29:27 -----------------------------------------------
433 void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor
& _rAccessor
)
436 DBG_ASSERT( !m_pImpl
->aConfigRoot
.isValid() || m_pImpl
->aConfigRoot
.hasByHierarchicalName( _rAccessor
.getPath() ),
437 "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" );
440 // another check (should be the first container for this node)
441 ConstNodeValueAccessorsIterator aExistent
= ::std::find(
442 m_pImpl
->aAccessors
.begin(),
443 m_pImpl
->aAccessors
.end(),
446 DBG_ASSERT( m_pImpl
->aAccessors
.end() == aExistent
, "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" );
449 // remember the accessor
450 m_pImpl
->aAccessors
.push_back( _rAccessor
);
452 // and initially fill the value
453 lcl_copyData( _rAccessor
, m_pImpl
->aConfigRoot
.getNodeValue( _rAccessor
.getPath() ), m_pImpl
->rMutex
);
456 //.........................................................................
458 //.........................................................................