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