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