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