From bcdea3b379637a98e5bbc304078149ca6c2b6e03 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Tue, 13 Dec 2011 12:37:00 +0100 Subject: Simplified, type-safe C++ configuration access. * New offapi com.sun.star.configuration entities to access the complete configuration read-only or read/write... * ...configmgr adapted to support those new services/singletons... * ...new unotools/configuration.hxx is the type-safe C++ plumbing on top of that... * ...officecfg now generates C++ headers to access all the properties and sets given in the .xcs files... * ...and svl's asiancfg.cxx exemplarily makes use of the new officecfg/Office/Common.hxx to access the configuration. * There is still TODOs: For one, see those listed in officecfg/registry/cppheader.xsl. For another, at least a notification mechanism for the new read-only configuration access and the C++ wrapper is missing. --- configmgr/source/access.cxx | 2994 ++++++++++---------- configmgr/source/access.hxx | 136 +- configmgr/source/components.cxx | 6 +- configmgr/source/configmgr.component | 6 + configmgr/source/data.cxx | 18 +- configmgr/source/data.hxx | 4 + configmgr/source/groupnode.cxx | 4 +- configmgr/source/groupnode.hxx | 2 +- configmgr/source/localizedpropertynode.cxx | 4 +- configmgr/source/localizedpropertynode.hxx | 2 +- configmgr/source/makefile.mk | 3 + configmgr/source/node.cxx | 22 +- configmgr/source/node.hxx | 5 +- configmgr/source/readonlyaccess.cxx | 126 + configmgr/source/readonlyaccess.hxx | 61 + configmgr/source/readwriteaccess.cxx | 151 + configmgr/source/readwriteaccess.hxx | 61 + configmgr/source/rootaccess.cxx | 179 +- configmgr/source/rootaccess.hxx | 40 +- configmgr/source/rootnode.cxx | 66 + configmgr/source/rootnode.hxx | 65 + configmgr/source/services.cxx | 10 + configmgr/source/setnode.cxx | 4 +- configmgr/source/setnode.hxx | 2 +- configmgr/source/valueparser.cxx | 9 +- configmgr/source/writemodfile.cxx | 7 +- configmgr/source/xcsparser.cxx | 46 +- configmgr/source/xcuparser.cxx | 48 +- offapi/UnoApi_offapi.mk | 3 + .../com/sun/star/configuration/ReadOnlyAccess.idl | 49 + .../com/sun/star/configuration/ReadWriteAccess.idl | 49 + .../sun/star/configuration/XReadWriteAccess.idl | 54 + officecfg/Module_officecfg.mk | 1 + officecfg/Package_cppheader.mk | 45 + officecfg/registry/Makefile | 56 + officecfg/registry/cppheader.xsl | 275 ++ officecfg/registry/files.mk | 100 + svl/inc/svl/asiancfg.hxx | 2 +- svl/source/config/asiancfg.cxx | 99 +- unotools/Library_utl.mk | 1 + unotools/Package_inc.mk | 1 + unotools/inc/unotools/configuration.hxx | 270 ++ unotools/source/config/configuration.cxx | 207 ++ 43 files changed, 3510 insertions(+), 1783 deletions(-) create mode 100644 configmgr/source/readonlyaccess.cxx create mode 100644 configmgr/source/readonlyaccess.hxx create mode 100644 configmgr/source/readwriteaccess.cxx create mode 100644 configmgr/source/readwriteaccess.hxx create mode 100644 configmgr/source/rootnode.cxx create mode 100644 configmgr/source/rootnode.hxx create mode 100644 offapi/com/sun/star/configuration/ReadOnlyAccess.idl create mode 100644 offapi/com/sun/star/configuration/ReadWriteAccess.idl create mode 100644 offapi/com/sun/star/configuration/XReadWriteAccess.idl create mode 100644 officecfg/Package_cppheader.mk create mode 100644 officecfg/registry/Makefile create mode 100644 officecfg/registry/cppheader.xsl create mode 100644 officecfg/registry/files.mk create mode 100644 unotools/inc/unotools/configuration.hxx create mode 100644 unotools/source/config/configuration.cxx diff --git a/configmgr/source/access.cxx b/configmgr/source/access.cxx index dab5e21c62fd..c34a8acc08be 100644 --- a/configmgr/source/access.cxx +++ b/configmgr/source/access.cxx @@ -54,6 +54,7 @@ #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/XHierarchicalNameReplace.hpp" #include "com/sun/star/container/XNameAccess.hpp" #include "com/sun/star/container/XNameContainer.hpp" #include "com/sun/star/container/XNamed.hpp" @@ -163,873 +164,640 @@ void Access::initBroadcaster( initBroadcasterAndChanges(modifications, broadcaster, 0); } -Access::Access(Components & components): - components_(components), disposed_(false) -{ - lock_ = lock(); -} - -Access::~Access() {} - -void Access::initDisposeBroadcaster(Broadcaster * broadcaster) { - 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::clearListeners() throw() { - disposeListeners_.clear(); - containerListeners_.clear(); - propertyChangeListeners_.clear(); - vetoableChangeListeners_.clear(); - propertiesChangeListeners_.clear(); - //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->clearListeners(); - } - } -} - -css::uno::Any Access::queryInterface(css::uno::Type const & aType) +css::uno::Sequence< css::uno::Type > Access::getTypes() throw (css::uno::RuntimeException) { - css::uno::Any res(OWeakObject::queryInterface(aType)); - if (res.hasValue()) { - 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; - } + 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::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) { - 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; - } + 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()) { - res = cppu::queryInterface( - aType, static_cast< css::container::XNameReplace * >(this)); - if (res.hasValue()) { - return res; - } + types.push_back(cppu::UnoType< css::container::XNameReplace >::get()); + types.push_back( + cppu::UnoType< css::container::XHierarchicalNameReplace >::get()); if (getNode()->kind() != Node::KIND_GROUP || dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) { - res = cppu::queryInterface( - aType, static_cast< css::container::XNameContainer * >(this)); - if (res.hasValue()) { - return res; - } + types.push_back( + cppu::UnoType< css::container::XNameContainer >::get()); } if (getNode()->kind() == Node::KIND_SET) { - res = cppu::queryInterface( - aType, static_cast< css::lang::XSingleServiceFactory * >(this)); + types.push_back( + cppu::UnoType< css::lang::XSingleServiceFactory >::get()); } + } else { + types.push_back( + cppu::UnoType< css::container::XHierarchicalNameAccess >::get()); } - return res; -} - -Components & Access::getComponents() const { - return components_; -} - -void Access::checkLocalizedPropertyAccess() { - if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && - !Components::allLocales(getRootAccess()->getLocale())) - { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr Access to specialized LocalizedPropertyNode")), - static_cast< cppu::OWeakObject * >(this)); - } + addTypes(&types); + return types.getAsConstList(); } -rtl::Reference< Node > Access::getParentNode() { - rtl::Reference< Access > parent(getParentAccess()); - return parent.is() ? parent->getNode() : rtl::Reference< Node >(); +css::uno::Sequence< sal_Int8 > Access::getImplementationId() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return css::uno::Sequence< sal_Int8 >(); } -rtl::Reference< ChildAccess > Access::getChild(rtl::OUString const & name) { - ModifiedChildren::iterator i(modifiedChildren_.find(name)); - return i == modifiedChildren_.end() - ? getUnmodifiedChild(name) : getModifiedChild(i); +rtl::OUString Access::getImplementationName() throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("org.openoffice-configmgr::Access")); } -std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() { - std::vector< rtl::Reference< ChildAccess > > vec; - NodeMap & members = getNode()->getMembers(); - for (NodeMap::iterator i(members.begin()); i != members.end(); ++i) { - if (modifiedChildren_.find(i->first) == modifiedChildren_.end()) { - vec.push_back(getUnmodifiedChild(i->first)); - assert(vec.back().is()); - } - } - for (ModifiedChildren::iterator i(modifiedChildren_.begin()); - i != modifiedChildren_.end(); ++i) - { - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - vec.push_back(child); +sal_Bool Access::supportsService(rtl::OUString const & ServiceName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames()); + for (sal_Int32 i = 0; i < names.getLength(); ++i) { + if (names[i] == ServiceName) { + return true; } } - return vec; + return false; } -void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) { - bool ok; - switch (type) { - case TYPE_NIL: - assert(false); - // fall through (cannot happen) - case TYPE_ERROR: - ok = false; - break; - case TYPE_ANY: - switch (getDynamicType(value)) { - case TYPE_ANY: - assert(false); - // fall through (cannot happen) - case TYPE_ERROR: - ok = false; - break; - case TYPE_NIL: - ok = nillable; - break; - default: - ok = true; - break; - } - break; - default: - ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable; - break; - } - if (!ok) { - throw css::lang::IllegalArgumentException( - rtl::OUString( +css::uno::Sequence< rtl::OUString > Access::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + comphelper::SequenceAsVector< rtl::OUString > services; + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess"))); + if (getRootAccess()->isUpdate()) { + services.push_back( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "configmgr inappropriate property value")), - static_cast< cppu::OWeakObject * >(this), -1); + "com.sun.star.configuration.ConfigurationUpdateAccess"))); + } + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.HierarchyAccess"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.HierarchyElement"))); + if (getNode()->kind() == Node::KIND_GROUP) { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.GroupAccess"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.PropertyHierarchy"))); + if (getRootAccess()->isUpdate()) { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.GroupUpdate"))); + } + } else { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SetAccess"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SimpleSetAccess"))); + if (getRootAccess()->isUpdate()) { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SetUpdate"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SimpleSetUpdate"))); + } } + addSupportedServiceNames(&services); + return services.getAsConstList(); } -void Access::insertLocalizedValueChild( - rtl::OUString const & name, css::uno::Any const & value, - Modifications * localModifications) -{ - assert(localModifications != 0); - LocalizedPropertyNode * locprop = dynamic_cast< LocalizedPropertyNode * >( - getNode().get()); - checkValue(value, locprop->getStaticType(), locprop->isNillable()); - rtl::Reference< ChildAccess > child( - new ChildAccess( - components_, getRootAccess(), this, name, - new LocalizedValueNode(Data::NO_LAYER, value))); - markChildAsModified(child); - localModifications->add(child->getRelativePath()); +void Access::dispose() throw (css::uno::RuntimeException) { + 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); + clearListeners(); + disposed_ = true; + } + bc.send(); } -void Access::reportChildChanges( - std::vector< css::util::ElementChange > * changes) +void Access::addEventListener( + css::uno::Reference< css::lang::XEventListener > const & xListener) + throw (css::uno::RuntimeException) { - assert(changes != 0); - for (ModifiedChildren::iterator i(modifiedChildren_.begin()); - i != modifiedChildren_.end(); ++i) + assert(thisIs(IS_ANY)); { - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - child->reportChildChanges(changes); - changes->push_back(css::util::ElementChange()); - //TODO: changed value and/or inserted node - } else { - changes->push_back(css::util::ElementChange()); //TODO: removed node + 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::commitChildChanges( - bool valid, Modifications * globalModifications) +void Access::removeEventListener( + css::uno::Reference< css::lang::XEventListener > const & aListener) + throw (css::uno::RuntimeException) { - 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, 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 - // children); clarify what exactly should happen here for - // directly inserted children - } - NodeMap & members = getNode()->getMembers(); - NodeMap::iterator j(members.find(i->first)); - if (child.is()) { - // Inserted: - if (j != members.end()) { - childValid = childValid && - j->second->getFinalized() == Data::NO_LAYER; - if (childValid) { - child->getNode()->setMandatory(j->second->getMandatory()); - } - } - if (childValid) { - members[i->first] = child->getNode(); - } - } else { - // Removed: - childValid = childValid && j != members.end() && - j->second->getFinalized() == Data::NO_LAYER && - j->second->getMandatory() == Data::NO_LAYER; - if (childValid) { - members.erase(j); - } - } - if (childValid && i->second.directlyModified) { - Path path(getAbsolutePath()); - path.push_back(i->first); - components_.addModification(path); - globalModifications->add(path); - } - i->second.child->committed(); - modifiedChildren_.erase(i); + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + DisposeListeners::iterator i(disposeListeners_.find(aListener)); + if (i != disposeListeners_.end()) { + disposeListeners_.erase(i); } } -void Access::initBroadcasterAndChanges( - Modifications::Node const & modifications, Broadcaster * broadcaster, - std::vector< css::util::ElementChange > * allChanges) +css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) { + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< Node > p(getNode()); + switch (p->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + return mapType( + dynamic_cast< LocalizedPropertyNode * >(p.get())->getStaticType()); + case Node::KIND_GROUP: + //TODO: Should a specific type be returned for a non-extensible group + // with homogeneous members or for an extensible group that currently + // has only homegeneous members? + return cppu::UnoType< cppu::UnoVoidType >::get(); + case Node::KIND_SET: + return cppu::UnoType< cppu::UnoVoidType >::get(); //TODO: correct? + default: + assert(false); + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), + static_cast< cppu::OWeakObject * >(this)); + } +} + +sal_Bool Access::hasElements() throw (css::uno::RuntimeException) { + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return !getAllChildren().empty(); //TODO: optimize +} + +css::uno::Any Access::getByName(rtl::OUString const & aName) + throw ( + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(broadcaster != 0); - comphelper::SequenceAsVector< css::beans::PropertyChangeEvent > propChanges; - bool collectPropChanges = !propertiesChangeListeners_.empty(); - for (Modifications::Node::Children::const_iterator i( - modifications.children.begin()); - i != modifications.children.end(); ++i) + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asValue(); +} + +css::uno::Sequence< rtl::OUString > Access::getElementNames() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); + comphelper::SequenceAsVector< rtl::OUString > names; + for (std::vector< rtl::Reference< ChildAccess > >::iterator i( + children.begin()); + i != children.end(); ++i) { - rtl::Reference< ChildAccess > child(getChild(i->first)); - if (child.is()) { - switch (child->getNode()->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - if (!i->second.children.empty()) { - if (Components::allLocales(getRootAccess()->getLocale())) { - child->initBroadcasterAndChanges( - i->second, broadcaster, allChanges); - //TODO: if allChanges==0, recurse only into children - // w/ listeners - } else { - //TODO: filter child mods that are irrelevant for - // locale: - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster-> - addContainerElementReplacedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >( - this), - css::uno::makeAny(i->first), - css::uno::Any(), css::uno::Any())); - //TODO: non-void Element, ReplacedElement - } - PropertyChangeListeners::iterator j( - propertyChangeListeners_.find(i->first)); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >( - this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - j = propertyChangeListeners_.find(rtl::OUString()); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >( - this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void Element, ReplacedElement - } - if (collectPropChanges) { - propChanges.push_back( - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - } - // else: spurious Modifications::Node not representing a change - break; - case Node::KIND_LOCALIZED_VALUE: - assert(Components::allLocales(getRootAccess()->getLocale())); - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementReplacedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), child->asValue(), - css::uno::Any())); - //TODO: distinguish add/modify; non-void ReplacedElement - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - child->asValue(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - assert(!collectPropChanges); - break; - case Node::KIND_PROPERTY: - { - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementReplacedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), child->asValue(), - css::uno::Any())); - //TODO: distinguish add/remove/modify; non-void - // ReplacedElement - } - PropertyChangeListeners::iterator j( - propertyChangeListeners_.find(i->first)); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - j = propertyChangeListeners_.find(rtl::OUString()); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - child->asValue(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (collectPropChanges) { - propChanges.push_back( - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - break; - case Node::KIND_GROUP: - case Node::KIND_SET: - if (i->second.children.empty()) { - if (child->getNode()->getTemplateName().getLength() != 0) { - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster-> - addContainerElementInsertedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >( - this), - css::uno::makeAny(i->first), - child->asValue(), css::uno::Any())); - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void Element, ReplacedElement - } - } - // else: spurious Modifications::Node not representing a - // change - } else { - child->initBroadcasterAndChanges( - i->second, broadcaster, allChanges); - //TODO: if allChanges==0, recurse only into children w/ - // listeners - } - break; - } - } else { - switch (getNode()->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - // Removed localized property value: - assert(Components::allLocales(getRootAccess()->getLocale())); - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementRemovedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), css::uno::Any(), - css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (allChanges != 0) { - rtl::OUStringBuffer path(getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append( - Data::createSegment( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), - i->first)); - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny(path.makeStringAndClear()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - assert(!collectPropChanges); - break; - case Node::KIND_GROUP: - { - // Removed (non-localized) extension property: - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementRemovedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), css::uno::Any(), - css::uno::Any())); - //TODO: non-void ReplacedElement - } - PropertyChangeListeners::iterator j( - propertyChangeListeners_.find(i->first)); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - j = propertyChangeListeners_.find(rtl::OUString()); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - if (allChanges != 0) { - rtl::OUStringBuffer path( - getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append(i->first); - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny(path.makeStringAndClear()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (collectPropChanges) { - propChanges.push_back( - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - break; - case Node::KIND_SET: - // Removed set member: - if (i->second.children.empty()) { - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementRemovedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (allChanges != 0) { - rtl::OUStringBuffer path( - getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append( - Data::createSegment( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), - i->first)); - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny(path.makeStringAndClear()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - } - // else: spurious Modifications::Node not representing a change - break; - default: - assert(false); // this cannot happen - break; - } - } + names.push_back((*i)->getNameInternal()); } - if (!propChanges.empty()) { - css::uno::Sequence< css::beans::PropertyChangeEvent > seq( - propChanges.getAsConstList()); - for (PropertiesChangeListeners::iterator i( - propertiesChangeListeners_.begin()); - i != propertiesChangeListeners_.end(); ++i) - { - broadcaster->addPropertiesChangeNotification(*i, seq); + return names.getAsConstList(); +} + +sal_Bool Access::hasByName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return getChild(aName).is(); +} + +css::uno::Any Access::getByHierarchicalName(rtl::OUString const & aName) + throw (css::container::NoSuchElementException, css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getSubChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asValue(); +} + +sal_Bool Access::hasByHierarchicalName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return getSubChild(aName).is(); +} + +void Access::replaceByHierarchicalName( + rtl::OUString const & aName, css::uno::Any const & aElement) + throw ( + css::lang::IllegalArgumentException, + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) +{ + //TODO: Actually support sets and combine with replaceByName: + assert(thisIs(IS_UPDATE)); + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getSubChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + child->checkFinalized(); + rtl::Reference< Node > parent(child->getParentNode()); + assert(parent.is()); + Modifications localMods; + switch (parent->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + case Node::KIND_GROUP: + child->setProperty(aElement, &localMods); + break; + case Node::KIND_SET: + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr::Access::replaceByHierarchicalName does not" + " currently support set members")), + static_cast< cppu::OWeakObject * >(this), 0); + case Node::KIND_ROOT: + throw css::lang::IllegalArgumentException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr::Access::replaceByHierarchicalName does not" + " allow changing component ")) + + aName), + static_cast< cppu::OWeakObject * >(this), 0); + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } + bc.send(); } -bool Access::isDisposed() const { - return disposed_; -} - -Access::ModifiedChild::ModifiedChild() {} - -Access::ModifiedChild::ModifiedChild( - rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified): - child(theChild), directlyModified(theDirectlyModified) -{} - -css::uno::Sequence< css::uno::Type > Access::getTypes() +void Access::addContainerListener( + css::uno::Reference< css::container::XContainerListener > const & xListener) throw (css::uno::RuntimeException) { 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()); + { + 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 (getNode()->kind() == Node::KIND_SET) { - types.push_back( - cppu::UnoType< css::lang::XSingleServiceFactory >::get()); + if (!disposed_) { + containerListeners_.insert(xListener); + return; } } - addTypes(&types); - return types.getAsConstList(); + try { + xListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } -css::uno::Sequence< sal_Int8 > Access::getImplementationId() +void Access::removeContainerListener( + css::uno::Reference< css::container::XContainerListener > const & xListener) throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - return css::uno::Sequence< sal_Int8 >(); + ContainerListeners::iterator i(containerListeners_.find(xListener)); + if (i != containerListeners_.end()) { + containerListeners_.erase(i); + } } -rtl::OUString Access::getImplementationName() throw (css::uno::RuntimeException) +rtl::OUString Access::getExactName(rtl::OUString const & aApproximateName) + throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - return rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("org.openoffice-configmgr::Access")); + return aApproximateName; } -sal_Bool Access::supportsService(rtl::OUString const & ServiceName) +css::uno::Sequence< css::beans::Property > Access::getProperties() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); + comphelper::SequenceAsVector< css::beans::Property > properties; + for (std::vector< rtl::Reference< ChildAccess > >::iterator i( + children.begin()); + i != children.end(); ++i) + { + properties.push_back((*i)->asProperty()); + } + return properties.getAsConstList(); +} + +css::beans::Property Access::getPropertyByName(rtl::OUString const & aName) + throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is()) { + throw css::beans::UnknownPropertyException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asProperty(); +} + +sal_Bool Access::hasPropertyByName(rtl::OUString const & Name) throw (css::uno::RuntimeException) { + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + return getChild(Name).is(); +} + +rtl::OUString Access::getHierarchicalName() throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames()); - for (sal_Int32 i = 0; i < names.getLength(); ++i) { - if (names[i] == ServiceName) { - return true; - } + // For backwards compatibility, return an absolute path representation where + // available: + rtl::OUStringBuffer path; + rtl::Reference< RootAccess > root(getRootAccess()); + if (root.is()) { + path.append(root->getAbsolutePathRepresentation()); } - return false; + rtl::OUString rel(getRelativePathRepresentation()); + if (path.getLength() != 0 && rel.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append(rel); + return path.makeStringAndClear(); } -css::uno::Sequence< rtl::OUString > Access::getSupportedServiceNames() - throw (css::uno::RuntimeException) +rtl::OUString Access::composeHierarchicalName( + rtl::OUString const & aRelativeName) + throw ( + css::lang::IllegalArgumentException, css::lang::NoSupportException, + css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - comphelper::SequenceAsVector< rtl::OUString > services; - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.ConfigurationAccess"))); - if (getRootAccess()->isUpdate()) { - services.push_back( + if (aRelativeName.getLength() == 0 || aRelativeName[0] == '/') { + throw css::lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.ConfigurationUpdateAccess"))); + "configmgr composeHierarchicalName inappropriate relative" + " name")), + static_cast< cppu::OWeakObject * >(this), -1); } - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.HierarchyAccess"))); - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.HierarchyElement"))); - if (getNode()->kind() == Node::KIND_GROUP) { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.GroupAccess"))); - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.PropertyHierarchy"))); - if (getRootAccess()->isUpdate()) { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.GroupUpdate"))); - } - } else { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SetAccess"))); - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SimpleSetAccess"))); - if (getRootAccess()->isUpdate()) { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SetUpdate"))); - services.push_back( + rtl::OUStringBuffer path(getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append(aRelativeName); + return path.makeStringAndClear(); +} + +rtl::OUString Access::getName() throw (css::uno::RuntimeException) { + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return getNameInternal(); +} + +void Access::setName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + checkFinalized(); + Modifications localMods; + switch (getNode()->kind()) { + case Node::KIND_GROUP: + case Node::KIND_SET: + { + rtl::Reference< Access > parent(getParentAccess()); + if (parent.is()) { + rtl::Reference< Node > node(getNode()); + if (node->getTemplateName().getLength() != 0) { + rtl::Reference< ChildAccess > other( + parent->getChild(aName)); + if (other.get() == this) { + break; + } + if (node->getMandatory() == Data::NO_LAYER && + !(other.is() && other->isFinalized())) + { + rtl::Reference< RootAccess > root(getRootAccess()); + rtl::Reference< ChildAccess > childAccess( + dynamic_cast< ChildAccess * >(this)); + localMods.add(getRelativePath()); + // unbind() modifies the parent chain that + // markChildAsModified() walks, so order is + // important: + parent->markChildAsModified(childAccess); + //TODO: must not throw + childAccess->unbind(); // must not throw + if (other.is()) { + other->unbind(); // must not throw + } + childAccess->bind(root, parent, aName); + // must not throw + parent->markChildAsModified(childAccess); + //TODO: must not throw + localMods.add(getRelativePath()); + break; + } + } + } + } + // fall through + case Node::KIND_LOCALIZED_PROPERTY: + // renaming a property could only work for an extension property, + // but a localized property is never an extension property + throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SimpleSetUpdate"))); + "configmgr setName inappropriate node")), + static_cast< cppu::OWeakObject * >(this)); + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - addSupportedServiceNames(&services); - return services.getAsConstList(); + bc.send(); } -void Access::dispose() throw (css::uno::RuntimeException) { +css::beans::Property Access::getAsProperty() throw (css::uno::RuntimeException) +{ assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return asProperty(); +} + +css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + return this; +} + +void Access::setPropertyValue( + rtl::OUString const & aPropertyName, css::uno::Any const & aValue) + throw ( + css::beans::UnknownPropertyException, css::beans::PropertyVetoException, + css::lang::IllegalArgumentException, css::lang::WrappedTargetException, + css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); Broadcaster bc; { osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - if (getParentAccess().is()) { + if (!getRootAccess()->isUpdate()) { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "configmgr dispose inappropriate Access")), + "configmgr setPropertyValue on non-update access")), static_cast< cppu::OWeakObject * >(this)); } - if (disposed_) { - return; + Modifications localMods; + if (!setChildProperty(aPropertyName, aValue, &localMods)) { + throw css::beans::UnknownPropertyException( + aPropertyName, static_cast< cppu::OWeakObject * >(this)); } - initDisposeBroadcaster(&bc); - clearListeners(); - disposed_ = true; + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } bc.send(); } -void Access::addEventListener( - css::uno::Reference< css::lang::XEventListener > const & xListener) - throw (css::uno::RuntimeException) +css::uno::Any Access::getPropertyValue(rtl::OUString const & PropertyName) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + rtl::Reference< ChildAccess > child(getChild(PropertyName)); + if (!child.is()) { + throw css::beans::UnknownPropertyException( + PropertyName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asValue(); +} + +void Access::addPropertyChangeListener( + rtl::OUString const & aPropertyName, + css::uno::Reference< css::beans::XPropertyChangeListener > const & + xListener) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); { osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); if (!xListener.is()) { throw css::uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), static_cast< cppu::OWeakObject * >(this)); } + checkKnownProperty(aPropertyName); if (!disposed_) { - disposeListeners_.insert(xListener); + propertyChangeListeners_[aPropertyName].insert(xListener); return; } } @@ -1039,130 +807,163 @@ void Access::addEventListener( } catch (css::lang::DisposedException &) {} } -void Access::removeEventListener( - css::uno::Reference< css::lang::XEventListener > const & aListener) - throw (css::uno::RuntimeException) +void Access::removePropertyChangeListener( + rtl::OUString const & aPropertyName, + css::uno::Reference< css::beans::XPropertyChangeListener > const & + aListener) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - DisposeListeners::iterator i(disposeListeners_.find(aListener)); - if (i != disposeListeners_.end()) { - disposeListeners_.erase(i); + checkKnownProperty(aPropertyName); + 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); + } + } } } -css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< Node > p(getNode()); - switch (p->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - return mapType( - dynamic_cast< LocalizedPropertyNode * >(p.get())->getStaticType()); - case Node::KIND_GROUP: - //TODO: Should a specific type be returned for a non-extensible group - // with homogeneous members or for an extensible group that currently - // has only homegeneous members? - return cppu::UnoType< cppu::UnoVoidType >::get(); - case Node::KIND_SET: - return cppu::UnoType< cppu::UnoVoidType >::get(); //TODO: correct? - default: - assert(false); - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), - static_cast< cppu::OWeakObject * >(this)); +void Access::addVetoableChangeListener( + rtl::OUString const & PropertyName, + css::uno::Reference< css::beans::XVetoableChangeListener > const & + aListener) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + { + osl::MutexGuard g(*lock_); + if (!aListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + checkKnownProperty(PropertyName); + if (!disposed_) { + vetoableChangeListeners_[PropertyName].insert(aListener); + //TODO: actually call vetoableChangeListeners_ + return; + } } + try { + aListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } -sal_Bool Access::hasElements() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return !getAllChildren().empty(); //TODO: optimize -} - -css::uno::Any Access::getByName(rtl::OUString const & aName) +void Access::removeVetoableChangeListener( + rtl::OUString const & PropertyName, + css::uno::Reference< css::beans::XVetoableChangeListener > const & + aListener) throw ( - css::container::NoSuchElementException, - css::lang::WrappedTargetException, css::uno::RuntimeException) + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< ChildAccess > child(getChild(aName)); - if (!child.is()) { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); + checkKnownProperty(PropertyName); + 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); + } + } } - return child->asValue(); } -css::uno::Sequence< rtl::OUString > Access::getElementNames() - throw (css::uno::RuntimeException) +void Access::setPropertyValues( + css::uno::Sequence< rtl::OUString > const & aPropertyNames, + css::uno::Sequence< css::uno::Any > const & aValues) + throw ( + css::beans::PropertyVetoException, css::lang::IllegalArgumentException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); - comphelper::SequenceAsVector< rtl::OUString > names; - for (std::vector< rtl::Reference< ChildAccess > >::iterator i( - children.begin()); - i != children.end(); ++i) + assert(thisIs(IS_GROUP)); + Broadcaster bc; { - names.push_back((*i)->getNameInternal()); + osl::MutexGuard g(*lock_); + if (!getRootAccess()->isUpdate()) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues on non-update access")), + static_cast< cppu::OWeakObject * >(this)); + } + if (aPropertyNames.getLength() != aValues.getLength()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues: aPropertyNames/aValues of" + " different length")), + static_cast< cppu::OWeakObject * >(this), -1); + } + Modifications localMods; + for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { + if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues inappropriate property" + " name")), + static_cast< cppu::OWeakObject * >(this), -1); + } + } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - return names.getAsConstList(); + bc.send(); } -sal_Bool Access::hasByName(rtl::OUString const & aName) +css::uno::Sequence< css::uno::Any > Access::getPropertyValues( + css::uno::Sequence< rtl::OUString > const & aPropertyNames) throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return getChild(aName).is(); -} - -css::uno::Any Access::getByHierarchicalName(rtl::OUString const & aName) - throw (css::container::NoSuchElementException, css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< ChildAccess > child(getSubChild(aName)); - if (!child.is()) { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); + css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength()); + for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { + rtl::Reference< ChildAccess > child(getChild(aPropertyNames[i])); + if (!child.is()) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr getPropertyValues inappropriate property" + " name")), + static_cast< cppu::OWeakObject * >(this)); + } + vals[i] = child->asValue(); } - return child->asValue(); -} - -sal_Bool Access::hasByHierarchicalName(rtl::OUString const & aName) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return getSubChild(aName).is(); + return vals; } -void Access::addContainerListener( - css::uno::Reference< css::container::XContainerListener > const & xListener) +void Access::addPropertiesChangeListener( + css::uno::Sequence< rtl::OUString > const &, + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + xListener) throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); { 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); + propertiesChangeListeners_.insert(xListener); return; } } @@ -1172,200 +973,47 @@ void Access::addContainerListener( } catch (css::lang::DisposedException &) {} } -void Access::removeContainerListener( - css::uno::Reference< css::container::XContainerListener > const & xListener) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - ContainerListeners::iterator i(containerListeners_.find(xListener)); - if (i != containerListeners_.end()) { - containerListeners_.erase(i); - } -} - -rtl::OUString Access::getExactName(rtl::OUString const & aApproximateName) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return aApproximateName; -} - -css::uno::Sequence< css::beans::Property > Access::getProperties() +void Access::removePropertiesChangeListener( + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + xListener) throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); - comphelper::SequenceAsVector< css::beans::Property > properties; - for (std::vector< rtl::Reference< ChildAccess > >::iterator i( - children.begin()); - i != children.end(); ++i) - { - properties.push_back((*i)->asProperty()); - } - return properties.getAsConstList(); -} - -css::beans::Property Access::getPropertyByName(rtl::OUString const & aName) - throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getChild(aName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aName, static_cast< cppu::OWeakObject * >(this)); + PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.find(xListener)); + if (i != propertiesChangeListeners_.end()) { + propertiesChangeListeners_.erase(i); } - return child->asProperty(); } -sal_Bool Access::hasPropertyByName(rtl::OUString const & Name) +void Access::firePropertiesChangeEvent( + css::uno::Sequence< rtl::OUString > const & aPropertyNames, + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + xListener) throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - return getChild(Name).is(); -} - -rtl::OUString Access::getHierarchicalName() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - // For backwards compatibility, return an absolute path representation where - // available: - rtl::OUStringBuffer path; - rtl::Reference< RootAccess > root(getRootAccess()); - if (root.is()) { - path.append(root->getAbsolutePathRepresentation()); - } - rtl::OUString rel(getRelativePathRepresentation()); - if (path.getLength() != 0 && rel.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append(rel); - return path.makeStringAndClear(); -} - -rtl::OUString Access::composeHierarchicalName( - rtl::OUString const & aRelativeName) - throw ( - css::lang::IllegalArgumentException, css::lang::NoSupportException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - if (aRelativeName.getLength() == 0 || aRelativeName[0] == '/') { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr composeHierarchicalName inappropriate relative" - " name")), - static_cast< cppu::OWeakObject * >(this), -1); - } - rtl::OUStringBuffer path(getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append(aRelativeName); - return path.makeStringAndClear(); -} - -rtl::OUString Access::getName() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return getNameInternal(); -} - -void Access::setName(rtl::OUString const & aName) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - checkFinalized(); - Modifications localMods; - switch (getNode()->kind()) { - case Node::KIND_GROUP: - case Node::KIND_SET: - { - rtl::Reference< Access > parent(getParentAccess()); - if (parent.is()) { - rtl::Reference< Node > node(getNode()); - if (node->getTemplateName().getLength() != 0) { - rtl::Reference< ChildAccess > other( - parent->getChild(aName)); - if (other.get() == this) { - break; - } - if (node->getMandatory() == Data::NO_LAYER && - !(other.is() && other->isFinalized())) - { - rtl::Reference< RootAccess > root(getRootAccess()); - rtl::Reference< ChildAccess > childAccess( - dynamic_cast< ChildAccess * >(this)); - localMods.add(getRelativePath()); - // unbind() modifies the parent chain that - // markChildAsModified() walks, so order is - // important: - parent->markChildAsModified(childAccess); - //TODO: must not throw - childAccess->unbind(); // must not throw - if (other.is()) { - other->unbind(); // must not throw - } - childAccess->bind(root, parent, aName); - // must not throw - parent->markChildAsModified(childAccess); - //TODO: must not throw - localMods.add(getRelativePath()); - break; - } - } - } - } - // fall through - case Node::KIND_LOCALIZED_PROPERTY: - // renaming a property could only work for an extension property, - // but a localized property is never an extension property - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setName inappropriate node")), - static_cast< cppu::OWeakObject * >(this)); - default: - assert(false); // this cannot happen - break; - } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); + 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; } - bc.send(); -} - -css::beans::Property Access::getAsProperty() throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return asProperty(); + xListener->propertiesChange(events); } -css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo() - throw (css::uno::RuntimeException) -{ +css::uno::Reference< css::beans::XHierarchicalPropertySetInfo > +Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); return this; } -void Access::setPropertyValue( - rtl::OUString const & aPropertyName, css::uno::Any const & aValue) +void Access::setHierarchicalPropertyValue( + rtl::OUString const & aHierarchicalPropertyName, + css::uno::Any const & aValue) throw ( css::beans::UnknownPropertyException, css::beans::PropertyVetoException, css::lang::IllegalArgumentException, css::lang::WrappedTargetException, @@ -1379,583 +1027,997 @@ void Access::setPropertyValue( throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValue on non-update access")), + "configmgr setHierarchicalPropertyName on non-update" + " access")), static_cast< cppu::OWeakObject * >(this)); } - Modifications localMods; - if (!setChildProperty(aPropertyName, aValue, &localMods)) { + rtl::Reference< ChildAccess > child( + getSubChild(aHierarchicalPropertyName)); + if (!child.is()) { throw css::beans::UnknownPropertyException( - aPropertyName, static_cast< cppu::OWeakObject * >(this)); + aHierarchicalPropertyName, + static_cast< cppu::OWeakObject * >(this)); } + child->checkFinalized(); + Modifications localMods; + child->setProperty(aValue, &localMods); getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } bc.send(); } -css::uno::Any Access::getPropertyValue(rtl::OUString const & PropertyName) +css::uno::Any Access::getHierarchicalPropertyValue( + rtl::OUString const & aHierarchicalPropertyName) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::beans::UnknownPropertyException, + css::lang::IllegalArgumentException, css::lang::WrappedTargetException, css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getChild(PropertyName)); + rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName)); if (!child.is()) { throw css::beans::UnknownPropertyException( - PropertyName, static_cast< cppu::OWeakObject * >(this)); + aHierarchicalPropertyName, + static_cast< cppu::OWeakObject * >(this)); } return child->asValue(); } -void Access::addPropertyChangeListener( - rtl::OUString const & aPropertyName, - css::uno::Reference< css::beans::XPropertyChangeListener > const & - xListener) +void Access::setHierarchicalPropertyValues( + css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames, + css::uno::Sequence< css::uno::Any > const & Values) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, - css::uno::RuntimeException) + css::beans::PropertyVetoException, css::lang::IllegalArgumentException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); + Broadcaster bc; { osl::MutexGuard g(*lock_); - if (!xListener.is()) { + if (!getRootAccess()->isUpdate()) { throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues on non-update access")), static_cast< cppu::OWeakObject * >(this)); } - checkKnownProperty(aPropertyName); - if (!disposed_) { - propertyChangeListeners_[aPropertyName].insert(xListener); - return; + if (aHierarchicalPropertyNames.getLength() != Values.getLength()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setHierarchicalPropertyValues:" + " aHierarchicalPropertyNames/Values of different" + " length")), + static_cast< cppu::OWeakObject * >(this), -1); + } + Modifications localMods; + for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { + rtl::Reference< ChildAccess > child( + getSubChild(aHierarchicalPropertyNames[i])); + if (!child.is()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setHierarchicalPropertyValues" + " inappropriate property name")), + static_cast< cppu::OWeakObject * >(this), -1); + } + child->checkFinalized(); + child->setProperty(Values[i], &localMods); } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - try { - xListener->disposing( - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } catch (css::lang::DisposedException &) {} + bc.send(); } -void Access::removePropertyChangeListener( - rtl::OUString const & aPropertyName, - css::uno::Reference< css::beans::XPropertyChangeListener > const & - aListener) +css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues( + css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::lang::IllegalArgumentException, css::lang::WrappedTargetException, css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkKnownProperty(aPropertyName); - 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); - } + css::uno::Sequence< css::uno::Any > vals( + aHierarchicalPropertyNames.getLength()); + for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { + rtl::Reference< ChildAccess > child( + getSubChild(aHierarchicalPropertyNames[i])); + if (!child.is()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr getHierarchicalPropertyValues inappropriate" + " hierarchical property name")), + static_cast< cppu::OWeakObject * >(this), -1); } + vals[i] = child->asValue(); } + return vals; } -void Access::addVetoableChangeListener( - rtl::OUString const & PropertyName, - css::uno::Reference< css::beans::XVetoableChangeListener > const & - aListener) - throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, - css::uno::RuntimeException) +css::beans::Property Access::getPropertyByHierarchicalName( + rtl::OUString const & aHierarchicalName) + throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName)); + if (!child.is()) { + throw css::beans::UnknownPropertyException( + aHierarchicalName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asProperty(); +} + +sal_Bool Access::hasPropertyByHierarchicalName( + rtl::OUString const & aHierarchicalName) + throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + return getSubChild(aHierarchicalName).is(); +} + +void Access::replaceByName( + rtl::OUString const & aName, css::uno::Any const & aElement) + throw ( + css::lang::IllegalArgumentException, + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) +{ + assert(thisIs(IS_UPDATE)); + Broadcaster bc; { osl::MutexGuard g(*lock_); - if (!aListener.is()) { - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), - static_cast< cppu::OWeakObject * >(this)); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); } - checkKnownProperty(PropertyName); - if (!disposed_) { - vetoableChangeListeners_[PropertyName].insert(aListener); - //TODO: actually call vetoableChangeListeners_ - return; + 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()); + localMods.add(child->getRelativePath()); + child->unbind(); // must not throw + freeAcc->bind(root, this, aName); // must not throw + markChildAsModified(freeAcc); //TODO: must not throw + } + break; + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - try { - aListener->disposing( - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } catch (css::lang::DisposedException &) {} + bc.send(); } -void Access::removeVetoableChangeListener( - rtl::OUString const & PropertyName, - css::uno::Reference< css::beans::XVetoableChangeListener > const & - aListener) +void Access::insertByName( + rtl::OUString const & aName, css::uno::Any const & aElement) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, - css::uno::RuntimeException) + css::lang::IllegalArgumentException, + css::container::ElementExistException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - checkKnownProperty(PropertyName); - 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); + assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + checkFinalized(); + if (getChild(aName).is()) { + throw css::container::ElementExistException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + Modifications localMods; + switch (getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + insertLocalizedValueChild(aName, aElement, &localMods); + break; + case Node::KIND_GROUP: + { + checkValue(aElement, TYPE_ANY, true); + rtl::Reference< ChildAccess > child( + new ChildAccess( + components_, getRootAccess(), this, aName, + new PropertyNode( + Data::NO_LAYER, TYPE_ANY, true, aElement, true))); + markChildAsModified(child); + localMods.add(child->getRelativePath()); + } + break; + case Node::KIND_SET: + { + rtl::Reference< ChildAccess > freeAcc( + getFreeSetMember(aElement)); + freeAcc->bind(getRootAccess(), this, aName); // must not throw + markChildAsModified(freeAcc); //TODO: must not throw + localMods.add(freeAcc->getRelativePath()); } + break; + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } + bc.send(); } -void Access::setPropertyValues( - css::uno::Sequence< rtl::OUString > const & aPropertyNames, - css::uno::Sequence< css::uno::Any > const & aValues) +void Access::removeByName(rtl::OUString const & aName) throw ( - css::beans::PropertyVetoException, css::lang::IllegalArgumentException, + css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); + assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); Broadcaster bc; { osl::MutexGuard g(*lock_); - if (!getRootAccess()->isUpdate()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues on non-update access")), - static_cast< cppu::OWeakObject * >(this)); - } - if (aPropertyNames.getLength() != aValues.getLength()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues: aPropertyNames/aValues of" - " different length")), - static_cast< cppu::OWeakObject * >(this), -1); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is() || child->isFinalized() || + child->getNode()->getMandatory() != Data::NO_LAYER) + { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); } - Modifications localMods; - for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { - if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues inappropriate property" - " name")), - static_cast< cppu::OWeakObject * >(this), -1); + if (getNode()->kind() == Node::KIND_GROUP) { + rtl::Reference< Node > p(child->getNode()); + if (p->kind() != Node::KIND_PROPERTY || + !dynamic_cast< PropertyNode * >(p.get())->isExtension()) + { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); } } + Modifications localMods; + localMods.add(child->getRelativePath()); + // unbind() modifies the parent chain that markChildAsModified() walks, + // so order is important: + markChildAsModified(child); //TODO: must not throw + child->unbind(); getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } bc.send(); } -css::uno::Sequence< css::uno::Any > Access::getPropertyValues( - css::uno::Sequence< rtl::OUString > const & aPropertyNames) - throw (css::uno::RuntimeException) +css::uno::Reference< css::uno::XInterface > Access::createInstance() + throw (css::uno::Exception, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength()); - for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { - rtl::Reference< ChildAccess > child(getChild(aPropertyNames[i])); - if (!child.is()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr getPropertyValues inappropriate property" - " name")), - static_cast< cppu::OWeakObject * >(this)); - } - vals[i] = child->asValue(); + assert(thisIs(IS_SET|IS_UPDATE)); + rtl::OUString tmplName( + dynamic_cast< SetNode * >(getNode().get())->getDefaultTemplateName()); + rtl::Reference< Node > tmpl( + components_.getTemplate(Data::NO_LAYER, tmplName)); + if (!tmpl.is()) { + throw css::uno::Exception( + (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown template ")) + + tmplName), + static_cast< cppu::OWeakObject * >(this)); } - return vals; + rtl::Reference< Node > node(tmpl->clone(true)); + node->setLayer(Data::NO_LAYER); + return static_cast< cppu::OWeakObject * >( + new ChildAccess(components_, getRootAccess(), node)); } -void Access::addPropertiesChangeListener( - css::uno::Sequence< rtl::OUString > const &, - css::uno::Reference< css::beans::XPropertiesChangeListener > const & - xListener) - throw (css::uno::RuntimeException) +css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments( + css::uno::Sequence< css::uno::Any > const & aArguments) + throw (css::uno::Exception, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); + assert(thisIs(IS_SET|IS_UPDATE)); + if (aArguments.getLength() != 0) { + throw css::uno::Exception( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configuration SimpleSetUpdate createInstanceWithArguments" + " must not specify any arguments")), + static_cast< cppu::OWeakObject * >(this)); + } + return createInstance(); +} + +Access::Access(Components & components): + components_(components), disposed_(false) +{ + lock_ = lock(); +} + +Access::~Access() {} + +void Access::initDisposeBroadcaster(Broadcaster * broadcaster) { + assert(broadcaster != 0); + for (DisposeListeners::iterator i(disposeListeners_.begin()); + i != disposeListeners_.end(); ++i) { - osl::MutexGuard g(*lock_); - if (!xListener.is()) { - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), - static_cast< cppu::OWeakObject * >(this)); + 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))); } - if (!disposed_) { - propertiesChangeListeners_.insert(xListener); - return; + } + 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))); } } - try { - xListener->disposing( + for (PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.begin()); + i != propertiesChangeListeners_.end(); ++i) + { + broadcaster->addDisposeNotification( + i->get(), css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } catch (css::lang::DisposedException &) {} + } + //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::removePropertiesChangeListener( - css::uno::Reference< css::beans::XPropertiesChangeListener > const & - xListener) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - PropertiesChangeListeners::iterator i( - propertiesChangeListeners_.find(xListener)); - if (i != propertiesChangeListeners_.end()) { - propertiesChangeListeners_.erase(i); +void Access::clearListeners() throw() { + disposeListeners_.clear(); + containerListeners_.clear(); + propertyChangeListeners_.clear(); + vetoableChangeListeners_.clear(); + propertiesChangeListeners_.clear(); + //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->clearListeners(); + } } } -void Access::firePropertiesChangeEvent( - css::uno::Sequence< rtl::OUString > const & aPropertyNames, - css::uno::Reference< css::beans::XPropertiesChangeListener > const & - xListener) +css::uno::Any Access::queryInterface(css::uno::Type const & aType) throw (css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - 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; + css::uno::Any res(OWeakObject::queryInterface(aType)); + if (res.hasValue()) { + 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), + static_cast< css::container::XHierarchicalNameReplace * >(this)); + if (res.hasValue()) { + return res; + } + if (getNode()->kind() != Node::KIND_GROUP || + dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) + { + 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)); + } } - xListener->propertiesChange(events); + return res; } -css::uno::Reference< css::beans::XHierarchicalPropertySetInfo > -Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - return this; +Components & Access::getComponents() const { + return components_; } -void Access::setHierarchicalPropertyValue( - rtl::OUString const & aHierarchicalPropertyName, - css::uno::Any const & aValue) - throw ( - css::beans::UnknownPropertyException, css::beans::PropertyVetoException, - css::lang::IllegalArgumentException, css::lang::WrappedTargetException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - Broadcaster bc; +void Access::checkLocalizedPropertyAccess() { + if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && + !Components::allLocales(getRootAccess()->getLocale())) { - osl::MutexGuard g(*lock_); - if (!getRootAccess()->isUpdate()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setHierarchicalPropertyName on non-update" - " access")), - static_cast< cppu::OWeakObject * >(this)); - } - rtl::Reference< ChildAccess > child( - getSubChild(aHierarchicalPropertyName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aHierarchicalPropertyName, - static_cast< cppu::OWeakObject * >(this)); - } - child->checkFinalized(); - Modifications localMods; - child->setProperty(aValue, &localMods); - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr Access to specialized LocalizedPropertyNode")), + static_cast< cppu::OWeakObject * >(this)); } - bc.send(); } -css::uno::Any Access::getHierarchicalPropertyValue( - rtl::OUString const & aHierarchicalPropertyName) - throw ( - css::beans::UnknownPropertyException, - css::lang::IllegalArgumentException, css::lang::WrappedTargetException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aHierarchicalPropertyName, - static_cast< cppu::OWeakObject * >(this)); - } - return child->asValue(); +rtl::Reference< Node > Access::getParentNode() { + rtl::Reference< Access > parent(getParentAccess()); + return parent.is() ? parent->getNode() : rtl::Reference< Node >(); } -void Access::setHierarchicalPropertyValues( - css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames, - css::uno::Sequence< css::uno::Any > const & Values) - throw ( - css::beans::PropertyVetoException, css::lang::IllegalArgumentException, - css::lang::WrappedTargetException, css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - if (!getRootAccess()->isUpdate()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues on non-update access")), - static_cast< cppu::OWeakObject * >(this)); - } - if (aHierarchicalPropertyNames.getLength() != Values.getLength()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setHierarchicalPropertyValues:" - " aHierarchicalPropertyNames/Values of different" - " length")), - static_cast< cppu::OWeakObject * >(this), -1); +rtl::Reference< ChildAccess > Access::getChild(rtl::OUString const & name) { + ModifiedChildren::iterator i(modifiedChildren_.find(name)); + return i == modifiedChildren_.end() + ? getUnmodifiedChild(name) : getModifiedChild(i); +} + +std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() { + std::vector< rtl::Reference< ChildAccess > > vec; + NodeMap const & members = getNode()->getMembers(); + for (NodeMap::const_iterator i(members.begin()); i != members.end(); ++i) { + if (modifiedChildren_.find(i->first) == modifiedChildren_.end()) { + vec.push_back(getUnmodifiedChild(i->first)); + assert(vec.back().is()); } - Modifications localMods; - for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { - rtl::Reference< ChildAccess > child( - getSubChild(aHierarchicalPropertyNames[i])); - if (!child.is()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setHierarchicalPropertyValues" - " inappropriate property name")), - static_cast< cppu::OWeakObject * >(this), -1); - } - child->checkFinalized(); - child->setProperty(Values[i], &localMods); + } + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + vec.push_back(child); } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - bc.send(); + return vec; } -css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues( - css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames) - throw ( - css::lang::IllegalArgumentException, css::lang::WrappedTargetException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - css::uno::Sequence< css::uno::Any > vals( - aHierarchicalPropertyNames.getLength()); - for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { - rtl::Reference< ChildAccess > child( - getSubChild(aHierarchicalPropertyNames[i])); - if (!child.is()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr getHierarchicalPropertyValues inappropriate" - " hierarchical property name")), - static_cast< cppu::OWeakObject * >(this), -1); +void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) { + bool ok; + switch (type) { + case TYPE_NIL: + assert(false); + // fall through (cannot happen) + case TYPE_ERROR: + ok = false; + break; + case TYPE_ANY: + switch (getDynamicType(value)) { + case TYPE_ANY: + assert(false); + // fall through (cannot happen) + case TYPE_ERROR: + ok = false; + break; + case TYPE_NIL: + ok = nillable; + break; + default: + ok = true; + break; } - vals[i] = child->asValue(); + break; + default: + ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable; + break; + } + if (!ok) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr inappropriate property value")), + static_cast< cppu::OWeakObject * >(this), -1); } - return vals; } -css::beans::Property Access::getPropertyByHierarchicalName( - rtl::OUString const & aHierarchicalName) - throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) +void Access::insertLocalizedValueChild( + rtl::OUString const & name, css::uno::Any const & value, + Modifications * localModifications) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aHierarchicalName, static_cast< cppu::OWeakObject * >(this)); - } - return child->asProperty(); + assert(localModifications != 0); + LocalizedPropertyNode * locprop = dynamic_cast< LocalizedPropertyNode * >( + getNode().get()); + checkValue(value, locprop->getStaticType(), locprop->isNillable()); + rtl::Reference< ChildAccess > child( + new ChildAccess( + components_, getRootAccess(), this, name, + new LocalizedValueNode(Data::NO_LAYER, value))); + markChildAsModified(child); + localModifications->add(child->getRelativePath()); } -sal_Bool Access::hasPropertyByHierarchicalName( - rtl::OUString const & aHierarchicalName) - throw (css::uno::RuntimeException) +void Access::reportChildChanges( + std::vector< css::util::ElementChange > * changes) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - return getSubChild(aHierarchicalName).is(); + assert(changes != 0); + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + child->reportChildChanges(changes); + changes->push_back(css::util::ElementChange()); + //TODO: changed value and/or inserted node + } else { + changes->push_back(css::util::ElementChange()); //TODO: removed node + } + } } -void Access::replaceByName( - rtl::OUString const & aName, css::uno::Any const & aElement) - throw ( - css::lang::IllegalArgumentException, - css::container::NoSuchElementException, - css::lang::WrappedTargetException, css::uno::RuntimeException) +void Access::commitChildChanges( + bool valid, Modifications * globalModifications) { - assert(thisIs(IS_UPDATE)); - 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)); + 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, 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 + // children); clarify what exactly should happen here for + // directly inserted children } - 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()); - localMods.add(child->getRelativePath()); - child->unbind(); // must not throw - freeAcc->bind(root, this, aName); // must not throw - markChildAsModified(freeAcc); //TODO: must not throw + NodeMap * members = getNode()->getMemberMap(); + if (members != 0) { + NodeMap::const_iterator j(members->find(i->first)); + if (child.is()) { + // Inserted: + if (j != members->end()) { + childValid = childValid && + j->second->getFinalized() == Data::NO_LAYER; + if (childValid) { + child->getNode()->setMandatory( + j->second->getMandatory()); + } + } + if (childValid) { + (*members)[i->first] = child->getNode(); + } + } else { + // Removed: + childValid = childValid && j != members->end() && + j->second->getFinalized() == Data::NO_LAYER && + j->second->getMandatory() == Data::NO_LAYER; + if (childValid) { + members->erase(j); + } } - break; - default: - assert(false); // this cannot happen - break; } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); + if (childValid && i->second.directlyModified) { + Path path(getAbsolutePath()); + path.push_back(i->first); + components_.addModification(path); + globalModifications->add(path); + } + i->second.child->committed(); + modifiedChildren_.erase(i); } - bc.send(); } -void Access::insertByName( - rtl::OUString const & aName, css::uno::Any const & aElement) - throw ( - css::lang::IllegalArgumentException, - css::container::ElementExistException, - css::lang::WrappedTargetException, css::uno::RuntimeException) +void Access::initBroadcasterAndChanges( + Modifications::Node const & modifications, Broadcaster * broadcaster, + std::vector< css::util::ElementChange > * allChanges) { - assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); - Broadcaster bc; + assert(broadcaster != 0); + comphelper::SequenceAsVector< css::beans::PropertyChangeEvent > propChanges; + bool collectPropChanges = !propertiesChangeListeners_.empty(); + for (Modifications::Node::Children::const_iterator i( + modifications.children.begin()); + i != modifications.children.end(); ++i) { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - checkFinalized(); - if (getChild(aName).is()) { - throw css::container::ElementExistException( - aName, static_cast< cppu::OWeakObject * >(this)); - } - Modifications localMods; - switch (getNode()->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - insertLocalizedValueChild(aName, aElement, &localMods); - break; - case Node::KIND_GROUP: - { - checkValue(aElement, TYPE_ANY, true); - rtl::Reference< ChildAccess > child( - new ChildAccess( - components_, getRootAccess(), this, aName, - new PropertyNode( - Data::NO_LAYER, TYPE_ANY, true, aElement, true))); - markChildAsModified(child); - localMods.add(child->getRelativePath()); + rtl::Reference< ChildAccess > child(getChild(i->first)); + if (child.is()) { + switch (child->getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + if (!i->second.children.empty()) { + if (Components::allLocales(getRootAccess()->getLocale())) { + child->initBroadcasterAndChanges( + i->second, broadcaster, allChanges); + //TODO: if allChanges==0, recurse only into children + // w/ listeners + } else { + //TODO: filter child mods that are irrelevant for + // locale: + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster-> + addContainerElementReplacedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >( + this), + css::uno::makeAny(i->first), + css::uno::Any(), css::uno::Any())); + //TODO: non-void Element, ReplacedElement + } + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >( + this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + j = propertyChangeListeners_.find(rtl::OUString()); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >( + this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void Element, ReplacedElement + } + if (collectPropChanges) { + propChanges.push_back( + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + } + // else: spurious Modifications::Node not representing a change + break; + case Node::KIND_LOCALIZED_VALUE: + assert(Components::allLocales(getRootAccess()->getLocale())); + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementReplacedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), child->asValue(), + css::uno::Any())); + //TODO: distinguish add/modify; non-void ReplacedElement + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + child->asValue(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + assert(!collectPropChanges); + break; + case Node::KIND_PROPERTY: + { + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementReplacedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), child->asValue(), + css::uno::Any())); + //TODO: distinguish add/remove/modify; non-void + // ReplacedElement + } + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + j = propertyChangeListeners_.find(rtl::OUString()); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + child->asValue(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (collectPropChanges) { + propChanges.push_back( + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + break; + case Node::KIND_GROUP: + case Node::KIND_SET: + if (i->second.children.empty()) { + if (child->getNode()->getTemplateName().getLength() != 0) { + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster-> + addContainerElementInsertedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >( + this), + css::uno::makeAny(i->first), + child->asValue(), css::uno::Any())); + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void Element, ReplacedElement + } + } + // else: spurious Modifications::Node not representing a + // change + } else { + child->initBroadcasterAndChanges( + i->second, broadcaster, allChanges); + //TODO: if allChanges==0, recurse only into children w/ + // listeners + } + break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } - break; - case Node::KIND_SET: - { - rtl::Reference< ChildAccess > freeAcc( - getFreeSetMember(aElement)); - freeAcc->bind(getRootAccess(), this, aName); // must not throw - markChildAsModified(freeAcc); //TODO: must not throw - localMods.add(freeAcc->getRelativePath()); + } else { + switch (getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + // Removed localized property value: + assert(Components::allLocales(getRootAccess()->getLocale())); + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementRemovedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), css::uno::Any(), + css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (allChanges != 0) { + rtl::OUStringBuffer path(getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append( + Data::createSegment( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), + i->first)); + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny(path.makeStringAndClear()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + assert(!collectPropChanges); + break; + case Node::KIND_GROUP: + { + // Removed (non-localized) extension property: + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementRemovedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), css::uno::Any(), + css::uno::Any())); + //TODO: non-void ReplacedElement + } + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + j = propertyChangeListeners_.find(rtl::OUString()); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + if (allChanges != 0) { + rtl::OUStringBuffer path( + getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append(i->first); + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny(path.makeStringAndClear()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (collectPropChanges) { + propChanges.push_back( + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + break; + case Node::KIND_SET: + // Removed set member: + if (i->second.children.empty()) { + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementRemovedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (allChanges != 0) { + rtl::OUStringBuffer path( + getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append( + Data::createSegment( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), + i->first)); + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny(path.makeStringAndClear()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + } + // else: spurious Modifications::Node not representing a change + break; + default: + assert(false); // this cannot happen + break; } - break; - default: - assert(false); // this cannot happen - break; } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - bc.send(); -} - -void Access::removeByName(rtl::OUString const & aName) - throw ( - css::container::NoSuchElementException, - css::lang::WrappedTargetException, css::uno::RuntimeException) -{ - assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< ChildAccess > child(getChild(aName)); - if (!child.is() || child->isFinalized() || - child->getNode()->getMandatory() != Data::NO_LAYER) + if (!propChanges.empty()) { + css::uno::Sequence< css::beans::PropertyChangeEvent > seq( + propChanges.getAsConstList()); + for (PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.begin()); + i != propertiesChangeListeners_.end(); ++i) { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); - } - if (getNode()->kind() == Node::KIND_GROUP) { - rtl::Reference< Node > p(child->getNode()); - if (p->kind() != Node::KIND_PROPERTY || - !dynamic_cast< PropertyNode * >(p.get())->isExtension()) - { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); - } + broadcaster->addPropertiesChangeNotification(*i, seq); } - Modifications localMods; - localMods.add(child->getRelativePath()); - // unbind() modifies the parent chain that markChildAsModified() walks, - // so order is important: - markChildAsModified(child); //TODO: must not throw - child->unbind(); - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - bc.send(); } -css::uno::Reference< css::uno::XInterface > Access::createInstance() - throw (css::uno::Exception, css::uno::RuntimeException) -{ - assert(thisIs(IS_SET|IS_UPDATE)); - rtl::OUString tmplName( - dynamic_cast< SetNode * >(getNode().get())->getDefaultTemplateName()); - rtl::Reference< Node > tmpl( - components_.getTemplate(Data::NO_LAYER, tmplName)); - if (!tmpl.is()) { - throw css::uno::Exception( - (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown template ")) + - tmplName), - static_cast< cppu::OWeakObject * >(this)); - } - rtl::Reference< Node > node(tmpl->clone(true)); - node->setLayer(Data::NO_LAYER); - return static_cast< cppu::OWeakObject * >( - new ChildAccess(components_, getRootAccess(), node)); +bool Access::isDisposed() const { + return disposed_; } -css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments( - css::uno::Sequence< css::uno::Any > const & aArguments) - throw (css::uno::Exception, css::uno::RuntimeException) -{ - assert(thisIs(IS_SET|IS_UPDATE)); - if (aArguments.getLength() != 0) { - throw css::uno::Exception( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configuration SimpleSetUpdate createInstanceWithArguments" - " must not specify any arguments")), - static_cast< cppu::OWeakObject * >(this)); - } - return createInstance(); -} +Access::ModifiedChild::ModifiedChild() {} + +Access::ModifiedChild::ModifiedChild( + rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified): + child(theChild), directlyModified(theDirectlyModified) +{} rtl::Reference< ChildAccess > Access::getModifiedChild( ModifiedChildren::iterator const & childIterator) diff --git a/configmgr/source/access.hxx b/configmgr/source/access.hxx index d2409cbb2f1d..6401df3f8344 100644 --- a/configmgr/source/access.hxx +++ b/configmgr/source/access.hxx @@ -51,7 +51,7 @@ #include "com/sun/star/container/NoSuchElementException.hpp" #include "com/sun/star/container/XContainer.hpp" #include "com/sun/star/container/XHierarchicalName.hpp" -#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XHierarchicalNameReplace.hpp" #include "com/sun/star/container/XNameContainer.hpp" #include "com/sun/star/container/XNamed.hpp" #include "com/sun/star/lang/IllegalArgumentException.hpp" @@ -106,7 +106,7 @@ 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::XHierarchicalNameReplace, public com::sun::star::container::XContainer, public com::sun::star::beans::XExactName, public com::sun::star::beans::XPropertySetInfo, @@ -146,68 +146,6 @@ public: using OWeakObject::acquire; using OWeakObject::release; -protected: - Access(Components & components); - - virtual ~Access(); - - virtual rtl::OUString getNameInternal() = 0; - virtual rtl::Reference< RootAccess > getRootAccess() = 0; - virtual rtl::Reference< Access > getParentAccess() = 0; - - virtual void addTypes(std::vector< com::sun::star::uno::Type > * types) - const = 0; - - virtual void addSupportedServiceNames( - std::vector< rtl::OUString > * services) = 0; - - virtual void initDisposeBroadcaster(Broadcaster * broadcaster); - virtual void clearListeners() throw (); - - virtual com::sun::star::uno::Any SAL_CALL queryInterface( - com::sun::star::uno::Type const & aType) - throw (com::sun::star::uno::RuntimeException); - - Components & getComponents() const; - - void checkLocalizedPropertyAccess(); - - rtl::Reference< Node > getParentNode(); - rtl::Reference< ChildAccess > getChild(rtl::OUString const & name); - std::vector< rtl::Reference< ChildAccess > > getAllChildren(); - - void checkValue( - com::sun::star::uno::Any const & value, Type type, bool nillable); - - void insertLocalizedValueChild( - rtl::OUString const & name, com::sun::star::uno::Any const & value, - Modifications * localModifications); - - void reportChildChanges( - std::vector< com::sun::star::util::ElementChange > * changes); - - void commitChildChanges(bool valid, Modifications * globalModifications); - - void initBroadcasterAndChanges( - Modifications::Node const & modifications, Broadcaster * broadcaster, - std::vector< com::sun::star::util::ElementChange > * changes); - - bool isDisposed() const; - -private: - struct ModifiedChild { - rtl::Reference< ChildAccess > child; - bool directlyModified; - - ModifiedChild(); - - ModifiedChild( - rtl::Reference< ChildAccess > const & theChild, - bool theDirectlyModified); - }; - - 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); @@ -264,6 +202,14 @@ private: virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL replaceByHierarchicalName( + rtl::OUString const & aName, com::sun::star::uno::Any const & aElement) + throw ( + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addContainerListener( com::sun::star::uno::Reference< com::sun::star::container::XContainerListener > const & xListener) @@ -491,6 +437,68 @@ private: com::sun::star::uno::Exception, com::sun::star::uno::RuntimeException); +protected: + Access(Components & components); + + virtual ~Access(); + + virtual rtl::OUString getNameInternal() = 0; + virtual rtl::Reference< RootAccess > getRootAccess() = 0; + virtual rtl::Reference< Access > getParentAccess() = 0; + + virtual void addTypes(std::vector< com::sun::star::uno::Type > * types) + const = 0; + + virtual void addSupportedServiceNames( + std::vector< rtl::OUString > * services) = 0; + + virtual void initDisposeBroadcaster(Broadcaster * broadcaster); + virtual void clearListeners() throw (); + + virtual com::sun::star::uno::Any SAL_CALL queryInterface( + com::sun::star::uno::Type const & aType) + throw (com::sun::star::uno::RuntimeException); + + Components & getComponents() const; + + void checkLocalizedPropertyAccess(); + + rtl::Reference< Node > getParentNode(); + rtl::Reference< ChildAccess > getChild(rtl::OUString const & name); + std::vector< rtl::Reference< ChildAccess > > getAllChildren(); + + void checkValue( + com::sun::star::uno::Any const & value, Type type, bool nillable); + + void insertLocalizedValueChild( + rtl::OUString const & name, com::sun::star::uno::Any const & value, + Modifications * localModifications); + + void reportChildChanges( + std::vector< com::sun::star::util::ElementChange > * changes); + + void commitChildChanges(bool valid, Modifications * globalModifications); + + void initBroadcasterAndChanges( + Modifications::Node const & modifications, Broadcaster * broadcaster, + std::vector< com::sun::star::util::ElementChange > * changes); + + bool isDisposed() const; + +private: + struct ModifiedChild { + rtl::Reference< ChildAccess > child; + bool directlyModified; + + ModifiedChild(); + + ModifiedChild( + rtl::Reference< ChildAccess > const & theChild, + bool theDirectlyModified); + }; + + typedef std::map< rtl::OUString, ModifiedChild > ModifiedChildren; + rtl::Reference< ChildAccess > getModifiedChild( ModifiedChildren::iterator const & childIterator); diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index 48d555e3236e..56c597593395 100644 --- a/configmgr/source/components.cxx +++ b/configmgr/source/components.cxx @@ -137,7 +137,7 @@ bool canRemoveFromLayer(int layer, rtl::Reference< Node > const & node) { switch (node->kind()) { case Node::KIND_LOCALIZED_PROPERTY: case Node::KIND_GROUP: - for (NodeMap::iterator i(node->getMembers().begin()); + for (NodeMap::const_iterator i(node->getMembers().begin()); i != node->getMembers().end(); ++i) { if (!canRemoveFromLayer(layer, i->second)) { @@ -402,7 +402,9 @@ void Components::removeExtensionXcuFile( node->kind() == Node::KIND_GROUP || node->kind() == Node::KIND_SET); if (canRemoveFromLayer(item->layer, node)) { - parent->getMembers().erase(i->back()); + NodeMap * members = parent->getMemberMap(); + assert(members != 0); + members->erase(i->back()); data_.modifications.remove(*i); modifications->add(*i); } diff --git a/configmgr/source/configmgr.component b/configmgr/source/configmgr.component index 6ed51257005d..9ad4c79eed0b 100755 --- a/configmgr/source/configmgr.component +++ b/configmgr/source/configmgr.component @@ -38,6 +38,12 @@ + + + + + + diff --git a/configmgr/source/data.cxx b/configmgr/source/data.cxx index 0fdc1e5eba92..fcc42e97cecc 100644 --- a/configmgr/source/data.cxx +++ b/configmgr/source/data.cxx @@ -48,6 +48,7 @@ #include "groupnode.hxx" #include "node.hxx" #include "nodemap.hxx" +#include "rootnode.hxx" #include "setnode.hxx" namespace configmgr { @@ -207,6 +208,8 @@ rtl::Reference< Node > Data::findNode( ? rtl::Reference< Node >() : i->second; } +Data::Data(): root_(new RootNode(components)) {} + rtl::Reference< Node > Data::resolvePathRepresentation( rtl::OUString const & pathRepresentation, rtl::OUString * canonicRepresentation, Path * path, int * finalizedLayer) @@ -218,6 +221,18 @@ rtl::Reference< Node > Data::resolvePathRepresentation( pathRepresentation), css::uno::Reference< css::uno::XInterface >()); } + if (path != 0) { + path->clear(); + } + if (pathRepresentation.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) { + if (canonicRepresentation != 0) { + *canonicRepresentation = pathRepresentation; + } + if (finalizedLayer != 0) { + *finalizedLayer = NO_LAYER; + } + return root_; + } rtl::OUString seg; bool setElement; rtl::OUString templateName; @@ -231,9 +246,6 @@ rtl::Reference< Node > Data::resolvePathRepresentation( } NodeMap::const_iterator i(components.find(seg)); rtl::OUStringBuffer canonic; - if (path != 0) { - path->clear(); - } rtl::Reference< Node > parent; int finalized = NO_LAYER; for (rtl::Reference< Node > p(i == components.end() ? 0 : i->second);;) { diff --git a/configmgr/source/data.hxx b/configmgr/source/data.hxx index f60ecfa1e807..64980eef4056 100644 --- a/configmgr/source/data.hxx +++ b/configmgr/source/data.hxx @@ -81,6 +81,8 @@ struct Data: private boost::noncopyable { static rtl::Reference< Node > findNode( int layer, NodeMap const & map, rtl::OUString const & name); + Data(); + rtl::Reference< Node > resolvePathRepresentation( rtl::OUString const & pathRepresentation, rtl::OUString * canonicRepresenation, Path * path, int * finalizedLayer) @@ -99,6 +101,8 @@ private: typedef std::map< rtl::OUString, rtl::Reference< ExtensionXcu > > ExtensionXcuAdditions; + rtl::Reference< Node > root_; + ExtensionXcuAdditions extensionXcuAdditions_; }; diff --git a/configmgr/source/groupnode.cxx b/configmgr/source/groupnode.cxx index 5591acbe606d..09658567b4c3 100644 --- a/configmgr/source/groupnode.cxx +++ b/configmgr/source/groupnode.cxx @@ -48,8 +48,8 @@ rtl::Reference< Node > GroupNode::clone(bool keepTemplateName) const { return new GroupNode(*this, keepTemplateName); } -NodeMap & GroupNode::getMembers() { - return members_; +NodeMap * GroupNode::getMemberMap() { + return &members_; } rtl::OUString GroupNode::getTemplateName() const { diff --git a/configmgr/source/groupnode.hxx b/configmgr/source/groupnode.hxx index 02f1679998a2..1d14a9293a6b 100644 --- a/configmgr/source/groupnode.hxx +++ b/configmgr/source/groupnode.hxx @@ -45,7 +45,7 @@ public: virtual rtl::Reference< Node > clone(bool keepTemplateName) const; - virtual NodeMap & getMembers(); + virtual NodeMap * getMemberMap(); virtual rtl::OUString getTemplateName() const; diff --git a/configmgr/source/localizedpropertynode.cxx b/configmgr/source/localizedpropertynode.cxx index 270485835228..196e57f6a6f9 100644 --- a/configmgr/source/localizedpropertynode.cxx +++ b/configmgr/source/localizedpropertynode.cxx @@ -55,8 +55,8 @@ rtl::Reference< Node > LocalizedPropertyNode::clone(bool) const { return new LocalizedPropertyNode(*this); } -NodeMap & LocalizedPropertyNode::getMembers() { - return members_; +NodeMap * LocalizedPropertyNode::getMemberMap() { + return &members_; } Type LocalizedPropertyNode::getStaticType() const { diff --git a/configmgr/source/localizedpropertynode.hxx b/configmgr/source/localizedpropertynode.hxx index bbe934e36bcd..b49f375c43c2 100644 --- a/configmgr/source/localizedpropertynode.hxx +++ b/configmgr/source/localizedpropertynode.hxx @@ -50,7 +50,7 @@ public: virtual rtl::Reference< Node > clone(bool keepTemplateName) const; - virtual NodeMap & getMembers(); + virtual NodeMap * getMemberMap(); Type getStaticType() const; diff --git a/configmgr/source/makefile.mk b/configmgr/source/makefile.mk index e75af0dde734..f52b4f4c0af0 100644 --- a/configmgr/source/makefile.mk +++ b/configmgr/source/makefile.mk @@ -55,7 +55,10 @@ SLOFILES = \ $(SLO)/parsemanager.obj \ $(SLO)/partial.obj \ $(SLO)/propertynode.obj \ + $(SLO)/readonlyaccess.obj \ + $(SLO)/readwriteaccess.obj \ $(SLO)/rootaccess.obj \ + $(SLO)/rootnode.obj \ $(SLO)/services.obj \ $(SLO)/setnode.obj \ $(SLO)/type.obj \ diff --git a/configmgr/source/node.cxx b/configmgr/source/node.cxx index 892cdaa622fd..b6480820aedc 100644 --- a/configmgr/source/node.cxx +++ b/configmgr/source/node.cxx @@ -30,11 +30,7 @@ #include -#include "com/sun/star/uno/Reference.hxx" -#include "com/sun/star/uno/RuntimeException.hpp" -#include "com/sun/star/uno/XInterface.hpp" #include "rtl/ref.hxx" -#include "rtl/ustring.h" #include "rtl/ustring.hxx" #include "data.hxx" @@ -43,17 +39,15 @@ namespace configmgr { -namespace { - -namespace css = com::sun::star; - +NodeMap const & Node::getMembers() const { + NodeMap * members = const_cast< Node * >(this)->getMemberMap(); + assert(members != 0); + return *members; } -NodeMap & Node::getMembers() { +NodeMap * Node::getMemberMap() { assert(false); - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), - css::uno::Reference< css::uno::XInterface >()); + return 0; } rtl::OUString Node::getTemplateName() const { @@ -87,8 +81,8 @@ int Node::getFinalized() const { } rtl::Reference< Node > Node::getMember(rtl::OUString const & name) { - NodeMap & members = getMembers(); - NodeMap::iterator i(members.find(name)); + NodeMap const & members = getMembers(); + NodeMap::const_iterator i(members.find(name)); return i == members.end() ? rtl::Reference< Node >() : i->second; } diff --git a/configmgr/source/node.hxx b/configmgr/source/node.hxx index 932d11cf3744..01aef18c7a6a 100644 --- a/configmgr/source/node.hxx +++ b/configmgr/source/node.hxx @@ -44,13 +44,14 @@ class Node: public salhelper::SimpleReferenceObject { public: enum Kind { KIND_PROPERTY, KIND_LOCALIZED_PROPERTY, KIND_LOCALIZED_VALUE, - KIND_GROUP, KIND_SET }; + KIND_GROUP, KIND_SET, KIND_ROOT }; virtual Kind kind() const = 0; virtual rtl::Reference< Node > clone(bool keepTemplateName) const = 0; - virtual NodeMap & getMembers(); + virtual NodeMap const & getMembers() const; + virtual NodeMap * getMemberMap(); virtual rtl::OUString getTemplateName() const; virtual void setMandatory(int layer); diff --git a/configmgr/source/readonlyaccess.cxx b/configmgr/source/readonlyaccess.cxx new file mode 100644 index 000000000000..d9ab2dccd837 --- /dev/null +++ b/configmgr/source/readonlyaccess.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "cppuhelper/implbase2.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.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/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include "components.hxx" +#include "lock.hxx" +#include "readonlyaccess.hxx" +#include "rootaccess.hxx" + +namespace configmgr { namespace read_only_access { + +namespace { + +namespace css = com::sun::star; + +class Service: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::container::XHierarchicalNameAccess >, + private boost::noncopyable +{ +public: + Service(css::uno::Reference< css::uno::XComponentContext > const & context); + +private: + virtual ~Service() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return read_only_access::getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const &) + throw (css::uno::RuntimeException) + { return false; } + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return read_only_access::getSupportedServiceNames(); } + + virtual css::uno::Any SAL_CALL getByHierarchicalName( + rtl::OUString const & aName) + throw ( + css::container::NoSuchElementException, css::uno::RuntimeException) + { return root_->getByHierarchicalName(aName); } + + virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) + { return root_->hasByHierarchicalName(aName); } + + rtl::Reference< RootAccess > root_; +}; + +Service::Service( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + osl::MutexGuard guard(*lock()); + Components & components = Components::getSingleton(context); + root_ = new RootAccess( + components, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), false); + components.addRootAccess(root_); +} + +} + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + return static_cast< cppu::OWeakObject * >(new Service(context)); +} + +rtl::OUString getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.configuration.ReadOnlyAccess")); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + return css::uno::Sequence< rtl::OUString >(); +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/readonlyaccess.hxx b/configmgr/source/readonlyaccess.hxx new file mode 100644 index 000000000000..9549789469b4 --- /dev/null +++ b/configmgr/source/readonlyaccess.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_CONFIGMGR_SOURCE_READONLYACCESS_HXX +#define INCLUDED_CONFIGMGR_SOURCE_READONLYACCESS_HXX + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + class XInterface; + } +} } } +namespace rtl { class OUString; } + +namespace configmgr { namespace read_only_access { + +com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL +create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const &); + +rtl::OUString SAL_CALL getImplementationName(); + +com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL +getSupportedServiceNames(); + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/readwriteaccess.cxx b/configmgr/source/readwriteaccess.cxx new file mode 100644 index 000000000000..0e4415fd44ed --- /dev/null +++ b/configmgr/source/readwriteaccess.cxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "cppuhelper/implbase2.hxx" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/configuration/XReadWriteAccess.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/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/ChangesSet.hpp" +#include "rtl/ref.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include "components.hxx" +#include "lock.hxx" +#include "readwriteaccess.hxx" +#include "rootaccess.hxx" + +namespace configmgr { namespace read_write_access { + +namespace { + +namespace css = com::sun::star; + +class Service: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::configuration::XReadWriteAccess >, + private boost::noncopyable +{ +public: + Service(css::uno::Reference< css::uno::XComponentContext > const & context); + +private: + virtual ~Service() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return read_write_access::getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const &) + throw (css::uno::RuntimeException) + { return false; } + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return read_write_access::getSupportedServiceNames(); } + + virtual css::uno::Any SAL_CALL getByHierarchicalName( + rtl::OUString const & aName) + throw ( + css::container::NoSuchElementException, css::uno::RuntimeException) + { return root_->getByHierarchicalName(aName); } + + virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) + { return root_->hasByHierarchicalName(aName); } + + virtual void SAL_CALL replaceByHierarchicalName( + rtl::OUString const & aName, css::uno::Any const & aElement) + throw ( + css::lang::IllegalArgumentException, + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) + { root_->replaceByHierarchicalName(aName, aElement); } + + virtual void SAL_CALL commitChanges() + throw (css::lang::WrappedTargetException, css::uno::RuntimeException) + { root_->commitChanges(); } + + virtual sal_Bool SAL_CALL hasPendingChanges() + throw (css::uno::RuntimeException) + { return root_->hasPendingChanges(); } + + virtual css::util::ChangesSet SAL_CALL getPendingChanges() + throw (css::uno::RuntimeException) + { return root_->getPendingChanges(); } + + rtl::Reference< RootAccess > root_; +}; + +Service::Service( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + osl::MutexGuard guard(*lock()); + Components & components = Components::getSingleton(context); + root_ = new RootAccess( + components, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), true); + components.addRootAccess(root_); +} + +} + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + return static_cast< cppu::OWeakObject * >(new Service(context)); +} + +rtl::OUString getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.configuration.ReadWriteAccess")); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ReadWriteAccess")); + return css::uno::Sequence< rtl::OUString >(&name, 1); +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/readwriteaccess.hxx b/configmgr/source/readwriteaccess.hxx new file mode 100644 index 000000000000..b559b2a51f9f --- /dev/null +++ b/configmgr/source/readwriteaccess.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_CONFIGMGR_SOURCE_READWRITEACCESS_HXX +#define INCLUDED_CONFIGMGR_SOURCE_READWRITEACCESS_HXX + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + class XInterface; + } +} } } +namespace rtl { class OUString; } + +namespace configmgr { namespace read_write_access { + +com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL +create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const &); + +rtl::OUString SAL_CALL getImplementationName(); + +com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL +getSupportedServiceNames(); + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/rootaccess.cxx b/configmgr/source/rootaccess.cxx index fc1fe39e8073..03ee3b88e29a 100644 --- a/configmgr/source/rootaccess.cxx +++ b/configmgr/source/rootaccess.cxx @@ -133,6 +133,91 @@ void RootAccess::setAlive(bool b) { alive_ = b; } +void RootAccess::addChangesListener( + css::uno::Reference< css::util::XChangesListener > const & aListener) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + { + 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 &) {} +} + +void RootAccess::removeChangesListener( + css::uno::Reference< css::util::XChangesListener > const & aListener) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + ChangesListeners::iterator i(changesListeners_.find(aListener)); + if (i != changesListeners_.end()) { + changesListeners_.erase(i); + } +} + +void RootAccess::commitChanges() + throw (css::lang::WrappedTargetException, css::uno::RuntimeException) +{ + assert(thisIs(IS_UPDATE)); + if (!alive_) + { + return; + } + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + + checkLocalizedPropertyAccess(); + int finalizedLayer; + Modifications globalMods; + commitChildChanges( + ((getComponents().resolvePathRepresentation( + pathRepresentation_, 0, 0, &finalizedLayer) + == node_) && + finalizedLayer == Data::NO_LAYER), + &globalMods); + getComponents().writeModifications(); + getComponents().initGlobalBroadcaster(globalMods, this, &bc); + } + bc.send(); +} + +sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) { + assert(thisIs(IS_UPDATE)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + //TODO: Optimize: + std::vector< css::util::ElementChange > changes; + reportChildChanges(&changes); + return !changes.empty(); +} + +css::util::ChangesSet RootAccess::getPendingChanges() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_UPDATE)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + comphelper::SequenceAsVector< css::util::ElementChange > changes; + reportChildChanges(&changes); + return changes.getAsConstList(); +} + RootAccess::~RootAccess() { osl::MutexGuard g(*lock_); @@ -166,8 +251,10 @@ rtl::Reference< Node > RootAccess::getNode() { // RuntimeException.Context is left null here } pathRepresentation_ = canonic; - assert(!path_.empty()); - name_ = path_.back(); + assert(!path_.empty() || node_->kind() == Node::KIND_ROOT); + if (!path_.empty()) { + name_ = path_.back(); + } finalized_ = finalizedLayer != Data::NO_LAYER; } return node_; @@ -252,97 +339,13 @@ css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType) return res; } -void RootAccess::addChangesListener( - css::uno::Reference< css::util::XChangesListener > const & aListener) +rtl::OUString RootAccess::getImplementationName() throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - { - 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 &) {} -} - -void RootAccess::removeChangesListener( - css::uno::Reference< css::util::XChangesListener > const & aListener) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - ChangesListeners::iterator i(changesListeners_.find(aListener)); - if (i != changesListeners_.end()) { - changesListeners_.erase(i); - } -} - -void RootAccess::commitChanges() - throw (css::lang::WrappedTargetException, css::uno::RuntimeException) -{ - assert(thisIs(IS_UPDATE)); - if (!alive_) - { - return; - } - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - - checkLocalizedPropertyAccess(); - int finalizedLayer; - Modifications globalMods; - commitChildChanges( - ((getComponents().resolvePathRepresentation( - pathRepresentation_, 0, 0, &finalizedLayer) - == node_) && - finalizedLayer == Data::NO_LAYER), - &globalMods); - getComponents().writeModifications(); - getComponents().initGlobalBroadcaster(globalMods, this, &bc); - } - bc.send(); -} - -sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) { - assert(thisIs(IS_UPDATE)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - //TODO: Optimize: - std::vector< css::util::ElementChange > changes; - reportChildChanges(&changes); - return !changes.empty(); -} - -css::util::ChangesSet RootAccess::getPendingChanges() - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_UPDATE)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - comphelper::SequenceAsVector< css::util::ElementChange > changes; - reportChildChanges(&changes); - return changes.getAsConstList(); -} - -rtl::OUString RootAccess::getImplementationName() throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "configmgr.RootAccess" ) ); + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("configmgr.RootAccess")); } } diff --git a/configmgr/source/rootaccess.hxx b/configmgr/source/rootaccess.hxx index 1290519b5d99..3b9ab7bbfa94 100644 --- a/configmgr/source/rootaccess.hxx +++ b/configmgr/source/rootaccess.hxx @@ -88,9 +88,25 @@ public: void setAlive(bool b); -protected: + virtual void SAL_CALL addChangesListener( + com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > + const & aListener) + throw (com::sun::star::uno::RuntimeException); - virtual rtl::OUString SAL_CALL getImplementationName() + virtual void SAL_CALL removeChangesListener( + com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > + const & aListener) + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL commitChanges() + throw ( + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasPendingChanges() + throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::util::ChangesSet SAL_CALL getPendingChanges() throw (com::sun::star::uno::RuntimeException); private: @@ -124,25 +140,7 @@ private: com::sun::star::uno::Type const & aType) throw (com::sun::star::uno::RuntimeException); - virtual void SAL_CALL addChangesListener( - com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > - const & aListener) - throw (com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL removeChangesListener( - com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > - const & aListener) - throw (com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL commitChanges() - throw ( - com::sun::star::lang::WrappedTargetException, - com::sun::star::uno::RuntimeException); - - virtual sal_Bool SAL_CALL hasPendingChanges() - throw (com::sun::star::uno::RuntimeException); - - virtual com::sun::star::util::ChangesSet SAL_CALL getPendingChanges() + virtual rtl::OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException); typedef diff --git a/configmgr/source/rootnode.cxx b/configmgr/source/rootnode.cxx new file mode 100644 index 000000000000..3188ea1228dc --- /dev/null +++ b/configmgr/source/rootnode.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include "sal/config.h" + +#include "rtl/ref.hxx" + +#include "data.hxx" +#include "node.hxx" +#include "nodemap.hxx" +#include "rootnode.hxx" + +namespace configmgr { + +RootNode::RootNode(NodeMap const & members): + Node(Data::NO_LAYER), members_(members) +{} + +RootNode::~RootNode() {} + +Node::Kind RootNode::kind() const { + return KIND_ROOT; +} + +rtl::Reference< Node > RootNode::clone(bool) const { + assert(false); // this cannot happen + return rtl::Reference< Node >(); +} + +NodeMap const & RootNode::getMembers() const { + return members_; +} + +NodeMap * RootNode::getMemberMap() { + return 0; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/rootnode.hxx b/configmgr/source/rootnode.hxx new file mode 100644 index 000000000000..97244e470737 --- /dev/null +++ b/configmgr/source/rootnode.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_CONFIGMGR_SOURCE_ROOTNODE_HXX +#define INCLUDED_CONFIGMGR_SOURCE_ROOTNODE_HXX + +#include "sal/config.h" + +#include "rtl/ref.hxx" + +#include "node.hxx" +#include "nodemap.hxx" + +namespace configmgr { + +class RootNode: public Node { +public: + RootNode(NodeMap const & members); + +private: + RootNode(RootNode const & other); + + virtual ~RootNode(); + + virtual Kind kind() const; + + virtual rtl::Reference< Node > clone(bool keepTemplateName) const; + + virtual NodeMap const & getMembers() const; + virtual NodeMap * getMemberMap(); + + NodeMap const & members_; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/services.cxx b/configmgr/source/services.cxx index 365c50c0e064..5c58eb719ac2 100644 --- a/configmgr/source/services.cxx +++ b/configmgr/source/services.cxx @@ -42,6 +42,8 @@ #include "configurationprovider.hxx" #include "configurationregistry.hxx" #include "defaultprovider.hxx" +#include "readonlyaccess.hxx" +#include "readwriteaccess.hxx" #include "update.hxx" namespace { @@ -68,6 +70,14 @@ static cppu::ImplementationEntry const services[] = { &configmgr::configuration_registry::getImplementationName, &configmgr::configuration_registry::getSupportedServiceNames, &cppu::createSingleComponentFactory, 0, 0 }, + { &configmgr::read_only_access::create, + &configmgr::read_only_access::getImplementationName, + &configmgr::read_only_access::getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { &configmgr::read_write_access::create, + &configmgr::read_write_access::getImplementationName, + &configmgr::read_write_access::getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, { &configmgr::update::create, &configmgr::update::getImplementationName, &configmgr::update::getSupportedServiceNames, &cppu::createSingleComponentFactory, 0, 0 }, diff --git a/configmgr/source/setnode.cxx b/configmgr/source/setnode.cxx index e2a8b2c888eb..214885fff66f 100644 --- a/configmgr/source/setnode.cxx +++ b/configmgr/source/setnode.cxx @@ -73,8 +73,8 @@ rtl::Reference< Node > SetNode::clone(bool keepTemplateName) const { return new SetNode(*this, keepTemplateName); } -NodeMap & SetNode::getMembers() { - return members_; +NodeMap * SetNode::getMemberMap() { + return &members_; } rtl::OUString SetNode::getTemplateName() const { diff --git a/configmgr/source/setnode.hxx b/configmgr/source/setnode.hxx index 00bcab2a55a1..59bd2587a5ab 100644 --- a/configmgr/source/setnode.hxx +++ b/configmgr/source/setnode.hxx @@ -49,7 +49,7 @@ public: virtual rtl::Reference< Node > clone(bool keepTemplateName) const; - virtual NodeMap & getMembers(); + virtual NodeMap * getMemberMap(); virtual rtl::OUString getTemplateName() const; diff --git a/configmgr/source/valueparser.cxx b/configmgr/source/valueparser.cxx index a98aae6ccf03..105d9ef323b8 100644 --- a/configmgr/source/valueparser.cxx +++ b/configmgr/source/valueparser.cxx @@ -413,10 +413,11 @@ bool ValueParser::endElement() { break; case Node::KIND_LOCALIZED_PROPERTY: { - NodeMap::iterator i( - node_->getMembers().find(localizedName_)); - if (i == node_->getMembers().end()) { - node_->getMembers().insert( + NodeMap * members = node_->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(localizedName_)); + if (i == members->end()) { + members->insert( NodeMap::value_type( localizedName_, new LocalizedValueNode(layer_, value))); diff --git a/configmgr/source/writemodfile.cxx b/configmgr/source/writemodfile.cxx index 1bae01ab88c5..eb896fffbf34 100644 --- a/configmgr/source/writemodfile.cxx +++ b/configmgr/source/writemodfile.cxx @@ -395,7 +395,7 @@ void writeNode( writeData(handle, RTL_CONSTASCII_STRINGPARAM("")); - for (NodeMap::iterator i(node->getMembers().begin()); + for (NodeMap::const_iterator i(node->getMembers().begin()); i != node->getMembers().end(); ++i) { writeNode(components, handle, node, i->first, i->second); @@ -443,13 +443,16 @@ void writeNode( handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"replace")); } writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">")); - for (NodeMap::iterator i(node->getMembers().begin()); + for (NodeMap::const_iterator i(node->getMembers().begin()); i != node->getMembers().end(); ++i) { writeNode(components, handle, node, i->first, i->second); } writeData(handle, RTL_CONSTASCII_STRINGPARAM("")); break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } } diff --git a/configmgr/source/xcsparser.cxx b/configmgr/source/xcsparser.cxx index 95d994327b85..66f3f2891713 100644 --- a/configmgr/source/xcsparser.cxx +++ b/configmgr/source/xcsparser.cxx @@ -79,16 +79,18 @@ void merge( case Node::KIND_LOCALIZED_VALUE: break; //TODO: merge certain parts? case Node::KIND_GROUP: - for (NodeMap::iterator i2(update->getMembers().begin()); + for (NodeMap::const_iterator i2(update->getMembers().begin()); i2 != update->getMembers().end(); ++i2) { - NodeMap::iterator i1(original->getMembers().find(i2->first)); - if (i1 == original->getMembers().end()) { + NodeMap * members = original->getMemberMap(); + assert(members != 0); + NodeMap::iterator i1(members->find(i2->first)); + if (i1 == members->end()) { if (i2->second->kind() == Node::KIND_PROPERTY && dynamic_cast< GroupNode * >( original.get())->isExtensible()) { - original->getMembers().insert(*i2); + members->insert(*i2); } } else if (i2->second->kind() == i1->second->kind()) { merge(i1->second, i2->second); @@ -96,15 +98,17 @@ void merge( } break; case Node::KIND_SET: - for (NodeMap::iterator i2(update->getMembers().begin()); + for (NodeMap::const_iterator i2(update->getMembers().begin()); i2 != update->getMembers().end(); ++i2) { - NodeMap::iterator i1(original->getMembers().find(i2->first)); - if (i1 == original->getMembers().end()) { + NodeMap * members = original->getMemberMap(); + assert(members != 0); + NodeMap::iterator i1(members->find(i2->first)); + if (i1 == members->end()) { if (dynamic_cast< SetNode * >(original.get())-> isValidTemplate(i2->second->getTemplateName())) { - original->getMembers().insert(*i2); + members->insert(*i2); } } else if (i2->second->kind() == i1->second->kind() && (i2->second->getTemplateName() == @@ -114,6 +118,9 @@ void merge( } } break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } } } @@ -308,15 +315,20 @@ void XcsParser::endElement(xmlreader::XmlReader const & reader) { RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), css::uno::Reference< css::uno::XInterface >()); } - } else if (!elements_.top().node->getMembers().insert( - NodeMap::value_type(top.name, top.node)).second) - { - throw css::uno::RuntimeException( - (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("duplicate ")) + - top.name + - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) + - reader.getUrl()), - css::uno::Reference< css::uno::XInterface >()); + } else { + NodeMap * members = elements_.top().node->getMemberMap(); + assert(members != 0); + if (!members->insert(NodeMap::value_type(top.name, top.node)). + second) + { + throw css::uno::RuntimeException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("duplicate ")) + + top.name + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) + + reader.getUrl()), + css::uno::Reference< css::uno::XInterface >()); + } } } } else { diff --git a/configmgr/source/xcuparser.cxx b/configmgr/source/xcuparser.cxx index 764cf8ce36f3..b05fe0e7e3c5 100644 --- a/configmgr/source/xcuparser.cxx +++ b/configmgr/source/xcuparser.cxx @@ -218,6 +218,9 @@ bool XcuParser::startElement( css::uno::Reference< css::uno::XInterface >()); } break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } } return true; @@ -239,7 +242,9 @@ void XcuParser::endElement(xmlreader::XmlReader const &) { state_.pop(); if (insert.is()) { assert(!state_.empty() && state_.top().node.is()); - state_.top().node->getMembers()[name] = insert; + NodeMap * members = state_.top().node->getMemberMap(); + assert(members != 0); + (*members)[name] = insert; } if (pop && !path_.empty()) { path_.pop_back(); @@ -590,9 +595,10 @@ void XcuParser::handleLocpropValue( return; } } - NodeMap::iterator i(locprop->getMembers().find(name)); - if (i != locprop->getMembers().end() && - i->second->getLayer() > valueParser_.getLayer()) + NodeMap * members = locprop->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(name)); + if (i != members->end() && i->second->getLayer() > valueParser_.getLayer()) { state_.push(State(true)); // ignored return; @@ -610,8 +616,8 @@ void XcuParser::handleLocpropValue( { bool pop = false; if (nil) { - if (i == locprop->getMembers().end()) { - locprop->getMembers()[name] = new LocalizedValueNode( + if (i == members->end()) { + (*members)[name] = new LocalizedValueNode( valueParser_.getLayer(), css::uno::Any()); } else { dynamic_cast< LocalizedValueNode * >( @@ -635,8 +641,8 @@ void XcuParser::handleLocpropValue( case OPERATION_REMOVE: //TODO: only allow if parent.op == OPERATION_FUSE //TODO: disallow removing when e.g. lang=""? - if (i != locprop->getMembers().end()) { - locprop->getMembers().erase(i); + if (i != members->end()) { + members->erase(i); } state_.push(State(true)); recordModification(false); @@ -702,8 +708,10 @@ void XcuParser::handleGroupProp( return; } } - NodeMap::iterator i(group->getMembers().find(name)); - if (i == group->getMembers().end()) { + NodeMap * members = group->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(name)); + if (i == members->end()) { handleUnknownGroupProp(reader, group, name, type, op, finalized); } else { switch (i->second->kind()) { @@ -814,7 +822,9 @@ void XcuParser::handlePlainGroupProp( reader.getUrl()), css::uno::Reference< css::uno::XInterface >()); } - group->getMembers().erase(propertyIndex); + NodeMap * members = group->getMemberMap(); + assert(members != 0); + members->erase(propertyIndex); state_.push(State(true)); // ignore children recordModification(false); break; @@ -1035,8 +1045,10 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { } int finalizedLayer = finalized ? valueParser_.getLayer() : Data::NO_LAYER; int mandatoryLayer = mandatory ? valueParser_.getLayer() : Data::NO_LAYER; - NodeMap::iterator i(set->getMembers().find(name)); - if (i != set->getMembers().end()) { + NodeMap * members = set->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(name)); + if (i != members->end()) { finalizedLayer = std::min(finalizedLayer, i->second->getFinalized()); i->second->setFinalized(finalizedLayer); mandatoryLayer = std::min(mandatoryLayer, i->second->getMandatory()); @@ -1048,7 +1060,7 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { } switch (op) { case OPERATION_MODIFY: - if (i == set->getMembers().end()) { + if (i == members->end()) { SAL_WARN( "configmgr", "ignoring modify of unknown set member node \"" << name @@ -1071,11 +1083,11 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { member->setFinalized(finalizedLayer); member->setMandatory(mandatoryLayer); state_.push(State(member, name, false)); - recordModification(i == set->getMembers().end()); + recordModification(i == members->end()); } break; case OPERATION_FUSE: - if (i == set->getMembers().end()) { + if (i == members->end()) { if (state_.top().locked || finalizedLayer < valueParser_.getLayer()) { state_.push(State(true)); // ignored @@ -1102,13 +1114,13 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { // forget about user-layer removals that no longer remove anything // (so that paired additions/removals in the user layer do not grow // registrymodifications.xcu unbounded): - bool known = i != set->getMembers().end(); + bool known = i != members->end(); if (known && !state_.top().locked && finalizedLayer >= valueParser_.getLayer() && (mandatoryLayer == Data::NO_LAYER || mandatoryLayer > valueParser_.getLayer())) { - set->getMembers().erase(i); + members->erase(i); } state_.push(State(true)); if (known) { diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index 333a9caa7793..e83b667a81b4 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -65,6 +65,8 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles_nohdl,offapi,offapi/com/sun/star/char DatabaseDataProvider \ )) $(eval $(call gb_UnoApiTarget_add_idlfiles_nohdl,offapi,offapi/com/sun/star/configuration,\ + ReadOnlyAccess \ + ReadWriteAccess \ Update \ theDefaultProvider \ )) @@ -1990,6 +1992,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,offapi,offapi/com/sun/star/configurat InstallationIncompleteException \ InvalidBootstrapFileException \ MissingBootstrapFileException \ + XReadWriteAccess \ XTemplateContainer \ XTemplateInstance \ XUpdate \ diff --git a/offapi/com/sun/star/configuration/ReadOnlyAccess.idl b/offapi/com/sun/star/configuration/ReadOnlyAccess.idl new file mode 100644 index 000000000000..06e2a332758e --- /dev/null +++ b/offapi/com/sun/star/configuration/ReadOnlyAccess.idl @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_COM_SUN_STAR_CONFIGURATION_READONLYACCESS_IDL +#define INCLUDED_COM_SUN_STAR_CONFIGURATION_READONLYACCESS_IDL + +#include "com/sun/star/container/XHierarchicalNameAccess.idl" + +module com { module sun { module star { module configuration { + +/* Provides easy read/write access to the complete configuration. + +

