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 {
115 return mxInfo;
116 }
117
registerSlave(ChainablePropertySet * pNewSet)118 void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet )
119 throw()
120 {
121 maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet );
122 mpInfo->add ( pNewSet->mpInfo->maMap, mnLastId );
123 }
124
setPropertyValue(const::rtl::OUString & rPropertyName,const Any & rValue)125 void SAL_CALL MasterPropertySet::setPropertyValue( const ::rtl::OUString& rPropertyName, const Any& rValue )
126 {
127 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
128 std::auto_ptr< vos::OGuard > pMutexGuard;
129 if (mpMutex)
130 pMutexGuard.reset( new vos::OGuard(mpMutex) );
131
132 PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
133
134 if( aIter == mpInfo->maMap.end())
135 throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
136
137 if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
138 {
139 _preSetValues();
140 _setSingleValue( *((*aIter).second->mpInfo), rValue );
141 _postSetValues();
142 }
143 else
144 {
145 ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
146
147 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
148 std::auto_ptr< vos::OGuard > pMutexGuard2;
149 if (pSlave->mpMutex)
150 pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
151
152 pSlave->_preSetValues();
153 pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue );
154 pSlave->_postSetValues();
155 }
156 }
157
getPropertyValue(const::rtl::OUString & rPropertyName)158 Any SAL_CALL MasterPropertySet::getPropertyValue( const ::rtl::OUString& rPropertyName )
159 {
160 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
161 std::auto_ptr< vos::OGuard > pMutexGuard;
162 if (mpMutex)
163 pMutexGuard.reset( new vos::OGuard(mpMutex) );
164
165 PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
166
167 if( aIter == mpInfo->maMap.end())
168 throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
169
170 Any aAny;
171 if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
172 {
173 _preGetValues();
174 _getSingleValue( *((*aIter).second->mpInfo), aAny );
175 _postGetValues();
176 }
177 else
178 {
179 ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
180
181 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
182 std::auto_ptr< vos::OGuard > pMutexGuard2;
183 if (pSlave->mpMutex)
184 pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
185
186 pSlave->_preGetValues();
187 pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny );
188 pSlave->_postGetValues();
189 }
190 return aAny;
191 }
192
addPropertyChangeListener(const::rtl::OUString &,const Reference<XPropertyChangeListener> &)193 void SAL_CALL MasterPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
194 {
195 // todo
196 }
197
removePropertyChangeListener(const::rtl::OUString &,const Reference<XPropertyChangeListener> &)198 void SAL_CALL MasterPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
199 {
200 // todo
201 }
202
addVetoableChangeListener(const::rtl::OUString &,const Reference<XVetoableChangeListener> &)203 void SAL_CALL MasterPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
204 {
205 // todo
206 }
207
removeVetoableChangeListener(const::rtl::OUString &,const Reference<XVetoableChangeListener> &)208 void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
209 {
210 // todo
211 }
212
213 // XMultiPropertySet
setPropertyValues(const Sequence<::rtl::OUString> & aPropertyNames,const Sequence<Any> & aValues)214 void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues )
215 {
216 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
217 std::auto_ptr< vos::OGuard > pMutexGuard;
218 if (mpMutex)
219 pMutexGuard.reset( new vos::OGuard(mpMutex) );
220
221 const sal_Int32 nCount = aPropertyNames.getLength();
222
223 if( nCount != aValues.getLength() )
224 throw IllegalArgumentException();
225
226 if( nCount )
227 {
228 _preSetValues();
229
230 const Any * pAny = aValues.getConstArray();
231 const OUString * pString = aPropertyNames.getConstArray();
232 PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
233
234 //!! have an auto_ptr to an array of OGuards in order to have the
235 //!! allocated memory properly freed (exception safe!).
236 //!! Since the array itself has auto_ptrs as members we have to use a
237 //!! helper class 'AutoOGuardArray' in order to have
238 //!! the acquired locks properly released.
239 AutoOGuardArray aOGuardArray( nCount );
240
241 for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
242 {
243 aIter = mpInfo->maMap.find ( *pString );
244 if ( aIter == aEnd )
245 throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
246
247 if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
248 _setSingleValue( *((*aIter).second->mpInfo), *pAny );
249 else
250 {
251 SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
252 if (!pSlave->IsInit())
253 {
254 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
255 if (pSlave->mpSlave->mpMutex)
256 aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
257
258 pSlave->mpSlave->_preSetValues();
259 pSlave->SetInit ( sal_True );
260 }
261 pSlave->mpSlave->_setSingleValue( *((*aIter).second->mpInfo), *pAny );
262 }
263 }
264
265 _postSetValues();
266 SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
267 while (aSlaveIter != aSlaveEnd)
268 {
269 if ( (*aSlaveIter).second->IsInit())
270 {
271 (*aSlaveIter).second->mpSlave->_postSetValues();
272 (*aSlaveIter).second->SetInit ( sal_False );
273 }
274 ++aSlaveIter;
275 }
276 }
277 }
278
getPropertyValues(const Sequence<::rtl::OUString> & aPropertyNames)279 Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames )
280 {
281 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
282 std::auto_ptr< vos::OGuard > pMutexGuard;
283 if (mpMutex)
284 pMutexGuard.reset( new vos::OGuard(mpMutex) );
285
286 const sal_Int32 nCount = aPropertyNames.getLength();
287
288 Sequence < Any > aValues ( nCount );
289
290 if( nCount )
291 {
292 _preGetValues();
293
294 Any * pAny = aValues.getArray();
295 const OUString * pString = aPropertyNames.getConstArray();
296 PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
297
298 //!! have an auto_ptr to an array of OGuards in order to have the
299 //!! allocated memory properly freed (exception safe!).
300 //!! Since the array itself has auto_ptrs as members we have to use a
301 //!! helper class 'AutoOGuardArray' in order to have
302 //!! the acquired locks properly released.
303 AutoOGuardArray aOGuardArray( nCount );
304
305 for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
306 {
307 aIter = mpInfo->maMap.find ( *pString );
308 if ( aIter == aEnd )
309 throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
310
311 if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
312 _getSingleValue( *((*aIter).second->mpInfo), *pAny );
313 else
314 {
315 SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
316 if (!pSlave->IsInit())
317 {
318 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
319 if (pSlave->mpSlave->mpMutex)
320 aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
321
322 pSlave->mpSlave->_preGetValues();
323 pSlave->SetInit ( sal_True );
324 }
325 pSlave->mpSlave->_getSingleValue( *((*aIter).second->mpInfo), *pAny );
326 }
327 }
328
329 _postSetValues();
330 SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
331 while (aSlaveIter != aSlaveEnd)
332 {
333 if ( (*aSlaveIter).second->IsInit())
334 {
335 (*aSlaveIter).second->mpSlave->_postSetValues();
336 (*aSlaveIter).second->SetInit ( sal_False );
337 }
338 ++aSlaveIter;
339 }
340 }
341 return aValues;
342 }
343
addPropertiesChangeListener(const Sequence<::rtl::OUString> &,const Reference<XPropertiesChangeListener> &)344 void SAL_CALL MasterPropertySet::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
345 {
346 // todo
347 }
348
removePropertiesChangeListener(const Reference<XPropertiesChangeListener> &)349 void SAL_CALL MasterPropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& )
350 {
351 // todo
352 }
353
firePropertiesChangeEvent(const Sequence<::rtl::OUString> &,const Reference<XPropertiesChangeListener> &)354 void SAL_CALL MasterPropertySet::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
355 {
356 // todo
357 }
358
359 // XPropertyState
getPropertyState(const::rtl::OUString & PropertyName)360 PropertyState SAL_CALL MasterPropertySet::getPropertyState( const ::rtl::OUString& PropertyName )
361 {
362 PropertyDataHash::const_iterator aIter = mpInfo->maMap.find( PropertyName );
363 if( aIter == mpInfo->maMap.end())
364 throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
365
366 PropertyState aState;
367
368 if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
369 {
370 _preGetPropertyState();
371 _getPropertyState( *((*aIter).second->mpInfo), aState );
372 _postGetPropertyState();
373 }
374 else
375 {
376 ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
377
378 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
379 std::auto_ptr< vos::OGuard > pMutexGuard;
380 if (pSlave->mpMutex)
381 pMutexGuard.reset( new vos::OGuard(pSlave->mpMutex) );
382
383 pSlave->_preGetPropertyState();
384 pSlave->_getPropertyState( *((*aIter).second->mpInfo), aState );
385 pSlave->_postGetPropertyState();
386 }
387
388 return aState;
389 }
390
getPropertyStates(const Sequence<::rtl::OUString> & rPropertyNames)391 Sequence< PropertyState > SAL_CALL MasterPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& rPropertyNames )
392 {
393 const sal_Int32 nCount = rPropertyNames.getLength();
394
395 Sequence< PropertyState > aStates( nCount );
396 if( nCount )
397 {
398 PropertyState * pState = aStates.getArray();
399 const OUString * pString = rPropertyNames.getConstArray();
400 PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
401 _preGetPropertyState();
402
403 for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pState )
404 {
405 aIter = mpInfo->maMap.find ( *pString );
406 if ( aIter == aEnd )
407 throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
408
409 if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
410 _getPropertyState( *((*aIter).second->mpInfo), *pState );
411 else
412 {
413 SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
414 if (!pSlave->IsInit())
415 {
416 pSlave->mpSlave->_preGetPropertyState();
417 pSlave->SetInit ( sal_True );
418 }
419 pSlave->mpSlave->_getPropertyState( *((*aIter).second->mpInfo), *pState );
420 }
421 }
422 _postGetPropertyState();
423 SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
424 while (aSlaveIter != aSlaveEnd)
425 {
426 if ( (*aSlaveIter).second->IsInit())
427 {
428 (*aSlaveIter).second->mpSlave->_postGetPropertyState();
429 (*aSlaveIter).second->SetInit ( sal_False );
430 }
431 ++aSlaveIter;
432 }
433 }
434 return aStates;
435 }
436
setPropertyToDefault(const::rtl::OUString & rPropertyName)437 void SAL_CALL MasterPropertySet::setPropertyToDefault( const ::rtl::OUString& rPropertyName )
438 {
439 PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
440
441 if( aIter == mpInfo->maMap.end())
442 throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
443 _setPropertyToDefault( *((*aIter).second->mpInfo) );
444 }
445
getPropertyDefault(const::rtl::OUString & rPropertyName)446 Any SAL_CALL MasterPropertySet::getPropertyDefault( const ::rtl::OUString& rPropertyName )
447 {
448 PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
449
450 if( aIter == mpInfo->maMap.end())
451 throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
452 return _getPropertyDefault( *((*aIter).second->mpInfo) );
453 }
454
_preGetPropertyState()455 void MasterPropertySet::_preGetPropertyState ()
456 {
457 OSL_ENSURE( sal_False, "you have to implement this yourself!");
458 }
459
_getPropertyState(const comphelper::PropertyInfo &,PropertyState &)460 void MasterPropertySet::_getPropertyState( const comphelper::PropertyInfo&, PropertyState& )
461 {
462 OSL_ENSURE( sal_False, "you have to implement this yourself!");
463 }
464
_postGetPropertyState()465 void MasterPropertySet::_postGetPropertyState ()
466 {
467 OSL_ENSURE( sal_False, "you have to implement this yourself!");
468 }
469
_setPropertyToDefault(const comphelper::PropertyInfo &)470 void MasterPropertySet::_setPropertyToDefault( const comphelper::PropertyInfo& )
471 {
472 OSL_ENSURE( sal_False, "you have to implement this yourself!");
473 }
474
_getPropertyDefault(const comphelper::PropertyInfo &)475 Any MasterPropertySet::_getPropertyDefault( const comphelper::PropertyInfo& )
476 {
477 OSL_ENSURE( sal_False, "you have to implement this yourself!");
478 Any aAny;
479 return aAny;
480 }
481