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_comphelper.hxx"
26 
27 #ifndef _COMPHELPER_MASTERPROPERTYSET_HXX_
28 #include <comphelper/MasterPropertySet.hxx>
29 #endif
30 #include <comphelper/MasterPropertySetInfo.hxx>
31 #include <comphelper/ChainablePropertySet.hxx>
32 #include <comphelper/ChainablePropertySetInfo.hxx>
33 #include <vos/mutex.hxx>
34 
35 #include <memory>       // STL auto_ptr
36 
37 //////////////////////////////////////////////////////////////////////
38 
39 class AutoOGuardArray
40 {
41     sal_Int32                       nSize;
42     std::auto_ptr< vos::OGuard > *  pGuardArray;
43 
44 public:
45     AutoOGuardArray( sal_Int32 nNumElements );
46     ~AutoOGuardArray();
47 
operator [](sal_Int32 i)48     std::auto_ptr< vos::OGuard > &  operator[] ( sal_Int32 i ) { return pGuardArray[i]; }
49 };
50 
AutoOGuardArray(sal_Int32 nNumElements)51 AutoOGuardArray::AutoOGuardArray( sal_Int32 nNumElements )
52 {
53     nSize       = nNumElements;
54     pGuardArray = new std::auto_ptr< vos::OGuard >[ nSize ];
55 }
56 
~AutoOGuardArray()57 AutoOGuardArray::~AutoOGuardArray()
58 {
59     //!! release auto_ptr's and thus the mutexes locks
60     delete [] pGuardArray;
61 
62 }
63 
64 //////////////////////////////////////////////////////////////////////
65 
66 using namespace ::rtl;
67 using namespace ::comphelper;
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::lang;
71 using namespace ::com::sun::star::beans;
72 using vos::IMutex;
73 
SlaveData(ChainablePropertySet * pSlave)74 SlaveData::SlaveData ( ChainablePropertySet *pSlave)
75 : mpSlave ( pSlave )
76 , mxSlave ( pSlave )
77 , mbInit ( sal_False )
78 {
79 }
80 
MasterPropertySet(comphelper::MasterPropertySetInfo * pInfo,IMutex * pMutex)81 MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, IMutex *pMutex )
82 	throw()
83 : mpInfo ( pInfo )
84 , mpMutex ( pMutex )
85 , mnLastId ( 0 )
86 , mxInfo ( pInfo )
87 {
88 }
89 
lockMutex()90 void MasterPropertySet::lockMutex()
91 {
92 	if (mpMutex)
93 		mpMutex->acquire();
94 }
unlockMutex()95 void MasterPropertySet::unlockMutex()
96 {
97 	if (mpMutex)
98 		mpMutex->release();
99 }
100 
~MasterPropertySet()101 MasterPropertySet::~MasterPropertySet()
102 	throw()
103 {
104 	SlaveMap::iterator aEnd = maSlaveMap.end(), aIter = maSlaveMap.begin();
105 	while (aIter != aEnd )
106 	{
107 		delete (*aIter).second;
108 		aIter++;
109 	}
110 }
111 
112 // XPropertySet
getPropertySetInfo()113 Reference< XPropertySetInfo > SAL_CALL MasterPropertySet::getPropertySetInfo(  )
114 	throw(RuntimeException)
115 {
116 	return mxInfo;
117 }
118 
registerSlave(ChainablePropertySet * pNewSet)119 void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet )
120 	throw()
121 {
122 	maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet );
123 	mpInfo->add ( pNewSet->mpInfo->maMap, mnLastId );
124 }
125 
setPropertyValue(const::rtl::OUString & rPropertyName,const Any & rValue)126 void SAL_CALL MasterPropertySet::setPropertyValue( const ::rtl::OUString& rPropertyName, const Any& rValue )
127 	throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
128 {
129     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
130     std::auto_ptr< vos::OGuard > pMutexGuard;
131     if (mpMutex)
132         pMutexGuard.reset( new vos::OGuard(mpMutex) );
133 
134     PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
135 
136 	if( aIter == mpInfo->maMap.end())
137 		throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
138 
139 	if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
140 	{
141 		_preSetValues();
142 		_setSingleValue( *((*aIter).second->mpInfo), rValue );
143 		_postSetValues();
144 	}
145 	else
146 	{
147         ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
148 
149         // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
150         std::auto_ptr< vos::OGuard > pMutexGuard2;
151         if (pSlave->mpMutex)
152             pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
153 
154 		pSlave->_preSetValues();
155 		pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue );
156 		pSlave->_postSetValues();
157 	}
158 }
159 
getPropertyValue(const::rtl::OUString & rPropertyName)160 Any SAL_CALL MasterPropertySet::getPropertyValue( const ::rtl::OUString& rPropertyName )
161 	throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
162 {
163     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
164     std::auto_ptr< vos::OGuard > pMutexGuard;
165     if (mpMutex)
166         pMutexGuard.reset( new vos::OGuard(mpMutex) );
167 
168     PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
169 
170 	if( aIter == mpInfo->maMap.end())
171 		throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
172 
173 	Any aAny;
174 	if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
175 	{
176 		_preGetValues();
177 		_getSingleValue( *((*aIter).second->mpInfo), aAny );
178 		_postGetValues();
179 	}
180 	else
181 	{
182 		ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
183 
184         // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
185         std::auto_ptr< vos::OGuard > pMutexGuard2;
186         if (pSlave->mpMutex)
187             pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
188 
189 		pSlave->_preGetValues();
190 		pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny );
191 		pSlave->_postGetValues();
192 	}
193 	return aAny;
194 }
195 
addPropertyChangeListener(const::rtl::OUString &,const Reference<XPropertyChangeListener> &)196 void SAL_CALL MasterPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
197 	throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
198 {
199 	// todo
200 }
201 
removePropertyChangeListener(const::rtl::OUString &,const Reference<XPropertyChangeListener> &)202 void SAL_CALL MasterPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
203 	throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
204 {
205 	// todo
206 }
207 
addVetoableChangeListener(const::rtl::OUString &,const Reference<XVetoableChangeListener> &)208 void SAL_CALL MasterPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
209 	throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
210 {
211 	// todo
212 }
213 
removeVetoableChangeListener(const::rtl::OUString &,const Reference<XVetoableChangeListener> &)214 void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
215 	throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
216 {
217 	// todo
218 }
219 
220 // XMultiPropertySet
setPropertyValues(const Sequence<::rtl::OUString> & aPropertyNames,const Sequence<Any> & aValues)221 void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues )
222 	throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
223 {
224     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
225     std::auto_ptr< vos::OGuard > pMutexGuard;
226     if (mpMutex)
227         pMutexGuard.reset( new vos::OGuard(mpMutex) );
228 
229     const sal_Int32 nCount = aPropertyNames.getLength();
230 
231 	if( nCount != aValues.getLength() )
232 		throw IllegalArgumentException();
233 
234 	if( nCount )
235 	{
236 		_preSetValues();
237 
238 		const Any * pAny = aValues.getConstArray();
239 		const OUString * pString = aPropertyNames.getConstArray();
240 		PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
241 
242         //!! have an auto_ptr to an array of OGuards in order to have the
243         //!! allocated memory properly freed (exception safe!).
244         //!! Since the array itself has auto_ptrs as members we have to use a
245         //!! helper class 'AutoOGuardArray' in order to have
246         //!! the acquired locks properly released.
247         AutoOGuardArray aOGuardArray( nCount );
248 
249 		for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
250 		{
251 			aIter = mpInfo->maMap.find ( *pString );
252 			if ( aIter == aEnd )
253 				throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
254 
255 			if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
256 				_setSingleValue( *((*aIter).second->mpInfo), *pAny );
257 			else
258 			{
259 				SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
260 				if (!pSlave->IsInit())
261 				{
262                     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
263                     if (pSlave->mpSlave->mpMutex)
264                         aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
265 
266 					pSlave->mpSlave->_preSetValues();
267 					pSlave->SetInit ( sal_True );
268 				}
269 				pSlave->mpSlave->_setSingleValue( *((*aIter).second->mpInfo), *pAny );
270 			}
271 		}
272 
273 		_postSetValues();
274 		SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
275 		while (aSlaveIter != aSlaveEnd)
276 		{
277 			if ( (*aSlaveIter).second->IsInit())
278 			{
279 				(*aSlaveIter).second->mpSlave->_postSetValues();
280 				(*aSlaveIter).second->SetInit ( sal_False );
281 			}
282 			++aSlaveIter;
283 		}
284 	}
285 }
286 
getPropertyValues(const Sequence<::rtl::OUString> & aPropertyNames)287 Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames )
288 	throw(RuntimeException)
289 {
290     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
291     std::auto_ptr< vos::OGuard > pMutexGuard;
292     if (mpMutex)
293         pMutexGuard.reset( new vos::OGuard(mpMutex) );
294 
295     const sal_Int32 nCount = aPropertyNames.getLength();
296 
297 	Sequence < Any > aValues ( nCount );
298 
299 	if( nCount )
300 	{
301 		_preGetValues();
302 
303 		Any * pAny = aValues.getArray();
304 		const OUString * pString = aPropertyNames.getConstArray();
305 		PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
306 
307         //!! have an auto_ptr to an array of OGuards in order to have the
308         //!! allocated memory properly freed (exception safe!).
309         //!! Since the array itself has auto_ptrs as members we have to use a
310         //!! helper class 'AutoOGuardArray' in order to have
311         //!! the acquired locks properly released.
312         AutoOGuardArray aOGuardArray( nCount );
313 
314 		for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
315 		{
316 			aIter = mpInfo->maMap.find ( *pString );
317 			if ( aIter == aEnd )
318 				throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
319 
320 			if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
321 				_getSingleValue( *((*aIter).second->mpInfo), *pAny );
322 			else
323 			{
324 				SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
325 				if (!pSlave->IsInit())
326 				{
327                     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
328                     if (pSlave->mpSlave->mpMutex)
329                         aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
330 
331 					pSlave->mpSlave->_preGetValues();
332 					pSlave->SetInit ( sal_True );
333 				}
334 				pSlave->mpSlave->_getSingleValue( *((*aIter).second->mpInfo), *pAny );
335 			}
336 		}
337 
338 		_postSetValues();
339 		SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
340 		while (aSlaveIter != aSlaveEnd)
341 		{
342 			if ( (*aSlaveIter).second->IsInit())
343 			{
344 				(*aSlaveIter).second->mpSlave->_postSetValues();
345 				(*aSlaveIter).second->SetInit ( sal_False );
346 			}
347 			++aSlaveIter;
348 		}
349 	}
350 	return aValues;
351 }
352 
addPropertiesChangeListener(const Sequence<::rtl::OUString> &,const Reference<XPropertiesChangeListener> &)353 void SAL_CALL MasterPropertySet::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
354 	throw(RuntimeException)
355 {
356 	// todo
357 }
358 
removePropertiesChangeListener(const Reference<XPropertiesChangeListener> &)359 void SAL_CALL MasterPropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& )
360 	throw(RuntimeException)
361 {
362 	// todo
363 }
364 
firePropertiesChangeEvent(const Sequence<::rtl::OUString> &,const Reference<XPropertiesChangeListener> &)365 void SAL_CALL MasterPropertySet::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
366 	throw(RuntimeException)
367 {
368 	// todo
369 }
370 
371 // XPropertyState
getPropertyState(const::rtl::OUString & PropertyName)372 PropertyState SAL_CALL MasterPropertySet::getPropertyState( const ::rtl::OUString& PropertyName )
373 	throw(UnknownPropertyException, RuntimeException)
374 {
375 	PropertyDataHash::const_iterator aIter =  mpInfo->maMap.find( PropertyName );
376 	if( aIter == mpInfo->maMap.end())
377 		throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
378 
379 	PropertyState aState;
380 
381 	if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
382 	{
383 		_preGetPropertyState();
384 		_getPropertyState( *((*aIter).second->mpInfo), aState );
385 		_postGetPropertyState();
386 	}
387 	else
388 	{
389 		ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
390 
391         // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
392         std::auto_ptr< vos::OGuard > pMutexGuard;
393         if (pSlave->mpMutex)
394             pMutexGuard.reset( new vos::OGuard(pSlave->mpMutex) );
395 
396 		pSlave->_preGetPropertyState();
397 		pSlave->_getPropertyState( *((*aIter).second->mpInfo), aState );
398 		pSlave->_postGetPropertyState();
399 	}
400 
401 	return aState;
402 }
403 
getPropertyStates(const Sequence<::rtl::OUString> & rPropertyNames)404 Sequence< PropertyState > SAL_CALL MasterPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& rPropertyNames )
405 	throw(UnknownPropertyException, RuntimeException)
406 {
407 	const sal_Int32 nCount = rPropertyNames.getLength();
408 
409 	Sequence< PropertyState > aStates( nCount );
410 	if( nCount )
411 	{
412 		PropertyState * pState = aStates.getArray();
413 		const OUString * pString = rPropertyNames.getConstArray();
414 		PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
415 		_preGetPropertyState();
416 
417 		for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pState )
418 		{
419 			aIter = mpInfo->maMap.find ( *pString );
420 			if ( aIter == aEnd )
421 				throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
422 
423 			if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
424 				_getPropertyState( *((*aIter).second->mpInfo), *pState );
425 			else
426 			{
427 				SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
428 				if (!pSlave->IsInit())
429 				{
430 					pSlave->mpSlave->_preGetPropertyState();
431 					pSlave->SetInit ( sal_True );
432 				}
433 				pSlave->mpSlave->_getPropertyState( *((*aIter).second->mpInfo), *pState );
434 			}
435 		}
436 		_postGetPropertyState();
437 		SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
438 		while (aSlaveIter != aSlaveEnd)
439 		{
440 			if ( (*aSlaveIter).second->IsInit())
441 			{
442 				(*aSlaveIter).second->mpSlave->_postGetPropertyState();
443 				(*aSlaveIter).second->SetInit ( sal_False );
444 			}
445 			++aSlaveIter;
446 		}
447 	}
448 	return aStates;
449 }
450 
setPropertyToDefault(const::rtl::OUString & rPropertyName)451 void SAL_CALL MasterPropertySet::setPropertyToDefault( const ::rtl::OUString& rPropertyName )
452 	throw(UnknownPropertyException, RuntimeException)
453 {
454 	PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
455 
456 	if( aIter == mpInfo->maMap.end())
457 		throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
458 	_setPropertyToDefault( *((*aIter).second->mpInfo) );
459 }
460 
getPropertyDefault(const::rtl::OUString & rPropertyName)461 Any SAL_CALL MasterPropertySet::getPropertyDefault( const ::rtl::OUString& rPropertyName )
462 	throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
463 {
464 	PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
465 
466 	if( aIter == mpInfo->maMap.end())
467 		throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
468 	return _getPropertyDefault( *((*aIter).second->mpInfo) );
469 }
470 
_preGetPropertyState()471 void MasterPropertySet::_preGetPropertyState ()
472 	throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException )
473 {
474 	OSL_ENSURE( sal_False, "you have to implement this yourself!");
475 }
476 
_getPropertyState(const comphelper::PropertyInfo &,PropertyState &)477 void MasterPropertySet::_getPropertyState( const comphelper::PropertyInfo&, PropertyState& )
478 	throw(UnknownPropertyException )
479 {
480 	OSL_ENSURE( sal_False, "you have to implement this yourself!");
481 }
482 
_postGetPropertyState()483 void MasterPropertySet::_postGetPropertyState ()
484 	throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException )
485 {
486 	OSL_ENSURE( sal_False, "you have to implement this yourself!");
487 }
488 
_setPropertyToDefault(const comphelper::PropertyInfo &)489 void MasterPropertySet::_setPropertyToDefault( const comphelper::PropertyInfo& )
490 	throw(UnknownPropertyException )
491 {
492 	OSL_ENSURE( sal_False, "you have to implement this yourself!");
493 }
494 
_getPropertyDefault(const comphelper::PropertyInfo &)495 Any MasterPropertySet::_getPropertyDefault( const comphelper::PropertyInfo& )
496 	throw(UnknownPropertyException, WrappedTargetException )
497 {
498 	OSL_ENSURE( sal_False, "you have to implement this yourself!");
499 	Any aAny;
500 	return aAny;
501 }
502