This singleton is still unpublished and unstable.

+ + @since LibreOffice 3.6 +*/ +singleton ReadOnlyAccess: com::sun::star::container::XHierarchicalNameAccess; + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/configuration/ReadWriteAccess.idl b/offapi/com/sun/star/configuration/ReadWriteAccess.idl new file mode 100644 index 000000000000..bae50bc2092d --- /dev/null +++ b/offapi/com/sun/star/configuration/ReadWriteAccess.idl @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_COM_SUN_STAR_CONFIGURATION_READWRITEACCESS_IDL +#define INCLUDED_COM_SUN_STAR_CONFIGURATION_READWRITEACCESS_IDL + +#include "com/sun/star/configuration/XReadWriteAccess.idl" + +module com { module sun { module star { module configuration { + +/* Provides easy read/write access to the complete configuration. + +

This service is still unpublished and unstable.

+ + @since LibreOffice 3.6 +*/ +service ReadWriteAccess: com::sun::star::configuration::XReadWriteAccess; + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/configuration/XReadWriteAccess.idl b/offapi/com/sun/star/configuration/XReadWriteAccess.idl new file mode 100644 index 000000000000..89b2acd65c9f --- /dev/null +++ b/offapi/com/sun/star/configuration/XReadWriteAccess.idl @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_COM_SUN_STAR_CONFIGURATION_XREADWRITEACCESS_IDL +#define INCLUDED_COM_SUN_STAR_CONFIGURATION_XREADWRITEACCESS_IDL + +#include "com/sun/star/container/XHierarchicalNameReplace.idl" +#include "com/sun/star/util/XChangesBatch.idl" + +module com { module sun { module star { module configuration { + +/* Provides easy read/write access to the complete configuration. + +

