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__anon7e0f37ac0111::AutoDispose97 AutoDispose() {}
98
~AutoDispose__anon7e0f37ac0111::AutoDispose99 ~AutoDispose() {
100 try {
101 dispose();
102 } catch (...) {}
103 }
104
dispose__anon7e0f37ac0111::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__anon7e0f37ac0111::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__anon7e0f37ac0111::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 SAL_DLLPRIVATE 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