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