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_framework.hxx" 26 27 //_________________________________________________________________________________________________________________ 28 // my own includes 29 30 #include <classes/propertysethelper.hxx> 31 #include <threadhelp/transactionguard.hxx> 32 #include <threadhelp/readguard.hxx> 33 #include <threadhelp/writeguard.hxx> 34 35 //_________________________________________________________________________________________________________________ 36 // interface includes 37 38 //_________________________________________________________________________________________________________________ 39 // other includes 40 41 //_________________________________________________________________________________________________________________ 42 // namespace 43 44 namespace framework{ 45 46 //_________________________________________________________________________________________________________________ 47 // non exported definitions 48 49 //----------------------------------------------------------------------------- 50 PropertySetHelper::PropertySetHelper(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , 51 LockHelper* pExternalLock , 52 TransactionManager* pExternalTransactionManager , 53 sal_Bool bReleaseLockOnCall ) 54 : m_xSMGR (xSMGR ) 55 , m_lSimpleChangeListener(pExternalLock->getShareableOslMutex()) 56 , m_lVetoChangeListener (pExternalLock->getShareableOslMutex()) 57 , m_bReleaseLockOnCall (bReleaseLockOnCall ) 58 , m_rLock (*pExternalLock ) 59 , m_rTransactionManager (*pExternalTransactionManager ) 60 { 61 } 62 63 //----------------------------------------------------------------------------- 64 PropertySetHelper::~PropertySetHelper() 65 { 66 } 67 68 //----------------------------------------------------------------------------- 69 void PropertySetHelper::impl_setPropertyChangeBroadcaster(const css::uno::Reference< css::uno::XInterface >& xBroadcaster) 70 { 71 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS); 72 73 // SAFE -> 74 WriteGuard aWriteLock(m_rLock); 75 m_xBroadcaster = xBroadcaster; 76 aWriteLock.unlock(); 77 // <- SAFE 78 } 79 80 //----------------------------------------------------------------------------- 81 void SAL_CALL PropertySetHelper::impl_addPropertyInfo(const css::beans::Property& aProperty) 82 throw(css::beans::PropertyExistException, 83 css::uno::Exception ) 84 { 85 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS); 86 87 // SAFE -> 88 WriteGuard aWriteLock(m_rLock); 89 90 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(aProperty.Name); 91 if (pIt != m_lProps.end()) 92 throw css::beans::PropertyExistException(); 93 94 m_lProps[aProperty.Name] = aProperty; 95 // <- SAFE 96 } 97 98 //----------------------------------------------------------------------------- 99 void SAL_CALL PropertySetHelper::impl_removePropertyInfo(const ::rtl::OUString& sProperty) 100 throw(css::beans::UnknownPropertyException, 101 css::uno::Exception ) 102 { 103 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS); 104 105 // SAFE -> 106 WriteGuard aWriteLock(m_rLock); 107 108 PropertySetHelper::TPropInfoHash::iterator pIt = m_lProps.find(sProperty); 109 if (pIt == m_lProps.end()) 110 throw css::beans::UnknownPropertyException(); 111 112 m_lProps.erase(pIt); 113 // <- SAFE 114 } 115 116 //----------------------------------------------------------------------------- 117 void SAL_CALL PropertySetHelper::impl_enablePropertySet() 118 { 119 } 120 121 //----------------------------------------------------------------------------- 122 void SAL_CALL PropertySetHelper::impl_disablePropertySet() 123 { 124 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS); 125 126 // SAFE -> 127 WriteGuard aWriteLock(m_rLock); 128 129 css::uno::Reference< css::uno::XInterface > xThis(static_cast< css::beans::XPropertySet* >(this), css::uno::UNO_QUERY); 130 css::lang::EventObject aEvent(xThis); 131 132 m_lSimpleChangeListener.disposeAndClear(aEvent); 133 m_lVetoChangeListener.disposeAndClear(aEvent); 134 m_lProps.free(); 135 136 aWriteLock.unlock(); 137 // <- SAFE 138 } 139 140 //----------------------------------------------------------------------------- 141 sal_Bool PropertySetHelper::impl_existsVeto(const css::beans::PropertyChangeEvent& aEvent) 142 { 143 /* Dont use the lock here! 144 The used helper is threadsafe and it lives for the whole lifetime of 145 our own object. 146 */ 147 ::cppu::OInterfaceContainerHelper* pVetoListener = m_lVetoChangeListener.getContainer(aEvent.PropertyName); 148 if (! pVetoListener) 149 return sal_False; 150 151 ::cppu::OInterfaceIteratorHelper pListener(*pVetoListener); 152 while (pListener.hasMoreElements()) 153 { 154 try 155 { 156 css::uno::Reference< css::beans::XVetoableChangeListener > xListener( 157 ((css::beans::XVetoableChangeListener*)pListener.next()), 158 css::uno::UNO_QUERY_THROW); 159 xListener->vetoableChange(aEvent); 160 } 161 catch(const css::uno::RuntimeException&) 162 { pListener.remove(); } 163 catch(const css::beans::PropertyVetoException&) 164 { return sal_True; } 165 } 166 167 return sal_False; 168 } 169 170 //----------------------------------------------------------------------------- 171 void PropertySetHelper::impl_notifyChangeListener(const css::beans::PropertyChangeEvent& aEvent) 172 { 173 /* Dont use the lock here! 174 The used helper is threadsafe and it lives for the whole lifetime of 175 our own object. 176 */ 177 ::cppu::OInterfaceContainerHelper* pSimpleListener = m_lSimpleChangeListener.getContainer(aEvent.PropertyName); 178 if (! pSimpleListener) 179 return; 180 181 ::cppu::OInterfaceIteratorHelper pListener(*pSimpleListener); 182 while (pListener.hasMoreElements()) 183 { 184 try 185 { 186 css::uno::Reference< css::beans::XPropertyChangeListener > xListener( 187 ((css::beans::XVetoableChangeListener*)pListener.next()), 188 css::uno::UNO_QUERY_THROW); 189 xListener->propertyChange(aEvent); 190 } 191 catch(const css::uno::RuntimeException&) 192 { pListener.remove(); } 193 } 194 } 195 196 //----------------------------------------------------------------------------- 197 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo() 198 throw(css::uno::RuntimeException) 199 { 200 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 201 202 css::uno::Reference< css::beans::XPropertySetInfo > xInfo(static_cast< css::beans::XPropertySetInfo* >(this), css::uno::UNO_QUERY_THROW); 203 return xInfo; 204 } 205 206 //----------------------------------------------------------------------------- 207 void SAL_CALL PropertySetHelper::setPropertyValue(const ::rtl::OUString& sProperty, 208 const css::uno::Any& aValue ) 209 throw(css::beans::UnknownPropertyException, 210 css::beans::PropertyVetoException , 211 css::lang::IllegalArgumentException , 212 css::lang::WrappedTargetException , 213 css::uno::RuntimeException ) 214 { 215 // TODO look for e.g. readonly props and reject setProp() call! 216 217 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 218 219 // SAFE -> 220 WriteGuard aWriteLock(m_rLock); 221 222 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty); 223 if (pIt == m_lProps.end()) 224 throw css::beans::UnknownPropertyException(); 225 226 css::beans::Property aPropInfo = pIt->second; 227 228 sal_Bool bLocked = sal_True; 229 if (m_bReleaseLockOnCall) 230 { 231 aWriteLock.unlock(); 232 bLocked = sal_False; 233 // <- SAFE 234 } 235 236 css::uno::Any aCurrentValue = impl_getPropertyValue(aPropInfo.Name, aPropInfo.Handle); 237 238 if (! bLocked) 239 { 240 // SAFE -> 241 aWriteLock.lock(); 242 bLocked = sal_True; 243 } 244 245 sal_Bool bWillBeChanged = (aCurrentValue != aValue); 246 if (! bWillBeChanged) 247 return; 248 249 css::beans::PropertyChangeEvent aEvent; 250 aEvent.PropertyName = aPropInfo.Name; 251 aEvent.Further = sal_False; 252 aEvent.PropertyHandle = aPropInfo.Handle; 253 aEvent.OldValue = aCurrentValue; 254 aEvent.NewValue = aValue; 255 aEvent.Source = css::uno::Reference< css::uno::XInterface >(m_xBroadcaster.get(), css::uno::UNO_QUERY); 256 257 if (m_bReleaseLockOnCall) 258 { 259 aWriteLock.unlock(); 260 bLocked = sal_False; 261 // <- SAFE 262 } 263 264 if (impl_existsVeto(aEvent)) 265 throw css::beans::PropertyVetoException(); 266 267 impl_setPropertyValue(aPropInfo.Name, aPropInfo.Handle, aValue); 268 269 impl_notifyChangeListener(aEvent); 270 } 271 272 //----------------------------------------------------------------------------- 273 css::uno::Any SAL_CALL PropertySetHelper::getPropertyValue(const ::rtl::OUString& sProperty) 274 throw(css::beans::UnknownPropertyException, 275 css::lang::WrappedTargetException , 276 css::uno::RuntimeException ) 277 { 278 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 279 280 // SAFE -> 281 ReadGuard aReadLock(m_rLock); 282 283 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty); 284 if (pIt == m_lProps.end()) 285 throw css::beans::UnknownPropertyException(); 286 287 css::beans::Property aPropInfo = pIt->second; 288 289 sal_Bool bLocked = sal_True; 290 if (m_bReleaseLockOnCall) 291 { 292 aReadLock.unlock(); 293 bLocked = sal_False; 294 // <- SAFE 295 } 296 297 return impl_getPropertyValue(aPropInfo.Name, aPropInfo.Handle); 298 } 299 300 //----------------------------------------------------------------------------- 301 void SAL_CALL PropertySetHelper::addPropertyChangeListener(const ::rtl::OUString& sProperty, 302 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener) 303 throw(css::beans::UnknownPropertyException, 304 css::lang::WrappedTargetException , 305 css::uno::RuntimeException ) 306 { 307 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 308 309 // SAFE -> 310 ReadGuard aReadLock(m_rLock); 311 312 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty); 313 if (pIt == m_lProps.end()) 314 throw css::beans::UnknownPropertyException(); 315 316 aReadLock.unlock(); 317 // <- SAFE 318 319 m_lSimpleChangeListener.addInterface(sProperty, xListener); 320 } 321 322 //----------------------------------------------------------------------------- 323 void SAL_CALL PropertySetHelper::removePropertyChangeListener(const ::rtl::OUString& sProperty, 324 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener) 325 throw(css::beans::UnknownPropertyException, 326 css::lang::WrappedTargetException , 327 css::uno::RuntimeException ) 328 { 329 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS); 330 331 // SAFE -> 332 ReadGuard aReadLock(m_rLock); 333 334 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty); 335 if (pIt == m_lProps.end()) 336 throw css::beans::UnknownPropertyException(); 337 338 aReadLock.unlock(); 339 // <- SAFE 340 341 m_lSimpleChangeListener.removeInterface(sProperty, xListener); 342 } 343 344 //----------------------------------------------------------------------------- 345 void SAL_CALL PropertySetHelper::addVetoableChangeListener(const ::rtl::OUString& sProperty, 346 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener) 347 throw(css::beans::UnknownPropertyException, 348 css::lang::WrappedTargetException , 349 css::uno::RuntimeException ) 350 { 351 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 352 353 // SAFE -> 354 ReadGuard aReadLock(m_rLock); 355 356 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty); 357 if (pIt == m_lProps.end()) 358 throw css::beans::UnknownPropertyException(); 359 360 aReadLock.unlock(); 361 // <- SAFE 362 363 m_lVetoChangeListener.addInterface(sProperty, xListener); 364 } 365 366 //----------------------------------------------------------------------------- 367 void SAL_CALL PropertySetHelper::removeVetoableChangeListener(const ::rtl::OUString& sProperty, 368 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener) 369 throw(css::beans::UnknownPropertyException, 370 css::lang::WrappedTargetException , 371 css::uno::RuntimeException ) 372 { 373 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS); 374 375 // SAFE -> 376 ReadGuard aReadLock(m_rLock); 377 378 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty); 379 if (pIt == m_lProps.end()) 380 throw css::beans::UnknownPropertyException(); 381 382 aReadLock.unlock(); 383 // <- SAFE 384 385 m_lVetoChangeListener.removeInterface(sProperty, xListener); 386 } 387 388 //----------------------------------------------------------------------------- 389 css::uno::Sequence< css::beans::Property > SAL_CALL PropertySetHelper::getProperties() 390 throw(css::uno::RuntimeException) 391 { 392 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 393 394 // SAFE -> 395 ReadGuard aReadLock(m_rLock); 396 397 sal_Int32 c = (sal_Int32)m_lProps.size(); 398 css::uno::Sequence< css::beans::Property > lProps(c); 399 PropertySetHelper::TPropInfoHash::const_iterator pIt ; 400 401 for ( pIt = m_lProps.begin(); 402 pIt != m_lProps.end() ; 403 ++pIt ) 404 { 405 lProps[--c] = pIt->second; 406 } 407 408 return lProps; 409 // <- SAFE 410 } 411 412 //----------------------------------------------------------------------------- 413 css::beans::Property SAL_CALL PropertySetHelper::getPropertyByName(const ::rtl::OUString& sName) 414 throw(css::beans::UnknownPropertyException, 415 css::uno::RuntimeException ) 416 { 417 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 418 419 // SAFE -> 420 ReadGuard aReadLock(m_rLock); 421 422 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sName); 423 if (pIt == m_lProps.end()) 424 throw css::beans::UnknownPropertyException(); 425 426 return pIt->second; 427 // <- SAFE 428 } 429 430 //----------------------------------------------------------------------------- 431 sal_Bool SAL_CALL PropertySetHelper::hasPropertyByName(const ::rtl::OUString& sName) 432 throw(css::uno::RuntimeException) 433 { 434 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS); 435 436 // SAFE -> 437 ReadGuard aReadLock(m_rLock); 438 439 PropertySetHelper::TPropInfoHash::iterator pIt = m_lProps.find(sName); 440 sal_Bool bExist = (pIt != m_lProps.end()); 441 442 return bExist; 443 // <- SAFE 444 } 445 446 } // namespace framework 447