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