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 throw (css::uno::RuntimeException); 342 343 virtual css::beans::Property SAL_CALL getPropertyByName( 344 rtl::OUString const & name) 345 throw ( 346 css::beans::UnknownPropertyException, css::uno::RuntimeException); 347 348 virtual sal_Bool SAL_CALL hasPropertyByName(rtl::OUString const & name) 349 throw (css::uno::RuntimeException); 350 351 private: 352 rtl::Reference< Data > m_data; 353 }; 354 355 css::uno::Sequence< css::beans::Property > Info::getProperties() 356 throw (css::uno::RuntimeException) 357 { 358 try { 359 OSL_ASSERT(m_data->properties.size() <= SAL_MAX_INT32); 360 css::uno::Sequence< css::beans::Property > s( 361 static_cast< sal_Int32 >(m_data->properties.size())); 362 sal_Int32 n = 0; 363 for (Data::PropertyMap::iterator i(m_data->properties.begin()); 364 i != m_data->properties.end(); ++i) 365 { 366 if (i->second.present) { 367 s[n++] = i->second.property; 368 } 369 } 370 s.realloc(n); 371 return s; 372 } catch (std::bad_alloc &) { 373 //TODO OutOfMemoryException: 374 throw css::uno::RuntimeException( 375 rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); 376 } 377 } 378 379 css::beans::Property Info::getPropertyByName(rtl::OUString const & name) 380 throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) 381 { 382 return m_data->get(static_cast< cppu::OWeakObject * >(this), name)-> 383 second.property; 384 } 385 386 sal_Bool Info::hasPropertyByName(rtl::OUString const & name) 387 throw (css::uno::RuntimeException) 388 { 389 Data::PropertyMap::iterator i(m_data->properties.find(name)); 390 return i != m_data->properties.end() && i->second.present; 391 } 392 393 typedef 394 std::multiset< css::uno::Reference< css::beans::XPropertyChangeListener > > 395 BoundListenerBag; 396 397 } 398 399 class PropertySetMixinImpl::BoundListeners::Impl { 400 public: 401 BoundListenerBag specificListeners; 402 BoundListenerBag unspecificListeners; 403 css::beans::PropertyChangeEvent event; 404 }; 405 406 PropertySetMixinImpl::BoundListeners::BoundListeners(): m_impl(new Impl) {} 407 408 PropertySetMixinImpl::BoundListeners::~BoundListeners() { 409 delete m_impl; 410 } 411 412 void PropertySetMixinImpl::BoundListeners::notify() const { 413 for (BoundListenerBag::const_iterator i(m_impl->specificListeners.begin()); 414 i != m_impl->specificListeners.end(); ++i) 415 { 416 try { 417 (*i)->propertyChange(m_impl->event); 418 } catch (css::lang::DisposedException &) {} 419 } 420 for (BoundListenerBag::const_iterator i( 421 m_impl->unspecificListeners.begin()); 422 i != m_impl->unspecificListeners.end(); ++i) 423 { 424 try { 425 (*i)->propertyChange(m_impl->event); 426 } catch (css::lang::DisposedException &) {} 427 } 428 } 429 430 class PropertySetMixinImpl::Impl: public Data { 431 public: 432 Impl( 433 css::uno::Reference< css::uno::XComponentContext > const & context, 434 Implements theImplements, 435 css::uno::Sequence< rtl::OUString > const & absentOptional, 436 css::uno::Type const & type); 437 438 rtl::OUString translateHandle( 439 css::uno::Reference< css::uno::XInterface > const & object, 440 sal_Int32 handle) const; 441 442 void setProperty( 443 css::uno::Reference< css::uno::XInterface > const & object, 444 rtl::OUString const & name, css::uno::Any const & value, 445 bool isAmbiguous, bool isDefaulted, sal_Int16 illegalArgumentPosition) 446 const; 447 448 css::uno::Any getProperty( 449 css::uno::Reference< css::uno::XInterface > const & object, 450 rtl::OUString const & name, css::beans::PropertyState * state) const; 451 452 PropertySetMixinImpl::Implements implements; 453 css::uno::Sequence< rtl::OUString > handleMap; 454 455 typedef std::map< rtl::OUString, BoundListenerBag > BoundListenerMap; 456 457 typedef 458 std::multiset< css::uno::Reference< css::beans::XVetoableChangeListener > > 459 VetoListenerBag; 460 461 typedef std::map< rtl::OUString, VetoListenerBag > VetoListenerMap; 462 463 mutable osl::Mutex mutex; 464 BoundListenerMap boundListeners; 465 VetoListenerMap vetoListeners; 466 bool disposed; 467 468 private: 469 css::uno::Reference< css::reflection::XIdlClass > getReflection( 470 rtl::OUString const & typeName) const; 471 472 static css::uno::Any wrapValue( 473 css::uno::Reference< css::uno::XInterface > const & object, 474 css::uno::Any const & value, 475 css::uno::Reference< css::reflection::XIdlClass > const & type, 476 bool wrapAmbiguous, bool isAmbiguous, bool wrapDefaulted, 477 bool isDefaulted, bool wrapOptional); 478 479 css::uno::Reference< css::uno::XComponentContext > const & m_context; 480 css::uno::Sequence< rtl::OUString > m_absentOptional; 481 css::uno::Type m_type; 482 css::uno::Reference< css::reflection::XIdlClass > m_idlClass; 483 }; 484 485 PropertySetMixinImpl::Impl::Impl( 486 css::uno::Reference< css::uno::XComponentContext > const & context, 487 Implements theImplements, 488 css::uno::Sequence< rtl::OUString > const & absentOptional, 489 css::uno::Type const & type): 490 implements(theImplements), disposed(false), m_context(context), 491 m_absentOptional(absentOptional), m_type(type) 492 { 493 OSL_ASSERT( 494 context.is() 495 && ((implements 496 & ~(IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET 497 | IMPLEMENTS_PROPERTY_ACCESS)) 498 == 0)); 499 m_idlClass = getReflection(m_type.getTypeName()); 500 css::uno::Reference< css::reflection::XTypeDescription > ifc; 501 try { 502 ifc = css::uno::Reference< css::reflection::XTypeDescription >( 503 css::uno::Reference< css::container::XHierarchicalNameAccess >( 504 m_context->getValueByName( 505 rtl::OUString( 506 RTL_CONSTASCII_USTRINGPARAM( 507 "/singletons/com.sun.star.reflection." 508 "theTypeDescriptionManager"))), 509 css::uno::UNO_QUERY_THROW)->getByHierarchicalName( 510 m_type.getTypeName()), 511 css::uno::UNO_QUERY_THROW); 512 } catch (css::container::NoSuchElementException & e) { 513 throw css::uno::RuntimeException( 514 (rtl::OUString( 515 RTL_CONSTASCII_USTRINGPARAM( 516 "unexpected" 517 " com.sun.star.container.NoSuchElementException: ")) 518 + e.Message), 519 css::uno::Reference< css::uno::XInterface >()); 520 } 521 std::vector< rtl::OUString > handleNames; 522 initProperties(ifc, m_absentOptional, &handleNames); 523 std::vector< rtl::OUString >::size_type size = handleNames.size(); 524 OSL_ASSERT(size <= SAL_MAX_INT32); 525 handleMap.realloc(static_cast< sal_Int32 >(size)); 526 std::copy(handleNames.begin(), handleNames.end(), handleMap.getArray()); 527 } 528 529 rtl::OUString PropertySetMixinImpl::Impl::translateHandle( 530 css::uno::Reference< css::uno::XInterface > const & object, 531 sal_Int32 handle) const 532 { 533 if (handle < 0 || handle >= handleMap.getLength()) { 534 throw css::beans::UnknownPropertyException( 535 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad handle ")) 536 + rtl::OUString::valueOf(handle)), 537 object); 538 } 539 return handleMap[handle]; 540 } 541 542 void PropertySetMixinImpl::Impl::setProperty( 543 css::uno::Reference< css::uno::XInterface > const & object, 544 rtl::OUString const & name, css::uno::Any const & value, bool isAmbiguous, 545 bool isDefaulted, sal_Int16 illegalArgumentPosition) const 546 { 547 PropertyMap::const_iterator i(properties.find(name)); 548 if (i == properties.end()) { 549 throw css::beans::UnknownPropertyException(name, object); 550 } 551 if ((isAmbiguous 552 && ((i->second.property.Attributes 553 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS) 554 == 0)) 555 || (isDefaulted 556 && ((i->second.property.Attributes 557 & css::beans::PropertyAttribute::MAYBEDEFAULT) 558 == 0))) 559 { 560 throw css::lang::IllegalArgumentException( 561 (rtl::OUString( 562 RTL_CONSTASCII_USTRINGPARAM( 563 "flagging as ambiguous/defaulted non-ambiguous/defaulted" 564 " property ")) 565 + name), 566 object, illegalArgumentPosition); 567 } 568 css::uno::Reference< css::reflection::XIdlField2 > f( 569 m_idlClass->getField(name), css::uno::UNO_QUERY_THROW); 570 css::uno::Any o(object->queryInterface(m_type)); 571 css::uno::Any v( 572 wrapValue( 573 object, value, 574 (css::uno::Reference< css::reflection::XIdlField2 >( 575 m_idlClass->getField(name), css::uno::UNO_QUERY_THROW)-> 576 getType()), 577 ((i->second.property.Attributes 578 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS) 579 != 0), 580 isAmbiguous, 581 ((i->second.property.Attributes 582 & css::beans::PropertyAttribute::MAYBEDEFAULT) 583 != 0), 584 isDefaulted, 585 ((i->second.property.Attributes 586 & css::beans::PropertyAttribute::MAYBEVOID) 587 != 0))); 588 try { 589 f->set(o, v); 590 } catch (css::lang::IllegalArgumentException & e) { 591 if (e.ArgumentPosition == 1) { 592 throw css::lang::IllegalArgumentException( 593 e.Message, object, illegalArgumentPosition); 594 } else { 595 throw css::uno::RuntimeException( 596 (rtl::OUString( 597 RTL_CONSTASCII_USTRINGPARAM( 598 "unexpected" 599 " com.sun.star.lang.IllegalArgumentException: ")) 600 + e.Message), 601 object); 602 } 603 } catch (css::lang::IllegalAccessException &) { 604 //TODO Clarify whether PropertyVetoException is the correct exception 605 // to throw when trying to set a read-only property: 606 throw css::beans::PropertyVetoException( 607 (rtl::OUString( 608 RTL_CONSTASCII_USTRINGPARAM("cannot set read-only property ")) 609 + name), 610 object); 611 } catch (css::lang::WrappedTargetRuntimeException & e) { 612 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not 613 // guaranteed to originate directly within XIdlField2.get (and thus have 614 // the expected semantics); it might also be passed through from lower 615 // layers. 616 if (e.TargetException.isExtractableTo( 617 getCppuType( 618 static_cast< css::beans::UnknownPropertyException * >(0))) 619 && ((i->second.property.Attributes 620 & css::beans::PropertyAttribute::OPTIONAL) 621 != 0)) 622 { 623 throw css::beans::UnknownPropertyException(name, object); 624 } else if (e.TargetException.isExtractableTo( 625 getCppuType( 626 static_cast< css::beans::PropertyVetoException * >( 627 0))) 628 && ((i->second.property.Attributes 629 & css::beans::PropertyAttribute::CONSTRAINED) 630 != 0)) 631 { 632 throw css::beans::PropertyVetoException(name, object); 633 } else { 634 throw css::lang::WrappedTargetException( 635 e.Message, object, e.TargetException); 636 } 637 } 638 } 639 640 css::uno::Any PropertySetMixinImpl::Impl::getProperty( 641 css::uno::Reference< css::uno::XInterface > const & object, 642 rtl::OUString const & name, css::beans::PropertyState * state) const 643 { 644 PropertyMap::const_iterator i(properties.find(name)); 645 if (i == properties.end()) { 646 throw css::beans::UnknownPropertyException(name, object); 647 } 648 css::uno::Reference< css::reflection::XIdlField2 > field( 649 m_idlClass->getField(name), css::uno::UNO_QUERY_THROW); 650 css::uno::Any value; 651 try { 652 value = field->get(object->queryInterface(m_type)); 653 } catch (css::lang::IllegalArgumentException & e) { 654 throw css::uno::RuntimeException( 655 (rtl::OUString( 656 RTL_CONSTASCII_USTRINGPARAM( 657 "unexpected com.sun.star.lang.IllegalArgumentException: ")) 658 + e.Message), 659 object); 660 } catch (css::lang::WrappedTargetRuntimeException & e) { 661 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not 662 // guaranteed to originate directly within XIdlField2.get (and thus have 663 // the expected semantics); it might also be passed through from lower 664 // layers. 665 if (e.TargetException.isExtractableTo( 666 getCppuType( 667 static_cast< css::beans::UnknownPropertyException * >(0))) 668 && ((i->second.property.Attributes 669 & css::beans::PropertyAttribute::OPTIONAL) 670 != 0)) 671 { 672 throw css::beans::UnknownPropertyException(name, object); 673 } else { 674 throw css::lang::WrappedTargetException( 675 e.Message, object, e.TargetException); 676 } 677 } 678 bool undoAmbiguous 679 = ((i->second.property.Attributes 680 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS) 681 != 0); 682 bool undoDefaulted 683 = ((i->second.property.Attributes 684 & css::beans::PropertyAttribute::MAYBEDEFAULT) 685 != 0); 686 bool undoOptional 687 = ((i->second.property.Attributes 688 & css::beans::PropertyAttribute::MAYBEVOID) 689 != 0); 690 bool isAmbiguous = false; 691 bool isDefaulted = false; 692 while (undoAmbiguous || undoDefaulted || undoOptional) { 693 if (undoAmbiguous 694 && value.getValueTypeName().matchAsciiL( 695 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<"))) 696 { 697 css::uno::Reference< css::reflection::XIdlClass > ambiguous( 698 getReflection(value.getValueTypeName())); 699 try { 700 if (!(css::uno::Reference< css::reflection::XIdlField2 >( 701 ambiguous->getField( 702 rtl::OUString( 703 RTL_CONSTASCII_USTRINGPARAM("IsAmbiguous"))), 704 css::uno::UNO_QUERY_THROW)->get(value) 705 >>= isAmbiguous)) 706 { 707 throw css::uno::RuntimeException( 708 rtl::OUString( 709 RTL_CONSTASCII_USTRINGPARAM( 710 "unexpected type of" 711 " com.sun.star.beans.Ambiguous IsAmbiguous" 712 " member")), 713 object); 714 } 715 value = css::uno::Reference< css::reflection::XIdlField2 >( 716 ambiguous->getField( 717 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))), 718 css::uno::UNO_QUERY_THROW)->get(value); 719 } catch (css::lang::IllegalArgumentException & e) { 720 throw css::uno::RuntimeException( 721 (rtl::OUString( 722 RTL_CONSTASCII_USTRINGPARAM( 723 "unexpected com.sun.star.lang." 724 "IllegalArgumentException: ")) 725 + e.Message), 726 object); 727 } 728 undoAmbiguous = false; 729 } else if (undoDefaulted 730 && value.getValueTypeName().matchAsciiL( 731 RTL_CONSTASCII_STRINGPARAM( 732 "com.sun.star.beans.Defaulted<"))) 733 { 734 css::uno::Reference< css::reflection::XIdlClass > defaulted( 735 getReflection(value.getValueTypeName())); 736 try { 737 738 if (!(css::uno::Reference< css::reflection::XIdlField2 >( 739 defaulted->getField( 740 rtl::OUString( 741 RTL_CONSTASCII_USTRINGPARAM("IsDefaulted"))), 742 css::uno::UNO_QUERY_THROW)->get(value) 743 >>= isDefaulted)) 744 { 745 throw css::uno::RuntimeException( 746 rtl::OUString( 747 RTL_CONSTASCII_USTRINGPARAM( 748 "unexpected type of" 749 " com.sun.star.beans.Defaulted IsDefaulted" 750 " member")), 751 object); 752 } 753 value = css::uno::Reference< css::reflection::XIdlField2 >( 754 defaulted->getField( 755 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))), 756 css::uno::UNO_QUERY_THROW)->get(value); 757 } catch (css::lang::IllegalArgumentException & e) { 758 throw css::uno::RuntimeException( 759 (rtl::OUString( 760 RTL_CONSTASCII_USTRINGPARAM( 761 "unexpected com.sun.star.lang." 762 "IllegalArgumentException: ")) 763 + e.Message), 764 object); 765 } 766 undoDefaulted = false; 767 } else if (undoOptional 768 && value.getValueTypeName().matchAsciiL( 769 RTL_CONSTASCII_STRINGPARAM( 770 "com.sun.star.beans.Optional<"))) 771 { 772 css::uno::Reference< css::reflection::XIdlClass > optional( 773 getReflection(value.getValueTypeName())); 774 try { 775 bool present = false; 776 if (!(css::uno::Reference< css::reflection::XIdlField2 >( 777 optional->getField( 778 rtl::OUString( 779 RTL_CONSTASCII_USTRINGPARAM("IsPresent"))), 780 css::uno::UNO_QUERY_THROW)->get(value) 781 >>= present)) 782 { 783 throw css::uno::RuntimeException( 784 rtl::OUString( 785 RTL_CONSTASCII_USTRINGPARAM( 786 "unexpected type of com.sun.star.beans.Optional" 787 " IsPresent member")), 788 object); 789 } 790 if (!present) { 791 value.clear(); 792 break; 793 } 794 value = css::uno::Reference< css::reflection::XIdlField2 >( 795 optional->getField( 796 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))), 797 css::uno::UNO_QUERY_THROW)->get(value); 798 } catch (css::lang::IllegalArgumentException & e) { 799 throw css::uno::RuntimeException( 800 (rtl::OUString( 801 RTL_CONSTASCII_USTRINGPARAM( 802 "unexpected com.sun.star.lang." 803 "IllegalArgumentException: ")) 804 + e.Message), 805 object); 806 } 807 undoOptional = false; 808 } else { 809 throw css::uno::RuntimeException( 810 (rtl::OUString( 811 RTL_CONSTASCII_USTRINGPARAM( 812 "unexpected type of attribute ")) 813 + name), 814 object); 815 } 816 } 817 if (state != 0) { 818 //XXX If isAmbiguous && isDefaulted, arbitrarily choose AMBIGUOUS_VALUE 819 // over DEFAULT_VALUE: 820 *state = isAmbiguous 821 ? css::beans::PropertyState_AMBIGUOUS_VALUE 822 : isDefaulted 823 ? css::beans::PropertyState_DEFAULT_VALUE 824 : css::beans::PropertyState_DIRECT_VALUE; 825 } 826 return value; 827 } 828 829 css::uno::Reference< css::reflection::XIdlClass > 830 PropertySetMixinImpl::Impl::getReflection(rtl::OUString const & typeName) const 831 { 832 css::uno::Reference< css::lang::XMultiComponentFactory > factory( 833 m_context->getServiceManager(), css::uno::UNO_QUERY_THROW); 834 AutoDispose< css::reflection::XIdlReflection > refl; 835 try { 836 refl.ifc = css::uno::Reference< css::reflection::XIdlReflection >( 837 factory->createInstanceWithContext( 838 rtl::OUString( 839 RTL_CONSTASCII_USTRINGPARAM( 840 "com.sun.star.reflection.CoreReflection")), 841 m_context), 842 css::uno::UNO_QUERY_THROW); 843 } catch (css::uno::RuntimeException &) { 844 throw; 845 } catch (css::uno::Exception & e) { 846 throw css::uno::DeploymentException( 847 (rtl::OUString( 848 RTL_CONSTASCII_USTRINGPARAM( 849 "component context fails to supply service" 850 " com.sun.star.reflection.CoreReflection: ")) 851 + e.Message), 852 m_context); 853 } 854 css::uno::Reference< css::reflection::XIdlClass > idlClass( 855 refl.ifc->forName(typeName), css::uno::UNO_QUERY_THROW); 856 refl.dispose(); 857 return idlClass; 858 } 859 860 css::uno::Any PropertySetMixinImpl::Impl::wrapValue( 861 css::uno::Reference< css::uno::XInterface > const & object, 862 css::uno::Any const & value, 863 css::uno::Reference< css::reflection::XIdlClass > const & type, 864 bool wrapAmbiguous, bool isAmbiguous, bool wrapDefaulted, bool isDefaulted, 865 bool wrapOptional) 866 { 867 OSL_ASSERT( 868 (wrapAmbiguous || !isAmbiguous) && (wrapDefaulted || !isDefaulted)); 869 if (wrapAmbiguous 870 && type->getName().matchAsciiL( 871 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<"))) 872 { 873 css::uno::Any strct; 874 type->createObject(strct); 875 try { 876 css::uno::Reference< css::reflection::XIdlField2 > field( 877 type->getField( 878 rtl::OUString( 879 RTL_CONSTASCII_USTRINGPARAM("Value"))), 880 css::uno::UNO_QUERY_THROW); 881 field->set( 882 strct, 883 wrapValue( 884 object, value, field->getType(), false, false, 885 wrapDefaulted, isDefaulted, wrapOptional)); 886 css::uno::Reference< css::reflection::XIdlField2 >( 887 type->getField( 888 rtl::OUString( 889 RTL_CONSTASCII_USTRINGPARAM("IsAmbiguous"))), 890 css::uno::UNO_QUERY_THROW)->set( 891 strct, css::uno::makeAny(isAmbiguous)); 892 } catch (css::lang::IllegalArgumentException & e) { 893 throw css::uno::RuntimeException( 894 (rtl::OUString( 895 RTL_CONSTASCII_USTRINGPARAM( 896 "unexpected" 897 " com.sun.star.lang.IllegalArgumentException: ")) 898 + e.Message), 899 object); 900 } catch (css::lang::IllegalAccessException & e) { 901 throw css::uno::RuntimeException( 902 (rtl::OUString( 903 RTL_CONSTASCII_USTRINGPARAM( 904 "unexpected" 905 " com.sun.star.lang.IllegalAccessException: ")) 906 + e.Message), 907 object); 908 } 909 return strct; 910 } else if (wrapDefaulted 911 && type->getName().matchAsciiL( 912 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Defaulted<"))) 913 { 914 css::uno::Any strct; 915 type->createObject(strct); 916 try { 917 css::uno::Reference< css::reflection::XIdlField2 > field( 918 type->getField( 919 rtl::OUString( 920 RTL_CONSTASCII_USTRINGPARAM("Value"))), 921 css::uno::UNO_QUERY_THROW); 922 field->set( 923 strct, 924 wrapValue( 925 object, value, field->getType(), wrapAmbiguous, isAmbiguous, 926 false, false, wrapOptional)); 927 css::uno::Reference< css::reflection::XIdlField2 >( 928 type->getField( 929 rtl::OUString( 930 RTL_CONSTASCII_USTRINGPARAM("IsDefaulted"))), 931 css::uno::UNO_QUERY_THROW)->set( 932 strct, css::uno::makeAny(isDefaulted)); 933 } catch (css::lang::IllegalArgumentException & e) { 934 throw css::uno::RuntimeException( 935 (rtl::OUString( 936 RTL_CONSTASCII_USTRINGPARAM( 937 "unexpected" 938 " com.sun.star.lang.IllegalArgumentException: ")) 939 + e.Message), 940 object); 941 } catch (css::lang::IllegalAccessException & e) { 942 throw css::uno::RuntimeException( 943 (rtl::OUString( 944 RTL_CONSTASCII_USTRINGPARAM( 945 "unexpected" 946 " com.sun.star.lang.IllegalAccessException: ")) 947 + e.Message), 948 object); 949 } 950 return strct; 951 } else if (wrapOptional 952 && type->getName().matchAsciiL( 953 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Optional<"))) 954 { 955 css::uno::Any strct; 956 type->createObject(strct); 957 bool present = value.hasValue(); 958 try { 959 css::uno::Reference< css::reflection::XIdlField2 >( 960 type->getField( 961 rtl::OUString( 962 RTL_CONSTASCII_USTRINGPARAM("IsPresent"))), 963 css::uno::UNO_QUERY_THROW)->set( 964 strct, css::uno::makeAny(present)); 965 if (present) { 966 css::uno::Reference< css::reflection::XIdlField2 > field( 967 type->getField( 968 rtl::OUString( 969 RTL_CONSTASCII_USTRINGPARAM("Value"))), 970 css::uno::UNO_QUERY_THROW); 971 field->set( 972 strct, 973 wrapValue( 974 object, value, field->getType(), wrapAmbiguous, 975 isAmbiguous, wrapDefaulted, isDefaulted, false)); 976 } 977 } catch (css::lang::IllegalArgumentException & e) { 978 throw css::uno::RuntimeException( 979 (rtl::OUString( 980 RTL_CONSTASCII_USTRINGPARAM( 981 "unexpected" 982 " com.sun.star.lang.IllegalArgumentException: ")) 983 + e.Message), 984 object); 985 } catch (css::lang::IllegalAccessException & e) { 986 throw css::uno::RuntimeException( 987 (rtl::OUString( 988 RTL_CONSTASCII_USTRINGPARAM( 989 "unexpected" 990 " com.sun.star.lang.IllegalAccessException: ")) 991 + e.Message), 992 object); 993 } 994 return strct; 995 } else { 996 if (wrapAmbiguous || wrapDefaulted || wrapOptional) { 997 throw css::uno::RuntimeException( 998 rtl::OUString( 999 RTL_CONSTASCII_USTRINGPARAM( 1000 "unexpected type of attribute")), 1001 object); 1002 } 1003 return value; 1004 } 1005 } 1006 1007 PropertySetMixinImpl::PropertySetMixinImpl( 1008 css::uno::Reference< css::uno::XComponentContext > const & context, 1009 Implements implements, 1010 css::uno::Sequence< rtl::OUString > const & absentOptional, 1011 css::uno::Type const & type) 1012 { 1013 m_impl = new Impl(context, implements, absentOptional, type); 1014 m_impl->acquire(); 1015 } 1016 1017 PropertySetMixinImpl::~PropertySetMixinImpl() { 1018 m_impl->release(); 1019 } 1020 1021 void PropertySetMixinImpl::checkUnknown(rtl::OUString const & propertyName) { 1022 if (propertyName.getLength() != 0) { 1023 m_impl->get( 1024 static_cast< css::beans::XPropertySet * >(this), propertyName); 1025 } 1026 } 1027 1028 void PropertySetMixinImpl::prepareSet( 1029 rtl::OUString const & propertyName, css::uno::Any const & oldValue, 1030 css::uno::Any const & newValue, BoundListeners * boundListeners) 1031 { 1032 Impl::PropertyMap::const_iterator it(m_impl->properties.find(propertyName)); 1033 OSL_ASSERT(it != m_impl->properties.end()); 1034 Impl::VetoListenerBag specificVeto; 1035 Impl::VetoListenerBag unspecificVeto; 1036 { 1037 osl::MutexGuard g(m_impl->mutex); 1038 if (m_impl->disposed) { 1039 throw css::lang::DisposedException( 1040 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("disposed")), 1041 static_cast< css::beans::XPropertySet * >(this)); 1042 } 1043 if ((it->second.property.Attributes 1044 & css::beans::PropertyAttribute::CONSTRAINED) 1045 != 0) 1046 { 1047 Impl::VetoListenerMap::const_iterator i( 1048 m_impl->vetoListeners.find(propertyName)); 1049 if (i != m_impl->vetoListeners.end()) { 1050 specificVeto = i->second; 1051 } 1052 i = m_impl->vetoListeners.find(rtl::OUString()); 1053 if (i != m_impl->vetoListeners.end()) { 1054 unspecificVeto = i->second; 1055 } 1056 } 1057 if ((it->second.property.Attributes 1058 & css::beans::PropertyAttribute::BOUND) 1059 != 0) 1060 { 1061 OSL_ASSERT(boundListeners != 0); 1062 Impl::BoundListenerMap::const_iterator i( 1063 m_impl->boundListeners.find(propertyName)); 1064 if (i != m_impl->boundListeners.end()) { 1065 boundListeners->m_impl->specificListeners = i->second; 1066 } 1067 i = m_impl->boundListeners.find(rtl::OUString()); 1068 if (i != m_impl->boundListeners.end()) { 1069 boundListeners->m_impl->unspecificListeners = i->second; 1070 } 1071 } 1072 } 1073 if ((it->second.property.Attributes 1074 & css::beans::PropertyAttribute::CONSTRAINED) 1075 != 0) 1076 { 1077 css::beans::PropertyChangeEvent event( 1078 static_cast< css::beans::XPropertySet * >(this), propertyName, 1079 false, it->second.property.Handle, oldValue, newValue); 1080 for (Impl::VetoListenerBag::iterator i(specificVeto.begin()); 1081 i != specificVeto.end(); ++i) 1082 { 1083 try { 1084 (*i)->vetoableChange(event); 1085 } catch (css::lang::DisposedException &) {} 1086 } 1087 for (Impl::VetoListenerBag::iterator i(unspecificVeto.begin()); 1088 i != unspecificVeto.end(); ++i) 1089 { 1090 try { 1091 (*i)->vetoableChange(event); 1092 } catch (css::lang::DisposedException &) {} 1093 } 1094 } 1095 if ((it->second.property.Attributes & css::beans::PropertyAttribute::BOUND) 1096 != 0) 1097 { 1098 OSL_ASSERT(boundListeners != 0); 1099 boundListeners->m_impl->event = css::beans::PropertyChangeEvent( 1100 static_cast< css::beans::XPropertySet * >(this), propertyName, 1101 false, it->second.property.Handle, oldValue, newValue); 1102 } 1103 } 1104 1105 void PropertySetMixinImpl::dispose() { 1106 Impl::BoundListenerMap boundListeners; 1107 Impl::VetoListenerMap vetoListeners; 1108 { 1109 osl::MutexGuard g(m_impl->mutex); 1110 boundListeners.swap(m_impl->boundListeners); 1111 vetoListeners.swap(m_impl->vetoListeners); 1112 m_impl->disposed = true; 1113 } 1114 css::lang::EventObject event( 1115 static_cast< css::beans::XPropertySet * >(this)); 1116 for (Impl::BoundListenerMap::iterator i(boundListeners.begin()); 1117 i != boundListeners.end(); ++i) 1118 { 1119 for (BoundListenerBag::iterator j(i->second.begin()); 1120 j != i->second.end(); ++j) 1121 { 1122 (*j)->disposing(event); 1123 } 1124 } 1125 for (Impl::VetoListenerMap::iterator i(vetoListeners.begin()); 1126 i != vetoListeners.end(); ++i) 1127 { 1128 for (Impl::VetoListenerBag::iterator j(i->second.begin()); 1129 j != i->second.end(); ++j) 1130 { 1131 (*j)->disposing(event); 1132 } 1133 } 1134 } 1135 1136 css::uno::Any PropertySetMixinImpl::queryInterface(css::uno::Type const & type) 1137 throw (css::uno::RuntimeException) 1138 { 1139 if (((m_impl->implements & IMPLEMENTS_PROPERTY_SET) != 0 1140 && type == css::beans::XPropertySet::static_type())) 1141 { 1142 css::uno::Reference< css::uno::XInterface > ifc( 1143 static_cast< css::beans::XPropertySet * >(this)); 1144 return css::uno::Any(&ifc, type); 1145 } else if ((m_impl->implements & IMPLEMENTS_FAST_PROPERTY_SET) != 0 1146 && type == css::beans::XFastPropertySet::static_type()) 1147 { 1148 css::uno::Reference< css::uno::XInterface > ifc( 1149 static_cast< css::beans::XFastPropertySet * >(this)); 1150 return css::uno::Any(&ifc, type); 1151 } else if ((m_impl->implements & IMPLEMENTS_PROPERTY_ACCESS) != 0 1152 && type == css::beans::XPropertyAccess::static_type()) 1153 { 1154 css::uno::Reference< css::uno::XInterface > ifc( 1155 static_cast< css::beans::XPropertyAccess * >(this)); 1156 return css::uno::Any(&ifc, type); 1157 } else { 1158 return css::uno::Any(); 1159 } 1160 } 1161 1162 css::uno::Reference< css::beans::XPropertySetInfo > 1163 PropertySetMixinImpl::getPropertySetInfo() throw (css::uno::RuntimeException) { 1164 try { 1165 return new Info(m_impl); 1166 } catch (std::bad_alloc &) { 1167 //TODO OutOfMemoryException: 1168 throw css::uno::RuntimeException( 1169 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1170 } 1171 } 1172 1173 void PropertySetMixinImpl::setPropertyValue( 1174 rtl::OUString const & propertyName, css::uno::Any const & value) 1175 throw ( 1176 css::beans::UnknownPropertyException, css::beans::PropertyVetoException, 1177 css::lang::IllegalArgumentException, css::lang::WrappedTargetException, 1178 css::uno::RuntimeException) 1179 { 1180 try { 1181 m_impl->setProperty( 1182 static_cast< css::beans::XPropertySet * >(this), propertyName, 1183 value, false, false, 1); 1184 } catch (std::bad_alloc &) { 1185 //TODO OutOfMemoryException: 1186 throw css::uno::RuntimeException( 1187 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1188 } 1189 } 1190 1191 css::uno::Any PropertySetMixinImpl::getPropertyValue( 1192 rtl::OUString const & propertyName) 1193 throw ( 1194 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1195 css::uno::RuntimeException) 1196 { 1197 try { 1198 return m_impl->getProperty( 1199 static_cast< css::beans::XPropertySet * >(this), propertyName, 0); 1200 } catch (std::bad_alloc &) { 1201 //TODO OutOfMemoryException: 1202 throw css::uno::RuntimeException( 1203 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1204 } 1205 } 1206 1207 void PropertySetMixinImpl::addPropertyChangeListener( 1208 rtl::OUString const & propertyName, 1209 css::uno::Reference< css::beans::XPropertyChangeListener > const & listener) 1210 throw ( 1211 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1212 css::uno::RuntimeException) 1213 { 1214 css::uno::Reference< css::beans::XPropertyChangeListener >( 1215 listener, css::uno::UNO_QUERY_THROW); // reject NULL listener 1216 checkUnknown(propertyName); 1217 try { 1218 bool disposed; 1219 { 1220 osl::MutexGuard g(m_impl->mutex); 1221 disposed = m_impl->disposed; 1222 if (!disposed) { 1223 m_impl->boundListeners[propertyName].insert(listener); 1224 } 1225 } 1226 if (disposed) { 1227 listener->disposing( 1228 css::lang::EventObject( 1229 static_cast< css::beans::XPropertySet * >(this))); 1230 } 1231 } catch (std::bad_alloc &) { 1232 //TODO OutOfMemoryException: 1233 throw css::uno::RuntimeException( 1234 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1235 } 1236 } 1237 1238 void PropertySetMixinImpl::removePropertyChangeListener( 1239 rtl::OUString const & propertyName, 1240 css::uno::Reference< css::beans::XPropertyChangeListener > const & listener) 1241 throw ( 1242 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1243 css::uno::RuntimeException) 1244 { 1245 OSL_ASSERT(listener.is()); 1246 checkUnknown(propertyName); 1247 try { 1248 osl::MutexGuard g(m_impl->mutex); 1249 Impl::BoundListenerMap::iterator i( 1250 m_impl->boundListeners.find(propertyName)); 1251 if (i != m_impl->boundListeners.end()) { 1252 BoundListenerBag::iterator j(i->second.find(listener)); 1253 if (j != i->second.end()) { 1254 i->second.erase(j); 1255 } 1256 } 1257 } catch (std::bad_alloc &) { 1258 //TODO OutOfMemoryException: 1259 throw css::uno::RuntimeException( 1260 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1261 } 1262 } 1263 1264 void PropertySetMixinImpl::addVetoableChangeListener( 1265 rtl::OUString const & propertyName, 1266 css::uno::Reference< css::beans::XVetoableChangeListener > const & listener) 1267 throw ( 1268 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1269 css::uno::RuntimeException) 1270 { 1271 css::uno::Reference< css::beans::XVetoableChangeListener >( 1272 listener, css::uno::UNO_QUERY_THROW); // reject NULL listener 1273 checkUnknown(propertyName); 1274 try { 1275 bool disposed; 1276 { 1277 osl::MutexGuard g(m_impl->mutex); 1278 disposed = m_impl->disposed; 1279 if (!disposed) { 1280 m_impl->vetoListeners[propertyName].insert(listener); 1281 } 1282 } 1283 if (disposed) { 1284 listener->disposing( 1285 css::lang::EventObject( 1286 static_cast< css::beans::XPropertySet * >(this))); 1287 } 1288 } catch (std::bad_alloc &) { 1289 //TODO OutOfMemoryException: 1290 throw css::uno::RuntimeException( 1291 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1292 } 1293 } 1294 1295 void PropertySetMixinImpl::removeVetoableChangeListener( 1296 rtl::OUString const & propertyName, 1297 css::uno::Reference< css::beans::XVetoableChangeListener > const & listener) 1298 throw ( 1299 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1300 css::uno::RuntimeException) 1301 { 1302 OSL_ASSERT(listener.is()); 1303 checkUnknown(propertyName); 1304 try { 1305 osl::MutexGuard g(m_impl->mutex); 1306 Impl::VetoListenerMap::iterator i( 1307 m_impl->vetoListeners.find(propertyName)); 1308 if (i != m_impl->vetoListeners.end()) { 1309 Impl::VetoListenerBag::iterator j(i->second.find(listener)); 1310 if (j != i->second.end()) { 1311 i->second.erase(j); 1312 } 1313 } 1314 } catch (std::bad_alloc &) { 1315 //TODO OutOfMemoryException: 1316 throw css::uno::RuntimeException( 1317 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1318 } 1319 } 1320 1321 void PropertySetMixinImpl::setFastPropertyValue( 1322 sal_Int32 handle, css::uno::Any const & value) 1323 throw ( 1324 css::beans::UnknownPropertyException, css::beans::PropertyVetoException, 1325 css::lang::IllegalArgumentException, css::lang::WrappedTargetException, 1326 css::uno::RuntimeException) 1327 { 1328 try { 1329 m_impl->setProperty( 1330 static_cast< css::beans::XPropertySet * >(this), 1331 m_impl->translateHandle( 1332 static_cast< css::beans::XPropertySet * >(this), handle), 1333 value, false, false, 1); 1334 } catch (std::bad_alloc &) { 1335 //TODO OutOfMemoryException: 1336 throw css::uno::RuntimeException( 1337 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1338 } 1339 } 1340 1341 css::uno::Any PropertySetMixinImpl::getFastPropertyValue(sal_Int32 handle) 1342 throw ( 1343 css::beans::UnknownPropertyException, css::lang::WrappedTargetException, 1344 css::uno::RuntimeException) 1345 { 1346 try { 1347 return m_impl->getProperty( 1348 static_cast< css::beans::XPropertySet * >(this), 1349 m_impl->translateHandle( 1350 static_cast< css::beans::XPropertySet * >(this), handle), 1351 0); 1352 } catch (std::bad_alloc &) { 1353 //TODO OutOfMemoryException: 1354 throw css::uno::RuntimeException( 1355 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1356 } 1357 } 1358 1359 css::uno::Sequence< css::beans::PropertyValue > 1360 PropertySetMixinImpl::getPropertyValues() throw (css::uno::RuntimeException) { 1361 try { 1362 css::uno::Sequence< css::beans::PropertyValue > s( 1363 m_impl->handleMap.getLength()); 1364 sal_Int32 n = 0; 1365 for (sal_Int32 i = 0; i < m_impl->handleMap.getLength(); ++i) { 1366 try { 1367 s[n].Value = m_impl->getProperty( 1368 static_cast< css::beans::XPropertySet * >(this), 1369 m_impl->handleMap[i], &s[n].State); 1370 } catch (css::beans::UnknownPropertyException &) { 1371 continue; 1372 } catch (css::lang::WrappedTargetException & e) { 1373 throw css::lang::WrappedTargetRuntimeException( 1374 e.Message, static_cast< css::beans::XPropertySet * >(this), 1375 e.TargetException); 1376 } 1377 s[n].Name = m_impl->handleMap[i]; 1378 s[n].Handle = i; 1379 ++n; 1380 } 1381 s.realloc(n); 1382 return s; 1383 } catch (std::bad_alloc &) { 1384 //TODO OutOfMemoryException: 1385 throw css::uno::RuntimeException( 1386 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1387 } 1388 } 1389 1390 void PropertySetMixinImpl::setPropertyValues( 1391 css::uno::Sequence< css::beans::PropertyValue > const & props) 1392 throw ( 1393 css::beans::UnknownPropertyException, css::beans::PropertyVetoException, 1394 css::lang::IllegalArgumentException, css::lang::WrappedTargetException, 1395 css::uno::RuntimeException) 1396 { 1397 try { 1398 for (sal_Int32 i = 0; i < props.getLength(); ++i) { 1399 if (props[i].Handle != -1 1400 && (props[i].Name 1401 != m_impl->translateHandle( 1402 static_cast< css::beans::XPropertySet * >(this), 1403 props[i].Handle))) 1404 { 1405 throw css::beans::UnknownPropertyException( 1406 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("name ")) 1407 + props[i].Name 1408 + rtl::OUString( 1409 RTL_CONSTASCII_USTRINGPARAM(" does not match handle ")) 1410 + rtl::OUString::valueOf(props[i].Handle)), 1411 static_cast< css::beans::XPropertySet * >(this)); 1412 } 1413 m_impl->setProperty( 1414 static_cast< css::beans::XPropertySet * >(this), props[i].Name, 1415 props[i].Value, 1416 props[i].State == css::beans::PropertyState_AMBIGUOUS_VALUE, 1417 props[i].State == css::beans::PropertyState_DEFAULT_VALUE, 0); 1418 } 1419 } catch (std::bad_alloc &) { 1420 //TODO OutOfMemoryException: 1421 throw css::uno::RuntimeException( 1422 rtl::OUString(), static_cast< css::beans::XPropertySet * >(this)); 1423 } 1424 } 1425