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