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 48 std::auto_ptr< vos::OGuard > & operator[] ( sal_Int32 i ) { return pGuardArray[i]; } 49 }; 50 51 AutoOGuardArray::AutoOGuardArray( sal_Int32 nNumElements ) 52 { 53 nSize = nNumElements; 54 pGuardArray = new std::auto_ptr< vos::OGuard >[ nSize ]; 55 } 56 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 74 SlaveData::SlaveData ( ChainablePropertySet *pSlave) 75 : mpSlave ( pSlave ) 76 , mxSlave ( pSlave ) 77 , mbInit ( sal_False ) 78 { 79 } 80 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 90 void MasterPropertySet::lockMutex() 91 { 92 if (mpMutex) 93 mpMutex->acquire(); 94 } 95 void MasterPropertySet::unlockMutex() 96 { 97 if (mpMutex) 98 mpMutex->release(); 99 } 100 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 113 Reference< XPropertySetInfo > SAL_CALL MasterPropertySet::getPropertySetInfo( ) 114 throw(RuntimeException) 115 { 116 return mxInfo; 117 } 118 119 void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) 120 throw() 121 { 122 maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet ); 123 mpInfo->add ( pNewSet->mpInfo->maMap, mnLastId ); 124 } 125 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 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 196 void SAL_CALL MasterPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) 197 throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 198 { 199 // todo 200 } 201 202 void SAL_CALL MasterPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) 203 throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 204 { 205 // todo 206 } 207 208 void SAL_CALL MasterPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) 209 throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 210 { 211 // todo 212 } 213 214 void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) 215 throw(UnknownPropertyException, WrappedTargetException, RuntimeException) 216 { 217 // todo 218 } 219 220 // XMultiPropertySet 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 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 353 void SAL_CALL MasterPropertySet::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) 354 throw(RuntimeException) 355 { 356 // todo 357 } 358 359 void SAL_CALL MasterPropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& ) 360 throw(RuntimeException) 361 { 362 // todo 363 } 364 365 void SAL_CALL MasterPropertySet::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) 366 throw(RuntimeException) 367 { 368 // todo 369 } 370 371 // XPropertyState 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 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 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 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 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 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 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 489 void MasterPropertySet::_setPropertyToDefault( const comphelper::PropertyInfo& ) 490 throw(UnknownPropertyException ) 491 { 492 OSL_ENSURE( sal_False, "you have to implement this yourself!"); 493 } 494 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