diff options
author | sb <sb@openoffice.org> | 2009-09-22 10:36:09 +0200 |
---|---|---|
committer | sb <sb@openoffice.org> | 2009-09-22 10:36:09 +0200 |
commit | ec826ada913dcbe494f07055683538f525d80418 (patch) | |
tree | 62e2ed3f3c71179e161ea6d2314a000d401cbe58 | |
parent | b5ba31ba01639a189a0c7077b763a2c3dd02a347 (diff) |
#i101955# rudimentary notification support, continued (to be continued; known to not work correctly yet)
-rw-r--r-- | configmgr2/qa/unit/test.cxx | 2 | ||||
-rw-r--r-- | configmgr2/source/access.cxx | 583 | ||||
-rw-r--r-- | configmgr2/source/access.hxx | 133 | ||||
-rw-r--r-- | configmgr2/source/broadcaster.cxx | 179 | ||||
-rw-r--r-- | configmgr2/source/broadcaster.hxx | 131 | ||||
-rw-r--r-- | configmgr2/source/childaccess.cxx | 33 | ||||
-rw-r--r-- | configmgr2/source/childaccess.hxx | 20 | ||||
-rw-r--r-- | configmgr2/source/components.cxx | 11 | ||||
-rw-r--r-- | configmgr2/source/rootaccess.cxx | 117 | ||||
-rw-r--r-- | configmgr2/source/rootaccess.hxx | 35 |
10 files changed, 1031 insertions, 213 deletions
diff --git a/configmgr2/qa/unit/test.cxx b/configmgr2/qa/unit/test.cxx index 9ce74cf8093c..d7fa8eed753f 100644 --- a/configmgr2/qa/unit/test.cxx +++ b/configmgr2/qa/unit/test.cxx @@ -297,7 +297,7 @@ void RecursiveTest::disposing(css::lang::EventObject const & Source) properties_.clear(); } -void RecursiveTest::propertyChange(css::beans::PropertyChangeEvent const &) +void RecursiveTest::propertyChange(css::beans::PropertyChangeEvent const & evt) throw (css::uno::RuntimeException) { CPPUNIT_ASSERT( diff --git a/configmgr2/source/access.cxx b/configmgr2/source/access.cxx index 190037db67f1..aef585f7d2a9 100644 --- a/configmgr2/source/access.cxx +++ b/configmgr2/source/access.cxx @@ -37,15 +37,37 @@ #include "com/sun/star/beans/PropertyChangeEvent.hpp" #include "com/sun/star/beans/PropertyVetoException.hpp" #include "com/sun/star/beans/UnknownPropertyException.hpp" +#include "com/sun/star/beans/XExactName.hpp" +#include "com/sun/star/beans/XHierarchicalPropertySet.hpp" +#include "com/sun/star/beans/XHierarchicalPropertySetInfo.hpp" +#include "com/sun/star/beans/XMultiHierarchicalPropertySet.hpp" +#include "com/sun/star/beans/XMultiPropertySet.hpp" #include "com/sun/star/beans/XPropertiesChangeListener.hpp" +#include "com/sun/star/beans/XProperty.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/ContainerEvent.hpp" #include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XContainer.hpp" #include "com/sun/star/container/XContainerListener.hpp" +#include "com/sun/star/container/XElementAccess.hpp" +#include "com/sun/star/container/XHierarchicalName.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/container/XNameContainer.hpp" +#include "com/sun/star/container/XNamed.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/EventObject.hpp" #include "com/sun/star/lang/IllegalArgumentException.hpp" #include "com/sun/star/lang/NoSupportException.hpp" #include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/lang/XTypeProvider.hpp" #include "com/sun/star/lang/XUnoTunnel.hpp" #include "com/sun/star/uno/Any.hxx" #include "com/sun/star/uno/Reference.hxx" @@ -54,12 +76,14 @@ #include "com/sun/star/uno/Type.hxx" #include "com/sun/star/uno/TypeClass.hpp" #include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uno/XWeak.hpp" #include "com/sun/star/util/ElementChange.hpp" #include "comphelper/sequenceasvector.hxx" #include "cppu/unotype.hxx" -#include "cppuhelper/interfacecontainer.hxx" +#include "cppuhelper/queryinterface.hxx" #include "cppuhelper/weak.hxx" #include "osl/diagnose.h" +#include "osl/interlck.h" #include "osl/mutex.hxx" #include "rtl/ref.hxx" #include "rtl/ustrbuf.hxx" @@ -92,6 +116,14 @@ namespace css = com::sun::star; } +oslInterlockedCount Access::acquireCounting() { + return osl_incrementInterlockedCount(&m_refCount); +} + +void Access::releaseNondeleting() { + osl_decrementInterlockedCount(&m_refCount); +} + bool Access::isValue() { rtl::Reference< Node > p(getNode()); switch (p->kind()) { @@ -130,22 +162,52 @@ void Access::initGlobalBroadcaster( Modifications const & globalModifications, Broadcaster * broadcaster) { OSL_ASSERT(broadcaster != 0); - cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer( - cppu::UnoType< css::beans::XPropertyChangeListener >::get()); - if (cont != 0) { - css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > els( - cont->getElements()); //TODO: performance - for (sal_Int32 i = 0; i < els.getLength(); ++i) { - //TODO: only for matching modifications - broadcaster->addPropertyChange( - css::uno::Reference< css::beans::XPropertyChangeListener >( - els[i], css::uno::UNO_QUERY_THROW), + //TODO: only for matching modifications: + for (ContainerListeners::iterator i(containerListeners_.begin()); + i != containerListeners_.end(); ++i) + { + broadcaster->addContainerNotification( + *i, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::Any()/*TODO*/, css::uno::Any()/*TODO*/, + css::uno::Any()/*TODO*/)); + } + for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin()); + i != propertyChangeListeners_.end(); ++i) + { + for (PropertyChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addPropertyChangeNotification( + *j, css::beans::PropertyChangeEvent( static_cast< cppu::OWeakObject * >(this), getNameInternal(), false, -1, css::uno::Any(), css::uno::Any())); } } - //TODO: iterate over children w/ listeners (incl. unmodified ones) + for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin()); + i != vetoableChangeListeners_.end(); ++i) + { + for (VetoableChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addVetoableChangeNotification( + *j, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), getNameInternal(), + false, -1, css::uno::Any(), css::uno::Any())); + } + } + for (PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.begin()); + i != propertiesChangeListeners_.end(); ++i) + { + broadcaster->addPropertiesChangeNotification( + *i, + css::uno::Sequence< css::beans::PropertyChangeEvent >()/*TODO*/); + } + //TODO: iterate over children w/ listeners (incl. unmodified ones): for (ModifiedChildren::iterator i(modifiedChildren_.begin()); i != modifiedChildren_.end(); ++i) { @@ -156,66 +218,182 @@ void Access::initGlobalBroadcaster( } } -Access::Access(): AccessBase(lock) {} +Access::Access(): disposed_(false) {} Access::~Access() {} +void Access::initDisposeBroadcaster(Broadcaster * broadcaster) { + OSL_ASSERT(broadcaster != 0); + for (DisposeListeners::iterator i(disposeListeners_.begin()); + i != disposeListeners_.end(); ++i) + { + broadcaster->addDisposeNotification( + *i, + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } + for (ContainerListeners::iterator i(containerListeners_.begin()); + i != containerListeners_.end(); ++i) + { + broadcaster->addDisposeNotification( + i->get(), + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } + for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin()); + i != propertyChangeListeners_.end(); ++i) + { + for (PropertyChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addDisposeNotification( + j->get(), + css::lang::EventObject( + static_cast< cppu::OWeakObject * >(this))); + } + } + for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin()); + i != vetoableChangeListeners_.end(); ++i) + { + for (VetoableChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addDisposeNotification( + j->get(), + css::lang::EventObject( + static_cast< cppu::OWeakObject * >(this))); + } + } + for (PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.begin()); + i != propertiesChangeListeners_.end(); ++i) + { + broadcaster->addDisposeNotification( + i->get(), + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } + //TODO: iterate over children w/ listeners (incl. unmodified ones): + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + child->initDisposeBroadcaster(broadcaster); + } + } +} + +void Access::initLocalBroadcaster( + Modifications const & localModifications, Broadcaster * broadcaster) +{ + OSL_ASSERT(broadcaster != 0); + //TODO: only for matching modifications: + for (ContainerListeners::iterator i(containerListeners_.begin()); + i != containerListeners_.end(); ++i) + { + broadcaster->addContainerNotification( + *i, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::Any()/*TODO*/, css::uno::Any()/*TODO*/, + css::uno::Any()/*TODO*/)); + } + for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin()); + i != propertyChangeListeners_.end(); ++i) + { + for (PropertyChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addPropertyChangeNotification( + *j, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), getNameInternal(), + false, -1, css::uno::Any(), css::uno::Any())); + } + } + for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin()); + i != vetoableChangeListeners_.end(); ++i) + { + for (VetoableChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addVetoableChangeNotification( + *j, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), getNameInternal(), + false, -1, css::uno::Any(), css::uno::Any())); + } + } + for (PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.begin()); + i != propertiesChangeListeners_.end(); ++i) + { + broadcaster->addPropertiesChangeNotification( + *i, + css::uno::Sequence< css::beans::PropertyChangeEvent >()/*TODO*/); + } + //TODO: iterate over children w/ listeners (incl. unmodified ones): + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + child->initLocalBroadcaster(localModifications, broadcaster); + } + } +} + css::uno::Any Access::queryInterface(css::uno::Type const & aType) throw (css::uno::RuntimeException) { - OSL_ASSERT(thisIs(IS_ANY)); - osl::MutexGuard g(lock); - checkLocalizedPropertyAccess(); - css::uno::Any res(AccessBase::queryInterface(aType)); + css::uno::Any res(OWeakObject::queryInterface(aType)); if (res.hasValue()) { - if (aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM("com.sun.beans.XPropertySetInfo")) || - aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM("com.sun.beans.XPropertySet")) || - aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( - "com.sun.beans.XMultiPropertySet")) || - aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( - "com.sun.beans.XHierarchicalPropertySet")) || - aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( - "com.sun.beans.XMultiHierarchicalPropertySet")) || - aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( - "com.sun.beans.XHierarchicalPropertySetInfo"))) - { - if (getNode()->kind() != Node::KIND_GROUP) { - res.clear(); - } - } else if (aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( - "com.sun.star.container.XNameReplace"))) - { - if (!getRootAccess()->isUpdate()) { - res.clear(); - } - } else if (aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( - "com.sun.star.container.XNameContainer"))) - { - if ((getNode()->kind() == Node::KIND_GROUP && - !dynamic_cast< GroupNode * >( - getNode().get())->isExtensible()) || - !getRootAccess()->isUpdate()) - { - res.clear(); - } - } else if (aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( - "com.sun.star.lang.XSingleServiceFactory"))) + return res; + } + res = cppu::queryInterface( + aType, static_cast< css::lang::XTypeProvider * >(this), + static_cast< css::lang::XServiceInfo * >(this), + static_cast< css::lang::XComponent * >(this), + static_cast< css::container::XHierarchicalNameAccess * >(this), + static_cast< css::container::XContainer * >(this), + static_cast< css::beans::XExactName * >(this), + static_cast< css::container::XHierarchicalName * >(this), + static_cast< css::container::XNamed * >(this), + static_cast< css::beans::XProperty * >(this), + static_cast< css::container::XElementAccess * >(this), + static_cast< css::container::XNameAccess * >(this)); + if (res.hasValue()) { + return res; + } + if (getNode()->kind() == Node::KIND_GROUP) { + res = cppu::queryInterface( + aType, static_cast< css::beans::XPropertySetInfo * >(this), + static_cast< css::beans::XPropertySet * >(this), + static_cast< css::beans::XMultiPropertySet * >(this), + static_cast< css::beans::XHierarchicalPropertySet * >(this), + static_cast< css::beans::XMultiHierarchicalPropertySet * >(this), + static_cast< css::beans::XHierarchicalPropertySetInfo * >(this)); + if (res.hasValue()) { + return res; + } + } + if (getRootAccess()->isUpdate()) { + res = cppu::queryInterface( + aType, static_cast< css::container::XNameReplace * >(this)); + if (res.hasValue()) { + return res; + } + if (getNode()->kind() != Node::KIND_GROUP || + dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) { - if (getNode()->kind() != Node::KIND_SET || - !getRootAccess()->isUpdate()) - { - res.clear(); + res = cppu::queryInterface( + aType, static_cast< css::container::XNameContainer * >(this)); + if (res.hasValue()) { + return res; } } + if (getNode()->kind() == Node::KIND_SET) { + res = cppu::queryInterface( + aType, static_cast< css::lang::XSingleServiceFactory * >(this)); + } } return res; } @@ -386,6 +564,10 @@ void Access::commitChildChanges( } } +bool Access::isDisposed() const { + return disposed_; +} + Access::ModifiedChild::ModifiedChild() {} Access::ModifiedChild::ModifiedChild( @@ -393,6 +575,63 @@ Access::ModifiedChild::ModifiedChild( child(theChild), directlyModified(theDirectlyModified) {} +css::uno::Sequence< css::uno::Type > Access::getTypes() + throw (css::uno::RuntimeException) +{ + OSL_ASSERT(thisIs(IS_ANY)); + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + comphelper::SequenceAsVector< css::uno::Type > types; + types.push_back(cppu::UnoType< css::uno::XInterface >::get()); + types.push_back(cppu::UnoType< css::uno::XWeak >::get()); + types.push_back(cppu::UnoType< css::lang::XTypeProvider >::get()); + types.push_back(cppu::UnoType< css::lang::XServiceInfo >::get()); + types.push_back(cppu::UnoType< css::lang::XComponent >::get()); + types.push_back( + cppu::UnoType< css::container::XHierarchicalNameAccess >::get()); + types.push_back(cppu::UnoType< css::container::XContainer >::get()); + types.push_back(cppu::UnoType< css::beans::XExactName >::get()); + types.push_back(cppu::UnoType< css::container::XHierarchicalName >::get()); + types.push_back(cppu::UnoType< css::container::XNamed >::get()); + types.push_back(cppu::UnoType< css::beans::XProperty >::get()); + types.push_back(cppu::UnoType< css::container::XElementAccess >::get()); + types.push_back(cppu::UnoType< css::container::XNameAccess >::get()); + if (getNode()->kind() == Node::KIND_GROUP) { + types.push_back(cppu::UnoType< css::beans::XPropertySetInfo >::get()); + types.push_back(cppu::UnoType< css::beans::XPropertySet >::get()); + types.push_back(cppu::UnoType< css::beans::XMultiPropertySet >::get()); + types.push_back( + cppu::UnoType< css::beans::XHierarchicalPropertySet >::get()); + types.push_back( + cppu::UnoType< css::beans::XMultiHierarchicalPropertySet >::get()); + types.push_back( + cppu::UnoType< css::beans::XHierarchicalPropertySetInfo >::get()); + } + if (getRootAccess()->isUpdate()) { + types.push_back(cppu::UnoType< css::container::XNameReplace >::get()); + if (getNode()->kind() != Node::KIND_GROUP || + dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) + { + types.push_back( + cppu::UnoType< css::container::XNameContainer >::get()); + } + if (getNode()->kind() == Node::KIND_SET) { + types.push_back( + cppu::UnoType< css::lang::XSingleServiceFactory >::get()); + } + } + return types.getAsConstList(); +} + +css::uno::Sequence< sal_Int8 > Access::getImplementationId() + throw (css::uno::RuntimeException) +{ + OSL_ASSERT(thisIs(IS_ANY)); + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + return css::uno::Sequence< sal_Int8 >(); +} + rtl::OUString Access::getImplementationName() throw (css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_ANY)); @@ -484,6 +723,65 @@ css::uno::Sequence< rtl::OUString > Access::getSupportedServiceNames() return services.getAsConstList(); } +void Access::dispose() throw (css::uno::RuntimeException) { + OSL_ASSERT(thisIs(IS_ANY)); + Broadcaster bc; + { + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + if (getParentAccess().is()) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr dispose inappropriate Access")), + static_cast< cppu::OWeakObject * >(this)); + } + if (disposed_) { + return; + } + initDisposeBroadcaster(&bc); + disposed_ = true; + } + bc.send(); +} + +void Access::addEventListener( + css::uno::Reference< css::lang::XEventListener > const & xListener) + throw (css::uno::RuntimeException) +{ + OSL_ASSERT(thisIs(IS_ANY)); + { + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + if (!xListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!disposed_) { + disposeListeners_.insert(xListener); + return; + } + } + try { + xListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} +} + +void Access::removeEventListener( + css::uno::Reference< css::lang::XEventListener > const & aListener) + throw (css::uno::RuntimeException) +{ + OSL_ASSERT(thisIs(IS_ANY)); + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + DisposeListeners::iterator i(disposeListeners_.find(aListener)); + if (i != disposeListeners_.end()) { + disposeListeners_.erase(i); + } +} + css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_ANY)); osl::MutexGuard g(lock); @@ -585,10 +883,23 @@ void Access::addContainerListener( throw (css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_ANY)); - osl::MutexGuard g(lock); - checkLocalizedPropertyAccess(); - rBHelper.addListener( - cppu::UnoType< css::container::XContainerListener >::get(), xListener); + { + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + if (!xListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!disposed_) { + containerListeners_.insert(xListener); + return; + } + } + try { + xListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } void Access::removeContainerListener( @@ -598,8 +909,10 @@ void Access::removeContainerListener( OSL_ASSERT(thisIs(IS_ANY)); osl::MutexGuard g(lock); checkLocalizedPropertyAccess(); - rBHelper.removeListener( - cppu::UnoType< css::container::XContainerListener >::get(), xListener); + ContainerListeners::iterator i(containerListeners_.find(xListener)); + if (i != containerListeners_.end()) { + containerListeners_.erase(i); + } } rtl::OUString Access::getExactName(rtl::OUString const & aApproximateName) @@ -799,7 +1112,7 @@ css::uno::Any Access::getPropertyValue(rtl::OUString const & PropertyName) } void Access::addPropertyChangeListener( - rtl::OUString const & /*aPropertyName*/, //TODO + rtl::OUString const & aPropertyName, css::uno::Reference< css::beans::XPropertyChangeListener > const & xListener) throw ( @@ -807,12 +1120,26 @@ void Access::addPropertyChangeListener( css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_GROUP)); - rBHelper.addListener( - cppu::UnoType< css::beans::XPropertyChangeListener >::get(), xListener); + { + osl::MutexGuard g(lock); + if (!xListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!disposed_) { + propertyChangeListeners_[aPropertyName].insert(xListener); + return; + } + } + try { + xListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } void Access::removePropertyChangeListener( - rtl::OUString const & /*aPropertyName*/, //TODO + rtl::OUString const & aPropertyName, css::uno::Reference< css::beans::XPropertyChangeListener > const & aListener) throw ( @@ -820,12 +1147,22 @@ void Access::removePropertyChangeListener( css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_GROUP)); - rBHelper.removeListener( - cppu::UnoType< css::beans::XPropertyChangeListener >::get(), aListener); + osl::MutexGuard g(lock); + PropertyChangeListeners::iterator i( + propertyChangeListeners_.find(aPropertyName)); + if (i != propertyChangeListeners_.end()) { + PropertyChangeListenersElement::iterator j(i->second.find(aListener)); + if (j != i->second.end()) { + i->second.erase(j); + if (i->second.empty()) { + propertyChangeListeners_.erase(i); + } + } + } } void Access::addVetoableChangeListener( - rtl::OUString const & /*PropertyName*/, //TODO + rtl::OUString const & PropertyName, css::uno::Reference< css::beans::XVetoableChangeListener > const & aListener) throw ( @@ -833,12 +1170,26 @@ void Access::addVetoableChangeListener( css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_GROUP)); - rBHelper.addListener( - cppu::UnoType< css::beans::XVetoableChangeListener >::get(), aListener); + { + osl::MutexGuard g(lock); + if (!aListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!disposed_) { + vetoableChangeListeners_[PropertyName].insert(aListener); + return; + } + } + try { + aListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } void Access::removeVetoableChangeListener( - rtl::OUString const & /*PropertyName*/, //TODO + rtl::OUString const & PropertyName, css::uno::Reference< css::beans::XVetoableChangeListener > const & aListener) throw ( @@ -846,8 +1197,18 @@ void Access::removeVetoableChangeListener( css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_GROUP)); - rBHelper.removeListener( - cppu::UnoType< css::beans::XVetoableChangeListener >::get(), aListener); + osl::MutexGuard g(lock); + VetoableChangeListeners::iterator i( + vetoableChangeListeners_.find(PropertyName)); + if (i != vetoableChangeListeners_.end()) { + VetoableChangeListenersElement::iterator j(i->second.find(aListener)); + if (j != i->second.end()) { + i->second.erase(j); + if (i->second.empty()) { + vetoableChangeListeners_.erase(i); + } + } + } } void Access::setPropertyValues( @@ -915,9 +1276,22 @@ void Access::addPropertiesChangeListener( throw (css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_GROUP)); - rBHelper.addListener( - cppu::UnoType< css::beans::XPropertiesChangeListener >::get(), - xListener); + { + osl::MutexGuard g(lock); + if (!xListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!disposed_) { + propertiesChangeListeners_.insert(xListener); + return; + } + } + try { + xListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } void Access::removePropertiesChangeListener( @@ -926,9 +1300,12 @@ void Access::removePropertiesChangeListener( throw (css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_GROUP)); - rBHelper.removeListener( - cppu::UnoType< css::beans::XPropertiesChangeListener >::get(), - xListener); + osl::MutexGuard g(lock); + PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.find(xListener)); + if (i != propertiesChangeListeners_.end()) { + propertiesChangeListeners_.erase(i); + } } void Access::firePropertiesChangeEvent( @@ -1099,7 +1476,7 @@ void Access::replaceByName( css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException) { - OSL_ASSERT(thisIs(IS_ANY|IS_UPDATE)); + OSL_ASSERT(thisIs(IS_UPDATE)); Broadcaster bc; { osl::MutexGuard g(lock); @@ -1323,7 +1700,7 @@ rtl::Reference< ChildAccess > Access::getSubChild(rtl::OUString const & path) { } bool Access::setChildProperty( - rtl::OUString const & name, com::sun::star::uno::Any const & value) + rtl::OUString const & name, css::uno::Any const & value) { rtl::Reference< ChildAccess > child(getChild(name)); if (!child.is()) { @@ -1443,36 +1820,6 @@ rtl::Reference< Access > Access::getNotificationRoot() { } } -void Access::initLocalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster) -{ - OSL_ASSERT(broadcaster != 0); - cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer( - cppu::UnoType< css::beans::XPropertyChangeListener >::get()); - if (cont != 0) { - css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > els( - cont->getElements()); //TODO: performance - for (sal_Int32 i = 0; i < els.getLength(); ++i) { - //TODO: only for matching modifications - broadcaster->addPropertyChange( - css::uno::Reference< css::beans::XPropertyChangeListener >( - els[i], css::uno::UNO_QUERY_THROW), - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), getNameInternal(), - false, -1, css::uno::Any(), css::uno::Any())); - } - } - //TODO: iterate over children w/ listeners (incl. unmodified ones) - for (ModifiedChildren::iterator i(modifiedChildren_.begin()); - i != modifiedChildren_.end(); ++i) - { - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - child->initLocalBroadcaster(localModifications, broadcaster); - } - } -} - #if OSL_DEBUG_LEVEL > 0 bool Access::thisIs(int what) { osl::MutexGuard g(lock); diff --git a/configmgr2/source/access.hxx b/configmgr2/source/access.hxx index c2369dea531a..3e286b909a79 100644 --- a/configmgr2/source/access.hxx +++ b/configmgr2/source/access.hxx @@ -33,6 +33,7 @@ #include "sal/config.h" #include <map> +#include <set> #include <vector> #include "boost/noncopyable.hpp" @@ -56,24 +57,21 @@ #include "com/sun/star/lang/IllegalArgumentException.hpp" #include "com/sun/star/lang/NoSupportException.hpp" #include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XComponent.hpp" #include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XTypeProvider.hpp" #include "com/sun/star/lang/XSingleServiceFactory.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 "cppuhelper/weak.hxx" +#include "osl/interlck.h" #include "rtl/ref.hxx" #include "sal/types.h" #include "type.hxx" -#if !defined INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_15 -#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_15 -#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 15 -#include "comphelper/implbase_var.hxx" -#undef COMPHELPER_IMPLBASE_INTERFACE_NUMBER -#endif - namespace com { namespace sun { namespace star { namespace beans { class XHierarchicalPropertySetInfo; @@ -83,6 +81,7 @@ namespace com { namespace sun { namespace star { struct Property; } namespace container { class XContainerListener; } + namespace lang { class XEventListener; } namespace uno { class Any; class Type; @@ -101,27 +100,31 @@ class Node; class RootAccess; struct Modifications; -typedef - comphelper::WeakComponentImplHelper15< - com::sun::star::lang::XServiceInfo, - com::sun::star::container::XHierarchicalNameAccess, - com::sun::star::container::XContainer, - com::sun::star::beans::XExactName, - com::sun::star::beans::XPropertySetInfo, - com::sun::star::container::XHierarchicalName, - com::sun::star::container::XNamed, - com::sun::star::beans::XProperty, - com::sun::star::beans::XPropertySet, - com::sun::star::beans::XMultiPropertySet, - com::sun::star::beans::XHierarchicalPropertySet, - com::sun::star::beans::XMultiHierarchicalPropertySet, - com::sun::star::beans::XHierarchicalPropertySetInfo, - com::sun::star::container::XNameContainer, - com::sun::star::lang::XSingleServiceFactory > - AccessBase; - -class Access: public AccessBase, private boost::noncopyable { +class Access: + public cppu::OWeakObject, public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XComponent, + public com::sun::star::container::XHierarchicalNameAccess, + public com::sun::star::container::XContainer, + public com::sun::star::beans::XExactName, + public com::sun::star::beans::XPropertySetInfo, + public com::sun::star::container::XHierarchicalName, + public com::sun::star::container::XNamed, + public com::sun::star::beans::XProperty, + public com::sun::star::beans::XPropertySet, + public com::sun::star::beans::XMultiPropertySet, + public com::sun::star::beans::XHierarchicalPropertySet, + public com::sun::star::beans::XMultiHierarchicalPropertySet, + public com::sun::star::beans::XHierarchicalPropertySetInfo, + public com::sun::star::container::XNameContainer, + public com::sun::star::lang::XSingleServiceFactory, + private boost::noncopyable +{ public: + oslInterlockedCount acquireCounting(); + + void releaseNondeleting(); + bool isValue(); void markChildAsModified(rtl::Reference< ChildAccess > const & child); @@ -136,9 +139,12 @@ public: virtual bool isFinalized() = 0; - void initGlobalBroadcaster( + virtual void initGlobalBroadcaster( Modifications const & localModifications, Broadcaster * broadcaster); + using OWeakObject::acquire; + using OWeakObject::release; + protected: Access(); @@ -153,6 +159,11 @@ protected: virtual void addSupportedServiceNames( std::vector< rtl::OUString > * services) = 0; + virtual void initDisposeBroadcaster(Broadcaster * broadcaster); + + virtual void initLocalBroadcaster( + Modifications const & localModifications, Broadcaster * broadcaster); + virtual com::sun::star::uno::Any SAL_CALL queryInterface( com::sun::star::uno::Type const & aType) throw (com::sun::star::uno::RuntimeException); @@ -176,6 +187,8 @@ protected: void commitChildChanges(bool valid, Modifications * globalModifications); + bool isDisposed() const; + private: struct ModifiedChild { rtl::Reference< ChildAccess > child; @@ -190,6 +203,12 @@ private: typedef std::map< rtl::OUString, ModifiedChild > ModifiedChildren; + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL + getTypes() throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getImplementationId() throw (com::sun::star::uno::RuntimeException); + virtual rtl::OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException); @@ -199,6 +218,19 @@ private: virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL dispose() + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL addEventListener( + com::sun::star::uno::Reference< com::sun::star::lang::XEventListener > + const & xListener) + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL removeEventListener( + com::sun::star::uno::Reference< com::sun::star::lang::XEventListener > + const & aListener) + throw (com::sun::star::uno::RuntimeException); + virtual com::sun::star::uno::Type SAL_CALL getElementType() throw (com::sun::star::uno::RuntimeException); @@ -474,13 +506,52 @@ private: rtl::Reference< Access > getNotificationRoot(); - void initLocalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster); - typedef std::map< rtl::OUString, ChildAccess * > WeakChildMap; + typedef + std::multiset< + com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > > + DisposeListeners; + + typedef + std::multiset< + com::sun::star::uno::Reference< + com::sun::star::container::XContainerListener > > + ContainerListeners; + + typedef + std::multiset< + com::sun::star::uno::Reference< + com::sun::star::beans::XPropertyChangeListener > > + PropertyChangeListenersElement; + + typedef std::map< rtl::OUString, PropertyChangeListenersElement > + PropertyChangeListeners; + + typedef + std::multiset< + com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener > > + VetoableChangeListenersElement; + + typedef std::map< rtl::OUString, VetoableChangeListenersElement > + VetoableChangeListeners; + + typedef + std::multiset< + com::sun::star::uno::Reference< + com::sun::star::beans::XPropertiesChangeListener > > + PropertiesChangeListeners; + ModifiedChildren modifiedChildren_; WeakChildMap cachedChildren_; + DisposeListeners disposeListeners_; + ContainerListeners containerListeners_; + PropertyChangeListeners propertyChangeListeners_; + VetoableChangeListeners vetoableChangeListeners_; + PropertiesChangeListeners propertiesChangeListeners_; + bool disposed_; #if OSL_DEBUG_LEVEL > 0 protected: diff --git a/configmgr2/source/broadcaster.cxx b/configmgr2/source/broadcaster.cxx index 58f89af69272..a5ff3b7c18ca 100644 --- a/configmgr2/source/broadcaster.cxx +++ b/configmgr2/source/broadcaster.cxx @@ -30,9 +30,21 @@ #include "precompiled_configmgr.hxx" #include "sal/config.h" +#include "com/sun/star/beans/PropertyVetoException.hpp" +#include "com/sun/star/beans/XPropertiesChangeListener.hpp" #include "com/sun/star/beans/XPropertyChangeListener.hpp" +#include "com/sun/star/beans/XVetoableChangeListener.hpp" +#include "com/sun/star/container/XContainerListener.hpp" #include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/XEventListener.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/XInterface.hpp" +#include "com/sun/star/util/XChangesListener.hpp" #include "osl/diagnose.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" #include "broadcaster.hxx" @@ -44,27 +56,174 @@ namespace css = com::sun::star; } -void Broadcaster::addPropertyChange( +void Broadcaster::addDisposeNotification( + css::uno::Reference< css::lang::XEventListener > const & listener, + css::lang::EventObject const & event) +{ + disposeNotifications_.push_back(DisposeNotification(listener, event)); +} + +void Broadcaster::addContainerNotification( + css::uno::Reference< css::container::XContainerListener > const & listener, + css::container::ContainerEvent const & event) +{ + containerNotifications_.push_back(ContainerNotification(listener, event)); +} + +void Broadcaster::addPropertyChangeNotification( css::uno::Reference< css::beans::XPropertyChangeListener > const & listener, - com::sun::star::beans::PropertyChangeEvent const & event) + css::beans::PropertyChangeEvent const & event) +{ + propertyChangeNotifications_.push_back( + PropertyChangeNotification(listener, event)); +} + +void Broadcaster::addVetoableChangeNotification( + css::uno::Reference< css::beans::XVetoableChangeListener > const & listener, + css::beans::PropertyChangeEvent const & event) { - propertyChanges_.push_back(PropertyChange(listener, event)); + vetoableChangeNotifications_.push_back( + VetoableChangeNotification(listener, event)); +} + +void Broadcaster::addPropertiesChangeNotification( + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + listener, + css::uno::Sequence< css::beans::PropertyChangeEvent > const & event) +{ + propertiesChangeNotifications_.push_back( + PropertiesChangeNotification(listener, event)); +} + +void Broadcaster::addChangesNotification( + css::uno::Reference< css::util::XChangesListener > const & listener, + css::util::ChangesEvent const & event) +{ + changesNotifications_.push_back(ChangesNotification(listener, event)); } void Broadcaster::send() { - for (PropertyChanges::iterator i(propertyChanges_.begin()); - i != propertyChanges_.end(); ++i) + bool exception = false; + for (DisposeNotifications::iterator i(disposeNotifications_.begin()); + i != disposeNotifications_.end(); ++i) { + try { + i->listener->disposing(i->event); + } catch (css::lang::DisposedException &) { + } catch (css::uno::Exception &) { + exception = true; + } + } + for (ContainerNotifications::iterator i(containerNotifications_.begin()); + i != containerNotifications_.end(); ++i) + { + try { + i->listener->elementReplaced(i->event); + //TODO: elementInserted/Removed/Replaced + } catch (css::lang::DisposedException &) { + } catch (css::uno::Exception &) { + exception = true; + } + } + for (PropertyChangeNotifications::iterator i( + propertyChangeNotifications_.begin()); + i != propertyChangeNotifications_.end(); ++i) { try { i->listener->propertyChange(i->event); - } catch (css::lang::DisposedException &) {} + } catch (css::lang::DisposedException &) { + } catch (css::uno::Exception &) { + exception = true; + } + } + for (VetoableChangeNotifications::iterator i( + vetoableChangeNotifications_.begin()); + i != vetoableChangeNotifications_.end(); ++i) + { + try { + i->listener->vetoableChange(i->event); + } catch (css::lang::DisposedException &) { + } catch (css::beans::PropertyVetoException &) { + //TODO + } catch (css::uno::Exception &) { + exception = true; + } + } + for (PropertiesChangeNotifications::iterator i( + propertiesChangeNotifications_.begin()); + i != propertiesChangeNotifications_.end(); ++i) + { + try { + i->listener->propertiesChange(i->event); + } catch (css::lang::DisposedException &) { + } catch (css::uno::Exception &) { + exception = true; + } + } + for (ChangesNotifications::iterator i(changesNotifications_.begin()); + i != changesNotifications_.end(); ++i) { + try { + i->listener->changesOccurred(i->event); + } catch (css::lang::DisposedException &) { + } catch (css::uno::Exception &) { + exception = true; + } + } + if (exception) { //TODO + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr exceptions during listener notification")), + css::uno::Reference< css::uno::XInterface >()); } } -Broadcaster::PropertyChange::PropertyChange( - com::sun::star::uno::Reference< - com::sun::star::beans::XPropertyChangeListener > const & theListener, - com::sun::star::beans::PropertyChangeEvent const & theEvent): +Broadcaster::DisposeNotification::DisposeNotification( + css::uno::Reference< css::lang::XEventListener > const & theListener, + css::lang::EventObject const & theEvent): + listener(theListener), event(theEvent) +{ + OSL_ASSERT(theListener.is()); +} + +Broadcaster::ContainerNotification::ContainerNotification( + css::uno::Reference< css::container::XContainerListener > const & + theListener, + css::container::ContainerEvent const & theEvent): + listener(theListener), event(theEvent) +{ + OSL_ASSERT(theListener.is()); +} + +Broadcaster::PropertyChangeNotification::PropertyChangeNotification( + css::uno::Reference< css::beans::XPropertyChangeListener > const & + theListener, + css::beans::PropertyChangeEvent const & theEvent): + listener(theListener), event(theEvent) +{ + OSL_ASSERT(theListener.is()); +} + +Broadcaster::VetoableChangeNotification::VetoableChangeNotification( + css::uno::Reference< css::beans::XVetoableChangeListener > const & + theListener, + css::beans::PropertyChangeEvent const & theEvent): + listener(theListener), event(theEvent) +{ + OSL_ASSERT(theListener.is()); +} + +Broadcaster::PropertiesChangeNotification::PropertiesChangeNotification( + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + theListener, + css::uno::Sequence< css::beans::PropertyChangeEvent > const & theEvent): + listener(theListener), event(theEvent) +{ + OSL_ASSERT(theListener.is()); +} + +Broadcaster::ChangesNotification::ChangesNotification( + css::uno::Reference< css::util::XChangesListener > const & theListener, + css::util::ChangesEvent const & theEvent): listener(theListener), event(theEvent) { OSL_ASSERT(theListener.is()); diff --git a/configmgr2/source/broadcaster.hxx b/configmgr2/source/broadcaster.hxx index 824def8500b7..00697977e077 100644 --- a/configmgr2/source/broadcaster.hxx +++ b/configmgr2/source/broadcaster.hxx @@ -36,12 +36,23 @@ #include "boost/noncopyable.hpp" #include "com/sun/star/beans/PropertyChangeEvent.hpp" +#include "com/sun/star/container/ContainerEvent.hpp" +#include "com/sun/star/lang/EventObject.hpp" #include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/util/ChangesEvent.hpp" #include "rtl/ref.hxx" -namespace com { namespace sun { namespace star { namespace beans { - class XPropertyChangeListener; -} } } } +namespace com { namespace sun { namespace star { + namespace beans { + class XPropertiesChangeListener; + class XPropertyChangeListener; + class XVetoableChangeListener; + } + namespace container { class XContainerListener; } + namespace lang { class XEventListener; } + namespace util { class XChangesListener; } +} } } namespace configmgr { @@ -49,29 +60,133 @@ class Access; class Broadcaster: private boost::noncopyable { public: - void addPropertyChange( + void addDisposeNotification( + com::sun::star::uno::Reference< com::sun::star::lang::XEventListener > + const & listener, + com::sun::star::lang::EventObject const & event); + + void addContainerNotification( + com::sun::star::uno::Reference< + com::sun::star::container::XContainerListener > const & listener, + com::sun::star::container::ContainerEvent const & event); + + void addPropertyChangeNotification( com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener > const & listener, com::sun::star::beans::PropertyChangeEvent const & event); + void addVetoableChangeNotification( + com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener > const & listener, + com::sun::star::beans::PropertyChangeEvent const & event); + + void addPropertiesChangeNotification( + com::sun::star::uno::Reference< + com::sun::star::beans::XPropertiesChangeListener > const & listener, + com::sun::star::uno::Sequence< + com::sun::star::beans::PropertyChangeEvent > const & event); + + void addChangesNotification( + com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > + const & listener, + com::sun::star::util::ChangesEvent const & event); + void send(); private: - struct PropertyChange { + struct DisposeNotification { + com::sun::star::uno::Reference< com::sun::star::lang::XEventListener > + listener; + com::sun::star::lang::EventObject event; + + DisposeNotification( + com::sun::star::uno::Reference< + com::sun::star::lang::XEventListener > const & theListener, + com::sun::star::lang::EventObject const & theEvent); + }; + + struct ContainerNotification { + com::sun::star::uno::Reference< + com::sun::star::container::XContainerListener > listener; + com::sun::star::container::ContainerEvent event; + + ContainerNotification( + com::sun::star::uno::Reference< + com::sun::star::container::XContainerListener > const & + theListener, + com::sun::star::container::ContainerEvent const & theEvent); + }; + + struct PropertyChangeNotification { com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener > listener; com::sun::star::beans::PropertyChangeEvent event; - PropertyChange( + PropertyChangeNotification( com::sun::star::uno::Reference< com::sun::star::beans::XPropertyChangeListener > const & theListener, com::sun::star::beans::PropertyChangeEvent const & theEvent); }; - typedef std::vector< PropertyChange > PropertyChanges; + struct VetoableChangeNotification { + com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener > listener; + com::sun::star::beans::PropertyChangeEvent event; + + VetoableChangeNotification( + com::sun::star::uno::Reference< + com::sun::star::beans::XVetoableChangeListener > const & + theListener, + com::sun::star::beans::PropertyChangeEvent const & theEvent); + }; + + struct PropertiesChangeNotification { + com::sun::star::uno::Reference< + com::sun::star::beans::XPropertiesChangeListener > listener; + com::sun::star::uno::Sequence< + com::sun::star::beans::PropertyChangeEvent > event; + + PropertiesChangeNotification( + com::sun::star::uno::Reference< + com::sun::star::beans::XPropertiesChangeListener > const & + theListener, + com::sun::star::uno::Sequence< + com::sun::star::beans::PropertyChangeEvent > const & theEvent); + }; + + struct ChangesNotification { + com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > + listener; + com::sun::star::util::ChangesEvent event; + + ChangesNotification( + com::sun::star::uno::Reference< + com::sun::star::util::XChangesListener > const & theListener, + com::sun::star::util::ChangesEvent const & theEvent); + }; + + typedef std::vector< DisposeNotification > DisposeNotifications; + + typedef std::vector< ContainerNotification > ContainerNotifications; + + typedef std::vector< PropertyChangeNotification > + PropertyChangeNotifications; + + typedef std::vector< VetoableChangeNotification > + VetoableChangeNotifications; + + typedef std::vector< PropertiesChangeNotification > + PropertiesChangeNotifications; + + typedef std::vector< ChangesNotification > ChangesNotifications; - PropertyChanges propertyChanges_; + DisposeNotifications disposeNotifications_; + ContainerNotifications containerNotifications_; + PropertyChangeNotifications propertyChangeNotifications_; + VetoableChangeNotifications vetoableChangeNotifications_; + PropertiesChangeNotifications propertiesChangeNotifications_; + ChangesNotifications changesNotifications_; }; } diff --git a/configmgr2/source/childaccess.cxx b/configmgr2/source/childaccess.cxx index cd912338143a..9937ea0b87a6 100644 --- a/configmgr2/source/childaccess.cxx +++ b/configmgr2/source/childaccess.cxx @@ -38,10 +38,9 @@ #include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/uno/Sequence.hxx" #include "com/sun/star/uno/XInterface.hpp" -#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/queryinterface.hxx" #include "cppuhelper/weak.hxx" #include "osl/diagnose.h" -#include "osl/interlck.h" #include "osl/mutex.hxx" #include "rtl/ref.hxx" #include "rtl/string.h" @@ -144,6 +143,14 @@ rtl::Reference< Access > ChildAccess::getParentAccess() { return parent_; } +void ChildAccess::acquire() throw () { + Access::acquire(); +} + +void ChildAccess::release() throw () { + Access::release(); +} + css::uno::Reference< css::uno::XInterface > ChildAccess::getParent() throw (css::uno::RuntimeException) { @@ -175,14 +182,6 @@ sal_Int64 ChildAccess::getSomething( ? reinterpret_cast< sal_Int64 >(this) : 0; } -oslInterlockedCount ChildAccess::acquireCounting() { - return osl_incrementInterlockedCount(&m_refCount); -} - -void ChildAccess::releaseNondeleting() { - osl_decrementInterlockedCount(&m_refCount); -} - void ChildAccess::bind( rtl::Reference< RootAccess > const & root, rtl::Reference< Access > const & parent, rtl::OUString const & name) @@ -344,4 +343,18 @@ void ChildAccess::addSupportedServiceNames( "com.sun.star.configuration.SetElement"))); } +css::uno::Any ChildAccess::queryInterface(css::uno::Type const & aType) + throw (css::uno::RuntimeException) +{ + OSL_ASSERT(thisIs(IS_ANY)); + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + css::uno::Any res(Access::queryInterface(aType)); + return res.hasValue() + ? res + : cppu::queryInterface( + aType, static_cast< css::container::XChild * >(this), + static_cast< css::lang::XUnoTunnel * >(this)); +} + } diff --git a/configmgr2/source/childaccess.hxx b/configmgr2/source/childaccess.hxx index b97086b66032..cd5f1ead3421 100644 --- a/configmgr2/source/childaccess.hxx +++ b/configmgr2/source/childaccess.hxx @@ -41,8 +41,6 @@ #include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/uno/Sequence.hxx" -#include "cppuhelper/implbase2.hxx" -#include "osl/interlck.h" #include "rtl/ref.hxx" #include "sal/types.h" @@ -50,6 +48,7 @@ namespace com { namespace sun { namespace star { namespace uno { class Any; + class Type; class XInterface; } } } } @@ -60,9 +59,8 @@ class RootAccess; struct Modifications; class ChildAccess: - public cppu::ImplInheritanceHelper2< - Access, com::sun::star::container::XChild, - com::sun::star::lang::XUnoTunnel > + public Access, public com::sun::star::container::XChild, + public com::sun::star::lang::XUnoTunnel { public: static com::sun::star::uno::Sequence< sal_Int8 > getTunnelId(); @@ -90,6 +88,10 @@ public: virtual rtl::Reference< Access > getParentAccess(); + virtual void SAL_CALL acquire() throw (); + + virtual void SAL_CALL release() throw (); + virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL getParent() throw (com::sun::star::uno::RuntimeException); @@ -105,10 +107,6 @@ public: com::sun::star::uno::Sequence< sal_Int8 > const & aIdentifier) throw (com::sun::star::uno::RuntimeException); - oslInterlockedCount acquireCounting(); - - void releaseNondeleting(); - void bind( rtl::Reference< RootAccess > const & root, rtl::Reference< Access > const & parent, rtl::OUString const & name) @@ -136,6 +134,10 @@ private: virtual void addSupportedServiceNames( std::vector< rtl::OUString > * services); + virtual com::sun::star::uno::Any SAL_CALL queryInterface( + com::sun::star::uno::Type const & aType) + throw (com::sun::star::uno::RuntimeException); + rtl::Reference< RootAccess > root_; rtl::Reference< Access > parent_; // null iff free node rtl::OUString name_; diff --git a/configmgr2/source/components.cxx b/configmgr2/source/components.cxx index 7b58aa5abdf4..67728113b60e 100644 --- a/configmgr2/source/components.cxx +++ b/configmgr2/source/components.cxx @@ -140,8 +140,15 @@ void Components::initGlobalBroadcaster( rtl::Reference< RootAccess > const & exclude, Broadcaster * broadcaster) { for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) { - if (*i != exclude.get()) { - (*i)->initGlobalBroadcaster(globalModifications, broadcaster); + rtl::Reference< RootAccess > root; + if ((*i)->acquireCounting() > 1) { + root.set(*i); // must not throw + } + (*i)->releaseNondeleting(); + if (root.is()) { + if (root != exclude) { + root->initGlobalBroadcaster(globalModifications, broadcaster); + } } } } diff --git a/configmgr2/source/rootaccess.cxx b/configmgr2/source/rootaccess.cxx index 59ecbefb914a..96d4a2949055 100644 --- a/configmgr2/source/rootaccess.cxx +++ b/configmgr2/source/rootaccess.cxx @@ -32,13 +32,17 @@ #include <vector> +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/EventObject.hpp" #include "com/sun/star/lang/WrappedTargetException.hpp" #include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/util/ChangesEvent.hpp" #include "com/sun/star/util/ChangesSet.hpp" #include "com/sun/star/util/ElementChange.hpp" #include "com/sun/star/util/XChangesListener.hpp" #include "comphelper/sequenceasvector.hxx" #include "cppu/unotype.hxx" +#include "cppuhelper/queryinterface.hxx" #include "cppuhelper/weak.hxx" #include "osl/diagnose.h" #include "osl/mutex.hxx" @@ -67,6 +71,34 @@ RootAccess::RootAccess( path_(path), locale_(locale), update_(update) {} +void RootAccess::initGlobalBroadcaster( + Modifications const & globalModifications, Broadcaster * broadcaster) +{ + OSL_ASSERT(broadcaster != 0); + //TODO: only for matching modifications: + for (ChangesListeners::iterator i(changesListeners_.begin()); + i != changesListeners_.end(); ++i) + { + broadcaster->addChangesNotification( + *i, + css::util::ChangesEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(*static_cast< cppu::OWeakObject * >(this)), + //TODO: XInterface or something else? + css::uno::Sequence< css::util::ElementChange >()/*TODO*/)); + + } + Access::initGlobalBroadcaster(globalModifications, broadcaster); +} + +void RootAccess::acquire() throw () { + Access::acquire(); +} + +void RootAccess::release() throw () { + Access::release(); +} + rtl::OUString RootAccess::getLocale() const { return locale_; } @@ -139,19 +171,56 @@ void RootAccess::addSupportedServiceNames( } } +void RootAccess::initDisposeBroadcaster(Broadcaster * broadcaster) { + OSL_ASSERT(broadcaster != 0); + for (ChangesListeners::iterator i(changesListeners_.begin()); + i != changesListeners_.end(); ++i) + { + broadcaster->addDisposeNotification( + i->get(), + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } + Access::initDisposeBroadcaster(broadcaster); +} + +void RootAccess::initLocalBroadcaster( + Modifications const & localModifications, Broadcaster * broadcaster) +{ + OSL_ASSERT(broadcaster != 0); + //TODO: only for matching modifications: + for (ChangesListeners::iterator i(changesListeners_.begin()); + i != changesListeners_.end(); ++i) + { + broadcaster->addChangesNotification( + *i, + css::util::ChangesEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(*static_cast< cppu::OWeakObject * >(this)), + //TODO: XInterface or something else? + css::uno::Sequence< css::util::ElementChange >()/*TODO*/)); + + } + Access::initLocalBroadcaster(localModifications, broadcaster); +} + css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType) throw (css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_ANY)); osl::MutexGuard g(lock); checkLocalizedPropertyAccess(); - css::uno::Any res(RootAccessBase::queryInterface(aType)); - if (res.hasValue() && - aType.getTypeName().equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM("com.sun.star.util.XChangesBatch")) && - !update_) - { - res.clear(); + css::uno::Any res(Access::queryInterface(aType)); + if (res.hasValue()) { + return res; + } + res = cppu::queryInterface( + aType, static_cast< css::util::XChangesNotifier * >(this)); + if (res.hasValue()) { + return res; + } + if (!res.hasValue() && update_) { + res = cppu::queryInterface( + aType, static_cast< css::util::XChangesBatch * >(this)); } return res; } @@ -161,10 +230,24 @@ void RootAccess::addChangesListener( throw (css::uno::RuntimeException) { OSL_ASSERT(thisIs(IS_ANY)); - osl::MutexGuard g(lock); - checkLocalizedPropertyAccess(); - rBHelper.addListener( - cppu::UnoType< css::util::XChangesListener >::get(), aListener); + { + osl::MutexGuard g(lock); + checkLocalizedPropertyAccess(); + if (!aListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!isDisposed()) { + changesListeners_.insert(aListener); + return; + } + } + try { + aListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} + //TODO: actually fire changes events through Broadcaster::send } void RootAccess::removeChangesListener( @@ -174,14 +257,16 @@ void RootAccess::removeChangesListener( OSL_ASSERT(thisIs(IS_ANY)); osl::MutexGuard g(lock); checkLocalizedPropertyAccess(); - rBHelper.removeListener( - cppu::UnoType< css::util::XChangesListener >::get(), aListener); + ChangesListeners::iterator i(changesListeners_.find(aListener)); + if (i != changesListeners_.end()) { + changesListeners_.erase(i); + } } void RootAccess::commitChanges() throw (css::lang::WrappedTargetException, css::uno::RuntimeException) { - OSL_ASSERT(thisIs(IS_ANY|IS_UPDATE)); + OSL_ASSERT(thisIs(IS_UPDATE)); Broadcaster bc; { osl::MutexGuard g(lock); @@ -200,7 +285,7 @@ void RootAccess::commitChanges() } sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) { - OSL_ASSERT(thisIs(IS_ANY|IS_UPDATE)); + OSL_ASSERT(thisIs(IS_UPDATE)); osl::MutexGuard g(lock); checkLocalizedPropertyAccess(); //TODO: Optimize: @@ -212,7 +297,7 @@ sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) { css::util::ChangesSet RootAccess::getPendingChanges() throw (css::uno::RuntimeException) { - OSL_ASSERT(thisIs(IS_ANY|IS_UPDATE)); + OSL_ASSERT(thisIs(IS_UPDATE)); osl::MutexGuard g(lock); checkLocalizedPropertyAccess(); comphelper::SequenceAsVector< css::util::ElementChange > changes; diff --git a/configmgr2/source/rootaccess.hxx b/configmgr2/source/rootaccess.hxx index ea67ff2aa2de..3cf8e0620f5c 100644 --- a/configmgr2/source/rootaccess.hxx +++ b/configmgr2/source/rootaccess.hxx @@ -32,12 +32,13 @@ #include "sal/config.h" +#include <set> + #include "com/sun/star/lang/WrappedTargetException.hpp" #include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/util/ChangesSet.hpp" #include "com/sun/star/util/XChangesBatch.hpp" #include "com/sun/star/util/XChangesNotifier.hpp" -#include "cppuhelper/implbase2.hxx" #include "rtl/ref.hxx" #include "rtl/ustring.hxx" #include "sal/types.h" @@ -54,19 +55,25 @@ namespace com { namespace sun { namespace star { namespace configmgr { +class Broadcaster; class Node; +struct Modifications; -typedef - cppu::ImplInheritanceHelper2< - Access, com::sun::star::util::XChangesNotifier, - com::sun::star::util::XChangesBatch > - RootAccessBase; - -class RootAccess: public RootAccessBase { +class RootAccess: + public Access, public com::sun::star::util::XChangesNotifier, + public com::sun::star::util::XChangesBatch +{ public: RootAccess( rtl::OUString const & path, rtl::OUString const & locale, bool update); + virtual void initGlobalBroadcaster( + Modifications const & localModifications, Broadcaster * broadcaster); + + virtual void SAL_CALL acquire() throw (); + + virtual void SAL_CALL release() throw (); + rtl::OUString getLocale() const; bool isUpdate() const; @@ -91,6 +98,11 @@ private: virtual void addSupportedServiceNames( std::vector< rtl::OUString > * services); + virtual void initDisposeBroadcaster(Broadcaster * broadcaster); + + virtual void initLocalBroadcaster( + Modifications const & localModifications, Broadcaster * broadcaster); + virtual com::sun::star::uno::Any SAL_CALL queryInterface( com::sun::star::uno::Type const & aType) throw (com::sun::star::uno::RuntimeException); @@ -116,12 +128,19 @@ private: virtual com::sun::star::util::ChangesSet SAL_CALL getPendingChanges() throw (com::sun::star::uno::RuntimeException); + typedef + std::multiset< + com::sun::star::uno::Reference< + com::sun::star::util::XChangesListener > > + ChangesListeners; + rtl::OUString path_; rtl::OUString locale_; bool update_; bool finalized_; rtl::Reference< Node > node_; rtl::OUString name_; + ChangesListeners changesListeners_; }; } |