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 { 115 return mxInfo; 116 } 117 118 void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) 119 throw() 120 { 121 maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet ); 122 mpInfo->add ( pNewSet->mpInfo->maMap, mnLastId ); 123 } 124 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 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 193 void SAL_CALL MasterPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) 194 { 195 // todo 196 } 197 198 void SAL_CALL MasterPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) 199 { 200 // todo 201 } 202 203 void SAL_CALL MasterPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) 204 { 205 // todo 206 } 207 208 void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) 209 { 210 // todo 211 } 212 213 // XMultiPropertySet 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 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 344 void SAL_CALL MasterPropertySet::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) 345 { 346 // todo 347 } 348 349 void SAL_CALL MasterPropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& ) 350 { 351 // todo 352 } 353 354 void SAL_CALL MasterPropertySet::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) 355 { 356 // todo 357 } 358 359 // XPropertyState 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 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 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 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 455 void MasterPropertySet::_preGetPropertyState () 456 { 457 OSL_ENSURE( sal_False, "you have to implement this yourself!"); 458 } 459 460 void MasterPropertySet::_getPropertyState( const comphelper::PropertyInfo&, PropertyState& ) 461 { 462 OSL_ENSURE( sal_False, "you have to implement this yourself!"); 463 } 464 465 void MasterPropertySet::_postGetPropertyState () 466 { 467 OSL_ENSURE( sal_False, "you have to implement this yourself!"); 468 } 469 470 void MasterPropertySet::_setPropertyToDefault( const comphelper::PropertyInfo& ) 471 { 472 OSL_ENSURE( sal_False, "you have to implement this yourself!"); 473 } 474 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