This interface is still unpublished and unstable.

+ + @since LibreOffice 3.6 +*/ +interface XReadWriteAccess { + interface com::sun::star::container::XHierarchicalNameReplace; + + interface com::sun::star::util::XChangesBatch; +}; + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/officecfg/Module_officecfg.mk b/officecfg/Module_officecfg.mk index 22d91c9692bc..6db580498ba3 100644 --- a/officecfg/Module_officecfg.mk +++ b/officecfg/Module_officecfg.mk @@ -20,6 +20,7 @@ $(eval $(call gb_Module_Module,officecfg)) $(eval $(call gb_Module_add_targets,officecfg,\ + Package_cppheader \ Package_misc \ Package_tools \ Configuration_officecfg \ diff --git a/officecfg/Package_cppheader.mk b/officecfg/Package_cppheader.mk new file mode 100644 index 000000000000..b90102b2168d --- /dev/null +++ b/officecfg/Package_cppheader.mk @@ -0,0 +1,45 @@ +## +## Version: MPL 1.1 / GPLv3+ / LGPLv3+ +## +## The contents of this file are subject to the Mozilla Public License Version +## 1.1 (the "License"); you may not use this file except in compliance with +## the License or as specified alternatively below. You may obtain a copy of +## the License at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" basis, +## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +## for the specific language governing rights and limitations under the +## License. +## +## Major Contributor(s): +## Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann +## (initial developer) +## +## All Rights Reserved. +## +## For minor contributions see the git repository. +## +## Alternatively, the contents of this file may be used under the terms of +## either the GNU General Public License Version 3 or later (the "GPLv3+"), or +## the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +## in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +## instead of those above. +## + +include $(SRCDIR)/officecfg/registry/files.mk + +$(eval $(call gb_Package_Package,officecfg_cppheader,$(WORKDIR)/CustomTarget/officecfg/registry)) + +$(eval $(call \ + gb_Package_add_customtarget,officecfg_cppheader,officecfg/registry)) + +$(eval $(call gb_CustomTarget_add_outdir_dependencies,officecfg/registry, \ + $(gb_XSLTPROCTARGET) \ +)) + +$(eval $(call gb_CustomTarget_add_dependencies,officecfg/registry, \ + officecfg/registry/cppheader.xsl \ + $(foreach i,$(FILES),officecfg/registry/schema/org/openoffice/$(i).xcs))) + +$(eval $(foreach i,$(FILES),$(call \ + gb_Package_add_file,officecfg_cppheader,inc/officecfg/$(i).hxx,$(i).hxx))) diff --git a/officecfg/registry/Makefile b/officecfg/registry/Makefile new file mode 100644 index 000000000000..3f748f0d0959 --- /dev/null +++ b/officecfg/registry/Makefile @@ -0,0 +1,56 @@ +## +## Version: MPL 1.1 / GPLv3+ / LGPLv3+ +## +## The contents of this file are subject to the Mozilla Public License Version +## 1.1 (the "License"); you may not use this file except in compliance with +## the License or as specified alternatively below. You may obtain a copy of +## the License at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" basis, +## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +## for the specific language governing rights and limitations under the +## License. +## +## Major Contributor(s): +## Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann +## (initial developer) +## +## All Rights Reserved. +## +## For minor contributions see the git repository. +## +## Alternatively, the contents of this file may be used under the terms of +## either the GNU General Public License Version 3 or later (the "GPLv3+"), or +## the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +## in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +## instead of those above. +## + +WFDIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) +gb_PARTIALBUILD := T +include $(GBUILDDIR)/gbuild_simple.mk +include $(WFDIR)/files.mk + +.DEFAULT_GOAL := all +.PHONY: all +all: $(foreach i,$(FILES),$(i).hxx) + +define my_target +$(if $(1),$(1)/$(if $(2),$(2)/))%.hxx: \ + $(WFDIR)/schema/org/openoffice/$(if $(1),$(1)/$(if $(2),$(2)/))%.xcs \ + $(WFDIR)/cppheader.xsl + $$(call gb_Helper_abbreviate_dirs_native, \ + $$(gb_XSLTPROC) --nonet --stringparam ns1 \ + $(if $(1), \ + $(1) --stringparam ns2 $(if $(2),$(2) --stringparam ns3)) $$* \ + -o $$@ $$(WFDIR)/cppheader.xsl $$<) + +endef + +$(eval $(call my_target)) +$(eval $(call my_target,Office)) +$(eval $(call my_target,Office,DataAccess)) +$(eval $(call my_target,Office,OOoImprovement)) +$(eval $(call my_target,Office,UI)) +$(eval $(call my_target,TypeDetection)) +$(eval $(call my_target,ucb)) diff --git a/officecfg/registry/cppheader.xsl b/officecfg/registry/cppheader.xsl new file mode 100644 index 000000000000..2f8141d2ba70 --- /dev/null +++ b/officecfg/registry/cppheader.xsl @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + / + + . + + + + + + + + #ifndef INCLUDED_OFFICECFG_ + + + _ + + + _ + + + + _HXX + #define INCLUDED_OFFICECFG_ + + + _ + + + _ + + + + _HXX + + #include "sal/config.h" + + + #include "boost/optional.hpp" + + + #include "com/sun/star/uno/Any.hxx" + + + #include "com/sun/star/uno/Sequence.hxx" + + + #include "rtl/ustring.h" + #include "rtl/ustring.hxx" + + + #include "sal/types.h" + + + #include "unotools/configuration.hxx" + + + namespace officecfg { namespace + + + { namespace + + + { namespace + + + + { + + + + + + } + + } + + + } } + + #endif + + + + + + namespace + + { + + + + + / + + + + } + + + + + + + + struct + + : public unotools::ConfigurationSet< + + > { + static rtl::OUString path() { return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" + + / + + ")); } + private: + + + (); // not defined + ~ + + (); // not defined + }; + + + + + + + struct + + : public unotools:: + + + ConfigurationLocalizedProperty + + + ConfigurationProperty + + + < + + , + + boost::optional< + + + + com::sun::star::uno::Any + + + bool + + + sal_Int16 + + + sal_Int32 + + + sal_Int64 + + + double + + + rtl::OUString + + + com::sun::star::uno::Sequence<sal_Int8> + + + com::sun::star::uno::Sequence<bool> + + + com::sun::star::uno::Sequence<sal_Int16> + + + com::sun::star::uno::Sequence<sal_Int32> + + + com::sun::star::uno::Sequence<sal_Int64> + + + com::sun::star::uno::Sequence<double> + + + com::sun::star::uno::Sequence<rtl::OUString> + + + com::sun::star::uno::Sequence<com::sun::star::uno::Sequence<sal_Int8> > + + + + > + + > { + static rtl::OUString path() { return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" + + / + + ")); } + private: + + + (); // not defined + ~ + + (); // not defined + }; + + + diff --git a/officecfg/registry/files.mk b/officecfg/registry/files.mk new file mode 100644 index 000000000000..f4c72d7b9437 --- /dev/null +++ b/officecfg/registry/files.mk @@ -0,0 +1,100 @@ +FILES = \ + FirstStartWizard \ + Inet \ + Interaction \ + LDAP \ + Office/Accelerators \ + Office/Addons \ + Office/Calc \ + Office/CalcAddIns \ + Office/Canvas \ + Office/Chart \ + Office/Commands \ + Office/Common \ + Office/Compatibility \ + Office/DataAccess \ + Office/DataAccess/Drivers \ + Office/Draw \ + Office/Embedding \ + Office/Events \ + Office/ExtendedColorScheme \ + Office/ExtensionManager \ + Office/FormWizard \ + Office/Histories \ + Office/Impress \ + Office/Java \ + Office/Jobs \ + Office/Labels \ + Office/Linguistic \ + Office/Logging \ + Office/Math \ + Office/OOoImprovement/Settings \ + Office/OptionsDialog \ + Office/Paths \ + Office/ProtocolHandler \ + Office/Recovery \ + Office/SFX \ + Office/Scripting \ + Office/Security \ + Office/Substitution \ + Office/TabBrowse \ + Office/TableWizard \ + Office/TypeDetection \ + Office/UI \ + Office/UI/BaseWindowState \ + Office/UI/BasicIDECommands \ + Office/UI/BasicIDEWindowState \ + Office/UI/BibliographyCommands \ + Office/UI/BibliographyWindowState \ + Office/UI/CalcCommands \ + Office/UI/CalcWindowState \ + Office/UI/Category \ + Office/UI/ChartCommands \ + Office/UI/ChartWindowState \ + Office/UI/Commands \ + Office/UI/Controller \ + Office/UI/DbBrowserWindowState \ + Office/UI/DbQueryWindowState \ + Office/UI/DbRelationWindowState \ + Office/UI/DbTableDataWindowState \ + Office/UI/DbTableWindowState \ + Office/UI/DbuCommands \ + Office/UI/DrawImpressCommands \ + Office/UI/DrawWindowState \ + Office/UI/Effects \ + Office/UI/Factories \ + Office/UI/GenericCategories \ + Office/UI/GenericCommands \ + Office/UI/GlobalSettings \ + Office/UI/ImpressWindowState \ + Office/UI/MathCommands \ + Office/UI/MathWindowState \ + Office/UI/StartModuleCommands \ + Office/UI/StartModuleWindowState \ + Office/UI/WindowContentFactories \ + Office/UI/WindowState \ + Office/UI/WriterCommands \ + Office/UI/WriterFormWindowState \ + Office/UI/WriterGlobalWindowState \ + Office/UI/WriterReportWindowState \ + Office/UI/WriterWebWindowState \ + Office/UI/WriterWindowState \ + Office/UI/XFormsWindowState \ + Office/Views \ + Office/WebWizard \ + Office/Writer \ + Office/WriterWeb \ + Setup \ + System \ + TypeDetection/Filter \ + TypeDetection/GraphicFilter \ + TypeDetection/Misc \ + TypeDetection/Types \ + TypeDetection/UISort \ + UserProfile \ + VCL \ + ucb/Configuration \ + ucb/Hierarchy \ + ucb/InteractionHandler \ + ucb/Store \ + diff --git a/svl/inc/svl/asiancfg.hxx b/svl/inc/svl/asiancfg.hxx index 733aea6a3bc0..350a2372efac 100644 --- a/svl/inc/svl/asiancfg.hxx +++ b/svl/inc/svl/asiancfg.hxx @@ -70,7 +70,7 @@ public: rtl::OUString const * startChars, rtl::OUString const * endChars); private: - class Impl; + struct Impl; boost::scoped_ptr< Impl > impl_; }; diff --git a/svl/source/config/asiancfg.cxx b/svl/source/config/asiancfg.cxx index 697e74d89bd8..51c20858148b 100644 --- a/svl/source/config/asiancfg.cxx +++ b/svl/source/config/asiancfg.cxx @@ -31,19 +31,18 @@ #include #include "boost/noncopyable.hpp" -#include "com/sun/star/beans/NamedValue.hpp" #include "com/sun/star/beans/XPropertySet.hpp" #include "com/sun/star/container/ElementExistException.hpp" #include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XNameAccess.hpp" #include "com/sun/star/container/XNameContainer.hpp" #include "com/sun/star/lang/Locale.hpp" -#include "com/sun/star/lang/XMultiServiceFactory.hpp" #include "com/sun/star/lang/XSingleServiceFactory.hpp" #include "com/sun/star/uno/Any.hxx" #include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/Sequence.hxx" -#include "com/sun/star/util/XChangesBatch.hpp" #include "comphelper/processfactory.hxx" +#include "officecfg/Office/Common.hxx" #include "rtl/oustringostreaminserter.hxx" #include "rtl/ustrbuf.hxx" #include "rtl/ustring.h" @@ -51,38 +50,12 @@ #include "sal/log.hxx" #include "sal/types.h" #include "svl/asiancfg.hxx" +#include "unotools/configuration.hxx" namespace { namespace css = com::sun::star; -css::uno::Reference< css::beans::XPropertySet > -obtainPropertySet() { - css::uno::Sequence< css::uno::Any > args(1); - args[0] <<= css::beans::NamedValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath")), - css::uno::makeAny( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "/org.openoffice.Office.Common/AsianLayout")))); - return css::uno::Reference< css::beans::XPropertySet >( - (css::uno::Reference< css::lang::XMultiServiceFactory >( - (css::uno::Reference< css::lang::XMultiServiceFactory >( - comphelper::getProcessServiceFactory(), - css::uno::UNO_SET_THROW)-> - createInstance( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.ConfigurationProvider")))), - css::uno::UNO_QUERY_THROW)-> - createInstanceWithArguments( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.ConfigurationUpdateAccess")), - args)), - css::uno::UNO_QUERY_THROW); -} - rtl::OUString toString(css::lang::Locale const & locale) { SAL_WARN_IF( locale.Language.indexOf('-') != -1, "svl", @@ -108,74 +81,54 @@ rtl::OUString toString(css::lang::Locale const & locale) { } -class SvxAsianConfig::Impl: private boost::noncopyable { -public: - Impl(): propertySet_(obtainPropertySet()) {} +struct SvxAsianConfig::Impl: private boost::noncopyable { + Impl(): + context(comphelper::getProcessComponentContext()), + batch(unotools::ConfigurationChanges::create(context)) + {} - css::uno::Reference< css::beans::XPropertySet > getPropertySet() const - { return propertySet_; } + css::uno::Reference< css::uno::XComponentContext > context; - css::uno::Reference< css::container::XNameContainer > - getStartEndCharacters() const; - -private: - css::uno::Reference< css::beans::XPropertySet > propertySet_; + boost::shared_ptr< unotools::ConfigurationChanges > batch; }; -css::uno::Reference< css::container::XNameContainer > -SvxAsianConfig::Impl::getStartEndCharacters() const { - return - css::uno::Reference< css::container::XNameContainer >( - (propertySet_->getPropertyValue( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("StartEndCharacters"))). - get< css::uno::Reference< css::container::XNameContainer > >()), - css::uno::UNO_SET_THROW); -} - SvxAsianConfig::SvxAsianConfig(): impl_(new Impl) {} SvxAsianConfig::~SvxAsianConfig() {} void SvxAsianConfig::Commit() { - css::uno::Reference< css::util::XChangesBatch >( - impl_->getPropertySet(), css::uno::UNO_QUERY_THROW)->commitChanges(); + impl_->batch->commit(); } bool SvxAsianConfig::IsKerningWesternTextOnly() const { return - impl_->getPropertySet()->getPropertyValue( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("IsKerningWesternTextOnly"))). - get< bool >(); + officecfg::Office::Common::AsianLayout::IsKerningWesternTextOnly::get( + impl_->context); } void SvxAsianConfig::SetKerningWesternTextOnly(bool value) { - impl_->getPropertySet()->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsKerningWesternTextOnly")), - css::uno::makeAny(value)); + officecfg::Office::Common::AsianLayout::IsKerningWesternTextOnly::set( + impl_->context, impl_->batch, value); } sal_Int16 SvxAsianConfig::GetCharDistanceCompression() const { return - impl_->getPropertySet()->getPropertyValue( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("CompressCharacterDistance"))). - get< sal_Int16 >(); + officecfg::Office::Common::AsianLayout::CompressCharacterDistance::get( + impl_->context); } void SvxAsianConfig::SetCharDistanceCompression(sal_Int16 value) { - assert(value >= 0 && value <= 2); - impl_->getPropertySet()->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CompressCharacterDistance")), - css::uno::makeAny(value)); + officecfg::Office::Common::AsianLayout::CompressCharacterDistance::set( + impl_->context, impl_->batch, value); } css::uno::Sequence< css::lang::Locale > SvxAsianConfig::GetStartEndCharLocales() const { css::uno::Sequence< rtl::OUString > ns( - impl_->getStartEndCharacters()->getElementNames()); + officecfg::Office::Common::AsianLayout::StartEndCharacters::get( + impl_->context)-> + getElementNames()); css::uno::Sequence< css::lang::Locale > ls(ns.getLength()); for (sal_Int32 i = 0; i < ns.getLength(); ++i) { sal_Int32 n = 0; @@ -190,8 +143,9 @@ bool SvxAsianConfig::GetStartEndChars( css::lang::Locale const & locale, rtl::OUString & startChars, rtl::OUString & endChars) const { - css::uno::Reference< css::container::XNameContainer > set( - impl_->getStartEndCharacters()); + css::uno::Reference< css::container::XNameAccess > set( + officecfg::Office::Common::AsianLayout::StartEndCharacters::get( + impl_->context)); css::uno::Any v; try { v = set->getByName(toString(locale)); @@ -218,7 +172,8 @@ void SvxAsianConfig::SetStartEndChars( { assert((startChars == 0) == (endChars == 0)); css::uno::Reference< css::container::XNameContainer > set( - impl_->getStartEndCharacters()); + officecfg::Office::Common::AsianLayout::StartEndCharacters::get( + impl_->context, impl_->batch)); rtl::OUString name(toString(locale)); if (startChars == 0) { try { diff --git a/unotools/Library_utl.mk b/unotools/Library_utl.mk index e9f252d53792..01571459d571 100644 --- a/unotools/Library_utl.mk +++ b/unotools/Library_utl.mk @@ -81,6 +81,7 @@ $(eval $(call gb_Library_add_exception_objects,utl,\ unotools/source/config/configmgr \ unotools/source/config/confignode \ unotools/source/config/configpathes \ + unotools/source/config/configuration \ unotools/source/config/configvaluecontainer \ unotools/source/config/defaultoptions \ unotools/source/config/docinfohelper \ diff --git a/unotools/Package_inc.mk b/unotools/Package_inc.mk index 58d91273506b..615e762d8518 100644 --- a/unotools/Package_inc.mk +++ b/unotools/Package_inc.mk @@ -45,6 +45,7 @@ $(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/configitem.hxx,unoto $(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/configmgr.hxx,unotools/configmgr.hxx)) $(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/confignode.hxx,unotools/confignode.hxx)) $(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/configpathes.hxx,unotools/configpathes.hxx)) +$(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/configuration.hxx,unotools/configuration.hxx)) $(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/configvaluecontainer.hxx,unotools/configvaluecontainer.hxx)) $(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/datetime.hxx,unotools/datetime.hxx)) $(eval $(call gb_Package_add_file,unotools_inc,inc/unotools/defaultoptions.hxx,unotools/defaultoptions.hxx)) diff --git a/unotools/inc/unotools/configuration.hxx b/unotools/inc/unotools/configuration.hxx new file mode 100644 index 000000000000..c9969c8a024f --- /dev/null +++ b/unotools/inc/unotools/configuration.hxx @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_UNOTOOLS_CONFIGURATION_HXX +#define INCLUDED_UNOTOOLS_CONFIGURATION_HXX + +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "boost/shared_ptr.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Reference.hxx" +#include "sal/types.h" +#include "unotools/unotoolsdllapi.h" + +namespace com { namespace sun { namespace star { + namespace configuration { class XReadWriteAccess; } + namespace container { + class XHierarchicalNameAccess; + class XNameAccess; + class XNameContainer; + } + namespace uno { class XComponentContext; } +} } } +namespace rtl { class OUString; } + +namespace unotools { + +namespace detail { class ConfigurationWrapper; } + +/// A batch of configuration changes that is committed as a whole. +/// +/// Client code needs to call commit explicitly; otherwise the changes are lost +/// when the instance is destroyed. +/// +/// This is the only class from this header file that client code should use +/// directly. +class UNOTOOLS_DLLPUBLIC ConfigurationChanges: private boost::noncopyable { +public: + static boost::shared_ptr< ConfigurationChanges > create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context); + + ~ConfigurationChanges(); + + void commit() const; + +private: + SAL_DLLPRIVATE ConfigurationChanges( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context); + + SAL_DLLPRIVATE void setPropertyValue( + rtl::OUString const & path, com::sun::star::uno::Any const & value) + const; + + SAL_DLLPRIVATE + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > + getSet(rtl::OUString const & path) const; + + com::sun::star::uno::Reference< + com::sun::star::configuration::XReadWriteAccess > access_; + + friend class detail::ConfigurationWrapper; +}; + +namespace detail { + +/// @internal +class UNOTOOLS_DLLPUBLIC ConfigurationWrapper: private boost::noncopyable { +public: + static ConfigurationWrapper const & get( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context); + + SAL_DLLPRIVATE explicit ConfigurationWrapper( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context); + + SAL_DLLPRIVATE ~ConfigurationWrapper(); + + com::sun::star::uno::Any getPropertyValue(rtl::OUString const & path) const; + + void setPropertyValue( + boost::shared_ptr< ConfigurationChanges > const & batch, + rtl::OUString const & path, com::sun::star::uno::Any const & value) + const; + + com::sun::star::uno::Any getLocalizedPropertyValue( + rtl::OUString const & path) const; + + void setLocalizedPropertyValue( + boost::shared_ptr< ConfigurationChanges > const & batch, + rtl::OUString const & path, com::sun::star::uno::Any const & value) + const; + + com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > + getSetReadOnly(rtl::OUString const & path) const; + + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > + getSetReadWrite( + boost::shared_ptr< ConfigurationChanges > const & batch, + rtl::OUString const & path) const; + + boost::shared_ptr< ConfigurationChanges > createChanges() const; + +private: + rtl::OUString extendLocalizedPath(rtl::OUString const & path) const; + + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + context_; + + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > access_; +}; + +} + +/// A type-safe wrapper around a (non-localized) configuration property. +/// +/// Automatically generated headers for the various configuration properties +/// derive from this template and make available its member functions to access +/// each given configuration property. +template< typename T, typename U > struct ConfigurationProperty: + private boost::noncopyable +{ + /// Get the value of the given (non-localized) configuration property. + /// + /// For nillable properties, U is of type boost::optional. + static U get( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context) + { + // Folding this into one statement causes a bogus error at least with + // Red Hat GCC 4.6.2-1: + com::sun::star::uno::Any a( + detail::ConfigurationWrapper::get(context).getPropertyValue( + T::path())); + return a.get< U >(); + } + + /// Set the value of the given (non-localized) configuration property, via a + /// given changes batch. + /// + /// For nillable properties, U is of type boost::optional. + static void set( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context, + boost::shared_ptr< ConfigurationChanges > const & batch, + U const & value) + { + detail::ConfigurationWrapper::get(context).setPropertyValue( + batch, T::path(), com::sun::star::uno::makeAny(value)); + } + +private: + ConfigurationProperty(); // not defined + ~ConfigurationProperty(); // not defined +}; + +/// A type-safe wrapper around a localized configuration property. +/// +/// Automatically generated headers for the various localized configuration +/// properties derive from this template and make available its member functions +/// to access each given localized configuration property. +template< typename T, typename U > struct ConfigurationLocalizedProperty: + private boost::noncopyable +{ + /// Get the value of the given localized configuration property, for the + /// locale currently set at the + /// com.sun.star.configuration.theDefaultProvider. + /// + /// For nillable properties, U is of type boost::optional. + static U get( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context) + { + // Folding this into one statement causes a bogus error at least with + // Red Hat GCC 4.6.2-1: + com::sun::star::uno::Any a( + detail::ConfigurationWrapper::get(context). + getLocalizedPropertyValue(T::path())); + return a.get< U >(); + } + + /// Set the value of the given localized configuration property, for the + /// locale currently set at the + /// com.sun.star.configuration.theDefaultProvider, via a given changes + /// batch. + /// + /// For nillable properties, U is of type boost::optional. + static void set( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context, + boost::shared_ptr< ConfigurationChanges > const & batch, + U const & value) + { + detail::ConfigurationWrapper::get(context).setLocalizedPropertyValue( + batch, T::path(), com::sun::star::uno::makeAny(value)); + } + +private: + ConfigurationLocalizedProperty(); // not defined + ~ConfigurationLocalizedProperty(); // not defined +}; + +/// A type-safe wrapper around a configuration set. +/// +/// Automatically generated headers for the various configuration sets derive +/// from this template and make available its member functions to access each +/// given configuration set. +template< typename T > struct ConfigurationSet: private boost::noncopyable { + /// Get read-only access to the given configuration set. + static + com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > + get(com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context) + { + return detail::ConfigurationWrapper::get(context).getSetReadOnly( + T::path()); + } + + /// Get read/write access to the given configuration set, storing any + /// modifications via the given changes batch. + static + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > + get(com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context, + boost::shared_ptr< ConfigurationChanges > const & batch) + { + return detail::ConfigurationWrapper::get(context).getSetReadWrite( + batch, T::path()); + } + +private: + ConfigurationSet(); // not defined + ~ConfigurationSet(); // not defined +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotools/source/config/configuration.cxx b/unotools/source/config/configuration.cxx new file mode 100644 index 000000000000..a4b30ed360fa --- /dev/null +++ b/unotools/source/config/configuration.cxx @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include "sal/config.h" + +#include + +#include "boost/shared_ptr.hpp" +#include "com/sun/star/configuration/ReadOnlyAccess.hpp" +#include "com/sun/star/configuration/ReadWriteAccess.hpp" +#include "com/sun/star/configuration/XReadWriteAccess.hpp" +#include "com/sun/star/configuration/theDefaultProvider.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/lang/Locale.hpp" +#include "com/sun/star/lang/XLocalizable.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "rtl/instance.hxx" +#include "rtl/oustringostreaminserter.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/log.hxx" +#include "unotools/configuration.hxx" + +namespace { + +namespace css = com::sun::star; + +struct TheConfigurationWrapper: + public rtl::StaticWithArg< + unotools::detail::ConfigurationWrapper, + css::uno::Reference< css::uno::XComponentContext >, + TheConfigurationWrapper > +{}; + +} + +boost::shared_ptr< unotools::ConfigurationChanges > +unotools::ConfigurationChanges::create( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + return TheConfigurationWrapper::get(context).createChanges(); +} + + +unotools::ConfigurationChanges::~ConfigurationChanges() {} + +void unotools::ConfigurationChanges::commit() const { + access_->commitChanges(); +} + +unotools::ConfigurationChanges::ConfigurationChanges( + css::uno::Reference< css::uno::XComponentContext > const & context): + access_(css::configuration::ReadWriteAccess::create(context)) +{} + +void unotools::ConfigurationChanges::setPropertyValue( + rtl::OUString const & path, css::uno::Any const & value) const +{ + access_->replaceByHierarchicalName(path, value); +} + +css::uno::Reference< css::container::XNameContainer > +unotools::ConfigurationChanges::getSet(rtl::OUString const & path) const +{ + return css::uno::Reference< css::container::XNameContainer >( + access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW); +} + +unotools::detail::ConfigurationWrapper const & +unotools::detail::ConfigurationWrapper::get( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + return TheConfigurationWrapper::get(context); +} + +unotools::detail::ConfigurationWrapper::ConfigurationWrapper( + css::uno::Reference< css::uno::XComponentContext > const & context): + context_(context), access_(css::configuration::ReadOnlyAccess::get(context)) +{} + +unotools::detail::ConfigurationWrapper::~ConfigurationWrapper() {} + +css::uno::Any unotools::detail::ConfigurationWrapper::getPropertyValue( + rtl::OUString const & path) const +{ + return access_->getByHierarchicalName(path); +} + +void unotools::detail::ConfigurationWrapper::setPropertyValue( + boost::shared_ptr< ConfigurationChanges > const & batch, + rtl::OUString const & path, com::sun::star::uno::Any const & value) const +{ + assert(batch.get() != 0); + batch->setPropertyValue(path, value); +} + +css::uno::Any unotools::detail::ConfigurationWrapper::getLocalizedPropertyValue( + rtl::OUString const & path) const +{ + return access_->getByHierarchicalName(extendLocalizedPath(path)); +} + +void unotools::detail::ConfigurationWrapper::setLocalizedPropertyValue( + boost::shared_ptr< ConfigurationChanges > const & batch, + rtl::OUString const & path, com::sun::star::uno::Any const & value) const +{ + assert(batch.get() != 0); + batch->setPropertyValue(extendLocalizedPath(path), value); +} + +css::uno::Reference< css::container::XNameAccess > +unotools::detail::ConfigurationWrapper::getSetReadOnly( + rtl::OUString const & path) const +{ + return css::uno::Reference< css::container::XNameAccess >( + access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW); +} + +css::uno::Reference< css::container::XNameContainer > +unotools::detail::ConfigurationWrapper::getSetReadWrite( + boost::shared_ptr< ConfigurationChanges > const & batch, + rtl::OUString const & path) const +{ + assert(batch.get() != 0); + return batch->getSet(path); +} + +boost::shared_ptr< unotools::ConfigurationChanges > +unotools::detail::ConfigurationWrapper::createChanges() const { + return boost::shared_ptr< ConfigurationChanges >( + new ConfigurationChanges(context_)); +} + +rtl::OUString unotools::detail::ConfigurationWrapper::extendLocalizedPath( + rtl::OUString const & path) const +{ + rtl::OUStringBuffer buf(path); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/['")); + css::lang::Locale locale( + css::uno::Reference< css::lang::XLocalizable >( + css::configuration::theDefaultProvider::get(context_), + css::uno::UNO_QUERY_THROW)-> + getLocale()); + SAL_WARN_IF( + locale.Language.indexOf('-') == -1, "unotools", + "Locale language \"" << locale.Language << "\" contains \"-\""); + assert(locale.Language.indexOf('&') == -1); + assert(locale.Language.indexOf('"') == -1); + assert(locale.Language.indexOf('\'') == -1); + buf.append(locale.Language); + SAL_WARN_IF( + locale.Country.isEmpty() && !locale.Variant.isEmpty(), "unotools", + "Locale has empty country but non-empty variant \"" << locale.Variant + << '"'); + if (!locale.Country.isEmpty()) { + buf.append('-'); + SAL_WARN_IF( + locale.Country.indexOf('-') == -1, "unotools", + "Locale language \"" << locale.Country << "\" contains \"-\""); + assert(locale.Country.indexOf('&') == -1); + assert(locale.Country.indexOf('"') == -1); + assert(locale.Country.indexOf('\'') == -1); + buf.append(locale.Country); + if (!locale.Variant.isEmpty()) { + buf.append('-'); + assert(locale.Variant.indexOf('&') == -1); + assert(locale.Variant.indexOf('"') == -1); + assert(locale.Variant.indexOf('\'') == -1); + buf.append(locale.Variant); + } + } + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("']")); + return buf.makeStringAndClear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit