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