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