diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2011-12-13 12:37:00 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2011-12-13 12:50:34 +0100 |
commit | bcdea3b379637a98e5bbc304078149ca6c2b6e03 (patch) | |
tree | a3803df980a54ab1a03c740c3114a54ca7d12f27 /configmgr | |
parent | ddf1cf333174777e7923aa0d6126daf2c8645fed (diff) |
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.
Diffstat (limited to 'configmgr')
28 files changed, 1590 insertions, 929 deletions
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,689 +164,6 @@ 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) - 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; - } - if (getNode()->kind() == Node::KIND_GROUP) { - res = cppu::queryInterface( - aType, static_cast< css::beans::XPropertySetInfo * >(this), - static_cast< css::beans::XPropertySet * >(this), - static_cast< css::beans::XMultiPropertySet * >(this), - static_cast< css::beans::XHierarchicalPropertySet * >(this), - static_cast< css::beans::XMultiHierarchicalPropertySet * >(this), - static_cast< css::beans::XHierarchicalPropertySetInfo * >(this)); - if (res.hasValue()) { - return res; - } - } - if (getRootAccess()->isUpdate()) { - res = cppu::queryInterface( - aType, static_cast< css::container::XNameReplace * >(this)); - if (res.hasValue()) { - return res; - } - if (getNode()->kind() != Node::KIND_GROUP || - dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) - { - res = cppu::queryInterface( - aType, static_cast< css::container::XNameContainer * >(this)); - if (res.hasValue()) { - return res; - } - } - if (getNode()->kind() == Node::KIND_SET) { - res = cppu::queryInterface( - aType, static_cast< css::lang::XSingleServiceFactory * >(this)); - } - } - return res; -} - -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)); - } -} - -rtl::Reference< Node > Access::getParentNode() { - rtl::Reference< Access > parent(getParentAccess()); - return parent.is() ? parent->getNode() : rtl::Reference< Node >(); -} - -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 & 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); - } - } - return vec; -} - -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( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr inappropriate property value")), - static_cast< cppu::OWeakObject * >(this), -1); - } -} - -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::reportChildChanges( - std::vector< css::util::ElementChange > * changes) -{ - 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::commitChildChanges( - bool valid, Modifications * globalModifications) -{ - 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); - } -} - -void Access::initBroadcasterAndChanges( - Modifications::Node const & modifications, Broadcaster * broadcaster, - std::vector< css::util::ElementChange > * allChanges) -{ - 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) - { - 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; - } - } - } - 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); - } - } -} - -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() throw (css::uno::RuntimeException) { @@ -858,8 +176,6 @@ css::uno::Sequence< css::uno::Type > Access::getTypes() 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()); @@ -880,6 +196,8 @@ css::uno::Sequence< css::uno::Type > Access::getTypes() } if (getRootAccess()->isUpdate()) { 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()) { @@ -890,6 +208,9 @@ css::uno::Sequence< css::uno::Type > Access::getTypes() types.push_back( cppu::UnoType< css::lang::XSingleServiceFactory >::get()); } + } else { + types.push_back( + cppu::UnoType< css::container::XHierarchicalNameAccess >::get()); } addTypes(&types); return types.getAsConstList(); @@ -1148,6 +469,57 @@ sal_Bool Access::hasByHierarchicalName(rtl::OUString const & aName) 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(); +} + void Access::addContainerListener( css::uno::Reference< css::container::XContainerListener > const & xListener) throw (css::uno::RuntimeException) @@ -1957,6 +1329,696 @@ css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments( 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) + { + 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) + 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; + } + 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)); + } + } + 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)); + } +} + +rtl::Reference< Node > Access::getParentNode() { + rtl::Reference< Access > parent(getParentAccess()); + return parent.is() ? parent->getNode() : rtl::Reference< Node >(); +} + +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()); + } + } + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + vec.push_back(child); + } + } + return vec; +} + +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( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr inappropriate property value")), + static_cast< cppu::OWeakObject * >(this), -1); + } +} + +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::reportChildChanges( + std::vector< css::util::ElementChange > * changes) +{ + 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::commitChildChanges( + bool valid, Modifications * globalModifications) +{ + 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()->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); + } + } + } + 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); + } +} + +void Access::initBroadcasterAndChanges( + Modifications::Node const & modifications, Broadcaster * broadcaster, + std::vector< css::util::ElementChange > * allChanges) +{ + 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) + { + 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; + } + } 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; + } + } + } + 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); + } + } +} + +bool Access::isDisposed() const { + return disposed_; +} + +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 @@ <service name="com.sun.star.configuration.DefaultProvider"/> <singleton name="com.sun.star.configuration.theDefaultProvider"/> </implementation> + <implementation name="com.sun.star.comp.configuration.ReadOnlyAccess"> + <singleton name="com.sun.star.configuration.ReadOnlyAccess"/> + </implementation> + <implementation name="com.sun.star.comp.configuration.ReadWriteAccess"> + <service name="com.sun.star.configuration.ReadWriteAccess"/> + </implementation> <implementation name="com.sun.star.comp.configuration.Update"> <service name="com.sun.star.configuration.Update_Service"/> <singleton name="com.sun.star.configuration.Update"/> 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 <cassert> -#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 <sbergman@redhat.com> + * (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 <sbergman@redhat.com> + * (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 <sbergman@redhat.com> + * (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 <sbergman@redhat.com> + * (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 <sbergman@redhat.com> + * (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 <sbergman@redhat.com> + * (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("<prop oor:name=\"")); writeAttributeValue(handle, name); writeData(handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\">")); - 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("</node>")); 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) { |