3ebbdfec20
2007/06/05 08:17:25 sb 1.5.24.1: #i68624# Do not crash on adding NULL listeners.
1436 lines
56 KiB
C++
1436 lines
56 KiB
C++
/*************************************************************************
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: propertysetmixin.cxx,v $
|
|
*
|
|
* $Revision: 1.6 $
|
|
*
|
|
* last change: $Author: hr $ $Date: 2007-06-27 13:21:55 $
|
|
*
|
|
* The Contents of this file are made available subject to
|
|
* the terms of GNU Lesser General Public License Version 2.1.
|
|
*
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2005 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_cppuhelper.hxx"
|
|
|
|
#include "sal/config.h"
|
|
|
|
#include "cppuhelper/propertysetmixin.hxx"
|
|
|
|
#include "com/sun/star/beans/Property.hpp"
|
|
#include "com/sun/star/beans/PropertyChangeEvent.hpp"
|
|
#include "com/sun/star/beans/PropertyAttribute.hpp"
|
|
#include "com/sun/star/beans/PropertyValue.hpp"
|
|
#include "com/sun/star/beans/PropertyVetoException.hpp"
|
|
#include "com/sun/star/beans/UnknownPropertyException.hpp"
|
|
#include "com/sun/star/beans/XFastPropertySet.hpp"
|
|
#include "com/sun/star/beans/XPropertyAccess.hpp"
|
|
#include "com/sun/star/beans/XPropertyChangeListener.hpp"
|
|
#include "com/sun/star/beans/XPropertySet.hpp"
|
|
#include "com/sun/star/beans/XPropertySetInfo.hpp"
|
|
#include "com/sun/star/beans/XVetoableChangeListener.hpp"
|
|
#include "com/sun/star/container/NoSuchElementException.hpp"
|
|
#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
|
|
#include "com/sun/star/lang/DisposedException.hpp"
|
|
#include "com/sun/star/lang/EventObject.hpp"
|
|
#include "com/sun/star/lang/IllegalAccessException.hpp"
|
|
#include "com/sun/star/lang/IllegalArgumentException.hpp"
|
|
#include "com/sun/star/lang/WrappedTargetException.hpp"
|
|
#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
|
|
#include "com/sun/star/lang/XComponent.hpp"
|
|
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
|
|
#include "com/sun/star/reflection/XCompoundTypeDescription.hpp"
|
|
#include "com/sun/star/reflection/XIdlClass.hpp"
|
|
#include "com/sun/star/reflection/XIdlField2.hpp"
|
|
#include "com/sun/star/reflection/XIdlReflection.hpp"
|
|
#include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
|
|
#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp"
|
|
#include "com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp"
|
|
#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
|
|
#include "com/sun/star/reflection/XStructTypeDescription.hpp"
|
|
#include "com/sun/star/reflection/XTypeDescription.hpp"
|
|
#include "com/sun/star/uno/Any.hxx"
|
|
#include "com/sun/star/uno/DeploymentException.hpp"
|
|
#include "com/sun/star/uno/Exception.hpp"
|
|
#include "com/sun/star/uno/Reference.hxx"
|
|
#include "com/sun/star/uno/RuntimeException.hpp"
|
|
#include "com/sun/star/uno/Sequence.hxx"
|
|
#include "com/sun/star/uno/Type.hxx"
|
|
#include "com/sun/star/uno/TypeClass.hpp"
|
|
#include "com/sun/star/uno/XComponentContext.hpp"
|
|
#include "com/sun/star/uno/XInterface.hpp"
|
|
#include "cppuhelper/implbase1.hxx"
|
|
#include "cppuhelper/weak.hxx"
|
|
#include "osl/diagnose.h"
|
|
#include "osl/mutex.hxx"
|
|
#include "rtl/ref.hxx"
|
|
#include "rtl/string.h"
|
|
#include "rtl/ustring.h"
|
|
#include "rtl/ustring.hxx"
|
|
#include "sal/types.h"
|
|
#include "salhelper/simplereferenceobject.hxx"
|
|
|
|
#include <algorithm>
|
|
#include <map>
|
|
#include <new>
|
|
#include <set>
|
|
#include <vector>
|
|
|
|
using cppu::PropertySetMixinImpl;
|
|
|
|
namespace css = com::sun::star;
|
|
|
|
namespace {
|
|
|
|
template< typename T > struct AutoDispose {
|
|
AutoDispose() {}
|
|
|
|
~AutoDispose() {
|
|
try {
|
|
dispose();
|
|
} catch (...) {}
|
|
}
|
|
|
|
void dispose() {
|
|
css::uno::Reference< css::lang::XComponent > comp(
|
|
ifc, css::uno::UNO_QUERY);
|
|
if (comp.is()) {
|
|
comp->dispose();
|
|
}
|
|
ifc.clear();
|
|
}
|
|
|
|
css::uno::Reference< T > ifc;
|
|
|
|
private:
|
|
AutoDispose(AutoDispose &); // not defined
|
|
void operator =(AutoDispose); // not defined
|
|
};
|
|
|
|
struct PropertyData {
|
|
explicit PropertyData(
|
|
css::beans::Property const & theProperty, bool thePresent):
|
|
property(theProperty), present(thePresent) {}
|
|
|
|
css::beans::Property property;
|
|
bool present;
|
|
};
|
|
|
|
struct Data: public salhelper::SimpleReferenceObject {
|
|
typedef std::map< rtl::OUString, PropertyData > PropertyMap;
|
|
|
|
PropertyMap properties;
|
|
|
|
PropertyMap::const_iterator get(
|
|
css::uno::Reference< css::uno::XInterface > const & object,
|
|
rtl::OUString const & name) const;
|
|
|
|
protected:
|
|
void initProperties(
|
|
css::uno::Reference< css::reflection::XTypeDescription > const & type,
|
|
css::uno::Sequence< rtl::OUString > const & absentOptional,
|
|
std::vector< rtl::OUString > * handleNames)
|
|
{
|
|
TypeSet seen;
|
|
initProperties(type, absentOptional, handleNames, &seen);
|
|
}
|
|
|
|
private:
|
|
typedef std::set< rtl::OUString > TypeSet;
|
|
|
|
void initProperties(
|
|
css::uno::Reference< css::reflection::XTypeDescription > const & type,
|
|
css::uno::Sequence< rtl::OUString > const & absentOptional,
|
|
std::vector< rtl::OUString > * handleNames, TypeSet * seen);
|
|
|
|
static css::uno::Reference< css::reflection::XTypeDescription >
|
|
resolveTypedefs(
|
|
css::uno::Reference< css::reflection::XTypeDescription > const & type);
|
|
};
|
|
|
|
Data::PropertyMap::const_iterator Data::get(
|
|
css::uno::Reference< css::uno::XInterface > const & object,
|
|
rtl::OUString const & name) const
|
|
{
|
|
PropertyMap::const_iterator i(properties.find(name));
|
|
if (i == properties.end() || !i->second.present) {
|
|
throw css::beans::UnknownPropertyException(name, object);
|
|
}
|
|
return i;
|
|
}
|
|
|
|
void Data::initProperties(
|
|
css::uno::Reference< css::reflection::XTypeDescription > const & type,
|
|
css::uno::Sequence< rtl::OUString > const & absentOptional,
|
|
std::vector< rtl::OUString > * handleNames, TypeSet * seen)
|
|
{
|
|
css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > ifc(
|
|
resolveTypedefs(type), css::uno::UNO_QUERY_THROW);
|
|
if (seen->insert(ifc->getName()).second) {
|
|
css::uno::Sequence<
|
|
css::uno::Reference< css::reflection::XTypeDescription > > bases(
|
|
ifc->getBaseTypes());
|
|
for (sal_Int32 i = 0; i < bases.getLength(); ++i) {
|
|
initProperties(bases[i], absentOptional, handleNames, seen);
|
|
}
|
|
css::uno::Sequence<
|
|
css::uno::Reference<
|
|
css::reflection::XInterfaceMemberTypeDescription > > members(
|
|
ifc->getMembers());
|
|
rtl::OUString const * absentBegin = absentOptional.getConstArray();
|
|
rtl::OUString const * absentEnd =
|
|
absentBegin + absentOptional.getLength();
|
|
for (sal_Int32 i = 0; i < members.getLength(); ++i) {
|
|
if (members[i]->getTypeClass()
|
|
== css::uno::TypeClass_INTERFACE_ATTRIBUTE)
|
|
{
|
|
css::uno::Reference<
|
|
css::reflection::XInterfaceAttributeTypeDescription2 > attr(
|
|
members[i], css::uno::UNO_QUERY_THROW);
|
|
sal_Int16 attrAttribs = 0;
|
|
if (attr->isBound()) {
|
|
attrAttribs |= css::beans::PropertyAttribute::BOUND;
|
|
}
|
|
bool setUnknown = false;
|
|
if (attr->isReadOnly()) {
|
|
attrAttribs |= css::beans::PropertyAttribute::READONLY;
|
|
setUnknown = true;
|
|
}
|
|
css::uno::Sequence<
|
|
css::uno::Reference<
|
|
css::reflection::XCompoundTypeDescription > > excs(
|
|
attr->getGetExceptions());
|
|
bool getUnknown = false;
|
|
//XXX Special interpretation of getter/setter exceptions only
|
|
// works if the specified exceptions are of the exact type, not
|
|
// of a supertype:
|
|
for (sal_Int32 j = 0; j < excs.getLength(); ++j) {
|
|
if (excs[j]->getName().equalsAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans.UnknownPropertyException")))
|
|
{
|
|
getUnknown = true;
|
|
break;
|
|
}
|
|
}
|
|
excs = attr->getSetExceptions();
|
|
for (sal_Int32 j = 0; j < excs.getLength(); ++j) {
|
|
if (excs[j]->getName().equalsAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans.UnknownPropertyException")))
|
|
{
|
|
setUnknown = true;
|
|
} else if (excs[j]->getName().equalsAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans."
|
|
"PropertyVetoException")))
|
|
{
|
|
attrAttribs
|
|
|= css::beans::PropertyAttribute::CONSTRAINED;
|
|
}
|
|
}
|
|
if (getUnknown && setUnknown) {
|
|
attrAttribs |= css::beans::PropertyAttribute::OPTIONAL;
|
|
}
|
|
css::uno::Reference< css::reflection::XTypeDescription > t(
|
|
attr->getType());
|
|
for (;;)
|
|
{
|
|
t = resolveTypedefs(t);
|
|
sal_Int16 n;
|
|
if (t->getName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans.Ambiguous<")))
|
|
{
|
|
n = css::beans::PropertyAttribute::MAYBEAMBIGUOUS;
|
|
} else if (t->getName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans.Defaulted<")))
|
|
{
|
|
n = css::beans::PropertyAttribute::MAYBEDEFAULT;
|
|
} else if (t->getName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans.Optional<")))
|
|
{
|
|
n = css::beans::PropertyAttribute::MAYBEVOID;
|
|
} else {
|
|
break;
|
|
}
|
|
if ((attrAttribs & n) != 0) {
|
|
break;
|
|
}
|
|
attrAttribs |= n;
|
|
css::uno::Sequence<
|
|
css::uno::Reference< css::reflection::XTypeDescription > >
|
|
args(
|
|
css::uno::Reference<
|
|
css::reflection::XStructTypeDescription >(
|
|
t,
|
|
css::uno::UNO_QUERY_THROW)->getTypeArguments());
|
|
if (args.getLength() != 1) {
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"inconsistent UNO type registry")),
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
}
|
|
t = args[0];
|
|
}
|
|
std::vector< rtl::OUString >::size_type handles
|
|
= handleNames->size();
|
|
if (handles > SAL_MAX_INT32) {
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"interface type has too many attributes")),
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
}
|
|
rtl::OUString name(members[i]->getMemberName());
|
|
if (!properties.insert(
|
|
PropertyMap::value_type(
|
|
name,
|
|
PropertyData(
|
|
css::beans::Property(
|
|
name, static_cast< sal_Int32 >(handles),
|
|
css::uno::Type(
|
|
t->getTypeClass(), t->getName()),
|
|
attrAttribs),
|
|
(std::find(absentBegin, absentEnd, name)
|
|
== absentEnd)))).
|
|
second)
|
|
{
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"inconsistent UNO type registry")),
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
}
|
|
handleNames->push_back(name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
css::uno::Reference< css::reflection::XTypeDescription > Data::resolveTypedefs(
|
|
css::uno::Reference< css::reflection::XTypeDescription > const & type)
|
|
{
|
|
css::uno::Reference< css::reflection::XTypeDescription > t(type);
|
|
while (t->getTypeClass() == css::uno::TypeClass_TYPEDEF) {
|
|
t = css::uno::Reference< css::reflection::XIndirectTypeDescription >(
|
|
t, css::uno::UNO_QUERY_THROW)->getReferencedType();
|
|
}
|
|
return t;
|
|
}
|
|
|
|
class Info: public cppu::WeakImplHelper1< css::beans::XPropertySetInfo > {
|
|
public:
|
|
explicit Info(Data * data): m_data(data) {}
|
|
|
|
virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties()
|
|
throw (css::uno::RuntimeException);
|
|
|
|
virtual css::beans::Property SAL_CALL getPropertyByName(
|
|
rtl::OUString const & name)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::uno::RuntimeException);
|
|
|
|
virtual sal_Bool SAL_CALL hasPropertyByName(rtl::OUString const & name)
|
|
throw (css::uno::RuntimeException);
|
|
|
|
private:
|
|
rtl::Reference< Data > m_data;
|
|
};
|
|
|
|
css::uno::Sequence< css::beans::Property > Info::getProperties()
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
try {
|
|
OSL_ASSERT(m_data->properties.size() <= SAL_MAX_INT32);
|
|
css::uno::Sequence< css::beans::Property > s(
|
|
static_cast< sal_Int32 >(m_data->properties.size()));
|
|
sal_Int32 n = 0;
|
|
for (Data::PropertyMap::iterator i(m_data->properties.begin());
|
|
i != m_data->properties.end(); ++i)
|
|
{
|
|
if (i->second.present) {
|
|
s[n++] = i->second.property;
|
|
}
|
|
}
|
|
s.realloc(n);
|
|
return s;
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< cppu::OWeakObject * >(this));
|
|
}
|
|
}
|
|
|
|
css::beans::Property Info::getPropertyByName(rtl::OUString const & name)
|
|
throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
|
|
{
|
|
return m_data->get(static_cast< cppu::OWeakObject * >(this), name)->
|
|
second.property;
|
|
}
|
|
|
|
sal_Bool Info::hasPropertyByName(rtl::OUString const & name)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
Data::PropertyMap::iterator i(m_data->properties.find(name));
|
|
return i != m_data->properties.end() && i->second.present;
|
|
}
|
|
|
|
typedef
|
|
std::multiset< css::uno::Reference< css::beans::XPropertyChangeListener > >
|
|
BoundListenerBag;
|
|
|
|
}
|
|
|
|
class PropertySetMixinImpl::BoundListeners::Impl {
|
|
public:
|
|
BoundListenerBag specificListeners;
|
|
BoundListenerBag unspecificListeners;
|
|
css::beans::PropertyChangeEvent event;
|
|
};
|
|
|
|
PropertySetMixinImpl::BoundListeners::BoundListeners(): m_impl(new Impl) {}
|
|
|
|
PropertySetMixinImpl::BoundListeners::~BoundListeners() {
|
|
delete m_impl;
|
|
}
|
|
|
|
void PropertySetMixinImpl::BoundListeners::notify() const {
|
|
for (BoundListenerBag::const_iterator i(m_impl->specificListeners.begin());
|
|
i != m_impl->specificListeners.end(); ++i)
|
|
{
|
|
try {
|
|
(*i)->propertyChange(m_impl->event);
|
|
} catch (css::lang::DisposedException &) {}
|
|
}
|
|
for (BoundListenerBag::const_iterator i(
|
|
m_impl->unspecificListeners.begin());
|
|
i != m_impl->unspecificListeners.end(); ++i)
|
|
{
|
|
try {
|
|
(*i)->propertyChange(m_impl->event);
|
|
} catch (css::lang::DisposedException &) {}
|
|
}
|
|
}
|
|
|
|
class PropertySetMixinImpl::Impl: public Data {
|
|
public:
|
|
Impl(
|
|
css::uno::Reference< css::uno::XComponentContext > const & context,
|
|
Implements theImplements,
|
|
css::uno::Sequence< rtl::OUString > const & absentOptional,
|
|
css::uno::Type const & type);
|
|
|
|
rtl::OUString translateHandle(
|
|
css::uno::Reference< css::uno::XInterface > const & object,
|
|
sal_Int32 handle) const;
|
|
|
|
void 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)
|
|
const;
|
|
|
|
css::uno::Any getProperty(
|
|
css::uno::Reference< css::uno::XInterface > const & object,
|
|
rtl::OUString const & name, css::beans::PropertyState * state) const;
|
|
|
|
PropertySetMixinImpl::Implements implements;
|
|
css::uno::Sequence< rtl::OUString > handleMap;
|
|
|
|
typedef std::map< rtl::OUString, BoundListenerBag > BoundListenerMap;
|
|
|
|
typedef
|
|
std::multiset< css::uno::Reference< css::beans::XVetoableChangeListener > >
|
|
VetoListenerBag;
|
|
|
|
typedef std::map< rtl::OUString, VetoListenerBag > VetoListenerMap;
|
|
|
|
mutable osl::Mutex mutex;
|
|
BoundListenerMap boundListeners;
|
|
VetoListenerMap vetoListeners;
|
|
bool disposed;
|
|
|
|
private:
|
|
css::uno::Reference< css::reflection::XIdlClass > getReflection(
|
|
rtl::OUString const & typeName) const;
|
|
|
|
static css::uno::Any 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);
|
|
|
|
css::uno::Reference< css::uno::XComponentContext > const & m_context;
|
|
css::uno::Sequence< rtl::OUString > m_absentOptional;
|
|
css::uno::Type m_type;
|
|
css::uno::Reference< css::reflection::XIdlClass > m_idlClass;
|
|
};
|
|
|
|
PropertySetMixinImpl::Impl::Impl(
|
|
css::uno::Reference< css::uno::XComponentContext > const & context,
|
|
Implements theImplements,
|
|
css::uno::Sequence< rtl::OUString > const & absentOptional,
|
|
css::uno::Type const & type):
|
|
implements(theImplements), disposed(false), m_context(context),
|
|
m_absentOptional(absentOptional), m_type(type)
|
|
{
|
|
OSL_ASSERT(
|
|
context.is()
|
|
&& ((implements
|
|
& ~(IMPLEMENTS_PROPERTY_SET | IMPLEMENTS_FAST_PROPERTY_SET
|
|
| IMPLEMENTS_PROPERTY_ACCESS))
|
|
== 0));
|
|
m_idlClass = getReflection(m_type.getTypeName());
|
|
css::uno::Reference< css::reflection::XTypeDescription > ifc;
|
|
try {
|
|
ifc = css::uno::Reference< css::reflection::XTypeDescription >(
|
|
css::uno::Reference< css::container::XHierarchicalNameAccess >(
|
|
m_context->getValueByName(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"/singletons/com.sun.star.reflection."
|
|
"theTypeDescriptionManager"))),
|
|
css::uno::UNO_QUERY_THROW)->getByHierarchicalName(
|
|
m_type.getTypeName()),
|
|
css::uno::UNO_QUERY_THROW);
|
|
} catch (css::container::NoSuchElementException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.container.NoSuchElementException: "))
|
|
+ e.Message),
|
|
css::uno::Reference< css::uno::XInterface >());
|
|
}
|
|
std::vector< rtl::OUString > handleNames;
|
|
initProperties(ifc, m_absentOptional, &handleNames);
|
|
std::vector< rtl::OUString >::size_type size = handleNames.size();
|
|
OSL_ASSERT(size <= SAL_MAX_INT32);
|
|
handleMap.realloc(static_cast< sal_Int32 >(size));
|
|
std::copy(handleNames.begin(), handleNames.end(), handleMap.getArray());
|
|
}
|
|
|
|
rtl::OUString PropertySetMixinImpl::Impl::translateHandle(
|
|
css::uno::Reference< css::uno::XInterface > const & object,
|
|
sal_Int32 handle) const
|
|
{
|
|
if (handle < 0 || handle >= handleMap.getLength()) {
|
|
throw css::beans::UnknownPropertyException(
|
|
(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad handle "))
|
|
+ rtl::OUString::valueOf(handle)),
|
|
object);
|
|
}
|
|
return handleMap[handle];
|
|
}
|
|
|
|
void PropertySetMixinImpl::Impl::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) const
|
|
{
|
|
PropertyMap::const_iterator i(properties.find(name));
|
|
if (i == properties.end()) {
|
|
throw css::beans::UnknownPropertyException(name, object);
|
|
}
|
|
if ((isAmbiguous
|
|
&& ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEAMBIGUOUS)
|
|
== 0))
|
|
|| (isDefaulted
|
|
&& ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEDEFAULT)
|
|
== 0)))
|
|
{
|
|
throw css::lang::IllegalArgumentException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"flagging as ambiguous/defaulted non-ambiguous/defaulted"
|
|
" property "))
|
|
+ name),
|
|
object, illegalArgumentPosition);
|
|
}
|
|
css::uno::Reference< css::reflection::XIdlField2 > f(
|
|
m_idlClass->getField(name), css::uno::UNO_QUERY_THROW);
|
|
css::uno::Any o(object->queryInterface(m_type));
|
|
css::uno::Any v(
|
|
wrapValue(
|
|
object, value,
|
|
(css::uno::Reference< css::reflection::XIdlField2 >(
|
|
m_idlClass->getField(name), css::uno::UNO_QUERY_THROW)->
|
|
getType()),
|
|
((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEAMBIGUOUS)
|
|
!= 0),
|
|
isAmbiguous,
|
|
((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEDEFAULT)
|
|
!= 0),
|
|
isDefaulted,
|
|
((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEVOID)
|
|
!= 0)));
|
|
try {
|
|
f->set(o, v);
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
if (e.ArgumentPosition == 1) {
|
|
throw css::lang::IllegalArgumentException(
|
|
e.Message, object, illegalArgumentPosition);
|
|
} else {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.lang.IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
}
|
|
} catch (css::lang::IllegalAccessException &) {
|
|
//TODO Clarify whether PropertyVetoException is the correct exception
|
|
// to throw when trying to set a read-only property:
|
|
throw css::beans::PropertyVetoException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("cannot set read-only property "))
|
|
+ name),
|
|
object);
|
|
} catch (css::lang::WrappedTargetRuntimeException & e) {
|
|
//FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
|
|
// guaranteed to originate directly within XIdlField2.get (and thus have
|
|
// the expected semantics); it might also be passed through from lower
|
|
// layers.
|
|
if (e.TargetException.isExtractableTo(
|
|
getCppuType(
|
|
static_cast< css::beans::UnknownPropertyException * >(0)))
|
|
&& ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::OPTIONAL)
|
|
!= 0))
|
|
{
|
|
throw css::beans::UnknownPropertyException(name, object);
|
|
} else if (e.TargetException.isExtractableTo(
|
|
getCppuType(
|
|
static_cast< css::beans::PropertyVetoException * >(
|
|
0)))
|
|
&& ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::CONSTRAINED)
|
|
!= 0))
|
|
{
|
|
throw css::beans::PropertyVetoException(name, object);
|
|
} else {
|
|
throw css::lang::WrappedTargetException(
|
|
e.Message, object, e.TargetException);
|
|
}
|
|
}
|
|
}
|
|
|
|
css::uno::Any PropertySetMixinImpl::Impl::getProperty(
|
|
css::uno::Reference< css::uno::XInterface > const & object,
|
|
rtl::OUString const & name, css::beans::PropertyState * state) const
|
|
{
|
|
PropertyMap::const_iterator i(properties.find(name));
|
|
if (i == properties.end()) {
|
|
throw css::beans::UnknownPropertyException(name, object);
|
|
}
|
|
css::uno::Reference< css::reflection::XIdlField2 > field(
|
|
m_idlClass->getField(name), css::uno::UNO_QUERY_THROW);
|
|
css::uno::Any value;
|
|
try {
|
|
value = field->get(object->queryInterface(m_type));
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected com.sun.star.lang.IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
} catch (css::lang::WrappedTargetRuntimeException & e) {
|
|
//FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
|
|
// guaranteed to originate directly within XIdlField2.get (and thus have
|
|
// the expected semantics); it might also be passed through from lower
|
|
// layers.
|
|
if (e.TargetException.isExtractableTo(
|
|
getCppuType(
|
|
static_cast< css::beans::UnknownPropertyException * >(0)))
|
|
&& ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::OPTIONAL)
|
|
!= 0))
|
|
{
|
|
throw css::beans::UnknownPropertyException(name, object);
|
|
} else {
|
|
throw css::lang::WrappedTargetException(
|
|
e.Message, object, e.TargetException);
|
|
}
|
|
}
|
|
bool undoAmbiguous
|
|
= ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEAMBIGUOUS)
|
|
!= 0);
|
|
bool undoDefaulted
|
|
= ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEDEFAULT)
|
|
!= 0);
|
|
bool undoOptional
|
|
= ((i->second.property.Attributes
|
|
& css::beans::PropertyAttribute::MAYBEVOID)
|
|
!= 0);
|
|
bool isAmbiguous = false;
|
|
bool isDefaulted = false;
|
|
while (undoAmbiguous || undoDefaulted || undoOptional) {
|
|
if (undoAmbiguous
|
|
&& value.getValueTypeName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<")))
|
|
{
|
|
css::uno::Reference< css::reflection::XIdlClass > ambiguous(
|
|
getReflection(value.getValueTypeName()));
|
|
try {
|
|
if (!(css::uno::Reference< css::reflection::XIdlField2 >(
|
|
ambiguous->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("IsAmbiguous"))),
|
|
css::uno::UNO_QUERY_THROW)->get(value)
|
|
>>= isAmbiguous))
|
|
{
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected type of"
|
|
" com.sun.star.beans.Ambiguous IsAmbiguous"
|
|
" member")),
|
|
object);
|
|
}
|
|
value = css::uno::Reference< css::reflection::XIdlField2 >(
|
|
ambiguous->getField(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))),
|
|
css::uno::UNO_QUERY_THROW)->get(value);
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected com.sun.star.lang."
|
|
"IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
}
|
|
undoAmbiguous = false;
|
|
} else if (undoDefaulted
|
|
&& value.getValueTypeName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans.Defaulted<")))
|
|
{
|
|
css::uno::Reference< css::reflection::XIdlClass > defaulted(
|
|
getReflection(value.getValueTypeName()));
|
|
try {
|
|
|
|
if (!(css::uno::Reference< css::reflection::XIdlField2 >(
|
|
defaulted->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("IsDefaulted"))),
|
|
css::uno::UNO_QUERY_THROW)->get(value)
|
|
>>= isDefaulted))
|
|
{
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected type of"
|
|
" com.sun.star.beans.Defaulted IsDefaulted"
|
|
" member")),
|
|
object);
|
|
}
|
|
value = css::uno::Reference< css::reflection::XIdlField2 >(
|
|
defaulted->getField(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))),
|
|
css::uno::UNO_QUERY_THROW)->get(value);
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected com.sun.star.lang."
|
|
"IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
}
|
|
undoDefaulted = false;
|
|
} else if (undoOptional
|
|
&& value.getValueTypeName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM(
|
|
"com.sun.star.beans.Optional<")))
|
|
{
|
|
css::uno::Reference< css::reflection::XIdlClass > optional(
|
|
getReflection(value.getValueTypeName()));
|
|
try {
|
|
bool present = false;
|
|
if (!(css::uno::Reference< css::reflection::XIdlField2 >(
|
|
optional->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("IsPresent"))),
|
|
css::uno::UNO_QUERY_THROW)->get(value)
|
|
>>= present))
|
|
{
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected type of com.sun.star.beans.Optional"
|
|
" IsPresent member")),
|
|
object);
|
|
}
|
|
if (!present) {
|
|
value.clear();
|
|
break;
|
|
}
|
|
value = css::uno::Reference< css::reflection::XIdlField2 >(
|
|
optional->getField(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"))),
|
|
css::uno::UNO_QUERY_THROW)->get(value);
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected com.sun.star.lang."
|
|
"IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
}
|
|
undoOptional = false;
|
|
} else {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected type of attribute "))
|
|
+ name),
|
|
object);
|
|
}
|
|
}
|
|
if (state != 0) {
|
|
//XXX If isAmbiguous && isDefaulted, arbitrarily choose AMBIGUOUS_VALUE
|
|
// over DEFAULT_VALUE:
|
|
*state = isAmbiguous
|
|
? css::beans::PropertyState_AMBIGUOUS_VALUE
|
|
: isDefaulted
|
|
? css::beans::PropertyState_DEFAULT_VALUE
|
|
: css::beans::PropertyState_DIRECT_VALUE;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
css::uno::Reference< css::reflection::XIdlClass >
|
|
PropertySetMixinImpl::Impl::getReflection(rtl::OUString const & typeName) const
|
|
{
|
|
css::uno::Reference< css::lang::XMultiComponentFactory > factory(
|
|
m_context->getServiceManager(), css::uno::UNO_QUERY_THROW);
|
|
AutoDispose< css::reflection::XIdlReflection > refl;
|
|
try {
|
|
refl.ifc = css::uno::Reference< css::reflection::XIdlReflection >(
|
|
factory->createInstanceWithContext(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"com.sun.star.reflection.CoreReflection")),
|
|
m_context),
|
|
css::uno::UNO_QUERY_THROW);
|
|
} catch (css::uno::RuntimeException &) {
|
|
throw;
|
|
} catch (css::uno::Exception & e) {
|
|
throw css::uno::DeploymentException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"component context fails to supply service"
|
|
" com.sun.star.reflection.CoreReflection: "))
|
|
+ e.Message),
|
|
m_context);
|
|
}
|
|
css::uno::Reference< css::reflection::XIdlClass > idlClass(
|
|
refl.ifc->forName(typeName), css::uno::UNO_QUERY_THROW);
|
|
refl.dispose();
|
|
return idlClass;
|
|
}
|
|
|
|
css::uno::Any PropertySetMixinImpl::Impl::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)
|
|
{
|
|
OSL_ASSERT(
|
|
(wrapAmbiguous || !isAmbiguous) && (wrapDefaulted || !isDefaulted));
|
|
if (wrapAmbiguous
|
|
&& type->getName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<")))
|
|
{
|
|
css::uno::Any strct;
|
|
type->createObject(strct);
|
|
try {
|
|
css::uno::Reference< css::reflection::XIdlField2 > field(
|
|
type->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("Value"))),
|
|
css::uno::UNO_QUERY_THROW);
|
|
field->set(
|
|
strct,
|
|
wrapValue(
|
|
object, value, field->getType(), false, false,
|
|
wrapDefaulted, isDefaulted, wrapOptional));
|
|
css::uno::Reference< css::reflection::XIdlField2 >(
|
|
type->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("IsAmbiguous"))),
|
|
css::uno::UNO_QUERY_THROW)->set(
|
|
strct, css::uno::makeAny(isAmbiguous));
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.lang.IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
} catch (css::lang::IllegalAccessException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.lang.IllegalAccessException: "))
|
|
+ e.Message),
|
|
object);
|
|
}
|
|
return strct;
|
|
} else if (wrapDefaulted
|
|
&& type->getName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Defaulted<")))
|
|
{
|
|
css::uno::Any strct;
|
|
type->createObject(strct);
|
|
try {
|
|
css::uno::Reference< css::reflection::XIdlField2 > field(
|
|
type->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("Value"))),
|
|
css::uno::UNO_QUERY_THROW);
|
|
field->set(
|
|
strct,
|
|
wrapValue(
|
|
object, value, field->getType(), wrapAmbiguous, isAmbiguous,
|
|
false, false, wrapOptional));
|
|
css::uno::Reference< css::reflection::XIdlField2 >(
|
|
type->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("IsDefaulted"))),
|
|
css::uno::UNO_QUERY_THROW)->set(
|
|
strct, css::uno::makeAny(isDefaulted));
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.lang.IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
} catch (css::lang::IllegalAccessException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.lang.IllegalAccessException: "))
|
|
+ e.Message),
|
|
object);
|
|
}
|
|
return strct;
|
|
} else if (wrapOptional
|
|
&& type->getName().matchAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Optional<")))
|
|
{
|
|
css::uno::Any strct;
|
|
type->createObject(strct);
|
|
bool present = value.hasValue();
|
|
try {
|
|
css::uno::Reference< css::reflection::XIdlField2 >(
|
|
type->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("IsPresent"))),
|
|
css::uno::UNO_QUERY_THROW)->set(
|
|
strct, css::uno::makeAny(present));
|
|
if (present) {
|
|
css::uno::Reference< css::reflection::XIdlField2 > field(
|
|
type->getField(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("Value"))),
|
|
css::uno::UNO_QUERY_THROW);
|
|
field->set(
|
|
strct,
|
|
wrapValue(
|
|
object, value, field->getType(), wrapAmbiguous,
|
|
isAmbiguous, wrapDefaulted, isDefaulted, false));
|
|
}
|
|
} catch (css::lang::IllegalArgumentException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.lang.IllegalArgumentException: "))
|
|
+ e.Message),
|
|
object);
|
|
} catch (css::lang::IllegalAccessException & e) {
|
|
throw css::uno::RuntimeException(
|
|
(rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected"
|
|
" com.sun.star.lang.IllegalAccessException: "))
|
|
+ e.Message),
|
|
object);
|
|
}
|
|
return strct;
|
|
} else {
|
|
if (wrapAmbiguous || wrapDefaulted || wrapOptional) {
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(
|
|
"unexpected type of attribute")),
|
|
object);
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
|
|
PropertySetMixinImpl::PropertySetMixinImpl(
|
|
css::uno::Reference< css::uno::XComponentContext > const & context,
|
|
Implements implements,
|
|
css::uno::Sequence< rtl::OUString > const & absentOptional,
|
|
css::uno::Type const & type)
|
|
{
|
|
m_impl = new Impl(context, implements, absentOptional, type);
|
|
m_impl->acquire();
|
|
}
|
|
|
|
PropertySetMixinImpl::~PropertySetMixinImpl() {
|
|
m_impl->release();
|
|
}
|
|
|
|
void PropertySetMixinImpl::checkUnknown(rtl::OUString const & propertyName) {
|
|
if (propertyName.getLength() != 0) {
|
|
m_impl->get(
|
|
static_cast< css::beans::XPropertySet * >(this), propertyName);
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::prepareSet(
|
|
rtl::OUString const & propertyName, css::uno::Any const & oldValue,
|
|
css::uno::Any const & newValue, BoundListeners * boundListeners)
|
|
{
|
|
Impl::PropertyMap::const_iterator it(m_impl->properties.find(propertyName));
|
|
OSL_ASSERT(it != m_impl->properties.end());
|
|
Impl::VetoListenerBag specificVeto;
|
|
Impl::VetoListenerBag unspecificVeto;
|
|
{
|
|
osl::MutexGuard g(m_impl->mutex);
|
|
if (m_impl->disposed) {
|
|
throw css::lang::DisposedException(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("disposed")),
|
|
static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
if ((it->second.property.Attributes
|
|
& css::beans::PropertyAttribute::CONSTRAINED)
|
|
!= 0)
|
|
{
|
|
Impl::VetoListenerMap::const_iterator i(
|
|
m_impl->vetoListeners.find(propertyName));
|
|
if (i != m_impl->vetoListeners.end()) {
|
|
specificVeto = i->second;
|
|
}
|
|
i = m_impl->vetoListeners.find(rtl::OUString());
|
|
if (i != m_impl->vetoListeners.end()) {
|
|
unspecificVeto = i->second;
|
|
}
|
|
}
|
|
if ((it->second.property.Attributes
|
|
& css::beans::PropertyAttribute::BOUND)
|
|
!= 0)
|
|
{
|
|
OSL_ASSERT(boundListeners != 0);
|
|
Impl::BoundListenerMap::const_iterator i(
|
|
m_impl->boundListeners.find(propertyName));
|
|
if (i != m_impl->boundListeners.end()) {
|
|
boundListeners->m_impl->specificListeners = i->second;
|
|
}
|
|
i = m_impl->boundListeners.find(rtl::OUString());
|
|
if (i != m_impl->boundListeners.end()) {
|
|
boundListeners->m_impl->unspecificListeners = i->second;
|
|
}
|
|
}
|
|
}
|
|
if ((it->second.property.Attributes
|
|
& css::beans::PropertyAttribute::CONSTRAINED)
|
|
!= 0)
|
|
{
|
|
css::beans::PropertyChangeEvent event(
|
|
static_cast< css::beans::XPropertySet * >(this), propertyName,
|
|
false, it->second.property.Handle, oldValue, newValue);
|
|
for (Impl::VetoListenerBag::iterator i(specificVeto.begin());
|
|
i != specificVeto.end(); ++i)
|
|
{
|
|
try {
|
|
(*i)->vetoableChange(event);
|
|
} catch (css::lang::DisposedException &) {}
|
|
}
|
|
for (Impl::VetoListenerBag::iterator i(unspecificVeto.begin());
|
|
i != unspecificVeto.end(); ++i)
|
|
{
|
|
try {
|
|
(*i)->vetoableChange(event);
|
|
} catch (css::lang::DisposedException &) {}
|
|
}
|
|
}
|
|
if ((it->second.property.Attributes & css::beans::PropertyAttribute::BOUND)
|
|
!= 0)
|
|
{
|
|
OSL_ASSERT(boundListeners != 0);
|
|
boundListeners->m_impl->event = css::beans::PropertyChangeEvent(
|
|
static_cast< css::beans::XPropertySet * >(this), propertyName,
|
|
false, it->second.property.Handle, oldValue, newValue);
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::dispose() {
|
|
Impl::BoundListenerMap boundListeners;
|
|
Impl::VetoListenerMap vetoListeners;
|
|
{
|
|
osl::MutexGuard g(m_impl->mutex);
|
|
boundListeners.swap(m_impl->boundListeners);
|
|
vetoListeners.swap(m_impl->vetoListeners);
|
|
m_impl->disposed = true;
|
|
}
|
|
css::lang::EventObject event(
|
|
static_cast< css::beans::XPropertySet * >(this));
|
|
for (Impl::BoundListenerMap::iterator i(boundListeners.begin());
|
|
i != boundListeners.end(); ++i)
|
|
{
|
|
for (BoundListenerBag::iterator j(i->second.begin());
|
|
j != i->second.end(); ++j)
|
|
{
|
|
(*j)->disposing(event);
|
|
}
|
|
}
|
|
for (Impl::VetoListenerMap::iterator i(vetoListeners.begin());
|
|
i != vetoListeners.end(); ++i)
|
|
{
|
|
for (Impl::VetoListenerBag::iterator j(i->second.begin());
|
|
j != i->second.end(); ++j)
|
|
{
|
|
(*j)->disposing(event);
|
|
}
|
|
}
|
|
}
|
|
|
|
css::uno::Any PropertySetMixinImpl::queryInterface(css::uno::Type const & type)
|
|
throw (css::uno::RuntimeException)
|
|
{
|
|
if (((m_impl->implements & IMPLEMENTS_PROPERTY_SET) != 0
|
|
&& type == css::beans::XPropertySet::static_type()))
|
|
{
|
|
css::uno::Reference< css::uno::XInterface > ifc(
|
|
static_cast< css::beans::XPropertySet * >(this));
|
|
return css::uno::Any(&ifc, type);
|
|
} else if ((m_impl->implements & IMPLEMENTS_FAST_PROPERTY_SET) != 0
|
|
&& type == css::beans::XFastPropertySet::static_type())
|
|
{
|
|
css::uno::Reference< css::uno::XInterface > ifc(
|
|
static_cast< css::beans::XFastPropertySet * >(this));
|
|
return css::uno::Any(&ifc, type);
|
|
} else if ((m_impl->implements & IMPLEMENTS_PROPERTY_ACCESS) != 0
|
|
&& type == css::beans::XPropertyAccess::static_type())
|
|
{
|
|
css::uno::Reference< css::uno::XInterface > ifc(
|
|
static_cast< css::beans::XPropertyAccess * >(this));
|
|
return css::uno::Any(&ifc, type);
|
|
} else {
|
|
return css::uno::Any();
|
|
}
|
|
}
|
|
|
|
css::uno::Reference< css::beans::XPropertySetInfo >
|
|
PropertySetMixinImpl::getPropertySetInfo() throw (css::uno::RuntimeException) {
|
|
try {
|
|
return new Info(m_impl);
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::setPropertyValue(
|
|
rtl::OUString const & propertyName, css::uno::Any const & value)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
|
|
css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
try {
|
|
m_impl->setProperty(
|
|
static_cast< css::beans::XPropertySet * >(this), propertyName,
|
|
value, false, false, 1);
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
css::uno::Any PropertySetMixinImpl::getPropertyValue(
|
|
rtl::OUString const & propertyName)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
try {
|
|
return m_impl->getProperty(
|
|
static_cast< css::beans::XPropertySet * >(this), propertyName, 0);
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::addPropertyChangeListener(
|
|
rtl::OUString const & propertyName,
|
|
css::uno::Reference< css::beans::XPropertyChangeListener > const & listener)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
css::uno::Reference< css::beans::XPropertyChangeListener >(
|
|
listener, css::uno::UNO_QUERY_THROW); // reject NULL listener
|
|
checkUnknown(propertyName);
|
|
try {
|
|
bool disposed;
|
|
{
|
|
osl::MutexGuard g(m_impl->mutex);
|
|
disposed = m_impl->disposed;
|
|
if (!disposed) {
|
|
m_impl->boundListeners[propertyName].insert(listener);
|
|
}
|
|
}
|
|
if (disposed) {
|
|
listener->disposing(
|
|
css::lang::EventObject(
|
|
static_cast< css::beans::XPropertySet * >(this)));
|
|
}
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::removePropertyChangeListener(
|
|
rtl::OUString const & propertyName,
|
|
css::uno::Reference< css::beans::XPropertyChangeListener > const & listener)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
OSL_ASSERT(listener.is());
|
|
checkUnknown(propertyName);
|
|
try {
|
|
osl::MutexGuard g(m_impl->mutex);
|
|
Impl::BoundListenerMap::iterator i(
|
|
m_impl->boundListeners.find(propertyName));
|
|
if (i != m_impl->boundListeners.end()) {
|
|
BoundListenerBag::iterator j(i->second.find(listener));
|
|
if (j != i->second.end()) {
|
|
i->second.erase(j);
|
|
}
|
|
}
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::addVetoableChangeListener(
|
|
rtl::OUString const & propertyName,
|
|
css::uno::Reference< css::beans::XVetoableChangeListener > const & listener)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
css::uno::Reference< css::beans::XVetoableChangeListener >(
|
|
listener, css::uno::UNO_QUERY_THROW); // reject NULL listener
|
|
checkUnknown(propertyName);
|
|
try {
|
|
bool disposed;
|
|
{
|
|
osl::MutexGuard g(m_impl->mutex);
|
|
disposed = m_impl->disposed;
|
|
if (!disposed) {
|
|
m_impl->vetoListeners[propertyName].insert(listener);
|
|
}
|
|
}
|
|
if (disposed) {
|
|
listener->disposing(
|
|
css::lang::EventObject(
|
|
static_cast< css::beans::XPropertySet * >(this)));
|
|
}
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::removeVetoableChangeListener(
|
|
rtl::OUString const & propertyName,
|
|
css::uno::Reference< css::beans::XVetoableChangeListener > const & listener)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
OSL_ASSERT(listener.is());
|
|
checkUnknown(propertyName);
|
|
try {
|
|
osl::MutexGuard g(m_impl->mutex);
|
|
Impl::VetoListenerMap::iterator i(
|
|
m_impl->vetoListeners.find(propertyName));
|
|
if (i != m_impl->vetoListeners.end()) {
|
|
Impl::VetoListenerBag::iterator j(i->second.find(listener));
|
|
if (j != i->second.end()) {
|
|
i->second.erase(j);
|
|
}
|
|
}
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::setFastPropertyValue(
|
|
sal_Int32 handle, css::uno::Any const & value)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
|
|
css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
try {
|
|
m_impl->setProperty(
|
|
static_cast< css::beans::XPropertySet * >(this),
|
|
m_impl->translateHandle(
|
|
static_cast< css::beans::XPropertySet * >(this), handle),
|
|
value, false, false, 1);
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
css::uno::Any PropertySetMixinImpl::getFastPropertyValue(sal_Int32 handle)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
try {
|
|
return m_impl->getProperty(
|
|
static_cast< css::beans::XPropertySet * >(this),
|
|
m_impl->translateHandle(
|
|
static_cast< css::beans::XPropertySet * >(this), handle),
|
|
0);
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
css::uno::Sequence< css::beans::PropertyValue >
|
|
PropertySetMixinImpl::getPropertyValues() throw (css::uno::RuntimeException) {
|
|
try {
|
|
css::uno::Sequence< css::beans::PropertyValue > s(
|
|
m_impl->handleMap.getLength());
|
|
sal_Int32 n = 0;
|
|
for (sal_Int32 i = 0; i < m_impl->handleMap.getLength(); ++i) {
|
|
try {
|
|
s[n].Value = m_impl->getProperty(
|
|
static_cast< css::beans::XPropertySet * >(this),
|
|
m_impl->handleMap[i], &s[n].State);
|
|
} catch (css::beans::UnknownPropertyException &) {
|
|
continue;
|
|
} catch (css::lang::WrappedTargetException & e) {
|
|
throw css::lang::WrappedTargetRuntimeException(
|
|
e.Message, static_cast< css::beans::XPropertySet * >(this),
|
|
e.TargetException);
|
|
}
|
|
s[n].Name = m_impl->handleMap[i];
|
|
s[n].Handle = i;
|
|
++n;
|
|
}
|
|
s.realloc(n);
|
|
return s;
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|
|
|
|
void PropertySetMixinImpl::setPropertyValues(
|
|
css::uno::Sequence< css::beans::PropertyValue > const & props)
|
|
throw (
|
|
css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
|
|
css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
|
|
css::uno::RuntimeException)
|
|
{
|
|
try {
|
|
for (sal_Int32 i = 0; i < props.getLength(); ++i) {
|
|
if (props[i].Handle != -1
|
|
&& (props[i].Name
|
|
!= m_impl->translateHandle(
|
|
static_cast< css::beans::XPropertySet * >(this),
|
|
props[i].Handle)))
|
|
{
|
|
throw css::beans::UnknownPropertyException(
|
|
(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("name "))
|
|
+ props[i].Name
|
|
+ rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM(" does not match handle "))
|
|
+ rtl::OUString::valueOf(props[i].Handle)),
|
|
static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
m_impl->setProperty(
|
|
static_cast< css::beans::XPropertySet * >(this), props[i].Name,
|
|
props[i].Value,
|
|
props[i].State == css::beans::PropertyState_AMBIGUOUS_VALUE,
|
|
props[i].State == css::beans::PropertyState_DEFAULT_VALUE, 0);
|
|
}
|
|
} catch (std::bad_alloc &) {
|
|
//TODO OutOfMemoryException:
|
|
throw css::uno::RuntimeException(
|
|
rtl::OUString(), static_cast< css::beans::XPropertySet * >(this));
|
|
}
|
|
}
|