summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsb <sb@openoffice.org>2009-09-21 13:14:11 +0200
committersb <sb@openoffice.org>2009-09-21 13:14:11 +0200
commitb5ba31ba01639a189a0c7077b763a2c3dd02a347 (patch)
treef882b1bb2c32f5e0bee52e74fe3e8a70073c46b9
parent07efdd981d2da9de49b4887949c5cd6205335a44 (diff)
#i101955# rudimentary notification support (to be continued; known to not work correctly yet)
-rw-r--r--configmgr2/qa/unit/test.cxx5
-rw-r--r--configmgr2/source/access.cxx162
-rw-r--r--configmgr2/source/access.hxx12
-rw-r--r--configmgr2/source/broadcaster.cxx73
-rw-r--r--configmgr2/source/broadcaster.hxx79
-rw-r--r--configmgr2/source/childaccess.cxx20
-rw-r--r--configmgr2/source/childaccess.hxx7
-rw-r--r--configmgr2/source/components.cxx22
-rw-r--r--configmgr2/source/components.hxx17
-rw-r--r--configmgr2/source/configurationprovider.cxx2
-rw-r--r--configmgr2/source/data.cxx22
-rw-r--r--configmgr2/source/data.hxx6
-rw-r--r--configmgr2/source/makefile.mk2
-rw-r--r--configmgr2/source/modifications.cxx63
-rw-r--r--configmgr2/source/modifications.hxx54
-rw-r--r--configmgr2/source/rootaccess.cxx29
-rw-r--r--configmgr2/source/writemodfile.cxx5
-rw-r--r--configmgr2/source/xcuparser.cxx4
18 files changed, 496 insertions, 88 deletions
diff --git a/configmgr2/qa/unit/test.cxx b/configmgr2/qa/unit/test.cxx
index 0cb1a8d0940b..9ce74cf8093c 100644
--- a/configmgr2/qa/unit/test.cxx
+++ b/configmgr2/qa/unit/test.cxx
@@ -281,7 +281,7 @@ void RecursiveTest::test() {
properties_->addPropertyChangeListener(
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Label")), this);
step();
- //TODO: CPPUNIT_ASSERT(count_ == 0);
+ CPPUNIT_ASSERT(count_ == 0);
css::uno::Reference< css::lang::XComponent >(
properties_, css::uno::UNO_QUERY_THROW)->dispose();
}
@@ -300,6 +300,9 @@ void RecursiveTest::disposing(css::lang::EventObject const & Source)
void RecursiveTest::propertyChange(css::beans::PropertyChangeEvent const &)
throw (css::uno::RuntimeException)
{
+ CPPUNIT_ASSERT(
+ evt.Source == properties_ &&
+ evt.PropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Label")));
if (count_ > 0) {
--count_;
step();
diff --git a/configmgr2/source/access.cxx b/configmgr2/source/access.cxx
index 2e501b43417e..190037db67f1 100644
--- a/configmgr2/source/access.cxx
+++ b/configmgr2/source/access.cxx
@@ -57,7 +57,7 @@
#include "com/sun/star/util/ElementChange.hpp"
#include "comphelper/sequenceasvector.hxx"
#include "cppu/unotype.hxx"
-#include "cppuhelper/exc_hlp.hxx"
+#include "cppuhelper/interfacecontainer.hxx"
#include "cppuhelper/weak.hxx"
#include "osl/diagnose.h"
#include "osl/mutex.hxx"
@@ -68,6 +68,7 @@
#include "sal/types.h"
#include "access.hxx"
+#include "broadcaster.hxx"
#include "childaccess.hxx"
#include "components.hxx"
#include "data.hxx"
@@ -75,6 +76,7 @@
#include "localizedpropertynode.hxx"
#include "localizedvaluenode.hxx"
#include "lock.hxx"
+#include "modifications.hxx"
#include "node.hxx"
#include "nodemap.hxx"
#include "propertynode.hxx"
@@ -124,6 +126,36 @@ void Access::releaseChild(rtl::OUString const & name) {
cachedChildren_.erase(name);
}
+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),
+ 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->initGlobalBroadcaster(globalModifications, broadcaster);
+ }
+ }
+}
+
Access::Access(): AccessBase(lock) {}
Access::~Access() {}
@@ -300,14 +332,17 @@ void Access::reportChildChanges(
}
}
-void Access::commitChildChanges(bool valid) {
+void Access::commitChildChanges(
+ bool valid, Modifications * globalModifications)
+{
+ OSL_ASSERT(globalModifications != 0);
while (!modifiedChildren_.empty()) {
bool childValid = valid;
ModifiedChildren::iterator i(modifiedChildren_.begin());
rtl::Reference< ChildAccess > child(getModifiedChild(i));
if (child.is()) {
childValid = childValid && !child->isFinalized();
- child->commitChanges(childValid);
+ child->commitChanges(childValid, globalModifications);
//TODO: currently, this is called here for directly inserted
// children as well as for children whose sub-children were
// modified (and should never be called for directly removed
@@ -338,17 +373,26 @@ void Access::commitChildChanges(bool valid) {
}
}
if (childValid && i->second.directlyModified) {
- Components::singleton().addModification(
+ rtl::OUString path(
getAbsolutePath() +
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
Data::createSegment(
i->second.child->getNode()->getTemplateName(), i->first));
+ Components::singleton().addModification(path);
+ globalModifications->add(path);
}
i->second.child->committed();
modifiedChildren_.erase(i);
}
}
+Access::ModifiedChild::ModifiedChild() {}
+
+Access::ModifiedChild::ModifiedChild(
+ rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified):
+ child(theChild), directlyModified(theDirectlyModified)
+{}
+
rtl::OUString Access::getImplementationName() throw (css::uno::RuntimeException)
{
OSL_ASSERT(thisIs(IS_ANY));
@@ -897,6 +941,7 @@ void Access::firePropertiesChangeEvent(
css::uno::Sequence< css::beans::PropertyChangeEvent > events(
aPropertyNames.getLength());
for (sal_Int32 i = 0; i < events.getLength(); ++i) {
+ events[i].Source = static_cast< cppu::OWeakObject * >(this);
events[i].PropertyName = aPropertyNames[i];
events[i].Further = false;
events[i].PropertyHandle = -1;
@@ -935,7 +980,8 @@ void Access::setHierarchicalPropertyValue(
static_cast< cppu::OWeakObject * >(this));
}
child->checkFinalized();
- child->setProperty(aValue);
+ Modifications localMods; //TODO: use
+ child->setProperty(aValue, &localMods);
}
css::uno::Any Access::getHierarchicalPropertyValue(
@@ -992,7 +1038,8 @@ void Access::setHierarchicalPropertyValues(
static_cast< cppu::OWeakObject * >(this), -1);
}
child->checkFinalized();
- child->setProperty(Values[i]);
+ Modifications localMods; //TODO: use
+ child->setProperty(Values[i], &localMods);
}
}
@@ -1053,33 +1100,40 @@ void Access::replaceByName(
css::lang::WrappedTargetException, css::uno::RuntimeException)
{
OSL_ASSERT(thisIs(IS_ANY|IS_UPDATE));
- osl::MutexGuard g(lock);
- checkLocalizedPropertyAccess();
- rtl::Reference< ChildAccess > child(getChild(aName));
- if (!child.is()) {
- throw css::container::NoSuchElementException(
- aName, static_cast< cppu::OWeakObject * >(this));
- }
- child->checkFinalized();
- switch (getNode()->kind()) {
- case Node::KIND_LOCALIZED_PROPERTY:
- case Node::KIND_GROUP:
- child->setProperty(aElement);
- break;
- case Node::KIND_SET:
- {
- rtl::Reference< ChildAccess > freeAcc(getFreeSetMember(aElement));
- rtl::Reference< RootAccess > root(getRootAccess());
- child->unbind(); // must not throw
- freeAcc->bind(root, this, aName); // must not throw
- markChildAsModified(freeAcc); //TODO: must not throw
- //TODO notify change
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ rtl::Reference< ChildAccess > child(getChild(aName));
+ if (!child.is()) {
+ throw css::container::NoSuchElementException(
+ aName, static_cast< cppu::OWeakObject * >(this));
}
- break;
- default:
- OSL_ASSERT(false); // this cannot happen
- break;
+ child->checkFinalized();
+ Modifications localMods;
+ switch (getNode()->kind()) {
+ case Node::KIND_LOCALIZED_PROPERTY:
+ case Node::KIND_GROUP:
+ child->setProperty(aElement, &localMods);
+ break;
+ case Node::KIND_SET:
+ {
+ rtl::Reference< ChildAccess > freeAcc(
+ getFreeSetMember(aElement));
+ rtl::Reference< RootAccess > root(getRootAccess());
+ child->unbind(); // must not throw
+ freeAcc->bind(root, this, aName); // must not throw
+ markChildAsModified(freeAcc); //TODO: must not throw
+ //TODO notify change
+ }
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ getNotificationRoot()->initLocalBroadcaster(localMods, &bc);
}
+ bc.send();
}
void Access::insertByName(
@@ -1276,7 +1330,8 @@ bool Access::setChildProperty(
return false;
}
child->checkFinalized();
- child->setProperty(value);
+ Modifications localMods; //TODO: use
+ child->setProperty(value, &localMods);
return true;
}
@@ -1378,12 +1433,45 @@ rtl::Reference< ChildAccess > Access::getFreeSetMember(
return freeAcc;
}
-Access::ModifiedChild::ModifiedChild() {}
+rtl::Reference< Access > Access::getNotificationRoot() {
+ for (rtl::Reference< Access > p(this);;) {
+ rtl::Reference< Access > parent(p->getParentAccess());
+ if (!parent.is()) {
+ return p;
+ }
+ p = parent;
+ }
+}
-Access::ModifiedChild::ModifiedChild(
- rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified):
- child(theChild), directlyModified(theDirectlyModified)
-{}
+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) {
diff --git a/configmgr2/source/access.hxx b/configmgr2/source/access.hxx
index 1daed272450d..c2369dea531a 100644
--- a/configmgr2/source/access.hxx
+++ b/configmgr2/source/access.hxx
@@ -94,10 +94,12 @@ namespace rtl { class OUString; }
namespace configmgr {
+class Broadcaster;
class Change;
class ChildAccess;
class Node;
class RootAccess;
+struct Modifications;
typedef
comphelper::WeakComponentImplHelper15<
@@ -134,6 +136,9 @@ public:
virtual bool isFinalized() = 0;
+ void initGlobalBroadcaster(
+ Modifications const & localModifications, Broadcaster * broadcaster);
+
protected:
Access();
@@ -169,7 +174,7 @@ protected:
void reportChildChanges(
std::vector< com::sun::star::util::ElementChange > * changes);
- void commitChildChanges(bool valid);
+ void commitChildChanges(bool valid, Modifications * globalModifications);
private:
struct ModifiedChild {
@@ -467,6 +472,11 @@ private:
rtl::Reference< ChildAccess > getFreeSetMember(
com::sun::star::uno::Any const & value);
+ rtl::Reference< Access > getNotificationRoot();
+
+ void initLocalBroadcaster(
+ Modifications const & localModifications, Broadcaster * broadcaster);
+
typedef std::map< rtl::OUString, ChildAccess * > WeakChildMap;
ModifiedChildren modifiedChildren_;
diff --git a/configmgr2/source/broadcaster.cxx b/configmgr2/source/broadcaster.cxx
new file mode 100644
index 000000000000..58f89af69272
--- /dev/null
+++ b/configmgr2/source/broadcaster.cxx
@@ -0,0 +1,73 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2009 by Sun Microsystems, Inc.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* $RCSfile: code,v $
+*
+* $Revision: 1.4 $
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org 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 version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/beans/XPropertyChangeListener.hpp"
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "osl/diagnose.hxx"
+
+#include "broadcaster.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+void Broadcaster::addPropertyChange(
+ css::uno::Reference< css::beans::XPropertyChangeListener > const & listener,
+ com::sun::star::beans::PropertyChangeEvent const & event)
+{
+ propertyChanges_.push_back(PropertyChange(listener, event));
+}
+
+void Broadcaster::send() {
+ for (PropertyChanges::iterator i(propertyChanges_.begin());
+ i != propertyChanges_.end(); ++i)
+ {
+ try {
+ i->listener->propertyChange(i->event);
+ } catch (css::lang::DisposedException &) {}
+ }
+}
+
+Broadcaster::PropertyChange::PropertyChange(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > const & theListener,
+ com::sun::star::beans::PropertyChangeEvent const & theEvent):
+ listener(theListener), event(theEvent)
+{
+ OSL_ASSERT(theListener.is());
+}
+
+}
diff --git a/configmgr2/source/broadcaster.hxx b/configmgr2/source/broadcaster.hxx
new file mode 100644
index 000000000000..824def8500b7
--- /dev/null
+++ b/configmgr2/source/broadcaster.hxx
@@ -0,0 +1,79 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2009 by Sun Microsystems, Inc.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* $RCSfile: code,v $
+*
+* $Revision: 1.4 $
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org 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 version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_BROADCASTER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_BROADCASTER_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/beans/PropertyChangeEvent.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "rtl/ref.hxx"
+
+namespace com { namespace sun { namespace star { namespace beans {
+ class XPropertyChangeListener;
+} } } }
+
+namespace configmgr {
+
+class Access;
+
+class Broadcaster: private boost::noncopyable {
+public:
+ void addPropertyChange(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > const & listener,
+ com::sun::star::beans::PropertyChangeEvent const & event);
+
+ void send();
+
+private:
+ struct PropertyChange {
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > listener;
+ com::sun::star::beans::PropertyChangeEvent event;
+
+ PropertyChange(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > const &
+ theListener,
+ com::sun::star::beans::PropertyChangeEvent const & theEvent);
+ };
+
+ typedef std::vector< PropertyChange > PropertyChanges;
+
+ PropertyChanges propertyChanges_;
+};
+
+}
+
+#endif
diff --git a/configmgr2/source/childaccess.cxx b/configmgr2/source/childaccess.cxx
index 4dc0e2e126c4..cd912338143a 100644
--- a/configmgr2/source/childaccess.cxx
+++ b/configmgr2/source/childaccess.cxx
@@ -59,6 +59,7 @@
#include "localizedpropertynode.hxx"
#include "localizedvaluenode.hxx"
#include "lock.hxx"
+#include "modifications.hxx"
#include "node.hxx"
#include "propertynode.hxx"
#include "rootaccess.hxx"
@@ -209,7 +210,10 @@ void ChildAccess::setNode(rtl::Reference< Node > const & node) {
node_ = node;
}
-void ChildAccess::setProperty(css::uno::Any const & value) {
+void ChildAccess::setProperty(
+ css::uno::Any const & value, Modifications * localModifications)
+{
+ OSL_ASSERT(localModifications != 0);
Type type = TYPE_ERROR;
bool nillable = false;
switch (node_->kind()) {
@@ -226,7 +230,7 @@ void ChildAccess::setProperty(css::uno::Any const & value) {
if (!Components::allLocales(locale)) {
rtl::Reference< ChildAccess > child(getChild(locale));
if (child.is()) {
- child->setProperty(value);
+ child->setProperty(value, localModifications);
} else {
insertLocalizedValueChild(locale, value);
}
@@ -248,7 +252,7 @@ void ChildAccess::setProperty(css::uno::Any const & value) {
checkValue(value, type, nillable);
getParentAccess()->markChildAsModified(this);
changedValue_.reset(new css::uno::Any(value));
- //TODO notify change
+ localModifications->add(getRelativePath());
}
css::uno::Any ChildAccess::asValue() {
@@ -294,10 +298,14 @@ css::uno::Any ChildAccess::asValue() {
static_cast< cppu::OWeakObject * >(this)));
}
-void ChildAccess::commitChanges(bool valid) {
- commitChildChanges(valid);
+void ChildAccess::commitChanges(bool valid, Modifications * globalModifications)
+{
+ OSL_ASSERT(globalModifications != 0);
+ commitChildChanges(valid, globalModifications);
if (valid && changedValue_.get() != 0) {
- Components::singleton().addModification(getAbsolutePath());
+ rtl::OUString path(getAbsolutePath());
+ Components::singleton().addModification(path);
+ globalModifications->add(path);
switch (node_->kind()) {
case Node::KIND_PROPERTY:
dynamic_cast< PropertyNode * >(node_.get())->setValue(
diff --git a/configmgr2/source/childaccess.hxx b/configmgr2/source/childaccess.hxx
index f3b7fecff072..b97086b66032 100644
--- a/configmgr2/source/childaccess.hxx
+++ b/configmgr2/source/childaccess.hxx
@@ -57,6 +57,7 @@ namespace configmgr {
class Node;
class RootAccess;
+struct Modifications;
class ChildAccess:
public cppu::ImplInheritanceHelper2<
@@ -121,11 +122,13 @@ public:
void setNode(rtl::Reference< Node > const & node);
- void setProperty(com::sun::star::uno::Any const & value);
+ void setProperty(
+ com::sun::star::uno::Any const & value,
+ Modifications * localModifications);
com::sun::star::uno::Any asValue();
- void commitChanges(bool valid);
+ void commitChanges(bool valid, Modifications * globalModifications);
private:
virtual ~ChildAccess();
diff --git a/configmgr2/source/components.cxx b/configmgr2/source/components.cxx
index e90ffea65d0e..7b58aa5abdf4 100644
--- a/configmgr2/source/components.cxx
+++ b/configmgr2/source/components.cxx
@@ -50,6 +50,7 @@
#include "data.hxx"
#include "node.hxx"
#include "parsemanager.hxx"
+#include "rootaccess.hxx"
#include "writemodfile.hxx"
#include "xcdparser.hxx"
#include "xcuparser.hxx"
@@ -126,8 +127,27 @@ rtl::Reference< Node > Components::getTemplate(
return data_.getTemplate(layer, fullName);
}
+void Components::addRootAccess(rtl::Reference< RootAccess > const & access) {
+ roots_.insert(access.get());
+}
+
+void Components::removeRootAccess(RootAccess * access) {
+ roots_.erase(access);
+}
+
+void Components::initGlobalBroadcaster(
+ Modifications const & globalModifications,
+ 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);
+ }
+ }
+}
+
void Components::addModification(rtl::OUString const & path) {
- data_.addModification(path);
+ data_.modifications.add(path);
}
void Components::writeModifications() {
diff --git a/configmgr2/source/components.hxx b/configmgr2/source/components.hxx
index 1b467021de66..36c1df7d6598 100644
--- a/configmgr2/source/components.hxx
+++ b/configmgr2/source/components.hxx
@@ -32,6 +32,8 @@
#include "sal/config.h"
+#include <set>
+
#include "boost/noncopyable.hpp"
#include "rtl/ref.hxx"
@@ -44,7 +46,10 @@ namespace rtl {
namespace configmgr {
+class Broadcaster;
class Node;
+class RootAccess;
+struct Modifications;
class Components: private boost::noncopyable {
public:
@@ -59,6 +64,15 @@ public:
rtl::Reference< Node > getTemplate(
int layer, rtl::OUString const & fullName) const;
+ void addRootAccess(rtl::Reference< RootAccess > const & access);
+
+ void removeRootAccess(RootAccess * access);
+
+ void initGlobalBroadcaster(
+ Modifications const & globalModifications,
+ rtl::Reference< RootAccess > const & exclude,
+ Broadcaster * broadcaster);
+
void addModification(rtl::OUString const & path);
void writeModifications();
@@ -95,7 +109,10 @@ private:
void parseModificationLayer();
+ typedef std::set< RootAccess * > WeakRootSet;
+
Data data_;
+ WeakRootSet roots_;
};
}
diff --git a/configmgr2/source/configurationprovider.cxx b/configmgr2/source/configurationprovider.cxx
index 3a9a5ca45857..1d3f056e5605 100644
--- a/configmgr2/source/configurationprovider.cxx
+++ b/configmgr2/source/configurationprovider.cxx
@@ -67,6 +67,7 @@
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
+#include "components.hxx"
#include "configurationprovider.hxx"
#include "lock.hxx"
#include "rootaccess.hxx"
@@ -281,6 +282,7 @@ Service::createInstanceWithArguments(
nodepath),
static_cast< cppu::OWeakObject * >(this));
}
+ Components::singleton().addRootAccess(root);
return static_cast< cppu::OWeakObject * >(root.get());
}
diff --git a/configmgr2/source/data.cxx b/configmgr2/source/data.cxx
index 7e329ddfcbcf..c53d81b04b08 100644
--- a/configmgr2/source/data.cxx
+++ b/configmgr2/source/data.cxx
@@ -54,11 +54,6 @@ namespace {
namespace css = com::sun::star;
-bool isPrefix(rtl::OUString const & prefix, rtl::OUString const & path) {
- return prefix.getLength() < path.getLength() && path.match(prefix) &&
- path[prefix.getLength()] == '/';
-}
-
bool decode(
rtl::OUString const & encoded, sal_Int32 begin, sal_Int32 end,
rtl::OUString * decoded)
@@ -321,21 +316,4 @@ rtl::Reference< Node > Data::getTemplate(
return findNode(layer, templates, fullName);
}
-void Data::addModification(rtl::OUString const & path) {
- //TODO
- for (Modifications::iterator i(modifications.begin());
- i != modifications.end();)
- {
- if (path == *i || isPrefix(*i, path)) {
- return;
- }
- if (isPrefix(path, *i)) {
- modifications.erase(i++);
- } else {
- ++i;
- }
- }
- modifications.push_back(path);
-}
-
}
diff --git a/configmgr2/source/data.hxx b/configmgr2/source/data.hxx
index f944a4293097..c2b28281ac6e 100644
--- a/configmgr2/source/data.hxx
+++ b/configmgr2/source/data.hxx
@@ -33,12 +33,12 @@
#include "sal/config.h"
#include <climits>
-#include <list>
#include "boost/noncopyable.hpp"
#include "rtl/ref.hxx"
#include "sal/types.h"
+#include "modifications.hxx"
#include "nodemap.hxx"
namespace rtl { class OUString; }
@@ -48,8 +48,6 @@ namespace configmgr {
class Node;
struct Data: private boost::noncopyable {
- typedef std::list< rtl::OUString > Modifications;
-
enum { NO_LAYER = INT_MAX };
NodeMap templates;
@@ -81,8 +79,6 @@ struct Data: private boost::noncopyable {
rtl::Reference< Node > getTemplate(
int layer, rtl::OUString const & fullName) const;
-
- void addModification(rtl::OUString const & path);
};
}
diff --git a/configmgr2/source/makefile.mk b/configmgr2/source/makefile.mk
index 7606c0a9bc72..38a412394028 100644
--- a/configmgr2/source/makefile.mk
+++ b/configmgr2/source/makefile.mk
@@ -40,6 +40,7 @@ CDEFS += -DOOO_DLLIMPLEMENTATION_CONFIGMGR
SLOFILES = \
$(SLO)/access.obj \
+ $(SLO)/broadcaster.obj \
$(SLO)/childaccess.obj \
$(SLO)/components.obj \
$(SLO)/configurationprovider.obj \
@@ -49,6 +50,7 @@ SLOFILES = \
$(SLO)/localizedpropertynode.obj \
$(SLO)/localizedvaluenode.obj \
$(SLO)/lock.obj \
+ $(SLO)/modifications.obj \
$(SLO)/node.obj \
$(SLO)/nodemap.obj \
$(SLO)/pad.obj \
diff --git a/configmgr2/source/modifications.cxx b/configmgr2/source/modifications.cxx
new file mode 100644
index 000000000000..157ccf35fe82
--- /dev/null
+++ b/configmgr2/source/modifications.cxx
@@ -0,0 +1,63 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2009 by Sun Microsystems, Inc.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* $RCSfile: code,v $
+*
+* $Revision: 1.4 $
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org 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 version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "rtl/ustring.hxx"
+
+#include "modifications.hxx"
+
+namespace configmgr {
+
+namespace {
+
+bool isPrefix(rtl::OUString const & prefix, rtl::OUString const & path) {
+ return prefix.getLength() < path.getLength() && path.match(prefix) &&
+ path[prefix.getLength()] == '/';
+}
+
+}
+
+void Modifications::add(rtl::OUString const & path) {
+ //TODO: performance
+ for (List::iterator i(list.begin()); i != list.end();) {
+ if (path == *i || isPrefix(*i, path)) {
+ return;
+ }
+ if (isPrefix(path, *i)) {
+ list.erase(i++);
+ } else {
+ ++i;
+ }
+ }
+ list.push_back(path);
+}
+
+}
diff --git a/configmgr2/source/modifications.hxx b/configmgr2/source/modifications.hxx
new file mode 100644
index 000000000000..37f811b9ce6f
--- /dev/null
+++ b/configmgr2/source/modifications.hxx
@@ -0,0 +1,54 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2009 by Sun Microsystems, Inc.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* $RCSfile: code,v $
+*
+* $Revision: 1.4 $
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org 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 version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_MODIFICATIONS_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_MODIFICATIONS_HXX
+
+#include "sal/config.h"
+
+#include <list>
+
+#include "boost/noncopyable.hpp"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+struct Modifications: private boost::noncopyable {
+public:
+ typedef std::list< rtl::OUString > List;
+
+ List list;
+
+ void add(rtl::OUString const & path);
+};
+
+}
+
+#endif
diff --git a/configmgr2/source/rootaccess.cxx b/configmgr2/source/rootaccess.cxx
index 7591ad23847b..59ecbefb914a 100644
--- a/configmgr2/source/rootaccess.cxx
+++ b/configmgr2/source/rootaccess.cxx
@@ -46,6 +46,7 @@
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
+#include "broadcaster.hxx"
#include "childaccess.hxx"
#include "components.hxx"
#include "data.hxx"
@@ -74,7 +75,10 @@ bool RootAccess::isUpdate() const {
return update_;
}
-RootAccess::~RootAccess() {}
+RootAccess::~RootAccess() {
+ osl::MutexGuard g(lock);
+ Components::singleton().removeRootAccess(this);
+}
rtl::OUString RootAccess::getAbsolutePath() {
getNode();
@@ -178,14 +182,21 @@ void RootAccess::commitChanges()
throw (css::lang::WrappedTargetException, css::uno::RuntimeException)
{
OSL_ASSERT(thisIs(IS_ANY|IS_UPDATE));
- osl::MutexGuard g(lock);
- checkLocalizedPropertyAccess();
- int finalizedLayer;
- commitChildChanges(
- (Components::singleton().resolvePath(path_, 0, 0, &finalizedLayer)
- == node_) &&
- finalizedLayer == Data::NO_LAYER);
- Components::singleton().writeModifications();
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ int finalizedLayer;
+ Modifications globalMods;
+ commitChildChanges(
+ ((Components::singleton().resolvePath(path_, 0, 0, &finalizedLayer)
+ == node_) &&
+ finalizedLayer == Data::NO_LAYER),
+ &globalMods);
+ Components::singleton().writeModifications();
+ Components::singleton().initGlobalBroadcaster(globalMods, this, &bc);
+ }
+ bc.send();
}
sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) {
diff --git a/configmgr2/source/writemodfile.cxx b/configmgr2/source/writemodfile.cxx
index bd5a802bd4cd..960fa3479858 100644
--- a/configmgr2/source/writemodfile.cxx
+++ b/configmgr2/source/writemodfile.cxx
@@ -51,6 +51,7 @@
#include "groupnode.hxx"
#include "localizedpropertynode.hxx"
#include "localizedvaluenode.hxx"
+#include "modifications.hxx"
#include "node.hxx"
#include "nodemap.hxx"
#include "propertynode.hxx"
@@ -473,8 +474,8 @@ void writeModFile(rtl::OUString const & url, Data const & data) {
//TODO: Do not write back information about those removed items that did not
// come from the .xcs/.xcu files, anyway (but had been added dynamically
// instead):
- for (Data::Modifications::const_iterator j(data.modifications.begin());
- j != data.modifications.end(); ++j)
+ for (Modifications::List::const_iterator j(data.modifications.list.begin());
+ j != data.modifications.list.end(); ++j)
{
rtl::OUString name;
rtl::OUString parentPath(Data::parseLastSegment(*j, &name));
diff --git a/configmgr2/source/xcuparser.cxx b/configmgr2/source/xcuparser.cxx
index ca50bd7a01c1..2821d51eeb7a 100644
--- a/configmgr2/source/xcuparser.cxx
+++ b/configmgr2/source/xcuparser.cxx
@@ -525,7 +525,7 @@ void XcuParser::handleGroupProp(XmlReader & reader, GroupNode * group) {
}
rtl::OUString name(xmldata::convertFromUtf8(attrName));
if (state_.top().record) {
- data_->addModification(pathPrefix_ + name);
+ data_->modifications.add(pathPrefix_ + name);
}
Type type = xmldata::parseType(reader, attrType);
if (type == TYPE_ANY) {
@@ -842,7 +842,7 @@ void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) {
attrComponent, attrNodeType, componentName_,
&set->getDefaultTemplateName()));
if (state_.top().record) {
- data_->addModification(
+ data_->modifications.add(
pathPrefix_ + Data::createSegment(templateName, name));
}
if (!set->isValidTemplate(templateName)) {