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