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_cppuhelper.hxx" 30 31 #include "sal/config.h" 32 33 #include "cppuhelper/propertysetmixin.hxx" 34 35 #include "com/sun/star/beans/Property.hpp" 36 #include "com/sun/star/beans/PropertyChangeEvent.hpp" 37 #include "com/sun/star/beans/PropertyAttribute.hpp" 38 #include "com/sun/star/beans/PropertyValue.hpp" 39 #include "com/sun/star/beans/PropertyVetoException.hpp" 40 #include "com/sun/star/beans/UnknownPropertyException.hpp" 41 #include "com/sun/star/beans/XFastPropertySet.hpp" 42 #include "com/sun/star/beans/XPropertyAccess.hpp" 43 #include "com/sun/star/beans/XPropertyChangeListener.hpp" 44 #include "com/sun/star/beans/XPropertySet.hpp" 45 #include "com/sun/star/beans/XPropertySetInfo.hpp" 46 #include "com/sun/star/beans/XVetoableChangeListener.hpp" 47 #include "com/sun/star/container/NoSuchElementException.hpp" 48 #include "com/sun/star/container/XHierarchicalNameAccess.hpp" 49 #include "com/sun/star/lang/DisposedException.hpp" 50 #include "com/sun/star/lang/EventObject.hpp" 51 #include "com/sun/star/lang/IllegalAccessException.hpp" 52 #include "com/sun/star/lang/IllegalArgumentException.hpp" 53 #include "com/sun/star/lang/WrappedTargetException.hpp" 54 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" 55 #include "com/sun/star/lang/XComponent.hpp" 56 #include "com/sun/star/lang/XMultiComponentFactory.hpp" 57 #include "com/sun/star/reflection/XCompoundTypeDescription.hpp" 58 #include "com/sun/star/reflection/XIdlClass.hpp" 59 #include "com/sun/star/reflection/XIdlField2.hpp" 60 #include "com/sun/star/reflection/XIdlReflection.hpp" 61 #include "com/sun/star/reflection/XIndirectTypeDescription.hpp" 62 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" 63 #include "com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp" 64 #include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" 65 #include "com/sun/star/reflection/XStructTypeDescription.hpp" 66 #include "com/sun/star/reflection/XTypeDescription.hpp" 67 #include "com/sun/star/uno/Any.hxx" 68 #include "com/sun/star/uno/DeploymentException.hpp" 69 #include "com/sun/star/uno/Exception.hpp" 70 #include "com/sun/star/uno/Reference.hxx" 71 #include "com/sun/star/uno/RuntimeException.hpp" 72 #include "com/sun/star/uno/Sequence.hxx" 73 #include "com/sun/star/uno/Type.hxx" 74 #include "com/sun/star/uno/TypeClass.hpp" 75 #include "com/sun/star/uno/XComponentContext.hpp" 76 #include "com/sun/star/uno/XInterface.hpp" 77 #include "cppuhelper/implbase1.hxx" 78 #include "cppuhelper/weak.hxx" 79 #include "osl/diagnose.h" 80 #include "osl/mutex.hxx" 81 #include "rtl/ref.hxx" 82 #include "rtl/string.h" 83 #include "rtl/ustring.h" 84 #include "rtl/ustring.hxx" 85 #include "sal/types.h" 86 #include "salhelper/simplereferenceobject.hxx" 87 88 #include <algorithm> 89 #include <map> 90 #include <new> 91 #include <set> 92 #include <vector> 93 94 using cppu::PropertySetMixinImpl; 95 96 namespace css = com::sun::star; 97 98 namespace { 99 100 template< typename T > struct AutoDispose { 101 AutoDispose() {} 102 103 ~AutoDispose() { 104 try { 105 dispose(); 106 } catch (...) {} 107 } 108 109 void dispose() { 110 css::uno::Reference< css::lang::XComponent > comp( 111 ifc, css::uno::UNO_QUERY); 112 if (comp.is()) { 113 comp->dispose(); 114 } 115 ifc.clear(); 116 } 117 118 css::uno::Reference< T > ifc; 119 120 private: 121 AutoDispose(AutoDispose &); // not defined 122 void operator =(AutoDispose); // not defined 123 }; 124 125 struct PropertyData { 126 explicit PropertyData( 127 css::beans::Property const & theProperty, bool thePresent): 128 property(theProperty), present(thePresent) {} 129 130 css::beans::Property property; 131 bool present; 132 }; 133 134 struct Data: public salhelper::SimpleReferenceObject { 135 typedef std::map< rtl::OUString, PropertyData > PropertyMap; 136 137 PropertyMap properties; 138 139 PropertyMap::const_iterator get( 140 css::uno::Reference< css::uno::XInterface > const & object, 141 rtl::OUString const & name) const; 142 143 protected: 144 void initProperties( 145 css::uno::Reference< css::reflection::XTypeDescription > const & type, 146 css::uno::Sequence< rtl::OUString > const & absentOptional, 147 std::vector< rtl::OUString > * handleNames) 148 { 149 TypeSet seen; 150 initProperties(type, absentOptional, handleNames, &seen); 151 } 152 153 private: 154 typedef std::set< rtl::OUString > TypeSet; 155 156 void initProperties( 157 css::uno::Reference< css::reflection::XTypeDescription > const & type, 158 css::uno::Sequence< rtl::OUString > const & absentOptional, 159 std::vector< rtl::OUString > * handleNames, TypeSet * seen); 160 161 static css::uno::Reference< css::reflection::XTypeDescription > 162 resolveTypedefs( 163 css::uno::Reference< css::reflection::XTypeDescription > const & type); 164 }; 165 166 Data::PropertyMap::const_iterator Data::get( 167 css::uno::Reference< css::uno::XInterface > const & object, 168 rtl::OUString const & name) const 169 { 170 PropertyMap::const_iterator i(properties.find(name)); 171 if (i == properties.end() || !i->second.present) { 172 throw css::beans::UnknownPropertyException(name, object); 173 } 174 return i; 175 } 176 177 void Data::initProperties( 178 css::uno::Reference< css::reflection::XTypeDescription > const & type, 179 css::uno::Sequence< rtl::OUString > const & absentOptional, 180 std::vector< rtl::OUString > * handleNames, TypeSet * seen) 181 { 182 css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > ifc( 183 resolveTypedefs(type), css::uno::UNO_QUERY_THROW); 184 if (seen->insert(ifc->getName()).second) { 185 css::uno::Sequence< 186 css::uno::Reference< css::reflection::XTypeDescription > > bases( 187 ifc->getBaseTypes()); 188 for (sal_Int32 i = 0; i < bases.getLength(); ++i) { 189 initProperties(bases[i], absentOptional, handleNames, seen); 190 } 191 css::uno::Sequence< 192 css::uno::Reference< 193 css::reflection::XInterfaceMemberTypeDescription > > members( 194 ifc->getMembers()); 195 rtl::OUString const * absentBegin = absentOptional.getConstArray(); 196 rtl::OUString const * absentEnd = 197 absentBegin + absentOptional.getLength(); 198 for (sal_Int32 i = 0; i < members.getLength(); ++i) { 199 if (members[i]->getTypeClass() 200 == css::uno::TypeClass_INTERFACE_ATTRIBUTE) 201 { 202 css::uno::Reference< 203 css::reflection::XInterfaceAttributeTypeDescription2 > attr( 204 members[i], css::uno::UNO_QUERY_THROW); 205 sal_Int16 attrAttribs = 0; 206 if (attr->isBound()) { 207 attrAttribs |= css::beans::PropertyAttribute::BOUND; 208 } 209 bool setUnknown = false; 210 if (attr->isReadOnly()) { 211 attrAttribs |= css::beans::PropertyAttribute::READONLY; 212 setUnknown = true; 213 } 214 css::uno::Sequence< 215 css::uno::Reference< 216 css::reflection::XCompoundTypeDescription > > excs( 217 attr->getGetExceptions()); 218 bool getUnknown = false; 219 //XXX Special interpretation of getter/setter exceptions only 220 // works if the specified exceptions are of the exact type, not 221 // of a supertype: 222 for (sal_Int32 j = 0; j < excs.getLength(); ++j) { 223 if (excs[j]->getName().equalsAsciiL( 224 RTL_CONSTASCII_STRINGPARAM( 225 "com.sun.star.beans.UnknownPropertyException"))) 226 { 227 getUnknown = true; 228 break; 229 } 230 } 231 excs = attr->getSetExceptions(); 232 for (sal_Int32 j = 0; j < excs.getLength(); ++j) { 233 if (excs[j]->getName().equalsAsciiL( 234 RTL_CONSTASCII_STRINGPARAM( 235 "com.sun.star.beans.UnknownPropertyException"))) 236 { 237 setUnknown = true; 238 } else if (excs[j]->getName().equalsAsciiL( 239 RTL_CONSTASCII_STRINGPARAM( 240 "com.sun.star.beans." 241 "PropertyVetoException"))) 242 { 243 attrAttribs 244 |= css::beans::PropertyAttribute::CONSTRAINED; 245 } 246 } 247 if (getUnknown && setUnknown) { 248 attrAttribs |= css::beans::PropertyAttribute::OPTIONAL; 249 } 250 css::uno::Reference< css::reflection::XTypeDescription > t( 251 attr->getType()); 252 for (;;) 253 { 254 t = resolveTypedefs(t); 255 sal_Int16 n; 256 if (t->getName().matchAsciiL( 257 RTL_CONSTASCII_STRINGPARAM( 258 "com.sun.star.beans.Ambiguous<"))) 259 { 260 n = css::beans::PropertyAttribute::MAYBEAMBIGUOUS; 261 } else if (t->getName().matchAsciiL( 262 RTL_CONSTASCII_STRINGPARAM( 263 "com.sun.star.beans.Defaulted<"))) 264 { 265 n = css::beans::PropertyAttribute::MAYBEDEFAULT; 266 } else if (t->getName().matchAsciiL( 267 RTL_CONSTASCII_STRINGPARAM( 268 "com.sun.star.beans.Optional<"))) 269 { 270 n = css::beans::PropertyAttribute::MAYBEVOID; 271 } else { 272 break; 273 } 274 if ((attrAttribs & n) != 0) { 275 break; 276 } 277 attrAttribs |= n; 278 css::uno::Sequence< 279 css::uno::Reference< css::reflection::XTypeDescription > > 280 args( 281 css::uno::Reference< 282 css::reflection::XStructTypeDescription >( 283 t, 284 css::uno::UNO_QUERY_THROW)->getTypeArguments()); 285 if (args.getLength() != 1) { 286 throw css::uno::RuntimeException( 287 rtl::OUString( 288 RTL_CONSTASCII_USTRINGPARAM( 289 "inconsistent UNO type registry")), 290 css::uno::Reference< css::uno::XInterface >()); 291 } 292 t = args[0]; 293 } 294 std::vector< rtl::OUString >::size_type handles 295 = handleNames->size(); 296 if (handles > SAL_MAX_INT32) { 297 throw css::uno::RuntimeException( 298 rtl::OUString( 299 RTL_CONSTASCII_USTRINGPARAM( 300 "interface type has too many attributes")), 301 css::uno::Reference< css::uno::XInterface >()); 302 } 303 rtl::OUString name(members[i]->getMemberName()); 304 if (!properties.insert( 305 PropertyMap::value_type( 306 name, 307 PropertyData( 308 css::beans::Property( 309 name, static_cast< sal_Int32 >(handles), 310 css::uno::Type( 311 t->getTypeClass(), t->getName()), 312 attrAttribs), 313 (std::find(absentBegin, absentEnd, name) 314 == absentEnd)))). 315 second) 316 { 317 throw css::uno::RuntimeException( 318 rtl::OUString( 319 RTL_CONSTASCII_USTRINGPARAM( 320 "inconsistent UNO type registry")), 321 css::uno::Reference< css::uno::XInterface >()); 322 } 323 handleNames->push_back(name); 324 } 325 } 326 } 327 } 328 329 css::uno::Reference< css::reflection::XTypeDescription > Data::resolveTypedefs( 330 css::uno::Reference< css::reflection::XTypeDescription > const & type) 331 { 332 css::uno::Reference< css::reflection::XTypeDescription > t(type); 333 while (t->getTypeClass() == css::uno::TypeClass_TYPEDEF) { 334 t = css::uno::Reference< css::reflection::XIndirectTypeDescription >( 335 t, css::uno::UNO_QUERY_THROW)->getReferencedType(); 336 } 337 return t; 338 } 339 340 class Info: public cppu::WeakImplHelper1< css::beans::XPropertySetInfo > { 341 public: 342 explicit Info(Data * data): m_data(data) {} 343 344 virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() 345 throw (css::uno::RuntimeException); 346 347 virtual css::beans::Property SAL_CALL getPropertyByName( 348 rtl::OUString const & name) 349 throw ( 350 css::beans::UnknownPropertyException, css::uno::RuntimeException); 351 352 virtual sal_Bool SAL_CALL hasPropertyByName(rtl::OUString const & name) 353 throw (css::uno::RuntimeException); 354 355 private: 356 rtl::Reference< Data > m_data; 357 }; 358 359 css::uno::Sequence< css::beans::Property > Info::getProperties() 360 throw (css::uno::RuntimeException) 361 { 362 try { 363 OSL_ASSERT(m_data->properties.size() <= SAL_MAX_INT32); 364 css::uno::Sequence< css::beans::Property > s( 365 static_cast< sal_Int32 >(m_data->properties.size())); 366 sal_Int32 n = 0; 367 for (Data::PropertyMap::iterator i(m_data->properties.begin()); 368 i != m_data->properties.end(); ++i) 369 { 370 if (i->second.present) { 371 s[n++] = i->second.property; 372 } 373 } 374 s.realloc(n); 375 return s; 376 } catch (std::bad_alloc &) { 377 //TODO OutOfMemoryException: 378 throw css::uno::RuntimeException( 379 rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); 380 } 381 } 382 383 css::beans::Property Info::getPropertyByName(rtl::OUString const & name) 384 throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) 385 { 386 return m_data->get(static_cast< cppu::OWeakObject * >(this), name)-> 387 second.property; 388 } 389 390 sal_Bool Info::hasPropertyByName(rtl::OUString const & name) 391 throw (css::uno::RuntimeException) 392 { 393 Data::PropertyMap::iterator i(m_data->properties.find(name)); 394 return i != m_data->properties.end() && i->second.present; 395 } 396 397 typedef 398 std::multiset< css::uno::Reference< css::beans::XPropertyChangeListener > > 399 BoundListenerBag; 400 401 } 402 403 class PropertySetMixinImpl::BoundListeners::Impl { 404 public: 405 BoundListenerBag specificListeners; 406 BoundListenerBag unspecificListeners; 407 css::beans::PropertyChangeEvent event; 408 }; 409 410 PropertySetMixinImpl::BoundListeners::BoundListeners(): m_impl(new Impl) {} 411 412 PropertySetMixinImpl::BoundListeners::~BoundListeners() { 413 delete m_impl; 414 } 415 416 void PropertySetMixinImpl::BoundListeners::notify() const { 417 for (BoundListenerBag::const_iterator i(m_impl->specificListeners.begin()); 418 i != m_impl->specificListeners.end(); ++i) 419 { 420 try { 421 (*i)->propertyChange(m_impl->event); 422 } catch (css::lang::DisposedException &) {} 423 } 424 for (BoundListenerBag::const_iterator i( 425 m_impl->unspecificListeners.begin()); 426 i != m_impl->unspecificListeners.end(); ++i) 427 { 428 try { 429 (*i)->propertyChange(m_impl->event); 430 } catch (css::lang::DisposedException &) {} 431 } 432 } 433 434 class PropertySetMixinImpl::Impl: public Data { 435 public: 436 Impl( 437 css::uno::Reference< css::uno::XComponentContext > const & context, 438 Implements theImplements, 439 css::uno::Sequence< rtl::OUString > const & absentOptional, 440 css::uno::Type const & type); 441 442 rtl::OUString translateHandle( 443 css::uno::Reference< css::uno::XInterface > const & object, 444 sal_Int32 handle) const; 445 446 void setProperty( 447 css::uno::Reference< css::uno::XInterface > const & object, 448 rtl::OUString const & name, css::uno::Any const & value, 449 bool isAmbiguous, bool isDefaulted, sal_Int16 illegalArgumentPosition) 450 const; 451 452 css::uno::Any getProperty( 453 css::uno::Reference< css::uno::XInterface > const & object, 454 rtl::OUString const & name, css::beans::PropertyState * state) const; 455 456 PropertySetMixinImpl::Implements implements; 457 css::uno::Sequence< rtl::OUString > handleMap; 458 459 typedef std::map< rtl::OUString, BoundListenerBag > BoundListenerMap; 460 461 typedef 462 std::multiset< css::uno::Reference< css::beans::XVetoableChangeListener > > 463 VetoListenerBag; 464 465 typedef std::map< rtl::OUString, VetoListenerBag > VetoListenerMap; 466 467 mutable osl::Mutex mutex; 468 BoundListenerMap boundListeners; 469 VetoListenerMap vetoListeners; 470 bool disposed; 471 472 private: 473 css::uno::Reference< css::reflection::XIdlClass > getReflection( 474 rtl::OUString const & typeName) const; 475 476 static css::uno::Any wrapValue( 477 css::uno::Reference< css::uno::XInterface > const & object, 478 css::uno::Any const & value, 479 css::uno::Reference< css::reflection::XIdlClass > const & type, 480 bool wrapAmbiguous, bool isAmbiguous, bool wrapDefaulted, 481 bool isDefaulted, bool wrapOptional); 482 483 css::uno::Reference< css::uno::XComponentContext > const & m_context; 484 css::uno::Sequence< rtl::OUString > m_absentOptional; 485 css::uno::Type m_type; 486 css::uno::Reference< css::reflection::XIdlClass > m_idlClass; 487 }; 488 489 PropertySetMixinImpl::Impl::Impl( 490 css::uno::Reference< css::uno::XComponentContext > const & context, 491 Implements theImplements, 492 css::uno::Sequence< rtl::OUString > const & absentOptional, 493 css::uno::Type const & type): 494 implements(theImplements), disposed(false), m_context(context), 495 m_absentOptional(absentOptional), m_type(type) 496 { 497 OSL_ASSERT( 498 context.is() 499 && ((implements 500 & ~(IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET 501 | IMPLEMENTS_PROPERTY_ACCESS)) 502 == 0)); 503 m_idlClass = getReflection(m_type.getTypeName()); 504 css::uno::Reference< css::reflection::XTypeDescription > ifc; 505 try { 506 ifc = css::uno::Reference< css::reflection::XTypeDescription >( 507 css::uno::Reference< css::container::XHierarchicalNameAccess >( 508 m_context->getValueByName( 509 rtl::OUString( 510 RTL_CONSTASCII_USTRINGPARAM( 511 "/singletons/com.sun.star.reflection." 512 "theTypeDescriptionManager"))), 513 css::uno::UNO_QUERY_THROW)->getByHierarchicalName( 514 m_type.getTypeName()), 515 css::uno::UNO_QUERY_THROW); 516 } catch (css::container::NoSuchElementException & e) { 517 throw css::uno::RuntimeException( 518 (rtl::OUString( 519 RTL_CONSTASCII_USTRINGPARAM( 520 "unexpected" 521 " com.sun.star.container.NoSuchElementException: ")) 522 + e.Message), 523 css::uno::Reference< css::uno::XInterface >()); 524 } 525 std::vector< rtl::OUString > handleNames; 526 initProperties(ifc, m_absentOptional, &handleNames); 527 std::vector< rtl::OUString >::size_type size = handleNames.size(); 528 OSL_ASSERT(size <= SAL_MAX_INT32); 529 handleMap.realloc(static_cast< sal_Int32 >(size)); 530 std::copy(handleNames.begin(), handleNames.end(), handleMap.getArray()); 531 } 532 533 rtl::OUString PropertySetMixinImpl::Impl::translateHandle( 534 css::uno::Reference< css::uno::XInterface > const & object, 535 sal_Int32 handle) const 536 { 537 if (handle < 0 || handle >= handleMap.getLength()) { 538 throw css::beans::UnknownPropertyException( 539 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad handle ")) 540 + rtl::OUString::valueOf(handle)), 541 object); 542 } 543 return handleMap[handle]; 544 } 545 546 void PropertySetMixinImpl::Impl::setProperty( 547 css::uno::Reference< css::uno::XInterface > const & object, 548 rtl::OUString const & name, css::uno::Any const & value, bool isAmbiguous, 549 bool isDefaulted, sal_Int16 illegalArgumentPosition) const 550 { 551 PropertyMap::const_iterator i(properties.find(name)); 552 if (i == properties.end()) { 553 throw css::beans::UnknownPropertyException(name, object); 554 } 555 if ((isAmbiguous 556 && ((i->second.property.Attributes 557 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS) 558 == 0)) 559 || (isDefaulted 560 && ((i->second.property.Attributes 561 & css::beans::PropertyAttribute::MAYBEDEFAULT) 562 == 0))) 563 { 564 throw css::lang::IllegalArgumentException( 565 (rtl::OUString( 566 RTL_CONSTASCII_USTRINGPARAM( 567 "flagging as ambiguous/defaulted non-ambiguous/defaulted" 568 " property ")) 569 + name), 570 object, illegalArgumentPosition); 571 } 572 css::uno::Reference< css::reflection::XIdlField2 > f( 573 m_idlClass->getField(name), css::uno::UNO_QUERY_THROW); 574 css::uno::Any o(object->queryInterface(m_type)); 575 css::uno::Any v( 576 wrapValue( 577 object, value, 578 (css::uno::Reference< css::reflection::XIdlField2 >( 579 m_idlClass->getField(name), css::uno::UNO_QUERY_THROW)-> 580 getType()), 581 ((i->second.property.Attributes 582 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS) 583 != 0), 584 isAmbiguous, 585 ((i->second.property.Attributes 586 & css::beans::PropertyAttribute::MAYBEDEFAULT) 587 != 0), 588 isDefaulted, 589 ((i->second.property.Attributes 590 & css::beans::PropertyAttribute::MAYBEVOID) 591 != 0))); 592 try { 593 f->set(o, v); 594 } catch (css::lang::IllegalArgumentException & e) { 595 if (e.ArgumentPosition == 1) { 596 throw css::lang::IllegalArgumentException( 597 e.Message, object, illegalArgumentPosition); 598 } else { 599 throw css::uno::RuntimeException( 600 (rtl::OUString( 601 RTL_CONSTASCII_USTRINGPARAM( 602 "unexpected" 603 " com.sun.star.lang.IllegalArgumentException: ")) 604 + e.Message), 605 object); 606 } 607 } catch (css::lang::IllegalAccessException &) { 608 //TODO Clarify whether PropertyVetoException is the correct exception 609 // to throw when trying to set a read-only property: 610 throw css::beans::PropertyVetoException( 611 (rtl::OUString( 612 RTL_CONSTASCII_USTRINGPARAM("cannot set read-only property ")) 613 + name), 614 object); 615 } catch (css::lang::WrappedTargetRuntimeException & e) { 616 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not 617 // guaranteed to originate directly within XIdlField2.get (and thus have 618 // the expected semantics); it might also be passed through from lower 619 // layers. 620 if (e.TargetException.isExtractableTo( 621 getCppuType( 622 static_cast< css::beans::UnknownPropertyException * >(0))) 623 && ((i->second.property.Attributes 624 & css::beans::PropertyAttribute::OPTIONAL) 625 != 0)) 626 { 627 throw css::beans::UnknownPropertyException(name, object); 628 } else if (e.TargetException.isExtractableTo( 629 getCppuType( 630 static_cast< css::beans::PropertyVetoException * >( 631 0))) 632 && ((i->second.property.Attributes 633 & css::beans::PropertyAttribute::CONSTRAINED) 634 != 0)) 635 { 636 throw css::beans::PropertyVetoException(name, object); 637 } else { 638 throw css::lang::WrappedTargetException( 639 e.Message, object, e.TargetException); 640 } 641 } 642 } 643 644 css::uno::Any PropertySetMixinImpl::Impl::getProperty( 645 css::uno::Reference< css::uno::XInterface > const & object, 646 rtl::OUString const & name, css::beans::PropertyState * state) const 647 { 648 PropertyMap::const_iterator i(properties.find(name)); 649 if (i == properties.end()) { 650 throw css::beans::UnknownPropertyException(name, object); 651 } 652 css::uno::Reference< css::reflection::XIdlField2 > field( 653 m_idlClass->getField(name), css::uno::UNO_QUERY_THROW); 654 css::uno::Any value; 655 try { 656 value = field->get(object->queryInterface(m_type)); 657 } catch (css::lang::IllegalArgumentException & e) { 658 throw css::uno::RuntimeException( 659 (rtl::OUString( 660 RTL_CONSTASCII_USTRINGPARAM( 661 "unexpected com.sun.star.lang.IllegalArgumentException: ")) 662 + e.Message), 663 object); 664 } catch (css::lang::WrappedTargetRuntimeException & e) { 665 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not 666 // guaranteed to originate directly within XIdlField2.get (and thus have 667 // the expected semantics); it might also be passed through from lower 668 // layers. 669 if (e.TargetException.isExtractableTo( 670 getCppuType( 671 static_cast< css::beans::UnknownPropertyException * >(0))) 672 && ((i->second.property.Attributes 673 & css::beans::PropertyAttribute::OPTIONAL) 674 != 0)) 675 { 676 throw css::beans::UnknownPropertyException(name, object); 677 } else { 678 throw css::lang::WrappedTargetException( 679 e.Message, object, e.TargetException); 680 } 681 } 682 bool undoAmbiguous 683 = ((i->second.property.Attributes 684 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS) 685 != 0); 686 bool undoDefaulted 687 = ((i->second.property.Attributes 688 & css::beans::PropertyAttribute::MAYBEDEFAULT) 689 != 0); 690 bool undoOptional 691 = ((i->second.property.Attributes 692 & css::beans::PropertyAttribute::MAYBEVOID) 693 != 0); 694 bool isAmbiguous = false; 695 bool isDefaulted = false; 696 while (undoAmbiguous || undoDefaulted || undoOptional) { 697 if (undoAmbiguous 698 && value.getValueTypeName().matchAsciiL( 699 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<"))) 700 { 701 css::uno::Reference< css::reflection::XIdlClass > ambiguous( 702 getReflection(value.getValueTypeName())); 703 try { 704 if (!(css::uno::Reference< css::reflection::XIdlField2 >( 705 ambiguous->getField( 706 rtl::OUString( 707 RTL_CONSTASCII_USTRINGPARAM("IsAmbiguous"))), 708 css::uno::UNO_QUERY_THROW)->get(value) 709 >>= isAmbiguous)) 710 { 711 throw css::uno::RuntimeException( 712 rtl::OUString( 713 RTL_CONSTASCII_USTRINGPARAM( 714 "unexpected type of" 715 " com.sun.star.beans.Ambiguous IsAmbiguous" 716 " member")), 717 object); 718 } 719 value = css::uno::Reference< css::reflection::XIdlField2 >( 720 ambiguous->getField( 721 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))), 722 css::uno::UNO_QUERY_THROW)->get(value); 723 } catch (css::lang::IllegalArgumentException & e) { 724 throw css::uno::RuntimeException( 725 (rtl::OUString( 726 RTL_CONSTASCII_USTRINGPARAM( 727 "unexpected com.sun.star.lang." 728 "IllegalArgumentException: ")) 729 + e.Message), 730 object); 731 } 732 undoAmbiguous = false; 733 } else if (undoDefaulted 734 && value.getValueTypeName().matchAsciiL( 735 RTL_CONSTASCII_STRINGPARAM( 736 "com.sun.star.beans.Defaulted<"))) 737 { 738 css::uno::Reference< css::reflection::XIdlClass > defaulted( 739 getReflection(value.getValueTypeName())); 740 try { 741 742 if (!(css::uno::Reference< css::reflection::XIdlField2 >( 743 defaulted->getField( 744 rtl::OUString( 745 RTL_CONSTASCII_USTRINGPARAM("IsDefaulted"))), 746 css::uno::UNO_QUERY_THROW)->get(value) 747 >>= isDefaulted)) 748 { 749 throw css::uno::RuntimeException( 750 rtl::OUString( 751 RTL_CONSTASCII_USTRINGPARAM( 752 "unexpected type of" 753 " com.sun.star.beans.Defaulted IsDefaulted" 754 " member")), 755 object); 756 } 757 value = css::uno::Reference< css::reflection::XIdlField2 >( 758 defaulted->getField( 759 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))), 760 css::uno::UNO_QUERY_THROW)->get(value); 761 } catch (css::lang::IllegalArgumentException & e) { 762 throw css::uno::RuntimeException( 763 (rtl::OUString( 764 RTL_CONSTASCII_USTRINGPARAM( 765 "unexpected com.sun.star.lang." 766 "IllegalArgumentException: ")) 767 + e.Message), 768 object); 769 } 770 undoDefaulted = false; 771 } else if (undoOptional 772 && value.getValueTypeName().matchAsciiL( 773 RTL_CONSTASCII_STRINGPARAM( 774 "com.sun.star.beans.Optional<"))) 775 { 776 css::uno::Reference< css::reflection::XIdlClass > optional( 777 getReflection(value.getValueTypeName())); 778 try { 779 bool present = false; 780 if (!(css::uno::Reference< css::reflection::XIdlField2 >( 781 optional->getField( 782 rtl::OUString( 783 RTL_CONSTASCII_USTRINGPARAM("IsPresent"))), 784 css::uno::UNO_QUERY_THROW)->get(value) 785 >>= present)) 786 { 787 throw css::uno::RuntimeException( 788 rtl::OUString( 789 RTL_CONSTASCII_USTRINGPARAM( 790 "unexpected type of com.sun.star.beans.Optional" 791 " IsPresent member")), 792 object); 793 } 794 if (!present) { 795 value.clear(); 796 break; 797 } 798 value = css::uno::Reference< css::reflection::XIdlField2 >( 799 optional->getField( 800 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))), 801 css::uno::UNO_QUERY_THROW)->get(value); 802 } catch (css::lang::IllegalArgumentException & e) { 803 throw css::uno::RuntimeException( 804 (rtl::OUString( 805 RTL_CONSTASCII_USTRINGPARAM( 806 "unexpected com.sun.star.lang." 807 "IllegalArgumentException: ")) 808 + e.Message), 809 object); 810 } 811 undoOptional = false; 812 } else { 813 throw css::uno::RuntimeException( 814 (rtl::OUString( 815 RTL_CONSTASCII_USTRINGPARAM( 816 "unexpected type of attribute ")) 817 + name), 818 object); 819 } 820 } 821 if (state != 0) { 822 //XXX If isAmbiguous && isDefaulted, arbitrarily choose AMBIGUOUS_VALUE 823 // over DEFAULT_VALUE: 824 *state = isAmbiguous 825 ? css::beans::PropertyState_AMBIGUOUS_VALUE 826 : isDefaulted 827 ? css::beans::PropertyState_DEFAULT_VALUE 828 : css::beans::PropertyState_DIRECT_VALUE; 829 } 830 return value; 831 } 832 833 css::uno::Reference< css::reflection::XIdlClass > 834 PropertySetMixinImpl::Impl::getReflection(rtl::OUString const & typeName) const 835 { 836 css::uno::Reference< css::lang::XMultiComponentFactory > factory( 837 m_context->getServiceManager(), css::uno::UNO_QUERY_THROW); 838 AutoDispose< css::reflection::XIdlReflection > refl; 839 try { 840 refl.ifc = css::uno::Reference< css::reflection::XIdlReflection >( 841 factory->createInstanceWithContext( 842 rtl::OUString( 843 RTL_CONSTASCII_USTRINGPARAM( 844 "com.sun.star.reflection.CoreReflection")), 845 m_context), 846 css::uno::UNO_QUERY_THROW); 847 } catch (css::uno::RuntimeException &) { 848 throw; 849 } catch (css::uno::Exception & e) { 850 throw css::uno::DeploymentException( 851 (rtl::OUString( 852 RTL_CONSTASCII_USTRINGPARAM( 853 "component context fails to supply service" 854 " com.sun.star.reflection.CoreReflection: ")) 855 + e.Message), 856 m_context); 857 } 858 css::uno::Reference< css::reflection::XIdlClass > idlClass( 859 refl.ifc->forName(typeName), css::uno::UNO_QUERY_THROW); 860 refl.dispose(); 861 return idlClass; 862 } 863 864 css::uno::Any PropertySetMixinImpl::Impl::wrapValue( 865 css::uno::Reference< css::uno::XInterface > const & object, 866 css::uno::Any const & value, 867 css::uno::Reference< css::reflection::XIdlClass > const & type, 868 bool wrapAmbiguous, bool isAmbiguous, bool wrapDefaulted, bool isDefaulted, 869 bool wrapOptional) 870 { 871 OSL_ASSERT( 872 (wrapAmbiguous || !isAmbiguous) && (wrapDefaulted || !isDefaulted)); 873 if (wrapAmbiguous 874 && type->getName().matchAsciiL( 875 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<"))) 876 { 877 css::uno::Any strct; 878 type->createObject(strct); 879 try { 880 css::uno::Reference< css::reflection::XIdlField2 > field( 881 type->getField( 882 rtl::OUString( 883 RTL_CONSTASCII_USTRINGPARAM("Value"))), 884 css::uno::UNO_QUERY_THROW); 885 field->set( 886 strct, 887 wrapValue( 888 object, value, field->getType(), false, false, 889 wrapDefaulted, isDefaulted, wrapOptional)); 890 css::uno::Reference< css::reflection::XIdlField2 >( 891 type->getField( 892 rtl::OUString( 893 RTL_CONSTASCII_USTRINGPARAM("IsAmbiguous"))), 894 css::uno::UNO_QUERY_THROW)->set( 895 strct, css::uno::makeAny(isAmbiguous)); 896 } catch (css::lang::IllegalArgumentException & e) { 897 throw css::uno::RuntimeException( 898 (rtl::OUString( 899 RTL_CONSTASCII_USTRINGPARAM( 900 "unexpected" 901 " com.sun.star.lang.IllegalArgumentException: ")) 902 + e.Message), 903 object); 904 } catch (css::lang::IllegalAccessException & e) { 905 throw css::uno::RuntimeException( 906 (rtl::OUString( 907 RTL_CONSTASCII_USTRINGPARAM( 908 "unexpected" 909 " com.sun.star.lang.IllegalAccessException: ")) 910 + e.Message), 911 object); 912 } 913 return strct; 914 } else if (wrapDefaulted 915 && type->getName().matchAsciiL( 916 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Defaulted<"))) 917 { 918 css::uno::Any strct; 919 type->createObject(strct); 920 try { 921 css::uno::Reference< css::reflection::XIdlField2 > field( 922 type->getField( 923 rtl::OUString( 924 RTL_CONSTASCII_USTRINGPARAM("Value"))), 925 css::uno::UNO_QUERY_THROW); 926 field->set( 927 strct, 928 wrapValue( 929 object, value, field->getType(), wrapAmbiguous, isAmbiguous, 930 false, false, wrapOptional)); 931 css::uno::Reference< css::reflection::XIdlField2 >( 932 type->getField( 933 rtl::OUString( 934 RTL_CONSTASCII_USTRINGPARAM("IsDefaulted"))), 935 css::uno::UNO_QUERY_THROW)->set( 936 strct, css::uno::makeAny(isDefaulted)); 937 } catch (css::lang::IllegalArgumentException & e) { 938 throw css::uno::RuntimeException( 939 (rtl::OUString( 940 RTL_CONSTASCII_USTRINGPARAM( 941 "unexpected" 942 " com.sun.star.lang.IllegalArgumentException: ")) 943 + e.Message), 944 object); 945 } catch (css::lang::IllegalAccessException & e) { 946 throw css::uno::RuntimeException( 947 (rtl::OUString( 948 RTL_CONSTASCII_USTRINGPARAM( 949 "unexpected" 950 " com.sun.star.lang.IllegalAccessException: ")) 951 + e.Message), 952 object); 953 } 954 return strct; 955 } else if (wrapOptional 956 && type->getName().matchAsciiL( 957 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Optional<"))) 958 { 959 css::uno::Any strct; 960 type->createObject(strct); 961 bool present = value.hasValue(); 962 try { 963 css::uno::Reference< css::reflection::XIdlField2 >( 964 type->getField( 965 rtl::OUString( 966 RTL_CONSTASCII_USTRINGPARAM("IsPresent"))), 967 css::uno::UNO_QUERY_THROW)->set( 968 strct, css::uno::makeAny(present)); 969 if (present) { 970 css::uno::Reference< css::reflection::XIdlField2 > field( 971 type->getField( 972 rtl::OUString( 973 RTL_CONSTASCII_USTRINGPARAM("Value"))), 974 css::uno::UNO_QUERY_THROW); 975 field->set( 976 strct, 977 wrapValue( 978 object, value, field->getType(), wrapAmbiguous, 979 isAmbiguous, wrapDefaulted, isDefaulted, false)); 980 } 981 } catch (css::lang::IllegalArgumentException & e) { 982 throw css::uno::RuntimeException( 983 (rtl::OUString( 984 RTL_CONSTASCII_USTRINGPARAM( 985 "unexpected" 986 " com.sun.star.lang.IllegalArgumentException: ")) 987 + e.Message), 988 object); 989 } catch (css::lang::IllegalAccessException & e) { 990 throw css::uno::RuntimeException( 991 (rtl::OUString( 992 RTL_CONSTASCII_USTRINGPARAM( 993 "unexpected" 994 " com.sun.star.lang.IllegalAccessException: ")) 995 + e.Message), 996 object); 997 } 998 return strct; 999 } else { 1000 if (wrapAmbiguous || wrapDefaulted || wrapOptional) { 1001 throw css::uno::RuntimeException( 1002 rtl::OUString( 1003 RTL_CONSTASCII_USTRINGPARAM( 1004 "unexpected type of attribute")), 1005 object); 1006 } 1007 return value; 1008 } 1009 } 1010 1011 PropertySetMixinImpl::PropertySetMixinImpl( 1012 css::uno::Reference< css::uno::XComponentContext > const & context, 1013 Implements implements, 1014 css::uno::Sequence< rtl::OUString > const & absentOptional, 1015 css::uno::Type const & type) 1016 { 1017 m_impl = new Impl(context, implements, absentOptional, type); 1018 m_impl->acquire(); 1019 } 1020 1021 PropertySetMixinImpl::~PropertySetMixinImpl() { 1022 m_impl->release(); 1023 } 1024 1025 void PropertySetMixinImpl::checkUnknown(rtl::OUString const & propertyName) { 1026 if (propertyName.getLength() != 0) { 1027 m_impl->get( 1028 static_cast< css::beans::XPropertySet * >(this), propertyName); 1029 } 1030 } 1031 1032 void PropertySetMixinImpl::prepareSet( 1033 rtl::OUString const & propertyName, css::uno::Any const & oldValue, 1034 css::uno::Any const & newValue, BoundListeners * boundListeners) 1035 { 1036 Impl::PropertyMap::const_iterator it(m_impl->properties.find(propertyName)); 1037 OSL_ASSERT(it != m_impl->properties.end()); 1038 Impl::VetoListenerBag specificVeto; 1039 Impl::VetoListenerBag unspecificVeto; 1040 { 1041 osl::MutexGuard g(m_impl->mutex); 1042 if (m_impl->disposed) { 1043 throw css::lang::DisposedException( 1044 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("disposed")), 1045 static_cast< css::beans::XPropertySet * >(this)); 1046 } 1047 if ((it->second.property.Attributes 1048 & css::beans::PropertyAttribute::CONSTRAINED) 1049 != 0) 1050 { 1051 Impl::VetoListenerMap::const_iterator i( 1052 m_impl->vetoListeners.find(propertyName)); 1053 if (i != m_impl->vetoListeners.end()) { 1054 specificVeto = i->second; 1055 } 1056 i = m_impl->vetoListeners.find(rtl::OUString()); 1057 if (i != m_impl->vetoListeners.end()) { 1058 unspecificVeto = i->second; 1059 } 1060 } 1061 if ((it->second.property.Attributes 1062 & css::beans::PropertyAttribute::BOUND) 1063 != 0) 1064 { 1065 OSL_ASSERT(boundListeners != 0); 1066 Impl::BoundListenerMap::const_iterator i( 1067 m_impl->boundListeners.find(propertyName)); 1068 if (i != m_impl->boundListeners.end()) { 1069 boundListeners->m_impl->specificListeners = i->second; 1070 } 1071 i = m_impl->boundListeners.find(rtl::OUString()); 1072 if (i != m_impl->boundListeners.end()) { 1073 boundListeners->m_impl->unspecificListeners = i->second; 1074 } 1075 } 1076 } 1077 if ((it->second.property.Attributes 1078 & css::beans::PropertyAttribute::CONSTRAINED) 1079 != 0) 1080 { 1081 css::beans::PropertyChangeEvent event( 1082 static_cast< css::beans::XPropertySet * >(this), propertyName, 1083 false, it->second.property.Handle, oldValue, newValue); 1084 for (Impl::VetoListenerBag::iterator i(specificVeto.begin()); 1085 i != specificVeto.end(); ++i) 1086 { 1087 try { 1088 (*i)->vetoableChange(event); 1089 } catch (css::lang::DisposedException &) {} 1090 } 1091 for (Impl::VetoListenerBag::iterator i(unspecificVeto.begin()); 1092 i != unspecificVeto.end(); ++i) 1093 { 1094 try { 1095 (*i)->vetoableChange(event); 1096 } catch (css::lang::DisposedException &) {} 1097 } 1098 } 1099 if ((it->second.property.Attributes & css::beans::PropertyAttribute::BOUND) 1100 != 0) 1101 { 1102 OSL_ASSERT(boundListeners != 0); 1103 boundListeners->m_impl->event = css::beans::PropertyChangeEvent( 1104 static_cast< css::beans::XPropertySet * >(this), propertyName, 1105 false, it->second.property.Handle, oldValue, newValue); 1106 } 1107 } 1108 1109 void PropertySetMixinImpl::dispose() { 1110 Impl::BoundListenerMap boundListeners; 1111 Impl::VetoListenerMap vetoListeners; 1112 { 1113 osl::MutexGuard g(m_impl->mutex); 1114 boundListeners.swap(m_impl->boundListeners); 1115 vetoListeners.swap(m_impl->vetoListeners); 1116 m_impl->disposed = true; 1117 } 1118 css::lang::EventObject event( 1119 static_cast< css::beans::XPropertySet * >(this)); 1120 for (Impl::BoundListenerMap::iterator i(boundListeners.begin()); 1121 i != boundListeners.end(); ++i) 1122 { 1123 for (BoundListenerBag::iterator j(i->second.begin()); 1124 j != i->second.end(); ++j) 1125 { 1126 (*j)->disposing(event); 1127 } 1128 } 1129 for (Impl::VetoListenerMap::iterator i(vetoListeners.begin()); 1130 i != vetoListeners.end(); ++i) 1131 { 1132 for (Impl::VetoListenerBag::iterator j(i->second.begin()); 1133 j != i->second.end(); ++j) 1134 { 1135 (*j)->disposing(event); 1136 } 1137 } 1138 } 1139 1140 css::uno::Any PropertySetMixinImpl::queryInterface(css::uno::Type const & type) 1141 throw (css::uno::RuntimeException) 1142 { 1143 if (((m_impl->implements & IMPLEMENTS_PROPERTY_SET) != 0 1144 && type == css::beans::XPropertySet::static_type())) 1145 { 1146 css::uno::Reference< css::uno::XInterface > ifc( 1147 static_cast< css::beans::XPropertySet * >(this)); 1148 return css::uno::Any(&ifc, type); 1149 } else if ((m_impl->implements & IMPLEMENTS_FAST_PROPERTY_SET) != 0 1150 && type == css::beans::XFastPropertySet::static_type()) 1151 { 1152 css::uno::Reference< css::uno::XInterface > ifc( 1153 static_cast< css::beans::XFastPropertySet * >(this)); 1154 return css::uno::Any(&ifc, type); 1155 } else if ((m_impl->implements & IMPLEMENTS_PROPERTY_ACCESS) != 0 1156 && type == css::beans::XPropertyAccess::static_type()) 1157 { 1158 css::uno::Reference< css::uno::XInterface > ifc( 1159 static_cast< css::beans::XPropertyAccess * >(this)); 1160 return css::uno::Any(&ifc, type); 1161 } else { 1162 return css::uno::Any(); 1163 } 1164 } 1165 1166 css::uno::Reference< css::beans::XPropertySetInfo > 1167 PropertySetMixinImpl::getPropertySetInfo() throw (css::uno::RuntimeException) { 1168 try { 1169 return new Info(m_impl); 1170 } catch (std::bad_alloc &) { 1171 //TODO OutOfMemoryException: 1172 throw css::uno::RuntimeException( 1173 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1174 } 1175 } 1176 1177 void PropertySetMixinImpl::setPropertyValue( 1178 rtl::OUString const & propertyName, css::uno::Any const & value) 1179 throw ( 1180 css::beans::UnknownPropertyException, css::beans::PropertyVetoException, 1181 css::lang::IllegalArgumentException, css::lang::WrappedTargetException, 1182 css::uno::RuntimeException) 1183 { 1184 try { 1185 m_impl->setProperty( 1186 static_cast< css::beans::XPropertySet * >(this), propertyName, 1187 value, false, false, 1); 1188 } catch (std::bad_alloc &) { 1189 //TODO OutOfMemoryException: 1190 throw css::uno::RuntimeException( 1191 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1192 } 1193 } 1194 1195 css::uno::Any PropertySetMixinImpl::getPropertyValue( 1196 rtl::OUString const & propertyName) 1197 throw ( 1198 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1199 css::uno::RuntimeException) 1200 { 1201 try { 1202 return m_impl->getProperty( 1203 static_cast< css::beans::XPropertySet * >(this), propertyName, 0); 1204 } catch (std::bad_alloc &) { 1205 //TODO OutOfMemoryException: 1206 throw css::uno::RuntimeException( 1207 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1208 } 1209 } 1210 1211 void PropertySetMixinImpl::addPropertyChangeListener( 1212 rtl::OUString const & propertyName, 1213 css::uno::Reference< css::beans::XPropertyChangeListener > const & listener) 1214 throw ( 1215 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1216 css::uno::RuntimeException) 1217 { 1218 css::uno::Reference< css::beans::XPropertyChangeListener >( 1219 listener, css::uno::UNO_QUERY_THROW); // reject NULL listener 1220 checkUnknown(propertyName); 1221 try { 1222 bool disposed; 1223 { 1224 osl::MutexGuard g(m_impl->mutex); 1225 disposed = m_impl->disposed; 1226 if (!disposed) { 1227 m_impl->boundListeners[propertyName].insert(listener); 1228 } 1229 } 1230 if (disposed) { 1231 listener->disposing( 1232 css::lang::EventObject( 1233 static_cast< css::beans::XPropertySet * >(this))); 1234 } 1235 } catch (std::bad_alloc &) { 1236 //TODO OutOfMemoryException: 1237 throw css::uno::RuntimeException( 1238 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1239 } 1240 } 1241 1242 void PropertySetMixinImpl::removePropertyChangeListener( 1243 rtl::OUString const & propertyName, 1244 css::uno::Reference< css::beans::XPropertyChangeListener > const & listener) 1245 throw ( 1246 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1247 css::uno::RuntimeException) 1248 { 1249 OSL_ASSERT(listener.is()); 1250 checkUnknown(propertyName); 1251 try { 1252 osl::MutexGuard g(m_impl->mutex); 1253 Impl::BoundListenerMap::iterator i( 1254 m_impl->boundListeners.find(propertyName)); 1255 if (i != m_impl->boundListeners.end()) { 1256 BoundListenerBag::iterator j(i->second.find(listener)); 1257 if (j != i->second.end()) { 1258 i->second.erase(j); 1259 } 1260 } 1261 } catch (std::bad_alloc &) { 1262 //TODO OutOfMemoryException: 1263 throw css::uno::RuntimeException( 1264 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1265 } 1266 } 1267 1268 void PropertySetMixinImpl::addVetoableChangeListener( 1269 rtl::OUString const & propertyName, 1270 css::uno::Reference< css::beans::XVetoableChangeListener > const & listener) 1271 throw ( 1272 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1273 css::uno::RuntimeException) 1274 { 1275 css::uno::Reference< css::beans::XVetoableChangeListener >( 1276 listener, css::uno::UNO_QUERY_THROW); // reject NULL listener 1277 checkUnknown(propertyName); 1278 try { 1279 bool disposed; 1280 { 1281 osl::MutexGuard g(m_impl->mutex); 1282 disposed = m_impl->disposed; 1283 if (!disposed) { 1284 m_impl->vetoListeners[propertyName].insert(listener); 1285 } 1286 } 1287 if (disposed) { 1288 listener->disposing( 1289 css::lang::EventObject( 1290 static_cast< css::beans::XPropertySet * >(this))); 1291 } 1292 } catch (std::bad_alloc &) { 1293 //TODO OutOfMemoryException: 1294 throw css::uno::RuntimeException( 1295 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1296 } 1297 } 1298 1299 void PropertySetMixinImpl::removeVetoableChangeListener( 1300 rtl::OUString const & propertyName, 1301 css::uno::Reference< css::beans::XVetoableChangeListener > const & listener) 1302 throw ( 1303 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1304 css::uno::RuntimeException) 1305 { 1306 OSL_ASSERT(listener.is()); 1307 checkUnknown(propertyName); 1308 try { 1309 osl::MutexGuard g(m_impl->mutex); 1310 Impl::VetoListenerMap::iterator i( 1311 m_impl->vetoListeners.find(propertyName)); 1312 if (i != m_impl->vetoListeners.end()) { 1313 Impl::VetoListenerBag::iterator j(i->second.find(listener)); 1314 if (j != i->second.end()) { 1315 i->second.erase(j); 1316 } 1317 } 1318 } catch (std::bad_alloc &) { 1319 //TODO OutOfMemoryException: 1320 throw css::uno::RuntimeException( 1321 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1322 } 1323 } 1324 1325 void PropertySetMixinImpl::setFastPropertyValue( 1326 sal_Int32 handle, css::uno::Any const & value) 1327 throw ( 1328 css::beans::UnknownPropertyException, css::beans::PropertyVetoException, 1329 css::lang::IllegalArgumentException, css::lang::WrappedTargetException, 1330 css::uno::RuntimeException) 1331 { 1332 try { 1333 m_impl->setProperty( 1334 static_cast< css::beans::XPropertySet * >(this), 1335 m_impl->translateHandle( 1336 static_cast< css::beans::XPropertySet * >(this), handle), 1337 value, false, false, 1); 1338 } catch (std::bad_alloc &) { 1339 //TODO OutOfMemoryException: 1340 throw css::uno::RuntimeException( 1341 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1342 } 1343 } 1344 1345 css::uno::Any PropertySetMixinImpl::getFastPropertyValue(sal_Int32 handle) 1346 throw ( 1347 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1348 css::uno::RuntimeException) 1349 { 1350 try { 1351 return m_impl->getProperty( 1352 static_cast< css::beans::XPropertySet * >(this), 1353 m_impl->translateHandle( 1354 static_cast< css::beans::XPropertySet * >(this), handle), 1355 0); 1356 } catch (std::bad_alloc &) { 1357 //TODO OutOfMemoryException: 1358 throw css::uno::RuntimeException( 1359 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1360 } 1361 } 1362 1363 css::uno::Sequence< css::beans::PropertyValue > 1364 PropertySetMixinImpl::getPropertyValues() throw (css::uno::RuntimeException) { 1365 try { 1366 css::uno::Sequence< css::beans::PropertyValue > s( 1367 m_impl->handleMap.getLength()); 1368 sal_Int32 n = 0; 1369 for (sal_Int32 i = 0; i < m_impl->handleMap.getLength(); ++i) { 1370 try { 1371 s[n].Value = m_impl->getProperty( 1372 static_cast< css::beans::XPropertySet * >(this), 1373 m_impl->handleMap[i], &s[n].State); 1374 } catch (css::beans::UnknownPropertyException &) { 1375 continue; 1376 } catch (css::lang::WrappedTargetException & e) { 1377 throw css::lang::WrappedTargetRuntimeException( 1378 e.Message, static_cast< css::beans::XPropertySet * >(this), 1379 e.TargetException); 1380 } 1381 s[n].Name = m_impl->handleMap[i]; 1382 s[n].Handle = i; 1383 ++n; 1384 } 1385 s.realloc(n); 1386 return s; 1387 } catch (std::bad_alloc &) { 1388 //TODO OutOfMemoryException: 1389 throw css::uno::RuntimeException( 1390 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1391 } 1392 } 1393 1394 void PropertySetMixinImpl::setPropertyValues( 1395 css::uno::Sequence< css::beans::PropertyValue > const & props) 1396 throw ( 1397 css::beans::UnknownPropertyException, css::beans::PropertyVetoException, 1398 css::lang::IllegalArgumentException, css::lang::WrappedTargetException, 1399 css::uno::RuntimeException) 1400 { 1401 try { 1402 for (sal_Int32 i = 0; i < props.getLength(); ++i) { 1403 if (props[i].Handle != -1 1404 && (props[i].Name 1405 != m_impl->translateHandle( 1406 static_cast< css::beans::XPropertySet * >(this), 1407 props[i].Handle))) 1408 { 1409 throw css::beans::UnknownPropertyException( 1410 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("name ")) 1411 + props[i].Name 1412 + rtl::OUString( 1413 RTL_CONSTASCII_USTRINGPARAM(" does not match handle ")) 1414 + rtl::OUString::valueOf(props[i].Handle)), 1415 static_cast< css::beans::XPropertySet * >(this)); 1416 } 1417 m_impl->setProperty( 1418 static_cast< css::beans::XPropertySet * >(this), props[i].Name, 1419 props[i].Value, 1420 props[i].State == css::beans::PropertyState_AMBIGUOUS_VALUE, 1421 props[i].State == css::beans::PropertyState_DEFAULT_VALUE, 0); 1422 } 1423 } catch (std::bad_alloc &) { 1424 //TODO OutOfMemoryException: 1425 throw css::uno::RuntimeException( 1426 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1427 } 1428 } 1429