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