xref: /AOO41X/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