summaryrefslogtreecommitdiff
path: root/configmgr/source
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr/source')
-rw-r--r--configmgr/source/README157
-rw-r--r--configmgr/source/access.cxx2186
-rw-r--r--configmgr/source/access.hxx582
-rw-r--r--configmgr/source/broadcaster.cxx237
-rw-r--r--configmgr/source/broadcaster.hxx181
-rw-r--r--configmgr/source/childaccess.cxx391
-rw-r--r--configmgr/source/childaccess.hxx157
-rw-r--r--configmgr/source/components.cxx673
-rw-r--r--configmgr/source/components.hxx159
-rw-r--r--configmgr/source/configurationprovider.cxx519
-rw-r--r--configmgr/source/configurationprovider.hxx67
-rw-r--r--configmgr/source/configurationregistry.cxx950
-rw-r--r--configmgr/source/configurationregistry.hxx57
-rw-r--r--configmgr/source/data.cxx318
-rw-r--r--configmgr/source/data.hxx86
-rw-r--r--configmgr/source/defaultprovider.cxx131
-rw-r--r--configmgr/source/defaultprovider.hxx59
-rw-r--r--configmgr/source/groupnode.cxx88
-rw-r--r--configmgr/source/groupnode.hxx75
-rw-r--r--configmgr/source/localizedpropertynode.cxx87
-rw-r--r--configmgr/source/localizedpropertynode.hxx76
-rw-r--r--configmgr/source/localizedvaluenode.cxx78
-rw-r--r--configmgr/source/localizedvaluenode.hxx66
-rw-r--r--configmgr/source/lock.cxx39
-rw-r--r--configmgr/source/lock.hxx41
-rw-r--r--configmgr/source/makefile.mk84
-rw-r--r--configmgr/source/modifications.cxx66
-rw-r--r--configmgr/source/modifications.hxx65
-rw-r--r--configmgr/source/node.cxx108
-rw-r--r--configmgr/source/node.hxx86
-rw-r--r--configmgr/source/nodemap.cxx50
-rw-r--r--configmgr/source/nodemap.hxx49
-rw-r--r--configmgr/source/pad.cxx91
-rw-r--r--configmgr/source/pad.hxx61
-rw-r--r--configmgr/source/parsemanager.cxx85
-rw-r--r--configmgr/source/parsemanager.hxx69
-rw-r--r--configmgr/source/parser.hxx62
-rw-r--r--configmgr/source/partial.cxx137
-rw-r--r--configmgr/source/partial.hxx71
-rw-r--r--configmgr/source/path.hxx43
-rw-r--r--configmgr/source/propertynode.cxx110
-rw-r--r--configmgr/source/propertynode.hxx83
-rw-r--r--configmgr/source/rootaccess.cxx319
-rw-r--r--configmgr/source/rootaccess.hxx155
-rw-r--r--configmgr/source/services.cxx118
-rw-r--r--configmgr/source/setnode.cxx126
-rw-r--r--configmgr/source/setnode.hxx84
-rw-r--r--configmgr/source/span.hxx64
-rw-r--r--configmgr/source/type.cxx187
-rw-r--r--configmgr/source/type.hxx56
-rw-r--r--configmgr/source/update.cxx85
-rw-r--r--configmgr/source/valueparser.cxx470
-rw-r--r--configmgr/source/valueparser.hxx92
-rw-r--r--configmgr/source/writemodfile.cxx601
-rw-r--r--configmgr/source/writemodfile.hxx45
-rw-r--r--configmgr/source/xcdparser.cxx183
-rw-r--r--configmgr/source/xcdparser.hxx78
-rw-r--r--configmgr/source/xcsparser.cxx669
-rw-r--r--configmgr/source/xcsparser.hxx106
-rw-r--r--configmgr/source/xcuparser.cxx1112
-rw-r--r--configmgr/source/xcuparser.hxx153
-rw-r--r--configmgr/source/xmldata.cxx204
-rw-r--r--configmgr/source/xmldata.hxx58
-rw-r--r--configmgr/source/xmlreader.cxx1054
-rw-r--r--configmgr/source/xmlreader.hxx186
65 files changed, 14985 insertions, 0 deletions
diff --git a/configmgr/source/README b/configmgr/source/README
new file mode 100644
index 000000000000..b731043d34ed
--- /dev/null
+++ b/configmgr/source/README
@@ -0,0 +1,157 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#***********************************************************************/
+
+Source Overview
+===============
+
+configurationprovider.cxx
+configurationregistry.cxx
+defaultprovider.cxx
+services.cxx
+ UNO service implementations.
+
+access.cxx
+childaccess.cxx
+rootaccess.cxx
+ UNO objects passed to clients.
+
+components.cxx
+ Central singleton that aggregates all data (reads in the XML files, manages
+ modifications and global notifications).
+
+groupnode.cxx
+localizedpropertynode.cxx
+localizedvaluenode.cxx
+node.cxx
+propertynode.cxx
+setnode.cxx
+ Internal representations of data nodes.
+
+pad.cxx
+parsemanager.cxx
+parser.hxx
+span.hxx
+valueparser.cxx
+xcdparser.cxx
+xcsparser.cxx
+xcuparser.cxx
+xmldata.cxx
+xmlreader.cxx
+ XML file reading.
+
+modifications.cxx
+writemodfile.cxx
+ Modification management.
+
+broadcaster.cxx
+ Notification management.
+
+update.cxx
+ Extension manager interface.
+
+data.cxx
+lock.cxx
+nodemap.cxx
+partial.cxx
+path.hxx
+type.cxx
+ Utilities.
+
+
+Mandatory Set Members
+=====================
+
+- A set member can be marked as "mandatory," meaning that a member of that name
+must always be present in a set.
+
+- The above definition implies that calling replaceByName on a mandatory set
+member is OK.
+
+- The XCU format can contain oor:mandatory attributes on nodes. (The XCS format
+does not support them. In the registrymodifications file, oor:mandatory
+attributes should never be needed, as being mandatory cannot be controlled via
+the UNO API.) The XCU reading code only evaluates the oor:mandatory attribute
+for set members, and ignores it everywhere else.
+
+- Only true sets support mandatory members. A localized property for the "*"
+locale, though acting much like a set, does not support mandatory members.
+
+- The OpenOffice.org Registry Format document claims that group extension
+properties are implicitly mandatory, but at least the new configmgr code does
+not treat them like that (i.e., they can be removed again).
+
+- For simplicity, setMandatory/getMandatory are available as virtual functions
+at the base Node, even though they can only make sense for GroupNodes and
+SetNodes that are set members. The default getMandatory implementation returns
+NO_LAYER, meaning oor:mandatory is not set to true in any layer. (Returning
+NO_LAYER simplifies the code, e.g., removeByName does not have to check whether
+getMandatory is called on a member of a true set to decide whether to forbid
+removal.)
+
+- When committing changes (made through the UNO API), the "mandatory" status of
+inserted nodes must be updated (in case the insert is due to a replaceByName, or
+the "mandatory" flag was added by a concurrent modification of a lower layer).
+Also, for to-be-removed nodes, removal is ignored for (newly; due to concurrent
+modification of a lower layer) mandatory nodes (but still recorded in
+registrymodifications, so may take effect once the lower layer addition is
+removed again---whether or not that is a good idea).
+
+
+XcuParser Modification Recording
+================================
+
+- XcuParser records modifications when reading user layer data
+(valueParser_.getLayer() == Data::NO_LAYER).
+
+- oor:finalized and oor:mandatory attributes cannot be set via the UNO API, so
+it is assumed that user layer data does not contain them (for one, they are not
+written by writeModFile; for another, the logic to record modifications expects
+a locprop(modify,fuse) to be followed by one or more value(fuse,remove), which
+would not necessarily be true if the locprop were only present in the user layer
+data to flag it as finalized).
+
+- The logic to record modifications considers the top of the XML element stack.
+In the following list of all possible cases, items marked with an asterisk are
+recorded:
+ ... group(modify,fuse) - group(modify,fuse) - ...
+ ... group(modify,fuse) - set(modify,fuse) - ...
+ ... group(modify,fuse) - *prop(modify,fuse,replace) - value(fuse)
+ ... group(modify,fuse) - *prop(remove)
+ ... group(modify,fuse) - locprop(modify,fuse) - *value(fuse)
+ ... group(modify,fuse) - locprop(modify,fuse) - *value(remove)
+ ... group(modify,fuse) - *locprop(replace) ...
+ ... set(modify,fuse,replace) - group(modify/fuse) - ...
+ ... set(modify,fuse,replace) - *group(replace/fuse) - ...
+ ... set(modify,fuse,replace) - *group(remove)
+ ... set(modify,fuse,replace) - set(modify/fuse) - ...
+ ... set(modify,fuse,replace) - *set(replace/fuse) - ...
+ ... set(modify,fuse,replace) - *set(remove)
+Legend: "...": zero or more further items
+ "- ...": one or more further items
+ "modify,fuse" etc.: any of those operations
+ "modify/fuse": a modify or a fuse on an existing member
+ "replace/fuse": a replace or a fuse on a non-existing member
diff --git a/configmgr/source/access.cxx b/configmgr/source/access.cxx
new file mode 100644
index 000000000000..7af9c1f8d9c0
--- /dev/null
+++ b/configmgr/source/access.cxx
@@ -0,0 +1,2186 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <vector>
+
+#include "com/sun/star/beans/Property.hpp"
+#include "com/sun/star/beans/PropertyAttribute.hpp"
+#include "com/sun/star/beans/PropertyChangeEvent.hpp"
+#include "com/sun/star/beans/PropertyVetoException.hpp"
+#include "com/sun/star/beans/UnknownPropertyException.hpp"
+#include "com/sun/star/beans/XExactName.hpp"
+#include "com/sun/star/beans/XHierarchicalPropertySet.hpp"
+#include "com/sun/star/beans/XHierarchicalPropertySetInfo.hpp"
+#include "com/sun/star/beans/XMultiHierarchicalPropertySet.hpp"
+#include "com/sun/star/beans/XMultiPropertySet.hpp"
+#include "com/sun/star/beans/XPropertiesChangeListener.hpp"
+#include "com/sun/star/beans/XProperty.hpp"
+#include "com/sun/star/beans/XPropertyChangeListener.hpp"
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/beans/XPropertySetInfo.hpp"
+#include "com/sun/star/beans/XVetoableChangeListener.hpp"
+#include "com/sun/star/container/ContainerEvent.hpp"
+#include "com/sun/star/container/NoSuchElementException.hpp"
+#include "com/sun/star/container/XContainer.hpp"
+#include "com/sun/star/container/XContainerListener.hpp"
+#include "com/sun/star/container/XElementAccess.hpp"
+#include "com/sun/star/container/XHierarchicalName.hpp"
+#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
+#include "com/sun/star/container/XNameAccess.hpp"
+#include "com/sun/star/container/XNameContainer.hpp"
+#include "com/sun/star/container/XNamed.hpp"
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "com/sun/star/lang/EventObject.hpp"
+#include "com/sun/star/lang/IllegalArgumentException.hpp"
+#include "com/sun/star/lang/NoSupportException.hpp"
+#include "com/sun/star/lang/WrappedTargetException.hpp"
+#include "com/sun/star/lang/XComponent.hpp"
+#include "com/sun/star/lang/XEventListener.hpp"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/lang/XSingleServiceFactory.hpp"
+#include "com/sun/star/lang/XTypeProvider.hpp"
+#include "com/sun/star/lang/XUnoTunnel.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/Type.hxx"
+#include "com/sun/star/uno/TypeClass.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "com/sun/star/uno/XWeak.hpp"
+#include "com/sun/star/util/ElementChange.hpp"
+#include "comphelper/sequenceasvector.hxx"
+#include "cppu/unotype.hxx"
+#include "cppuhelper/queryinterface.hxx"
+#include "cppuhelper/weak.hxx"
+#include "osl/diagnose.h"
+#include "osl/interlck.h"
+#include "osl/mutex.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "access.hxx"
+#include "broadcaster.hxx"
+#include "childaccess.hxx"
+#include "components.hxx"
+#include "data.hxx"
+#include "groupnode.hxx"
+#include "localizedpropertynode.hxx"
+#include "localizedvaluenode.hxx"
+#include "lock.hxx"
+#include "modifications.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "path.hxx"
+#include "propertynode.hxx"
+#include "rootaccess.hxx"
+#include "setnode.hxx"
+#include "type.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+oslInterlockedCount Access::acquireCounting() {
+ return osl_incrementInterlockedCount(&m_refCount);
+}
+
+void Access::releaseNondeleting() {
+ osl_decrementInterlockedCount(&m_refCount);
+}
+
+bool Access::isValue() {
+ rtl::Reference< Node > p(getNode());
+ switch (p->kind()) {
+ case Node::KIND_PROPERTY:
+ case Node::KIND_LOCALIZED_VALUE:
+ return true;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ return !Components::allLocales(getRootAccess()->getLocale());
+ default:
+ return false;
+ }
+}
+
+void Access::markChildAsModified(rtl::Reference< ChildAccess > const & child) {
+ OSL_ASSERT(child.is() && child->getParentAccess() == this);
+ modifiedChildren_[child->getNameInternal()] = ModifiedChild(child, true);
+ for (rtl::Reference< Access > p(this);;) {
+ rtl::Reference< Access > parent(p->getParentAccess());
+ if (!parent.is()) {
+ break;
+ }
+ OSL_ASSERT(dynamic_cast< ChildAccess * >(p.get()) != 0);
+ parent->modifiedChildren_.insert(
+ ModifiedChildren::value_type(
+ p->getNameInternal(),
+ ModifiedChild(dynamic_cast< ChildAccess * >(p.get()), false)));
+ p = parent;
+ }
+}
+
+void Access::releaseChild(rtl::OUString const & name) {
+ cachedChildren_.erase(name);
+}
+
+void Access::initBroadcaster(
+ Modifications::Node const & modifications, Broadcaster * broadcaster)
+{
+ initBroadcasterAndChanges(modifications, broadcaster, 0);
+}
+
+Access::Access(Components & components):
+ components_(components), disposed_(false)
+{}
+
+Access::~Access() {}
+
+void Access::initDisposeBroadcaster(Broadcaster * broadcaster) {
+ OSL_ASSERT(broadcaster != 0);
+ for (DisposeListeners::iterator i(disposeListeners_.begin());
+ i != disposeListeners_.end(); ++i)
+ {
+ broadcaster->addDisposeNotification(
+ *i,
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ }
+ for (ContainerListeners::iterator i(containerListeners_.begin());
+ i != containerListeners_.end(); ++i)
+ {
+ broadcaster->addDisposeNotification(
+ i->get(),
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ }
+ for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin());
+ i != propertyChangeListeners_.end(); ++i)
+ {
+ for (PropertyChangeListenersElement::iterator j(i->second.begin());
+ j != i->second.end(); ++j)
+ {
+ broadcaster->addDisposeNotification(
+ j->get(),
+ css::lang::EventObject(
+ static_cast< cppu::OWeakObject * >(this)));
+ }
+ }
+ for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin());
+ i != vetoableChangeListeners_.end(); ++i)
+ {
+ for (VetoableChangeListenersElement::iterator j(i->second.begin());
+ j != i->second.end(); ++j)
+ {
+ broadcaster->addDisposeNotification(
+ j->get(),
+ css::lang::EventObject(
+ static_cast< cppu::OWeakObject * >(this)));
+ }
+ }
+ for (PropertiesChangeListeners::iterator i(
+ propertiesChangeListeners_.begin());
+ i != propertiesChangeListeners_.end(); ++i)
+ {
+ broadcaster->addDisposeNotification(
+ i->get(),
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ }
+ //TODO: iterate over children w/ listeners (incl. unmodified ones):
+ for (ModifiedChildren::iterator i(modifiedChildren_.begin());
+ i != modifiedChildren_.end(); ++i)
+ {
+ rtl::Reference< ChildAccess > child(getModifiedChild(i));
+ if (child.is()) {
+ child->initDisposeBroadcaster(broadcaster);
+ }
+ }
+}
+
+void Access::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));
+ OSL_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:
+ OSL_ASSERT(false);
+ // fall through (cannot happen)
+ case TYPE_ERROR:
+ ok = false;
+ break;
+ case TYPE_ANY:
+ switch (getDynamicType(value)) {
+ case TYPE_ANY:
+ OSL_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)
+{
+ OSL_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)
+{
+ OSL_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)
+{
+ OSL_ASSERT(globalModifications != 0);
+ while (!modifiedChildren_.empty()) {
+ bool childValid = valid;
+ ModifiedChildren::iterator i(modifiedChildren_.begin());
+ rtl::Reference< ChildAccess > child(getModifiedChild(i));
+ if (child.is()) {
+ childValid = childValid && !child->isFinalized();
+ child->commitChanges(childValid, 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)
+{
+ OSL_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:
+ OSL_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
+ }
+ OSL_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:
+ OSL_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
+ }
+ OSL_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
+ }
+ //TODO: if (allChanges != 0) {
+ // allChanges->push_back(
+ // css::util::ElementChange(
+ // css::uno::makeAny(...),
+ // css::uno::Any(), css::uno::Any()));
+ // //TODO: non-void ReplacedElement
+ //}
+ }
+ // else: spurious Modifications::Node not representing a change
+ break;
+ default:
+ OSL_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)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ comphelper::SequenceAsVector< css::uno::Type > types;
+ types.push_back(cppu::UnoType< css::uno::XInterface >::get());
+ types.push_back(cppu::UnoType< css::uno::XWeak >::get());
+ types.push_back(cppu::UnoType< css::lang::XTypeProvider >::get());
+ types.push_back(cppu::UnoType< css::lang::XServiceInfo >::get());
+ types.push_back(cppu::UnoType< css::lang::XComponent >::get());
+ types.push_back(
+ cppu::UnoType< css::container::XHierarchicalNameAccess >::get());
+ types.push_back(cppu::UnoType< css::container::XContainer >::get());
+ types.push_back(cppu::UnoType< css::beans::XExactName >::get());
+ types.push_back(cppu::UnoType< css::container::XHierarchicalName >::get());
+ types.push_back(cppu::UnoType< css::container::XNamed >::get());
+ types.push_back(cppu::UnoType< css::beans::XProperty >::get());
+ types.push_back(cppu::UnoType< css::container::XElementAccess >::get());
+ types.push_back(cppu::UnoType< css::container::XNameAccess >::get());
+ if (getNode()->kind() == Node::KIND_GROUP) {
+ types.push_back(cppu::UnoType< css::beans::XPropertySetInfo >::get());
+ types.push_back(cppu::UnoType< css::beans::XPropertySet >::get());
+ types.push_back(cppu::UnoType< css::beans::XMultiPropertySet >::get());
+ types.push_back(
+ cppu::UnoType< css::beans::XHierarchicalPropertySet >::get());
+ types.push_back(
+ cppu::UnoType< css::beans::XMultiHierarchicalPropertySet >::get());
+ types.push_back(
+ cppu::UnoType< css::beans::XHierarchicalPropertySetInfo >::get());
+ }
+ if (getRootAccess()->isUpdate()) {
+ types.push_back(cppu::UnoType< css::container::XNameReplace >::get());
+ if (getNode()->kind() != Node::KIND_GROUP ||
+ dynamic_cast< GroupNode * >(getNode().get())->isExtensible())
+ {
+ types.push_back(
+ cppu::UnoType< css::container::XNameContainer >::get());
+ }
+ if (getNode()->kind() == Node::KIND_SET) {
+ types.push_back(
+ cppu::UnoType< css::lang::XSingleServiceFactory >::get());
+ }
+ }
+ addTypes(&types);
+ return types.getAsConstList();
+}
+
+css::uno::Sequence< sal_Int8 > Access::getImplementationId()
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return css::uno::Sequence< sal_Int8 >();
+}
+
+rtl::OUString Access::getImplementationName() throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr Access has no service implementation name")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Bool Access::supportsService(rtl::OUString const & ServiceName)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames());
+ for (sal_Int32 i = 0; i < names.getLength(); ++i) {
+ if (names[i] == ServiceName) {
+ return true;
+ }
+ }
+ return false;
+}
+
+css::uno::Sequence< rtl::OUString > Access::getSupportedServiceNames()
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ comphelper::SequenceAsVector< rtl::OUString > services;
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationAccess")));
+ if (getRootAccess()->isUpdate()) {
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationUpdateAccess")));
+ }
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.HierarchyAccess")));
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.HierarchyElement")));
+ if (getNode()->kind() == Node::KIND_GROUP) {
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.GroupAccess")));
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.PropertyHierarchy")));
+ if (getRootAccess()->isUpdate()) {
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.GroupUpdate")));
+ }
+ } else {
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.SetAccess")));
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.SimpleSetAccess")));
+ if (getRootAccess()->isUpdate()) {
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.SetUpdate")));
+ services.push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.SimpleSetUpdate")));
+ }
+ }
+ addSupportedServiceNames(&services);
+ return services.getAsConstList();
+}
+
+void Access::dispose() throw (css::uno::RuntimeException) {
+ OSL_ASSERT(thisIs(IS_ANY));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ if (getParentAccess().is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr dispose inappropriate Access")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ if (disposed_) {
+ return;
+ }
+ initDisposeBroadcaster(&bc);
+ clearListeners();
+ disposed_ = true;
+ }
+ bc.send();
+}
+
+void Access::addEventListener(
+ css::uno::Reference< css::lang::XEventListener > const & xListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ if (!xListener.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ if (!disposed_) {
+ disposeListeners_.insert(xListener);
+ return;
+ }
+ }
+ try {
+ xListener->disposing(
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ } catch (css::lang::DisposedException &) {}
+}
+
+void Access::removeEventListener(
+ css::uno::Reference< css::lang::XEventListener > const & aListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ DisposeListeners::iterator i(disposeListeners_.find(aListener));
+ if (i != disposeListeners_.end()) {
+ disposeListeners_.erase(i);
+ }
+}
+
+css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) {
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ rtl::Reference< Node > p(getNode());
+ switch (p->kind()) {
+ case Node::KIND_LOCALIZED_PROPERTY:
+ return mapType(
+ dynamic_cast< LocalizedPropertyNode * >(p.get())->getStaticType());
+ case Node::KIND_GROUP:
+ //TODO: Should a specific type be returned for a non-extensible group
+ // with homogeneous members or for an extensible group that currently
+ // has only homegeneous members?
+ return cppu::UnoType< cppu::UnoVoidType >::get();
+ case Node::KIND_SET:
+ return cppu::UnoType< cppu::UnoVoidType >::get(); //TODO: correct?
+ default:
+ OSL_ASSERT(false);
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+sal_Bool Access::hasElements() throw (css::uno::RuntimeException) {
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return !getAllChildren().empty(); //TODO: optimize
+}
+
+css::uno::Any Access::getByName(rtl::OUString const & aName)
+ throw (
+ css::container::NoSuchElementException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ rtl::Reference< ChildAccess > child(getChild(aName));
+ if (!child.is()) {
+ throw css::container::NoSuchElementException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return child->asValue();
+}
+
+css::uno::Sequence< rtl::OUString > Access::getElementNames()
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
+ comphelper::SequenceAsVector< rtl::OUString > names;
+ for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
+ children.begin());
+ i != children.end(); ++i)
+ {
+ names.push_back((*i)->getNameInternal());
+ }
+ return names.getAsConstList();
+}
+
+sal_Bool Access::hasByName(rtl::OUString const & aName)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return getChild(aName).is();
+}
+
+css::uno::Any Access::getByHierarchicalName(rtl::OUString const & aName)
+ throw (css::container::NoSuchElementException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ rtl::Reference< ChildAccess > child(getSubChild(aName));
+ if (!child.is()) {
+ throw css::container::NoSuchElementException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return child->asValue();
+}
+
+sal_Bool Access::hasByHierarchicalName(rtl::OUString const & aName)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return getSubChild(aName).is();
+}
+
+void Access::addContainerListener(
+ css::uno::Reference< css::container::XContainerListener > const & xListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ if (!xListener.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ if (!disposed_) {
+ containerListeners_.insert(xListener);
+ return;
+ }
+ }
+ try {
+ xListener->disposing(
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ } catch (css::lang::DisposedException &) {}
+}
+
+void Access::removeContainerListener(
+ css::uno::Reference< css::container::XContainerListener > const & xListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ ContainerListeners::iterator i(containerListeners_.find(xListener));
+ if (i != containerListeners_.end()) {
+ containerListeners_.erase(i);
+ }
+}
+
+rtl::OUString Access::getExactName(rtl::OUString const & aApproximateName)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return aApproximateName;
+}
+
+css::uno::Sequence< css::beans::Property > Access::getProperties()
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
+ comphelper::SequenceAsVector< css::beans::Property > properties;
+ for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
+ children.begin());
+ i != children.end(); ++i)
+ {
+ properties.push_back((*i)->asProperty());
+ }
+ return properties.getAsConstList();
+}
+
+css::beans::Property Access::getPropertyByName(rtl::OUString const & aName)
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ rtl::Reference< ChildAccess > child(getChild(aName));
+ if (!child.is()) {
+ throw css::beans::UnknownPropertyException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return child->asProperty();
+}
+
+sal_Bool Access::hasPropertyByName(rtl::OUString const & Name)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ return getChild(Name).is();
+}
+
+rtl::OUString Access::getHierarchicalName() throw (css::uno::RuntimeException) {
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return getRelativePathRepresentation();
+}
+
+rtl::OUString Access::composeHierarchicalName(
+ rtl::OUString const & aRelativeName)
+ throw (
+ css::lang::IllegalArgumentException, css::lang::NoSupportException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ if (aRelativeName.getLength() == 0 || aRelativeName[0] == '/') {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr composeHierarchicalName inappropriate relative"
+ " name")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+ rtl::OUStringBuffer path(getRelativePathRepresentation());
+ if (path.getLength() != 0) {
+ path.append(sal_Unicode('/'));
+ }
+ path.append(aRelativeName);
+ return path.makeStringAndClear();
+}
+
+rtl::OUString Access::getName() throw (css::uno::RuntimeException) {
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return getNameInternal();
+}
+
+void Access::setName(rtl::OUString const & aName)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ checkFinalized();
+ Modifications localMods;
+ switch (getNode()->kind()) {
+ case Node::KIND_GROUP:
+ case Node::KIND_SET:
+ {
+ rtl::Reference< Access > parent(getParentAccess());
+ if (parent.is()) {
+ rtl::Reference< Node > node(getNode());
+ if (node->getTemplateName().getLength() != 0) {
+ rtl::Reference< ChildAccess > other(
+ parent->getChild(aName));
+ if (other.get() == this) {
+ break;
+ }
+ if (node->getMandatory() == Data::NO_LAYER &&
+ !(other.is() && other->isFinalized()))
+ {
+ rtl::Reference< RootAccess > root(getRootAccess());
+ rtl::Reference< ChildAccess > childAccess(
+ dynamic_cast< ChildAccess * >(this));
+ localMods.add(getRelativePath());
+ // unbind() modifies the parent chain that
+ // markChildAsModified() walks, so order is
+ // important:
+ parent->markChildAsModified(childAccess);
+ //TODO: must not throw
+ childAccess->unbind(); // must not throw
+ if (other.is()) {
+ other->unbind(); // must not throw
+ }
+ childAccess->bind(root, parent, aName);
+ // must not throw
+ parent->markChildAsModified(childAccess);
+ //TODO: must not throw
+ localMods.add(getRelativePath());
+ break;
+ }
+ }
+ }
+ }
+ // fall through
+ case Node::KIND_LOCALIZED_PROPERTY:
+ // renaming a property could only work for an extension property,
+ // but a localized property is never an extension property
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setName inappropriate node")),
+ static_cast< cppu::OWeakObject * >(this));
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+css::beans::Property Access::getAsProperty() throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return asProperty();
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo()
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ return this;
+}
+
+void Access::setPropertyValue(
+ rtl::OUString const & aPropertyName, css::uno::Any const & aValue)
+ throw (
+ css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
+ css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ if (!getRootAccess()->isUpdate()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setPropertyValue on non-update access")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ Modifications localMods;
+ if (!setChildProperty(aPropertyName, aValue, &localMods)) {
+ throw css::beans::UnknownPropertyException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+css::uno::Any Access::getPropertyValue(rtl::OUString const & PropertyName)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ rtl::Reference< ChildAccess > child(getChild(PropertyName));
+ if (!child.is()) {
+ throw css::beans::UnknownPropertyException(
+ PropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return child->asValue();
+}
+
+void Access::addPropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ xListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ {
+ osl::MutexGuard g(lock);
+ if (!xListener.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ checkKnownProperty(aPropertyName);
+ if (!disposed_) {
+ propertyChangeListeners_[aPropertyName].insert(xListener);
+ return;
+ }
+ }
+ try {
+ xListener->disposing(
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ } catch (css::lang::DisposedException &) {}
+}
+
+void Access::removePropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ checkKnownProperty(aPropertyName);
+ PropertyChangeListeners::iterator i(
+ propertyChangeListeners_.find(aPropertyName));
+ if (i != propertyChangeListeners_.end()) {
+ PropertyChangeListenersElement::iterator j(i->second.find(aListener));
+ if (j != i->second.end()) {
+ i->second.erase(j);
+ if (i->second.empty()) {
+ propertyChangeListeners_.erase(i);
+ }
+ }
+ }
+}
+
+void Access::addVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ {
+ osl::MutexGuard g(lock);
+ if (!aListener.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ checkKnownProperty(PropertyName);
+ if (!disposed_) {
+ vetoableChangeListeners_[PropertyName].insert(aListener);
+ //TODO: actually call vetoableChangeListeners_
+ return;
+ }
+ }
+ try {
+ aListener->disposing(
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ } catch (css::lang::DisposedException &) {}
+}
+
+void Access::removeVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ checkKnownProperty(PropertyName);
+ VetoableChangeListeners::iterator i(
+ vetoableChangeListeners_.find(PropertyName));
+ if (i != vetoableChangeListeners_.end()) {
+ VetoableChangeListenersElement::iterator j(i->second.find(aListener));
+ if (j != i->second.end()) {
+ i->second.erase(j);
+ if (i->second.empty()) {
+ vetoableChangeListeners_.erase(i);
+ }
+ }
+ }
+}
+
+void Access::setPropertyValues(
+ css::uno::Sequence< rtl::OUString > const & aPropertyNames,
+ css::uno::Sequence< css::uno::Any > const & aValues)
+ throw (
+ css::beans::PropertyVetoException, css::lang::IllegalArgumentException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ if (!getRootAccess()->isUpdate()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setPropertyValues on non-update access")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ if (aPropertyNames.getLength() != aValues.getLength()) {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setPropertyValues: aPropertyNames/aValues of"
+ " different length")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+ Modifications localMods;
+ for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) {
+ if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setPropertyValues inappropriate property"
+ " name")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+ }
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+css::uno::Sequence< css::uno::Any > Access::getPropertyValues(
+ css::uno::Sequence< rtl::OUString > const & aPropertyNames)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength());
+ for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) {
+ rtl::Reference< ChildAccess > child(getChild(aPropertyNames[i]));
+ if (!child.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr getPropertyValues inappropriate property"
+ " name")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ vals[i] = child->asValue();
+ }
+ return vals;
+}
+
+void Access::addPropertiesChangeListener(
+ css::uno::Sequence< rtl::OUString > const &,
+ css::uno::Reference< css::beans::XPropertiesChangeListener > const &
+ xListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ {
+ osl::MutexGuard g(lock);
+ if (!xListener.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ if (!disposed_) {
+ propertiesChangeListeners_.insert(xListener);
+ return;
+ }
+ }
+ try {
+ xListener->disposing(
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ } catch (css::lang::DisposedException &) {}
+}
+
+void Access::removePropertiesChangeListener(
+ css::uno::Reference< css::beans::XPropertiesChangeListener > const &
+ xListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ PropertiesChangeListeners::iterator i(
+ propertiesChangeListeners_.find(xListener));
+ if (i != propertiesChangeListeners_.end()) {
+ propertiesChangeListeners_.erase(i);
+ }
+}
+
+void Access::firePropertiesChangeEvent(
+ css::uno::Sequence< rtl::OUString > const & aPropertyNames,
+ css::uno::Reference< css::beans::XPropertiesChangeListener > const &
+ xListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ css::uno::Sequence< css::beans::PropertyChangeEvent > events(
+ aPropertyNames.getLength());
+ for (sal_Int32 i = 0; i < events.getLength(); ++i) {
+ events[i].Source = static_cast< cppu::OWeakObject * >(this);
+ events[i].PropertyName = aPropertyNames[i];
+ events[i].Further = false;
+ events[i].PropertyHandle = -1;
+ }
+ xListener->propertiesChange(events);
+}
+
+css::uno::Reference< css::beans::XHierarchicalPropertySetInfo >
+Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) {
+ OSL_ASSERT(thisIs(IS_GROUP));
+ return this;
+}
+
+void Access::setHierarchicalPropertyValue(
+ rtl::OUString const & aHierarchicalPropertyName,
+ css::uno::Any const & aValue)
+ throw (
+ css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
+ css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ if (!getRootAccess()->isUpdate()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setHierarchicalPropertyName on non-update"
+ " access")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ rtl::Reference< ChildAccess > child(
+ getSubChild(aHierarchicalPropertyName));
+ if (!child.is()) {
+ throw css::beans::UnknownPropertyException(
+ aHierarchicalPropertyName,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ child->checkFinalized();
+ Modifications localMods;
+ child->setProperty(aValue, &localMods);
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+css::uno::Any Access::getHierarchicalPropertyValue(
+ rtl::OUString const & aHierarchicalPropertyName)
+ throw (
+ css::beans::UnknownPropertyException,
+ css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName));
+ if (!child.is()) {
+ throw css::beans::UnknownPropertyException(
+ aHierarchicalPropertyName,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return child->asValue();
+}
+
+void Access::setHierarchicalPropertyValues(
+ css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames,
+ css::uno::Sequence< css::uno::Any > const & Values)
+ throw (
+ css::beans::PropertyVetoException, css::lang::IllegalArgumentException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ if (!getRootAccess()->isUpdate()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setPropertyValues on non-update access")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ if (aHierarchicalPropertyNames.getLength() != Values.getLength()) {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setHierarchicalPropertyValues:"
+ " aHierarchicalPropertyNames/Values of different"
+ " length")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+ Modifications localMods;
+ for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
+ rtl::Reference< ChildAccess > child(
+ getSubChild(aHierarchicalPropertyNames[i]));
+ if (!child.is()) {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr setHierarchicalPropertyValues"
+ " inappropriate property name")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+ child->checkFinalized();
+ child->setProperty(Values[i], &localMods);
+ }
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues(
+ css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames)
+ throw (
+ css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ css::uno::Sequence< css::uno::Any > vals(
+ aHierarchicalPropertyNames.getLength());
+ for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
+ rtl::Reference< ChildAccess > child(
+ getSubChild(aHierarchicalPropertyNames[i]));
+ if (!child.is()) {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr getHierarchicalPropertyValues inappropriate"
+ " hierarchical property name")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+ vals[i] = child->asValue();
+ }
+ return vals;
+}
+
+css::beans::Property Access::getPropertyByHierarchicalName(
+ rtl::OUString const & aHierarchicalName)
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName));
+ if (!child.is()) {
+ throw css::beans::UnknownPropertyException(
+ aHierarchicalName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return child->asProperty();
+}
+
+sal_Bool Access::hasPropertyByHierarchicalName(
+ rtl::OUString const & aHierarchicalName)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_GROUP));
+ osl::MutexGuard g(lock);
+ return getSubChild(aHierarchicalName).is();
+}
+
+void Access::replaceByName(
+ rtl::OUString const & aName, css::uno::Any const & aElement)
+ throw (
+ css::lang::IllegalArgumentException,
+ css::container::NoSuchElementException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_UPDATE));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ rtl::Reference< ChildAccess > child(getChild(aName));
+ if (!child.is()) {
+ throw css::container::NoSuchElementException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ child->checkFinalized();
+ Modifications localMods;
+ switch (getNode()->kind()) {
+ case Node::KIND_LOCALIZED_PROPERTY:
+ case Node::KIND_GROUP:
+ child->setProperty(aElement, &localMods);
+ break;
+ case Node::KIND_SET:
+ {
+ rtl::Reference< ChildAccess > freeAcc(
+ getFreeSetMember(aElement));
+ rtl::Reference< RootAccess > root(getRootAccess());
+ localMods.add(child->getRelativePath());
+ child->unbind(); // must not throw
+ freeAcc->bind(root, this, aName); // must not throw
+ markChildAsModified(freeAcc); //TODO: must not throw
+ }
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+void Access::insertByName(
+ rtl::OUString const & aName, css::uno::Any const & aElement)
+ throw (
+ css::lang::IllegalArgumentException,
+ css::container::ElementExistException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_EXTENSIBLE|IS_UPDATE));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ checkFinalized();
+ if (getChild(aName).is()) {
+ throw css::container::ElementExistException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ Modifications localMods;
+ switch (getNode()->kind()) {
+ case Node::KIND_LOCALIZED_PROPERTY:
+ insertLocalizedValueChild(aName, aElement, &localMods);
+ break;
+ case Node::KIND_GROUP:
+ {
+ checkValue(aElement, TYPE_ANY, true);
+ rtl::Reference< ChildAccess > child(
+ new ChildAccess(
+ components_, getRootAccess(), this, aName,
+ new PropertyNode(
+ Data::NO_LAYER, TYPE_ANY, true, aElement, true)));
+ markChildAsModified(child);
+ localMods.add(child->getRelativePath());
+ }
+ break;
+ case Node::KIND_SET:
+ {
+ rtl::Reference< ChildAccess > freeAcc(
+ getFreeSetMember(aElement));
+ freeAcc->bind(getRootAccess(), this, aName); // must not throw
+ markChildAsModified(freeAcc); //TODO: must not throw
+ localMods.add(freeAcc->getRelativePath());
+ }
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+void Access::removeByName(rtl::OUString const & aName)
+ throw (
+ css::container::NoSuchElementException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_EXTENSIBLE|IS_UPDATE));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ rtl::Reference< ChildAccess > child(getChild(aName));
+ if (!child.is() || child->isFinalized() ||
+ child->getNode()->getMandatory() != Data::NO_LAYER)
+ {
+ throw css::container::NoSuchElementException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ if (getNode()->kind() == Node::KIND_GROUP) {
+ rtl::Reference< Node > p(child->getNode());
+ if (p->kind() != Node::KIND_PROPERTY ||
+ !dynamic_cast< PropertyNode * >(p.get())->isExtension())
+ {
+ throw css::container::NoSuchElementException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ }
+ Modifications localMods;
+ localMods.add(child->getRelativePath());
+ // unbind() modifies the parent chain that markChildAsModified() walks,
+ // so order is important:
+ markChildAsModified(child); //TODO: must not throw
+ child->unbind();
+ getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
+ }
+ bc.send();
+}
+
+css::uno::Reference< css::uno::XInterface > Access::createInstance()
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_SET|IS_UPDATE));
+ rtl::OUString tmplName(
+ dynamic_cast< SetNode * >(getNode().get())->getDefaultTemplateName());
+ rtl::Reference< Node > tmpl(
+ components_.getTemplate(Data::NO_LAYER, tmplName));
+ if (!tmpl.is()) {
+ throw css::uno::Exception(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown template ")) +
+ tmplName),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ rtl::Reference< Node > node(tmpl->clone());
+ node->setLayer(Data::NO_LAYER);
+ return static_cast< cppu::OWeakObject * >(
+ new ChildAccess(components_, getRootAccess(), node));
+}
+
+css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments(
+ css::uno::Sequence< css::uno::Any > const & aArguments)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_SET|IS_UPDATE));
+ if (aArguments.getLength() != 0) {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configuration SimpleSetUpdate createInstanceWithArguments"
+ " must not specify any arguments")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return createInstance();
+}
+
+rtl::Reference< ChildAccess > Access::getModifiedChild(
+ ModifiedChildren::iterator const & childIterator)
+{
+ return (childIterator->second.child->getParentAccess() == this &&
+ (childIterator->second.child->getNameInternal() ==
+ childIterator->first))
+ ? childIterator->second.child : rtl::Reference< ChildAccess >();
+}
+
+rtl::Reference< ChildAccess > Access::getUnmodifiedChild(
+ rtl::OUString const & name)
+{
+ OSL_ASSERT(modifiedChildren_.find(name) == modifiedChildren_.end());
+ rtl::Reference< Node > node(getNode()->getMember(name));
+ if (!node.is()) {
+ return rtl::Reference< ChildAccess >();
+ }
+ WeakChildMap::iterator i(cachedChildren_.find(name));
+ if (i != cachedChildren_.end()) {
+ rtl::Reference< ChildAccess > child;
+ if (i->second->acquireCounting() > 1) {
+ child.set(i->second); // must not throw
+ }
+ i->second->releaseNondeleting();
+ if (child.is()) {
+ child->setNode(node);
+ return child;
+ }
+ }
+ rtl::Reference< ChildAccess > child(
+ new ChildAccess(components_, getRootAccess(), this, name, node));
+ cachedChildren_[name] = child.get();
+ return child;
+}
+
+rtl::Reference< ChildAccess > Access::getSubChild(rtl::OUString const & path) {
+ rtl::OUString name;
+ bool setElement;
+ rtl::OUString templateName;
+ sal_Int32 i = Data::parseSegment(
+ path, 0, &name, &setElement, &templateName);
+ if (i == -1 || (i != path.getLength() && path[i] != '/')) {
+ return rtl::Reference< ChildAccess >();
+ }
+ rtl::Reference< ChildAccess > child(getChild(name));
+ if (!child.is()) {
+ return rtl::Reference< ChildAccess >();
+ }
+ if (setElement) {
+ rtl::Reference< Node > p(getNode());
+ switch (p->kind()) {
+ case Node::KIND_LOCALIZED_PROPERTY:
+ if (!Components::allLocales(getRootAccess()->getLocale()) ||
+ templateName.getLength() != 0)
+ {
+ return rtl::Reference< ChildAccess >();
+ }
+ break;
+ case Node::KIND_SET:
+ if (templateName.getLength() != 0 &&
+ !dynamic_cast< SetNode * >(p.get())->isValidTemplate(
+ templateName))
+ {
+ return rtl::Reference< ChildAccess >();
+ }
+ break;
+ default:
+ return rtl::Reference< ChildAccess >();
+ }
+ }
+ // For backwards compatibility, ignore a final slash after non-value nodes:
+ return child->isValue()
+ ? (i == path.getLength() ? child : rtl::Reference< ChildAccess >())
+ : (i >= path.getLength() - 1
+ ? child : child->getSubChild(path.copy(i + 1)));
+}
+
+bool Access::setChildProperty(
+ rtl::OUString const & name, css::uno::Any const & value,
+ Modifications * localModifications)
+{
+ OSL_ASSERT(localModifications != 0);
+ rtl::Reference< ChildAccess > child(getChild(name));
+ if (!child.is()) {
+ return false;
+ }
+ child->checkFinalized();
+ child->setProperty(value, localModifications);
+ return true;
+}
+
+css::beans::Property Access::asProperty() {
+ css::uno::Type type;
+ bool nillable;
+ bool removable;
+ rtl::Reference< Node > p(getNode());
+ switch (p->kind()) {
+ case Node::KIND_PROPERTY:
+ {
+ PropertyNode * prop = dynamic_cast< PropertyNode * >(p.get());
+ type = mapType(prop->getStaticType());
+ nillable = prop->isNillable();
+ removable = prop->isExtension();
+ }
+ break;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ {
+ LocalizedPropertyNode * locprop =
+ dynamic_cast< LocalizedPropertyNode *>(p.get());
+ if (Components::allLocales(getRootAccess()->getLocale())) {
+ type = cppu::UnoType< css::uno::XInterface >::get();
+ //TODO: correct?
+ removable = false;
+ } else {
+ type = mapType(locprop->getStaticType());
+ removable = false; //TODO ???
+ }
+ nillable = locprop->isNillable();
+ }
+ break;
+ case Node::KIND_LOCALIZED_VALUE:
+ {
+ LocalizedPropertyNode * locprop =
+ dynamic_cast< LocalizedPropertyNode * >(getParentNode().get());
+ type = mapType(locprop->getStaticType());
+ nillable = locprop->isNillable();
+ removable = false; //TODO ???
+ }
+ break;
+ default:
+ type = cppu::UnoType< css::uno::XInterface >::get(); //TODO: correct?
+ nillable = false;
+ removable = getParentNode()->kind() == Node::KIND_SET;
+ break;
+ }
+ return css::beans::Property(
+ getNameInternal(), -1, type,
+ (css::beans::PropertyAttribute::BOUND | //TODO: correct for group/set?
+ css::beans::PropertyAttribute::CONSTRAINED |
+ (nillable ? css::beans::PropertyAttribute::MAYBEVOID : 0) |
+ (getRootAccess()->isUpdate()
+ ? (removable ? css::beans::PropertyAttribute::REMOVEABLE : 0)
+ : css::beans::PropertyAttribute::READONLY))); //TODO: MAYBEDEFAULT
+}
+
+void Access::checkFinalized() {
+ if (isFinalized()) {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr modification of finalized item")),
+ static_cast< cppu::OWeakObject * >(this), -1);
+ }
+}
+
+void Access::checkKnownProperty(rtl::OUString const & descriptor) {
+ if (descriptor.getLength() == 0) {
+ return;
+ }
+ rtl::Reference< ChildAccess > child(getChild(descriptor));
+ if (child.is()) {
+ switch (child->getNode()->kind()) {
+ case Node::KIND_PROPERTY:
+ return;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ if (!Components::allLocales(getRootAccess()->getLocale())) {
+ return;
+ }
+ break;
+ case Node::KIND_LOCALIZED_VALUE:
+ if (Components::allLocales(getRootAccess()->getLocale())) {
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ throw css::beans::UnknownPropertyException(
+ descriptor, static_cast< cppu::OWeakObject * >(this));
+}
+
+rtl::Reference< ChildAccess > Access::getFreeSetMember(
+ css::uno::Any const & value)
+{
+ rtl::Reference< ChildAccess > freeAcc;
+ css::uno::Reference< css::lang::XUnoTunnel > tunnel;
+ value >>= tunnel;
+ if (tunnel.is()) {
+ freeAcc.set(
+ reinterpret_cast< ChildAccess * >(
+ tunnel->getSomething(ChildAccess::getTunnelId())));
+ }
+ if (!freeAcc.is() || freeAcc->getParentAccess().is() ||
+ (freeAcc->isInTransaction() &&
+ freeAcc->getRootAccess() != getRootAccess()))
+ {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr inappropriate set element")),
+ static_cast< cppu::OWeakObject * >(this), 1);
+ }
+ OSL_ASSERT(dynamic_cast< SetNode * >(getNode().get()) != 0);
+ if (!dynamic_cast< SetNode * >(getNode().get())->isValidTemplate(
+ freeAcc->getNode()->getTemplateName()))
+ {
+ throw css::lang::IllegalArgumentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr inappropriate set element")),
+ static_cast< cppu::OWeakObject * >(this), 1);
+ }
+ return freeAcc;
+}
+
+rtl::Reference< Access > Access::getNotificationRoot() {
+ for (rtl::Reference< Access > p(this);;) {
+ rtl::Reference< Access > parent(p->getParentAccess());
+ if (!parent.is()) {
+ return p;
+ }
+ p = parent;
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 0
+bool Access::thisIs(int what) {
+ osl::MutexGuard g(lock);
+ rtl::Reference< Node > p(getNode());
+ Node::Kind k(p->kind());
+ return k != Node::KIND_PROPERTY && k != Node::KIND_LOCALIZED_VALUE &&
+ ((what & IS_GROUP) == 0 || k == Node::KIND_GROUP) &&
+ ((what & IS_SET) == 0 || k == Node::KIND_SET) &&
+ ((what & IS_EXTENSIBLE) == 0 || k != Node::KIND_GROUP ||
+ dynamic_cast< GroupNode * >(p.get())->isExtensible()) &&
+ ((what & IS_GROUP_MEMBER) == 0 ||
+ getParentNode()->kind() == Node::KIND_GROUP) ||
+ ((what & IS_SET_MEMBER) == 0 ||
+ getParentNode()->kind() == Node::KIND_SET) ||
+ ((what & IS_UPDATE) == 0 || getRootAccess()->isUpdate());
+}
+#endif
+
+}
diff --git a/configmgr/source/access.hxx b/configmgr/source/access.hxx
new file mode 100644
index 000000000000..8c10aa8ccece
--- /dev/null
+++ b/configmgr/source/access.hxx
@@ -0,0 +1,582 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_ACCESS_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_ACCESS_HXX
+
+#include "sal/config.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/beans/PropertyVetoException.hpp"
+#include "com/sun/star/beans/UnknownPropertyException.hpp"
+#include "com/sun/star/beans/XExactName.hpp"
+#include "com/sun/star/beans/XHierarchicalPropertySet.hpp"
+#include "com/sun/star/beans/XHierarchicalPropertySetInfo.hpp"
+#include "com/sun/star/beans/XMultiHierarchicalPropertySet.hpp"
+#include "com/sun/star/beans/XMultiPropertySet.hpp"
+#include "com/sun/star/beans/XProperty.hpp"
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/beans/XPropertySetInfo.hpp"
+#include "com/sun/star/container/ElementExistException.hpp"
+#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/XNameContainer.hpp"
+#include "com/sun/star/container/XNamed.hpp"
+#include "com/sun/star/lang/IllegalArgumentException.hpp"
+#include "com/sun/star/lang/NoSupportException.hpp"
+#include "com/sun/star/lang/WrappedTargetException.hpp"
+#include "com/sun/star/lang/XComponent.hpp"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/lang/XTypeProvider.hpp"
+#include "com/sun/star/lang/XSingleServiceFactory.hpp"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "cppuhelper/weak.hxx"
+#include "osl/interlck.h"
+#include "rtl/ref.hxx"
+#include "sal/types.h"
+
+#include "modifications.hxx"
+#include "path.hxx"
+#include "type.hxx"
+
+namespace com { namespace sun { namespace star {
+ namespace beans {
+ class XHierarchicalPropertySetInfo;
+ class XPropertiesChangeListener;
+ class XPropertyChangeListener;
+ class XVetoableChangeListener;
+ struct Property;
+ }
+ namespace container { class XContainerListener; }
+ namespace lang { class XEventListener; }
+ namespace uno {
+ class Any;
+ class Type;
+ class XInterface;
+ }
+ namespace util { struct ElementChange; }
+} } }
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Broadcaster;
+class Change;
+class ChildAccess;
+class Components;
+class Node;
+class RootAccess;
+
+class Access:
+ public cppu::OWeakObject, public com::sun::star::lang::XTypeProvider,
+ public com::sun::star::lang::XServiceInfo,
+ public com::sun::star::lang::XComponent,
+ public com::sun::star::container::XHierarchicalNameAccess,
+ public com::sun::star::container::XContainer,
+ public com::sun::star::beans::XExactName,
+ public com::sun::star::beans::XPropertySetInfo,
+ public com::sun::star::container::XHierarchicalName,
+ public com::sun::star::container::XNamed,
+ public com::sun::star::beans::XProperty,
+ public com::sun::star::beans::XPropertySet,
+ public com::sun::star::beans::XMultiPropertySet,
+ public com::sun::star::beans::XHierarchicalPropertySet,
+ public com::sun::star::beans::XMultiHierarchicalPropertySet,
+ public com::sun::star::beans::XHierarchicalPropertySetInfo,
+ public com::sun::star::container::XNameContainer,
+ public com::sun::star::lang::XSingleServiceFactory,
+ private boost::noncopyable
+{
+public:
+ oslInterlockedCount acquireCounting();
+
+ void releaseNondeleting();
+
+ bool isValue();
+
+ void markChildAsModified(rtl::Reference< ChildAccess > const & child);
+
+ void releaseChild(rtl::OUString const & name);
+
+ virtual Path getAbsolutePath() = 0;
+
+ virtual Path getRelativePath() = 0;
+
+ virtual rtl::OUString getRelativePathRepresentation() = 0;
+
+ virtual rtl::Reference< Node > getNode() = 0;
+
+ virtual bool isFinalized() = 0;
+
+ virtual void initBroadcaster(
+ Modifications::Node const & modifications, Broadcaster * broadcaster);
+
+ 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);
+
+ virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL
+ getImplementationId() throw (com::sun::star::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
+ getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL dispose()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL addEventListener(
+ com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >
+ const & xListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL removeEventListener(
+ com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >
+ const & aListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Type SAL_CALL getElementType()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL hasElements()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Any SAL_CALL getByName(
+ rtl::OUString const & aName)
+ throw (
+ com::sun::star::container::NoSuchElementException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
+ getElementNames() throw (com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL hasByName(rtl::OUString const & aName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Any SAL_CALL getByHierarchicalName(
+ rtl::OUString const & aName)
+ throw (
+ com::sun::star::container::NoSuchElementException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL addContainerListener(
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > const & xListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL removeContainerListener(
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > const & xListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getExactName(
+ rtl::OUString const & aApproximateName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property >
+ SAL_CALL getProperties() throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::beans::Property SAL_CALL getPropertyByName(
+ rtl::OUString const & aName)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL hasPropertyByName(rtl::OUString const & Name)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getHierarchicalName()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL composeHierarchicalName(
+ rtl::OUString const & aRelativeName)
+ throw (
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::lang::NoSupportException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getName()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL setName(rtl::OUString const & aName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::beans::Property SAL_CALL getAsProperty()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual
+ com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo >
+ SAL_CALL getPropertySetInfo() throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL setPropertyValue(
+ rtl::OUString const & aPropertyName,
+ com::sun::star::uno::Any const & aValue)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::beans::PropertyVetoException,
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Any SAL_CALL getPropertyValue(
+ rtl::OUString const & PropertyName)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL addPropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > const & xListener)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL removePropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > const & aListener)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL addVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XVetoableChangeListener > const & aListener)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL removeVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XVetoableChangeListener > const & aListener)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL setPropertyValues(
+ com::sun::star::uno::Sequence< rtl::OUString > const & aPropertyNames,
+ com::sun::star::uno::Sequence< com::sun::star::uno::Any > const &
+ aValues)
+ throw (
+ com::sun::star::beans::PropertyVetoException,
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Sequence< com::sun::star::uno::Any > SAL_CALL
+ getPropertyValues(
+ com::sun::star::uno::Sequence< rtl::OUString > const & aPropertyNames)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL addPropertiesChangeListener(
+ com::sun::star::uno::Sequence< rtl::OUString > const & aPropertyNames,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertiesChangeListener > const &
+ xListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL removePropertiesChangeListener(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertiesChangeListener > const &
+ xListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL firePropertiesChangeEvent(
+ com::sun::star::uno::Sequence< rtl::OUString > const & aPropertyNames,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertiesChangeListener > const &
+ xListener)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XHierarchicalPropertySetInfo > SAL_CALL
+ getHierarchicalPropertySetInfo()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL setHierarchicalPropertyValue(
+ rtl::OUString const & aHierarchicalPropertyName,
+ com::sun::star::uno::Any const & aValue)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::beans::PropertyVetoException,
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Any SAL_CALL getHierarchicalPropertyValue(
+ rtl::OUString const & aHierarchicalPropertyName)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL setHierarchicalPropertyValues(
+ com::sun::star::uno::Sequence< rtl::OUString > const &
+ aHierarchicalPropertyNames,
+ com::sun::star::uno::Sequence< com::sun::star::uno::Any > const &
+ Values)
+ throw (
+ com::sun::star::beans::PropertyVetoException,
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Sequence< com::sun::star::uno::Any > SAL_CALL
+ getHierarchicalPropertyValues(
+ com::sun::star::uno::Sequence< rtl::OUString > const &
+ aHierarchicalPropertyNames)
+ throw (
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::beans::Property SAL_CALL
+ getPropertyByHierarchicalName(rtl::OUString const & aHierarchicalName)
+ throw (
+ com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL hasPropertyByHierarchicalName(
+ rtl::OUString const & aHierarchicalName)
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL replaceByName(
+ 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 insertByName(
+ rtl::OUString const & aName, com::sun::star::uno::Any const & aElement)
+ throw (
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::container::ElementExistException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL removeByName(rtl::OUString const & aName)
+ throw (
+ com::sun::star::container::NoSuchElementException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface >
+ SAL_CALL createInstance()
+ throw (
+ com::sun::star::uno::Exception,
+ com::sun::star::uno::RuntimeException);
+
+ virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface >
+ SAL_CALL createInstanceWithArguments(
+ com::sun::star::uno::Sequence< com::sun::star::uno::Any > const &
+ aArguments)
+ throw (
+ com::sun::star::uno::Exception,
+ com::sun::star::uno::RuntimeException);
+
+ rtl::Reference< ChildAccess > getModifiedChild(
+ ModifiedChildren::iterator const & childIterator);
+
+ rtl::Reference< ChildAccess > getUnmodifiedChild(
+ rtl::OUString const & name);
+
+ rtl::Reference< ChildAccess > getSubChild(rtl::OUString const & path);
+
+ bool setChildProperty(
+ rtl::OUString const & name, com::sun::star::uno::Any const & value,
+ Modifications * localModifications);
+
+ com::sun::star::beans::Property asProperty();
+
+ void checkFinalized();
+
+ void checkKnownProperty(rtl::OUString const & descriptor);
+
+ rtl::Reference< ChildAccess > getFreeSetMember(
+ com::sun::star::uno::Any const & value);
+
+ rtl::Reference< Access > getNotificationRoot();
+
+ typedef std::map< rtl::OUString, ChildAccess * > WeakChildMap;
+
+ typedef
+ std::multiset<
+ com::sun::star::uno::Reference<
+ com::sun::star::lang::XEventListener > >
+ DisposeListeners;
+
+ typedef
+ std::multiset<
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > >
+ ContainerListeners;
+
+ typedef
+ std::multiset<
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > >
+ PropertyChangeListenersElement;
+
+ typedef std::map< rtl::OUString, PropertyChangeListenersElement >
+ PropertyChangeListeners;
+
+ typedef
+ std::multiset<
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XVetoableChangeListener > >
+ VetoableChangeListenersElement;
+
+ typedef std::map< rtl::OUString, VetoableChangeListenersElement >
+ VetoableChangeListeners;
+
+ typedef
+ std::multiset<
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertiesChangeListener > >
+ PropertiesChangeListeners;
+
+ Components & components_;
+ ModifiedChildren modifiedChildren_;
+ WeakChildMap cachedChildren_;
+ DisposeListeners disposeListeners_;
+ ContainerListeners containerListeners_;
+ PropertyChangeListeners propertyChangeListeners_;
+ VetoableChangeListeners vetoableChangeListeners_;
+ PropertiesChangeListeners propertiesChangeListeners_;
+ bool disposed_;
+
+#if OSL_DEBUG_LEVEL > 0
+protected:
+ enum {
+ IS_ANY = 0, IS_GROUP = 0x01, IS_SET = 0x02, IS_EXTENSIBLE = 0x04,
+ IS_GROUP_MEMBER = 0x08, IS_SET_MEMBER = 0x10, IS_UPDATE = 0x20 };
+ bool thisIs(int what);
+#endif
+};
+
+}
+
+#endif
diff --git a/configmgr/source/broadcaster.cxx b/configmgr/source/broadcaster.cxx
new file mode 100644
index 000000000000..bb77039dcc8f
--- /dev/null
+++ b/configmgr/source/broadcaster.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/beans/XPropertiesChangeListener.hpp"
+#include "com/sun/star/beans/XPropertyChangeListener.hpp"
+#include "com/sun/star/container/XContainerListener.hpp"
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "com/sun/star/lang/XEventListener.hpp"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "com/sun/star/util/XChangesListener.hpp"
+#include "osl/diagnose.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "broadcaster.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+void Broadcaster::addDisposeNotification(
+ css::uno::Reference< css::lang::XEventListener > const & listener,
+ css::lang::EventObject const & event)
+{
+ disposeNotifications_.push_back(DisposeNotification(listener, event));
+}
+
+void Broadcaster::addContainerElementReplacedNotification(
+ css::uno::Reference< css::container::XContainerListener > const & listener,
+ css::container::ContainerEvent const & event)
+{
+ containerElementReplacedNotifications_.push_back(
+ ContainerNotification(listener, event));
+}
+
+void Broadcaster::addContainerElementInsertedNotification(
+ css::uno::Reference< css::container::XContainerListener > const & listener,
+ css::container::ContainerEvent const & event)
+{
+ containerElementInsertedNotifications_.push_back(
+ ContainerNotification(listener, event));
+}
+
+void Broadcaster::addContainerElementRemovedNotification(
+ css::uno::Reference< css::container::XContainerListener > const & listener,
+ css::container::ContainerEvent const & event)
+{
+ containerElementRemovedNotifications_.push_back(
+ ContainerNotification(listener, event));
+}
+
+void Broadcaster::addPropertyChangeNotification(
+ css::uno::Reference< css::beans::XPropertyChangeListener > const & listener,
+ css::beans::PropertyChangeEvent const & event)
+{
+ propertyChangeNotifications_.push_back(
+ PropertyChangeNotification(listener, event));
+}
+
+void Broadcaster::addPropertiesChangeNotification(
+ css::uno::Reference< css::beans::XPropertiesChangeListener > const &
+ listener,
+ css::uno::Sequence< css::beans::PropertyChangeEvent > const & event)
+{
+ propertiesChangeNotifications_.push_back(
+ PropertiesChangeNotification(listener, event));
+}
+
+void Broadcaster::addChangesNotification(
+ css::uno::Reference< css::util::XChangesListener > const & listener,
+ css::util::ChangesEvent const & event)
+{
+ changesNotifications_.push_back(ChangesNotification(listener, event));
+}
+
+void Broadcaster::send() {
+ bool exception = false;
+ for (DisposeNotifications::iterator i(disposeNotifications_.begin());
+ i != disposeNotifications_.end(); ++i) {
+ try {
+ i->listener->disposing(i->event);
+ } catch (css::lang::DisposedException &) {
+ } catch (css::uno::Exception &) {
+ exception = true;
+ }
+ }
+ for (ContainerNotifications::iterator i(
+ containerElementInsertedNotifications_.begin());
+ i != containerElementInsertedNotifications_.end(); ++i)
+ {
+ try {
+ i->listener->elementInserted(i->event);
+ } catch (css::lang::DisposedException &) {
+ } catch (css::uno::Exception &) {
+ exception = true;
+ }
+ }
+ for (ContainerNotifications::iterator i(
+ containerElementRemovedNotifications_.begin());
+ i != containerElementRemovedNotifications_.end(); ++i)
+ {
+ try {
+ i->listener->elementRemoved(i->event);
+ } catch (css::lang::DisposedException &) {
+ } catch (css::uno::Exception &) {
+ exception = true;
+ }
+ }
+ for (ContainerNotifications::iterator i(
+ containerElementReplacedNotifications_.begin());
+ i != containerElementReplacedNotifications_.end(); ++i)
+ {
+ try {
+ i->listener->elementReplaced(i->event);
+ } catch (css::lang::DisposedException &) {
+ } catch (css::uno::Exception &) {
+ exception = true;
+ }
+ }
+ for (PropertyChangeNotifications::iterator i(
+ propertyChangeNotifications_.begin());
+ i != propertyChangeNotifications_.end(); ++i)
+ {
+ try {
+ i->listener->propertyChange(i->event);
+ } catch (css::lang::DisposedException &) {
+ } catch (css::uno::Exception &) {
+ exception = true;
+ }
+ }
+ for (PropertiesChangeNotifications::iterator i(
+ propertiesChangeNotifications_.begin());
+ i != propertiesChangeNotifications_.end(); ++i)
+ {
+ try {
+ i->listener->propertiesChange(i->event);
+ } catch (css::lang::DisposedException &) {
+ } catch (css::uno::Exception &) {
+ exception = true;
+ }
+ }
+ for (ChangesNotifications::iterator i(changesNotifications_.begin());
+ i != changesNotifications_.end(); ++i) {
+ try {
+ i->listener->changesOccurred(i->event);
+ } catch (css::lang::DisposedException &) {
+ } catch (css::uno::Exception &) {
+ exception = true;
+ }
+ }
+ if (exception) { //TODO
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr exceptions during listener notification")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+Broadcaster::DisposeNotification::DisposeNotification(
+ css::uno::Reference< css::lang::XEventListener > const & theListener,
+ css::lang::EventObject const & theEvent):
+ listener(theListener), event(theEvent)
+{
+ OSL_ASSERT(theListener.is());
+}
+
+Broadcaster::ContainerNotification::ContainerNotification(
+ css::uno::Reference< css::container::XContainerListener > const &
+ theListener,
+ css::container::ContainerEvent const & theEvent):
+ listener(theListener), event(theEvent)
+{
+ OSL_ASSERT(theListener.is());
+}
+
+Broadcaster::PropertyChangeNotification::PropertyChangeNotification(
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ theListener,
+ css::beans::PropertyChangeEvent const & theEvent):
+ listener(theListener), event(theEvent)
+{
+ OSL_ASSERT(theListener.is());
+}
+
+Broadcaster::PropertiesChangeNotification::PropertiesChangeNotification(
+ css::uno::Reference< css::beans::XPropertiesChangeListener > const &
+ theListener,
+ css::uno::Sequence< css::beans::PropertyChangeEvent > const & theEvent):
+ listener(theListener), event(theEvent)
+{
+ OSL_ASSERT(theListener.is());
+}
+
+Broadcaster::ChangesNotification::ChangesNotification(
+ css::uno::Reference< css::util::XChangesListener > const & theListener,
+ css::util::ChangesEvent const & theEvent):
+ listener(theListener), event(theEvent)
+{
+ OSL_ASSERT(theListener.is());
+}
+
+}
diff --git a/configmgr/source/broadcaster.hxx b/configmgr/source/broadcaster.hxx
new file mode 100644
index 000000000000..95c4b1fac49b
--- /dev/null
+++ b/configmgr/source/broadcaster.hxx
@@ -0,0 +1,181 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_BROADCASTER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_BROADCASTER_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/beans/PropertyChangeEvent.hpp"
+#include "com/sun/star/container/ContainerEvent.hpp"
+#include "com/sun/star/lang/EventObject.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/util/ChangesEvent.hpp"
+
+namespace com { namespace sun { namespace star {
+ namespace beans {
+ class XPropertiesChangeListener;
+ class XPropertyChangeListener;
+ }
+ namespace container { class XContainerListener; }
+ namespace lang { class XEventListener; }
+ namespace util { class XChangesListener; }
+} } }
+
+namespace configmgr {
+
+class Access;
+
+class Broadcaster: private boost::noncopyable {
+public:
+ void addDisposeNotification(
+ com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >
+ const & listener,
+ com::sun::star::lang::EventObject const & event);
+
+ void addContainerElementInsertedNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > const & listener,
+ com::sun::star::container::ContainerEvent const & event);
+
+ void addContainerElementRemovedNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > const & listener,
+ com::sun::star::container::ContainerEvent const & event);
+
+ void addContainerElementReplacedNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > const & listener,
+ com::sun::star::container::ContainerEvent const & event);
+
+ void addPropertyChangeNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > const & listener,
+ com::sun::star::beans::PropertyChangeEvent const & event);
+
+ void addPropertiesChangeNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertiesChangeListener > const & listener,
+ com::sun::star::uno::Sequence<
+ com::sun::star::beans::PropertyChangeEvent > const & event);
+
+ void addChangesNotification(
+ com::sun::star::uno::Reference< com::sun::star::util::XChangesListener >
+ const & listener,
+ com::sun::star::util::ChangesEvent const & event);
+
+ void send();
+
+private:
+ struct DisposeNotification {
+ com::sun::star::uno::Reference< com::sun::star::lang::XEventListener >
+ listener;
+ com::sun::star::lang::EventObject event;
+
+ DisposeNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::lang::XEventListener > const & theListener,
+ com::sun::star::lang::EventObject const & theEvent);
+ };
+
+ struct ContainerNotification {
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > listener;
+ com::sun::star::container::ContainerEvent event;
+
+ ContainerNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::container::XContainerListener > const &
+ theListener,
+ com::sun::star::container::ContainerEvent const & theEvent);
+ };
+
+ struct PropertyChangeNotification {
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > listener;
+ com::sun::star::beans::PropertyChangeEvent event;
+
+ PropertyChangeNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertyChangeListener > const &
+ theListener,
+ com::sun::star::beans::PropertyChangeEvent const & theEvent);
+ };
+
+ struct PropertiesChangeNotification {
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertiesChangeListener > listener;
+ com::sun::star::uno::Sequence<
+ com::sun::star::beans::PropertyChangeEvent > event;
+
+ PropertiesChangeNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertiesChangeListener > const &
+ theListener,
+ com::sun::star::uno::Sequence<
+ com::sun::star::beans::PropertyChangeEvent > const & theEvent);
+ };
+
+ struct ChangesNotification {
+ com::sun::star::uno::Reference< com::sun::star::util::XChangesListener >
+ listener;
+ com::sun::star::util::ChangesEvent event;
+
+ ChangesNotification(
+ com::sun::star::uno::Reference<
+ com::sun::star::util::XChangesListener > const & theListener,
+ com::sun::star::util::ChangesEvent const & theEvent);
+ };
+
+ typedef std::vector< DisposeNotification > DisposeNotifications;
+
+ typedef std::vector< ContainerNotification > ContainerNotifications;
+
+ typedef std::vector< PropertyChangeNotification >
+ PropertyChangeNotifications;
+
+ typedef std::vector< PropertiesChangeNotification >
+ PropertiesChangeNotifications;
+
+ typedef std::vector< ChangesNotification > ChangesNotifications;
+
+ DisposeNotifications disposeNotifications_;
+ ContainerNotifications containerElementInsertedNotifications_;
+ ContainerNotifications containerElementRemovedNotifications_;
+ ContainerNotifications containerElementReplacedNotifications_;
+ PropertyChangeNotifications propertyChangeNotifications_;
+ PropertiesChangeNotifications propertiesChangeNotifications_;
+ ChangesNotifications changesNotifications_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/childaccess.cxx b/configmgr/source/childaccess.cxx
new file mode 100644
index 000000000000..ef2b213d4ef1
--- /dev/null
+++ b/configmgr/source/childaccess.cxx
@@ -0,0 +1,391 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <vector>
+
+#include "com/sun/star/container/XChild.hpp"
+#include "com/sun/star/lang/NoSupportException.hpp"
+#include "com/sun/star/lang/XUnoTunnel.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/Type.hxx"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppu/unotype.hxx"
+#include "cppuhelper/queryinterface.hxx"
+#include "cppuhelper/weak.hxx"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/string.h"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "rtl/uuid.h"
+#include "sal/types.h"
+
+#include "access.hxx"
+#include "childaccess.hxx"
+#include "components.hxx"
+#include "data.hxx"
+#include "groupnode.hxx"
+#include "localizedpropertynode.hxx"
+#include "localizedvaluenode.hxx"
+#include "lock.hxx"
+#include "modifications.hxx"
+#include "node.hxx"
+#include "path.hxx"
+#include "propertynode.hxx"
+#include "rootaccess.hxx"
+#include "setnode.hxx"
+#include "type.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+css::uno::Sequence< sal_Int8 > ChildAccess::getTunnelId() {
+ static css::uno::Sequence< sal_Int8 > id;
+ if (id.getLength() == 0) {
+ css::uno::Sequence< sal_Int8 > uuid(16);
+ rtl_createUuid(
+ reinterpret_cast< sal_uInt8 * >(uuid.getArray()), 0, false);
+ id = uuid;
+ }
+ return id;
+}
+
+ChildAccess::ChildAccess(
+ Components & components, rtl::Reference< RootAccess > const & root,
+ rtl::Reference< Access > const & parent, rtl::OUString const & name,
+ rtl::Reference< Node > const & node):
+ Access(components), root_(root), parent_(parent), name_(name), node_(node),
+ inTransaction_(false)
+{
+ OSL_ASSERT(root.is() && parent.is() && node.is());
+}
+
+ChildAccess::ChildAccess(
+ Components & components, rtl::Reference< RootAccess > const & root,
+ rtl::Reference< Node > const & node):
+ Access(components), root_(root), node_(node), inTransaction_(false)
+{
+ OSL_ASSERT(root.is() && node.is());
+}
+
+Path ChildAccess::getAbsolutePath() {
+ OSL_ASSERT(getParentAccess().is());
+ Path path(getParentAccess()->getAbsolutePath());
+ path.push_back(name_);
+ return path;
+}
+
+Path ChildAccess::getRelativePath() {
+ Path path;
+ rtl::Reference< Access > parent(getParentAccess());
+ if (parent.is()) {
+ path = parent->getRelativePath();
+ }
+ path.push_back(name_);
+ return path;
+}
+
+rtl::OUString ChildAccess::getRelativePathRepresentation() {
+ rtl::OUStringBuffer path;
+ rtl::Reference< Access > parent(getParentAccess());
+ if (parent.is()) {
+ path.append(parent->getRelativePathRepresentation());
+ if (path.getLength() != 0) {
+ path.append(sal_Unicode('/'));
+ }
+ }
+ path.append(Data::createSegment(node_->getTemplateName(), name_));
+ return path.makeStringAndClear();
+}
+
+rtl::Reference< Node > ChildAccess::getNode() {
+ return node_;
+}
+
+bool ChildAccess::isFinalized() {
+ return node_->getFinalized() != Data::NO_LAYER ||
+ (parent_.is() && parent_->isFinalized());
+}
+
+rtl::OUString ChildAccess::getNameInternal() {
+ return name_;
+}
+
+rtl::Reference< RootAccess > ChildAccess::getRootAccess() {
+ return root_;
+}
+
+rtl::Reference< Access > ChildAccess::getParentAccess() {
+ return parent_;
+}
+
+void ChildAccess::acquire() throw () {
+ Access::acquire();
+}
+
+void ChildAccess::release() throw () {
+ Access::release();
+}
+
+css::uno::Reference< css::uno::XInterface > ChildAccess::getParent()
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return static_cast< cppu::OWeakObject * >(parent_.get());
+}
+
+void ChildAccess::setParent(css::uno::Reference< css::uno::XInterface > const &)
+ throw (css::lang::NoSupportException, css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ throw css::lang::NoSupportException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("setParent")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Int64 ChildAccess::getSomething(
+ css::uno::Sequence< sal_Int8 > const & aIdentifier)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ return aIdentifier == getTunnelId()
+ ? reinterpret_cast< sal_Int64 >(this) : 0;
+}
+
+void ChildAccess::bind(
+ rtl::Reference< RootAccess > const & root,
+ rtl::Reference< Access > const & parent, rtl::OUString const & name)
+ throw ()
+{
+ OSL_ASSERT(
+ !parent_.is() && root.is() && parent.is() && name.getLength() != 0);
+ root_ = root;
+ parent_ = parent;
+ name_ = name;
+}
+
+void ChildAccess::unbind() throw () {
+ OSL_ASSERT(parent_.is());
+ parent_->releaseChild(name_);
+ parent_.clear();
+ inTransaction_ = true;
+}
+
+void ChildAccess::committed() {
+ inTransaction_ = false;
+}
+
+void ChildAccess::setNode(rtl::Reference< Node > const & node) {
+ node_ = node;
+}
+
+void ChildAccess::setProperty(
+ css::uno::Any const & value, Modifications * localModifications)
+{
+ OSL_ASSERT(localModifications != 0);
+ Type type = TYPE_ERROR;
+ bool nillable = false;
+ switch (node_->kind()) {
+ case Node::KIND_PROPERTY:
+ {
+ PropertyNode * prop = dynamic_cast< PropertyNode * >(node_.get());
+ type = prop->getStaticType();
+ nillable = prop->isNillable();
+ }
+ break;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ {
+ rtl::OUString locale(getRootAccess()->getLocale());
+ if (!Components::allLocales(locale)) {
+ rtl::Reference< ChildAccess > child(getChild(locale));
+ if (child.is()) {
+ child->setProperty(value, localModifications);
+ } else {
+ insertLocalizedValueChild(
+ locale, value, localModifications);
+ }
+ return;
+ }
+ }
+ break;
+ case Node::KIND_LOCALIZED_VALUE:
+ {
+ LocalizedPropertyNode * locprop =
+ dynamic_cast< LocalizedPropertyNode * >(getParentNode().get());
+ type = locprop->getStaticType();
+ nillable = locprop->isNillable();
+ }
+ break;
+ default:
+ break;
+ }
+ checkValue(value, type, nillable);
+ getParentAccess()->markChildAsModified(this);
+ changedValue_.reset(new css::uno::Any(value));
+ localModifications->add(getRelativePath());
+}
+
+css::uno::Any ChildAccess::asValue() {
+ if (changedValue_.get() != 0) {
+ return *changedValue_;
+ }
+ switch (node_->kind()) {
+ case Node::KIND_PROPERTY:
+ return dynamic_cast< PropertyNode * >(node_.get())->getValue(
+ getComponents());
+ case Node::KIND_LOCALIZED_PROPERTY:
+ {
+ rtl::OUString locale(getRootAccess()->getLocale());
+ if (!Components::allLocales(locale)) {
+ // Find best match using an adaption of RFC 4647 lookup matching
+ // rules, removing "-" or "_" delimited segments from the end;
+ // defaults are the empty string locale, the "en-US" locale, the
+ // first child (if any), or a nil value (even though it may be
+ // illegal for the given property), in that order:
+ rtl::Reference< ChildAccess > child;
+ for (;;) {
+ child = getChild(locale);
+ if (child.is() || locale.getLength() == 0) {
+ break;
+ }
+ sal_Int32 i = locale.getLength() - 1;
+ while (i > 0 && locale[i] != '-' && locale[i] != '_') {
+ --i;
+ }
+ locale = locale.copy(0, i);
+ }
+ if (!child.is()) {
+ child = getChild(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US")));
+ if (!child.is()) {
+ std::vector< rtl::Reference< ChildAccess > > all(
+ getAllChildren());
+ if (!all.empty()) {
+ child = all.front();
+ }
+ }
+ }
+ return child.is() ? child->asValue() : css::uno::Any();
+ }
+ }
+ break;
+ case Node::KIND_LOCALIZED_VALUE:
+ return dynamic_cast< LocalizedValueNode * >(node_.get())->getValue();
+ default:
+ break;
+ }
+ return css::uno::makeAny(
+ css::uno::Reference< css::uno::XInterface >(
+ static_cast< cppu::OWeakObject * >(this)));
+}
+
+void ChildAccess::commitChanges(bool valid, Modifications * globalModifications)
+{
+ OSL_ASSERT(globalModifications != 0);
+ commitChildChanges(valid, globalModifications);
+ if (valid && changedValue_.get() != 0) {
+ Path path(getAbsolutePath());
+ getComponents().addModification(path);
+ globalModifications->add(path);
+ switch (node_->kind()) {
+ case Node::KIND_PROPERTY:
+ dynamic_cast< PropertyNode * >(node_.get())->setValue(
+ Data::NO_LAYER, *changedValue_);
+ break;
+ case Node::KIND_LOCALIZED_VALUE:
+ dynamic_cast< LocalizedValueNode * >(node_.get())->setValue(
+ Data::NO_LAYER, *changedValue_);
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ }
+ changedValue_.reset();
+}
+
+ChildAccess::~ChildAccess() {
+ osl::MutexGuard g(lock);
+ if (parent_.is()) {
+ parent_->releaseChild(name_);
+ }
+}
+
+void ChildAccess::addTypes(std::vector< css::uno::Type > * types) const {
+ OSL_ASSERT(types != 0);
+ types->push_back(cppu::UnoType< css::container::XChild >::get());
+ types->push_back(cppu::UnoType< css::lang::XUnoTunnel >::get());
+}
+
+void ChildAccess::addSupportedServiceNames(
+ std::vector< rtl::OUString > * services)
+{
+ OSL_ASSERT(services != 0);
+ services->push_back(
+ getParentNode()->kind() == Node::KIND_GROUP
+ ? rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.GroupElement"))
+ : rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.SetElement")));
+}
+
+css::uno::Any ChildAccess::queryInterface(css::uno::Type const & aType)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ css::uno::Any res(Access::queryInterface(aType));
+ return res.hasValue()
+ ? res
+ : cppu::queryInterface(
+ aType, static_cast< css::container::XChild * >(this),
+ static_cast< css::lang::XUnoTunnel * >(this));
+}
+
+}
diff --git a/configmgr/source/childaccess.hxx b/configmgr/source/childaccess.hxx
new file mode 100644
index 000000000000..c1cb14896978
--- /dev/null
+++ b/configmgr/source/childaccess.hxx
@@ -0,0 +1,157 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_CHILDACCESS_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_CHILDACCESS_HXX
+
+#include "sal/config.h"
+
+#include <memory>
+#include <vector>
+
+#include "com/sun/star/container/XChild.hpp"
+#include "com/sun/star/lang/NoSupportException.hpp"
+#include "com/sun/star/lang/XUnoTunnel.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "rtl/ref.hxx"
+#include "sal/types.h"
+
+#include "access.hxx"
+#include "path.hxx"
+
+namespace com { namespace sun { namespace star { namespace uno {
+ class Any;
+ class Type;
+ class XInterface;
+} } } }
+
+namespace configmgr {
+
+class Components;
+class Modifications;
+class Node;
+class RootAccess;
+
+class ChildAccess:
+ public Access, public com::sun::star::container::XChild,
+ public com::sun::star::lang::XUnoTunnel
+{
+public:
+ static com::sun::star::uno::Sequence< sal_Int8 > getTunnelId();
+
+ ChildAccess(
+ Components & components, rtl::Reference< RootAccess > const & root,
+ rtl::Reference< Access > const & parent, rtl::OUString const & name,
+ rtl::Reference< Node > const & node);
+
+ ChildAccess(
+ Components & components, rtl::Reference< RootAccess > const & root,
+ rtl::Reference< Node > const & node);
+
+ virtual Path getAbsolutePath();
+
+ virtual Path getRelativePath();
+
+ virtual rtl::OUString getRelativePathRepresentation();
+
+ virtual rtl::Reference< Node > getNode();
+
+ virtual bool isFinalized();
+
+ virtual rtl::OUString getNameInternal();
+
+ virtual rtl::Reference< RootAccess > getRootAccess();
+
+ virtual rtl::Reference< Access > getParentAccess();
+
+ virtual void SAL_CALL acquire() throw ();
+
+ virtual void SAL_CALL release() throw ();
+
+ virtual com::sun::star::uno::Reference< com::sun::star::uno::XInterface >
+ SAL_CALL getParent()
+ throw (com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL setParent(
+ com::sun::star::uno::Reference< com::sun::star::uno::XInterface >
+ const &)
+ throw (
+ com::sun::star::lang::NoSupportException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual sal_Int64 SAL_CALL getSomething(
+ com::sun::star::uno::Sequence< sal_Int8 > const & aIdentifier)
+ throw (com::sun::star::uno::RuntimeException);
+
+ void bind(
+ rtl::Reference< RootAccess > const & root,
+ rtl::Reference< Access > const & parent, rtl::OUString const & name)
+ throw ();
+
+ void unbind() throw ();
+
+ bool isInTransaction() const { return inTransaction_; }
+
+ void committed();
+
+ void setNode(rtl::Reference< Node > const & node);
+
+ void setProperty(
+ com::sun::star::uno::Any const & value,
+ Modifications * localModifications);
+
+ com::sun::star::uno::Any asValue();
+
+ void commitChanges(bool valid, Modifications * globalModifications);
+
+private:
+ virtual ~ChildAccess();
+
+ virtual void addTypes(
+ std::vector< com::sun::star::uno::Type > * types) const;
+
+ virtual void addSupportedServiceNames(
+ std::vector< rtl::OUString > * services);
+
+ virtual com::sun::star::uno::Any SAL_CALL queryInterface(
+ com::sun::star::uno::Type const & aType)
+ throw (com::sun::star::uno::RuntimeException);
+
+ rtl::Reference< RootAccess > root_;
+ rtl::Reference< Access > parent_; // null iff free node
+ rtl::OUString name_;
+ rtl::Reference< Node > node_;
+ std::auto_ptr< com::sun::star::uno::Any > changedValue_;
+ bool inTransaction_;
+ // to determine if a free node can be inserted underneath some root
+};
+
+}
+
+#endif
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx
new file mode 100644
index 000000000000..6d97971e1a2c
--- /dev/null
+++ b/configmgr/source/components.cxx
@@ -0,0 +1,673 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+#include <list>
+
+#include "com/sun/star/beans/Optional.hpp"
+#include "com/sun/star/beans/UnknownPropertyException.hpp"
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/container/NoSuchElementException.hpp"
+#include "com/sun/star/lang/WrappedTargetException.hpp"
+#include "com/sun/star/lang/XMultiComponentFactory.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/file.hxx"
+#include "rtl/bootstrap.hxx"
+#include "rtl/logfile.h"
+#include "rtl/ref.hxx"
+#include "rtl/string.h"
+#include "rtl/textenc.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "components.hxx"
+#include "data.hxx"
+#include "modifications.hxx"
+#include "node.hxx"
+#include "parsemanager.hxx"
+#include "partial.hxx"
+#include "rootaccess.hxx"
+#include "writemodfile.hxx"
+#include "xcdparser.hxx"
+#include "xcuparser.hxx"
+#include "xcsparser.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+struct UnresolvedListItem {
+ rtl::OUString name;
+ rtl::Reference< ParseManager > manager;
+
+ UnresolvedListItem(
+ rtl::OUString const & theName,
+ rtl::Reference< ParseManager > theManager):
+ name(theName), manager(theManager) {}
+};
+
+typedef std::list< UnresolvedListItem > UnresolvedList;
+
+void parseXcsFile(
+ rtl::OUString const & url, int layer, Data & data, Partial const * partial,
+ Modifications * modifications)
+ SAL_THROW((
+ css::container::NoSuchElementException, css::uno::RuntimeException))
+{
+ OSL_ASSERT(partial == 0 && modifications == 0);
+ (void) partial; (void) modifications;
+ OSL_VERIFY(
+ rtl::Reference< ParseManager >(
+ new ParseManager(url, new XcsParser(layer, data)))->parse());
+}
+
+void parseXcuFile(
+ rtl::OUString const & url, int layer, Data & data, Partial const * partial,
+ Modifications * modifications)
+ SAL_THROW((
+ css::container::NoSuchElementException, css::uno::RuntimeException))
+{
+ OSL_VERIFY(
+ rtl::Reference< ParseManager >(
+ new ParseManager(
+ url, new XcuParser(layer, data, partial, modifications)))->
+ parse());
+}
+
+rtl::OUString expand(rtl::OUString const & str) {
+ rtl::OUString s(str);
+ rtl::Bootstrap::expandMacros(s); //TODO: detect failure
+ return s;
+}
+
+static bool singletonCreated = false;
+static Components * singleton = 0;
+
+}
+
+void Components::initSingleton(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+{
+ OSL_ASSERT(context.is());
+ if (!singletonCreated) {
+ singletonCreated = true;
+ static Components theSingleton(context);
+ singleton = &theSingleton;
+ }
+}
+
+Components & Components::getSingleton() {
+ OSL_ASSERT(singletonCreated);
+ if (singleton == 0) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "configmgr no Components singleton")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return *singleton;
+}
+
+bool Components::allLocales(rtl::OUString const & locale) {
+ return locale.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("*"));
+}
+
+rtl::Reference< Node > Components::resolvePathRepresentation(
+ rtl::OUString const & pathRepresentation, Path * path,
+ int * finalizedLayer) const
+{
+ return data_.resolvePathRepresentation(
+ pathRepresentation, path, finalizedLayer);
+}
+
+rtl::Reference< Node > Components::getTemplate(
+ int layer, rtl::OUString const & fullName) const
+{
+ return data_.getTemplate(layer, fullName);
+}
+
+void Components::addRootAccess(rtl::Reference< RootAccess > const & access) {
+ roots_.insert(access.get());
+}
+
+void Components::removeRootAccess(RootAccess * access) {
+ roots_.erase(access);
+}
+
+void Components::initGlobalBroadcaster(
+ Modifications const & modifications,
+ rtl::Reference< RootAccess > const & exclude, Broadcaster * broadcaster)
+{
+ //TODO: Iterate only over roots w/ listeners:
+ for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) {
+ rtl::Reference< RootAccess > root;
+ if ((*i)->acquireCounting() > 1) {
+ root.set(*i); // must not throw
+ }
+ (*i)->releaseNondeleting();
+ if (root.is()) {
+ if (root != exclude) {
+ Path path(root->getAbsolutePath());
+ Modifications::Node const * mods = &modifications.getRoot();
+ for (Path::iterator j(path.begin()); j != path.end(); ++j) {
+ Modifications::Node::Children::const_iterator k(
+ mods->children.find(*j));
+ if (k == mods->children.end()) {
+ mods = 0;
+ break;
+ }
+ mods = &k->second;
+ }
+ //TODO: If the complete tree of which root is a part is deleted,
+ // or replaced, mods will be null, but some of the listeners
+ // from within root should probably fire nonetheless:
+ if (mods != 0) {
+ root->initBroadcaster(*mods, broadcaster);
+ }
+ }
+ }
+ }
+}
+
+void Components::addModification(Path const & path) {
+ data_.modifications.add(path);
+}
+
+void Components::writeModifications() {
+ writeModFile(*this, getModificationFileUrl(), data_);
+}
+
+void Components::insertExtensionXcsFile(
+ bool shared, rtl::OUString const & fileUri)
+{
+ try {
+ parseXcsFile(fileUri, shared ? 9 : 13, data_, 0, 0);
+ } catch (css::container::NoSuchElementException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "insertExtensionXcsFile does not exist: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void Components::insertExtensionXcuFile(
+ bool shared, rtl::OUString const & fileUri, Modifications * modifications)
+{
+ OSL_ASSERT(modifications != 0);
+ try {
+ parseXcuFile(fileUri, shared ? 10 : 14, data_, 0, modifications);
+ } catch (css::container::NoSuchElementException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "insertExtensionXcuFile does not exist: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void Components::insertModificationXcuFile(
+ rtl::OUString const & fileUri,
+ std::set< rtl::OUString > const & includedPaths,
+ std::set< rtl::OUString > const & excludedPaths,
+ Modifications * modifications)
+{
+ OSL_ASSERT(modifications != 0);
+ try {
+ Partial part(includedPaths, excludedPaths);
+ parseXcuFile(fileUri, Data::NO_LAYER, data_, &part, modifications);
+ } catch (css::uno::Exception & e) { //TODO: more specific exception catching
+ OSL_TRACE(
+ "configmgr error inserting %s: %s",
+ rtl::OUStringToOString(fileUri, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ }
+}
+
+css::beans::Optional< css::uno::Any > Components::getExternalValue(
+ rtl::OUString const & descriptor)
+{
+ sal_Int32 i = descriptor.indexOf(' ');
+ if (i <= 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad external value descriptor ")) +
+ descriptor),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ //TODO: Do not make calls with mutex locked:
+ rtl::OUString name(descriptor.copy(0, i));
+ ExternalServices::iterator j(externalServices_.find(name));
+ if (j == externalServices_.end()) {
+ css::uno::Reference< css::uno::XInterface > service;
+ try {
+ service = css::uno::Reference< css::lang::XMultiComponentFactory >(
+ context_->getServiceManager(), css::uno::UNO_SET_THROW)->
+ createInstanceWithContext(name, context_);
+ } catch (css::uno::RuntimeException &) {
+ // Assuming these exceptions are real errors:
+ throw;
+ } catch (css::uno::Exception & e) {
+ // Assuming these exceptions indicate that the service is not
+ // installed:
+ OSL_TRACE(
+ "createInstance(%s) failed with %s",
+ rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(
+ e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ css::uno::Reference< css::beans::XPropertySet > propset;
+ if (service.is()) {
+ propset = css::uno::Reference< css::beans::XPropertySet >(
+ service, css::uno::UNO_QUERY_THROW);
+ }
+ j = externalServices_.insert(
+ ExternalServices::value_type(name, propset)).first;
+ }
+ css::beans::Optional< css::uno::Any > value;
+ if (j->second.is()) {
+ try {
+ if (!(j->second->getPropertyValue(descriptor.copy(i + 1)) >>=
+ value))
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "cannot obtain external value through ")) +
+ descriptor),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } catch (css::beans::UnknownPropertyException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "unknwon external value descriptor ID: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >());
+ } catch (css::lang::WrappedTargetException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "cannot obtain external value: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ return value;
+}
+
+Components::Components(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ context_(context)
+{
+ OSL_ASSERT(context.is());
+ RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "begin parsing");
+ parseXcsXcuLayer(
+ 0,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))));
+ parseModuleLayer(
+ 2,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "$OOO_BASE_DIR/share/registry/modules"))));
+ parseResLayer(
+ 3,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))));
+ parseXcsXcuLayer(
+ 4,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "$BRAND_BASE_DIR/share/registry"))));
+ parseModuleLayer(
+ 6,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "$BRAND_BASE_DIR/share/registry/modules"))));
+ parseXcsXcuLayer( //TODO: migrate
+ 7,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
+ ":UNO_SHARED_PACKAGES_CACHE}/registry/"
+ "com.sun.star.comp.deployment.configuration."
+ "PackageRegistryBackend/registry"))));
+ parseXcsXcuIniLayer(
+ 9,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
+ ":UNO_SHARED_PACKAGES_CACHE}/registry/"
+ "com.sun.star.comp.deployment.configuration."
+ "PackageRegistryBackend/configmgr.ini"))));
+ parseXcsXcuLayer( //TODO: migrate
+ 11,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
+ ":UNO_USER_PACKAGES_CACHE}/registry/"
+ "com.sun.star.comp.deployment.configuration."
+ "PackageRegistryBackend/registry"))));
+ parseXcsXcuIniLayer(
+ 13,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
+ ":UNO_USER_PACKAGES_CACHE}/registry/"
+ "com.sun.star.comp.deployment.configuration."
+ "PackageRegistryBackend/configmgr.ini"))));
+ try {
+ parseModificationLayer();
+ } catch (css::uno::Exception & e) { //TODO: more specific exception catching
+ // Silently ignore unreadable parts of a corrupted user modification
+ // layer, instead of completely preventing OOo from starting:
+ OSL_TRACE(
+ "configmgr error reading user modification layer: %s",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "end parsing");
+}
+
+Components::~Components() {}
+
+void Components::parseFiles(
+ int layer, rtl::OUString const & extension, FileParser * parseFile,
+ rtl::OUString const & url, bool recursive)
+{
+ osl::Directory dir(url);
+ switch (dir.open()) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ if (!recursive) {
+ return;
+ }
+ // fall through
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
+ url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ for (;;) {
+ osl::DirectoryItem i;
+ osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
+ if (rc == osl::FileBase::E_NOENT) {
+ break;
+ }
+ if (rc != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
+ url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ osl::FileStatus stat(
+ FileStatusMask_Type | FileStatusMask_FileName |
+ FileStatusMask_FileURL);
+ if (i.getFileStatus(stat) != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
+ url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (stat.getFileType() == osl::FileStatus::Directory) { //TODO: symlinks
+ parseFiles(layer, extension, parseFile, stat.getFileURL(), true);
+ } else {
+ rtl::OUString file(stat.getFileName());
+ if (file.getLength() >= extension.getLength() &&
+ file.match(extension, file.getLength() - extension.getLength()))
+ {
+ try {
+ (*parseFile)(stat.getFileURL(), layer, data_, 0, 0);
+ } catch (css::container::NoSuchElementException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "stat'ed file does not exist: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ }
+ }
+}
+
+void Components::parseFileList(
+ int layer, FileParser * parseFile, rtl::OUString const & urls,
+ rtl::Bootstrap const & ini)
+{
+ for (sal_Int32 i = 0;;) {
+ rtl::OUString url(urls.getToken(0, ' ', i));
+ if (url.getLength() != 0) {
+ ini.expandMacrosFrom(url); //TODO: detect failure
+ try {
+ (*parseFile)(url, layer, data_, 0, 0);
+ } catch (css::container::NoSuchElementException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "stat'ed file does not exist: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ if (i == -1) {
+ break;
+ }
+ }
+}
+
+void Components::parseXcdFiles(int layer, rtl::OUString const & url) {
+ osl::Directory dir(url);
+ switch (dir.open()) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ return;
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
+ url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ UnresolvedList unres;
+ XcdParser::Dependencies deps;
+ for (;;) {
+ osl::DirectoryItem i;
+ osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
+ if (rc == osl::FileBase::E_NOENT) {
+ break;
+ }
+ if (rc != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
+ url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ osl::FileStatus stat(
+ FileStatusMask_Type | FileStatusMask_FileName |
+ FileStatusMask_FileURL);
+ if (i.getFileStatus(stat) != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
+ url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (stat.getFileType() != osl::FileStatus::Directory) { //TODO: symlinks
+ rtl::OUString file(stat.getFileName());
+ if (file.getLength() >= RTL_CONSTASCII_LENGTH(".xcd") &&
+ file.matchAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(".xcd"),
+ file.getLength() - RTL_CONSTASCII_LENGTH(".xcd")))
+ {
+ rtl::OUString name(
+ file.copy(
+ 0, file.getLength() - RTL_CONSTASCII_LENGTH(".xcd")));
+ rtl::Reference< ParseManager > manager;
+ try {
+ manager = new ParseManager(
+ stat.getFileURL(), new XcdParser(layer, deps, data_));
+ } catch (css::container::NoSuchElementException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "stat'ed file does not exist: ")) +
+ e.Message),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (manager->parse()) {
+ deps.insert(name);
+ } else {
+ unres.push_back(UnresolvedListItem(name, manager));
+ }
+ }
+ }
+ }
+ while (!unres.empty()) {
+ bool resolved = false;
+ for (UnresolvedList::iterator i(unres.begin()); i != unres.end();) {
+ if (i->manager->parse()) {
+ deps.insert(i->name);
+ unres.erase(i++);
+ resolved = true;
+ } else {
+ ++i;
+ }
+ }
+ if (!resolved) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "xcd: unresolved dependencies in ")) +
+ url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+}
+
+void Components::parseXcsXcuLayer(int layer, rtl::OUString const & url) {
+ parseXcdFiles(layer, url);
+ parseFiles(
+ layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcs")),
+ &parseXcsFile,
+ url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/schema")), false);
+ parseFiles(
+ layer + 1, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
+ &parseXcuFile,
+ url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/data")), false);
+}
+
+void Components::parseXcsXcuIniLayer(int layer, rtl::OUString const & url) {
+ //TODO: rtl::Bootstrap::getFrom "first trie[s] to retrieve the value via the
+ // global function"
+ rtl::Bootstrap ini(url);
+ rtl::OUString urls;
+ if (ini.getFrom(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SCHEMA")), urls))
+ {
+ parseFileList(layer, &parseXcsFile, urls, ini);
+ }
+ if (ini.getFrom(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DATA")), urls))
+ {
+ parseFileList(layer + 1, &parseXcuFile, urls, ini);
+ }
+}
+
+void Components::parseModuleLayer(int layer, rtl::OUString const & url) {
+ parseFiles(
+ layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
+ &parseXcuFile, url, false);
+}
+
+void Components::parseResLayer(int layer, rtl::OUString const & url) {
+ rtl::OUString resUrl(
+ url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/res")));
+ parseXcdFiles(layer, resUrl);
+ parseFiles(
+ layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
+ &parseXcuFile, resUrl, false);
+}
+
+rtl::OUString Components::getModificationFileUrl() const {
+ return expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
+ ":UserInstallation}/user/registrymodifications.xcu")));
+}
+
+void Components::parseModificationLayer() {
+ try {
+ parseXcuFile(getModificationFileUrl(), Data::NO_LAYER, data_, 0, 0);
+ } catch (css::container::NoSuchElementException &) {
+ OSL_TRACE(
+ "configmgr user registrymodifications.xcu does not (yet) exist");
+ // Migrate old user layer data (can be removed once migration is no
+ // longer relevant; also see hack for xsi namespace in XmlReader
+ // constructor):
+ parseFiles(
+ Data::NO_LAYER, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
+ &parseXcuFile,
+ expand(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
+ ":UserInstallation}/user/registry/data"))),
+ false);
+ }
+}
+
+}
diff --git a/configmgr/source/components.hxx b/configmgr/source/components.hxx
new file mode 100644
index 000000000000..a78ed325969d
--- /dev/null
+++ b/configmgr/source/components.hxx
@@ -0,0 +1,159 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_COMPONENTS_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_COMPONENTS_HXX
+
+#include "sal/config.h"
+
+#include <map>
+#include <set>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/beans/Optional.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "rtl/ref.hxx"
+
+#include "data.hxx"
+#include "path.hxx"
+
+namespace com { namespace sun { namespace star {
+ namespace beans { class XPropertySet; }
+ namespace uno {
+ class Any;
+ class XComponentContext;
+ }
+} } }
+namespace rtl {
+ class Bootstrap;
+ class OUString;
+}
+
+namespace configmgr {
+
+class Broadcaster;
+class Modifications;
+class Node;
+class Partial;
+class RootAccess;
+
+class Components: private boost::noncopyable {
+public:
+ static void initSingleton(
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ const & context);
+
+ static Components & getSingleton();
+
+ static bool allLocales(rtl::OUString const & locale);
+
+ rtl::Reference< Node > resolvePathRepresentation(
+ rtl::OUString const & pathRepresentation, Path * path,
+ int * finalizedLayer) const;
+
+ rtl::Reference< Node > getTemplate(
+ int layer, rtl::OUString const & fullName) const;
+
+ void addRootAccess(rtl::Reference< RootAccess > const & access);
+
+ void removeRootAccess(RootAccess * access);
+
+ void initGlobalBroadcaster(
+ Modifications const & modifications,
+ rtl::Reference< RootAccess > const & exclude,
+ Broadcaster * broadcaster);
+
+ void addModification(Path const & path);
+
+ void writeModifications();
+
+ void insertExtensionXcsFile(bool shared, rtl::OUString const & fileUri);
+
+ void insertExtensionXcuFile(
+ bool shared, rtl::OUString const & fileUri,
+ Modifications * modifications);
+
+ void insertModificationXcuFile(
+ rtl::OUString const & fileUri,
+ std::set< rtl::OUString > const & includedPaths,
+ std::set< rtl::OUString > const & excludedPaths,
+ Modifications * modifications);
+
+ com::sun::star::beans::Optional< com::sun::star::uno::Any >
+ getExternalValue(rtl::OUString const & descriptor);
+
+private:
+ typedef void FileParser(
+ rtl::OUString const &, int, Data &, Partial const *, Modifications *);
+
+ Components(
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ const & context);
+
+ ~Components();
+
+ void parseFiles(
+ int layer, rtl::OUString const & extension, FileParser * parseFile,
+ rtl::OUString const & url, bool recursive);
+
+ void parseFileList(
+ int layer, FileParser * parseFile, rtl::OUString const & urls,
+ rtl::Bootstrap const & ini);
+
+ void parseXcdFiles(int layer, rtl::OUString const & url);
+
+ void parseXcsXcuLayer(int layer, rtl::OUString const & url);
+
+ void parseXcsXcuIniLayer(int layer, rtl::OUString const & url);
+
+ void parseModuleLayer(int layer, rtl::OUString const & url);
+
+ void parseResLayer(int layer, rtl::OUString const & url);
+
+ rtl::OUString getModificationFileUrl() const;
+
+ void parseModificationLayer();
+
+ typedef std::set< RootAccess * > WeakRootSet;
+
+ typedef
+ std::map<
+ rtl::OUString,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertySet > >
+ ExternalServices;
+
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ context_;
+ Data data_;
+ WeakRootSet roots_;
+ ExternalServices externalServices_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/configurationprovider.cxx b/configmgr/source/configurationprovider.cxx
new file mode 100644
index 000000000000..a89540a88158
--- /dev/null
+++ b/configmgr/source/configurationprovider.cxx
@@ -0,0 +1,519 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/beans/NamedValue.hpp"
+#include "com/sun/star/beans/PropertyValue.hpp"
+#include "com/sun/star/lang/EventObject.hpp"
+#include "com/sun/star/lang/Locale.hpp"
+#include "com/sun/star/lang/XLocalizable.hpp"
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/lang/XSingleComponentFactory.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/DeploymentException.hpp"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "com/sun/star/util/XFlushListener.hpp"
+#include "com/sun/star/util/XFlushable.hpp"
+#include "com/sun/star/util/XRefreshListener.hpp"
+#include "com/sun/star/util/XRefreshable.hpp"
+#include "comphelper/locale.hxx"
+#include "cppu/unotype.hxx"
+#include "cppuhelper/compbase5.hxx"
+#include "cppuhelper/factory.hxx"
+#include "cppuhelper/implbase1.hxx"
+#include "cppuhelper/interfacecontainer.hxx"
+#include "cppuhelper/weak.hxx"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+#include "sal/types.h"
+#include "rtl/ref.hxx"
+#include "rtl/unload.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "components.hxx"
+#include "configurationprovider.hxx"
+#include "lock.hxx"
+#include "rootaccess.hxx"
+
+namespace configmgr { namespace configuration_provider {
+
+namespace {
+
+namespace css = com::sun::star;
+
+char const accessServiceName[] =
+ "com.sun.star.configuration.ConfigurationAccess";
+char const updateAccessServiceName[] =
+ "com.sun.star.configuration.ConfigurationUpdateAccess";
+
+void badNodePath() {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider expects a"
+ " single, non-empty, string nodepath argument")),
+ 0);
+}
+
+typedef
+ cppu::WeakComponentImplHelper5<
+ css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
+ css::util::XRefreshable, css::util::XFlushable,
+ css::lang::XLocalizable >
+ ServiceBase;
+
+class Service:
+ private osl::Mutex, public ServiceBase, private boost::noncopyable
+{
+public:
+ Service(
+ css::uno::Reference< css::uno::XComponentContext > const context,
+ rtl::OUString const & locale):
+ ServiceBase(*static_cast< osl::Mutex * >(this)), context_(context),
+ locale_(locale)
+ {
+ OSL_ASSERT(context.is());
+ }
+
+private:
+ virtual ~Service() {}
+
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (css::uno::RuntimeException)
+ { return configuration_provider::getImplementationName(); }
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
+ throw (css::uno::RuntimeException)
+ { return ServiceName == getSupportedServiceNames()[0]; } //TODO
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL
+ getSupportedServiceNames() throw (css::uno::RuntimeException)
+ { return configuration_provider::getSupportedServiceNames(); }
+ //TODO: DefaultProvider?
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
+ rtl::OUString const & aServiceSpecifier)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArguments(
+ rtl::OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL
+ getAvailableServiceNames() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL refresh() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL addRefreshListener(
+ css::uno::Reference< css::util::XRefreshListener > const & l)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL removeRefreshListener(
+ css::uno::Reference< css::util::XRefreshListener > const & l)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL flush() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL addFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const & l)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL removeFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const & l)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setLocale(css::lang::Locale const & eLocale)
+ throw (css::uno::RuntimeException);
+
+ virtual css::lang::Locale SAL_CALL getLocale()
+ throw (css::uno::RuntimeException);
+
+ css::uno::Reference< css::uno::XComponentContext > context_;
+ rtl::OUString locale_;
+};
+
+css::uno::Reference< css::uno::XInterface > Service::createInstance(
+ rtl::OUString const & aServiceSpecifier)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ return createInstanceWithArguments(
+ aServiceSpecifier, css::uno::Sequence< css::uno::Any >());
+}
+
+css::uno::Reference< css::uno::XInterface >
+Service::createInstanceWithArguments(
+ rtl::OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ rtl::OUString nodepath;
+ rtl::OUString locale;
+ for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
+ css::beans::NamedValue v1;
+ css::beans::PropertyValue v2;
+ rtl::OUString name;
+ css::uno::Any value;
+ if (Arguments[i] >>= v1) {
+ name = v1.Name;
+ value = v1.Value;
+ } else if (Arguments[i] >>= v2) {
+ name = v2.Name;
+ value = v2.Value;
+ } else if (Arguments.getLength() == 1 && (Arguments[i] >>= nodepath)) {
+ // For backwards compatibility, allow a single string argument that
+ // denotes nodepath.
+ if (nodepath.getLength() == 0) {
+ badNodePath();
+ }
+ break;
+ } else {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider"
+ " expects NamedValue or PropertyValue arguments")),
+ 0);
+ }
+ // For backwards compatibility, allow "nodepath" and "Locale" in any
+ // case:
+ if (name.equalsIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("nodepath")))
+ {
+ if (nodepath.getLength() != 0 || !(value >>= nodepath) ||
+ nodepath.getLength() == 0)
+ {
+ badNodePath();
+ }
+ } else if (name.equalsIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("locale")))
+ {
+ if (locale.getLength() != 0 || !(value >>= locale) ||
+ locale.getLength() == 0)
+ {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider"
+ " expects at most one, non-empty, string Locale"
+ " argument")),
+ 0);
+ }
+ }
+ }
+ if (nodepath.getLength() == 0) {
+ badNodePath();
+ }
+ // For backwards compatibility, allow a notepath that misses the leading
+ // slash:
+ if (nodepath[0] != '/') {
+ nodepath = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + nodepath;
+ }
+ if (locale.getLength() == 0) {
+ //TODO: should the Access use the dynamically changing locale_ instead?
+ locale = locale_;
+ if (locale.getLength() == 0) {
+ locale = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US"));
+ }
+ }
+ bool update;
+ if (ServiceSpecifier.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(accessServiceName)))
+ {
+ update = false;
+ } else if (ServiceSpecifier.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(updateAccessServiceName)))
+ {
+ update = true;
+ } else {
+ throw css::uno::Exception(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider does not"
+ " support service ")) +
+ ServiceSpecifier),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ osl::MutexGuard guard(lock);
+ Components::initSingleton(context_);
+ Components & components = Components::getSingleton();
+ rtl::Reference< RootAccess > root(
+ new RootAccess(components, nodepath, locale, update));
+ if (root->isValue()) {
+ throw css::uno::Exception(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider: there is"
+ " a leaf value at nodepath ")) +
+ nodepath),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ components.addRootAccess(root);
+ return static_cast< cppu::OWeakObject * >(root.get());
+}
+
+css::uno::Sequence< rtl::OUString > Service::getAvailableServiceNames()
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< rtl::OUString > names(2);
+ names[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(accessServiceName));
+ names[1] = rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(updateAccessServiceName));
+ return names;
+}
+
+void Service::refresh() throw (css::uno::RuntimeException) {
+ //TODO
+ cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
+ cppu::UnoType< css::util::XRefreshListener >::get());
+ if (cont != 0) {
+ css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
+ cont->notifyEach(&css::util::XRefreshListener::refreshed, ev);
+ }
+}
+
+void Service::addRefreshListener(
+ css::uno::Reference< css::util::XRefreshListener > const & l)
+ throw (css::uno::RuntimeException)
+{
+ rBHelper.addListener(
+ cppu::UnoType< css::util::XRefreshListener >::get(), l);
+}
+
+void Service::removeRefreshListener(
+ css::uno::Reference< css::util::XRefreshListener > const & l)
+ throw (css::uno::RuntimeException)
+{
+ rBHelper.removeListener(
+ cppu::UnoType< css::util::XRefreshListener >::get(), l);
+}
+
+void Service::flush() throw (css::uno::RuntimeException) {
+ //TODO
+ cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
+ cppu::UnoType< css::util::XFlushListener >::get());
+ if (cont != 0) {
+ css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
+ cont->notifyEach(&css::util::XFlushListener::flushed, ev);
+ }
+}
+
+void Service::addFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const & l)
+ throw (css::uno::RuntimeException)
+{
+ rBHelper.addListener(cppu::UnoType< css::util::XFlushListener >::get(), l);
+}
+
+void Service::removeFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const & l)
+ throw (css::uno::RuntimeException)
+{
+ rBHelper.removeListener(
+ cppu::UnoType< css::util::XFlushListener >::get(), l);
+}
+
+void Service::setLocale(css::lang::Locale const & eLocale)
+ throw (css::uno::RuntimeException)
+{
+ osl::MutexGuard guard(lock);
+ locale_ = comphelper::Locale(
+ eLocale.Language, eLocale.Country, eLocale.Variant).toISO();
+}
+
+css::lang::Locale Service::getLocale() throw (css::uno::RuntimeException) {
+ osl::MutexGuard guard(lock);
+ css::lang::Locale loc;
+ if (locale_.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("*"))) {
+ loc.Language = locale_;
+ } else if (locale_.getLength() != 0) {
+ try {
+ comphelper::Locale l(locale_);
+ loc.Language = l.getLanguage();
+ loc.Country = l.getCountry();
+ loc.Variant = l.getVariant();
+ } catch (comphelper::Locale::MalFormedLocaleException & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("MalformedLocaleException: ")) +
+ e.Message),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ }
+ return loc;
+}
+
+class Factory:
+ public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >,
+ private boost::noncopyable
+{
+public:
+ Factory() {}
+
+private:
+ virtual ~Factory() {}
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+};
+
+css::uno::Reference< css::uno::XInterface > Factory::createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ return createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any >(), Context);
+}
+
+css::uno::Reference< css::uno::XInterface >
+Factory::createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ if (Arguments.getLength() == 0) {
+ css::uno::Reference< css::uno::XInterface > instance;
+ if (!(Context->getValueByName(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "/singletons/"
+ "com.sun.star.configuration.theDefaultProvider")))
+ >>= instance) ||
+ !instance.is())
+ {
+ throw css::uno::DeploymentException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "component context fails to supply singleton"
+ " com.sun.star.configuration.theDefaultProvider")),
+ Context);
+ }
+ return instance;
+ } else {
+ rtl::OUString locale;
+ for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
+ css::beans::NamedValue v1;
+ css::beans::PropertyValue v2;
+ rtl::OUString name;
+ css::uno::Any value;
+ if (Arguments[i] >>= v1) {
+ name = v1.Name;
+ value = v1.Value;
+ } else if (Arguments[i] >>= v2) {
+ name = v2.Name;
+ value = v2.Value;
+ } else {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider"
+ " factory expects NamedValue or PropertyValue"
+ " arguments")),
+ 0);
+ }
+ // For backwards compatibility, allow "Locale" in any case:
+ if (name.equalsIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("locale")))
+ {
+ if (locale.getLength() != 0 || !(value >>= locale) ||
+ locale.getLength() == 0)
+ {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration."
+ "ConfigurationProvider factory expects at most"
+ " one, non-empty, string Locale argument")),
+ 0);
+ }
+ } else {
+ //TODO
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider"
+ " factory: unknown argument ")) + name,
+ 0);
+ }
+ }
+ return static_cast< cppu::OWeakObject * >(new Service(Context, locale));
+ }
+}
+
+}
+
+css::uno::Reference< css::uno::XInterface > createDefault(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+{
+ return static_cast< cppu::OWeakObject * >(
+ new Service(context, rtl::OUString()));
+}
+
+rtl::OUString getImplementationName() {
+ return rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.configuration.ConfigurationProvider"));
+}
+
+css::uno::Sequence< rtl::OUString > getSupportedServiceNames() {
+ rtl::OUString name(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider"));
+ return css::uno::Sequence< rtl::OUString >(&name, 1);
+}
+
+css::uno::Reference< css::lang::XSingleComponentFactory >
+createFactory(
+ cppu::ComponentFactoryFunc, rtl::OUString const &,
+ css::uno::Sequence< rtl::OUString > const &, rtl_ModuleCount *)
+ SAL_THROW(())
+{
+ return new Factory;
+}
+
+} }
diff --git a/configmgr/source/configurationprovider.hxx b/configmgr/source/configurationprovider.hxx
new file mode 100644
index 000000000000..4a8c38383774
--- /dev/null
+++ b/configmgr/source/configurationprovider.hxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_CONFIGURATIONPROVIDER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_CONFIGURATIONPROVIDER_HXX
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "cppuhelper/factory.hxx"
+#include "rtl/unload.h"
+#include "sal/types.h"
+
+namespace com { namespace sun { namespace star {
+ namespace lang { class XSingleComponentFactory; }
+ namespace uno {
+ class XComponentContext;
+ class XInterface;
+ }
+} } }
+namespace rtl { class OUString; }
+
+namespace configmgr { namespace configuration_provider {
+
+com::sun::star::uno::Reference< com::sun::star::uno::XInterface > createDefault(
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
+ const & context);
+
+rtl::OUString SAL_CALL getImplementationName();
+
+com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
+getSupportedServiceNames();
+
+com::sun::star::uno::Reference< com::sun::star::lang::XSingleComponentFactory >
+SAL_CALL createFactory(
+ cppu::ComponentFactoryFunc, rtl::OUString const &,
+ com::sun::star::uno::Sequence< rtl::OUString > const &, rtl_ModuleCount *)
+ SAL_THROW(());
+
+} }
+
+#endif
diff --git a/configmgr/source/configurationregistry.cxx b/configmgr/source/configurationregistry.cxx
new file mode 100644
index 000000000000..ffd7174c0ad7
--- /dev/null
+++ b/configmgr/source/configurationregistry.cxx
@@ -0,0 +1,950 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/beans/NamedValue.hpp"
+#include "com/sun/star/beans/Property.hpp"
+#include "com/sun/star/beans/XProperty.hpp"
+#include "com/sun/star/container/NoSuchElementException.hpp"
+#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
+#include "com/sun/star/container/XNamed.hpp"
+#include "com/sun/star/lang/XMultiComponentFactory.hpp"
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/lang/XSingleComponentFactory.hpp"
+#include "com/sun/star/registry/InvalidRegistryException.hpp"
+#include "com/sun/star/registry/InvalidValueException.hpp"
+#include "com/sun/star/registry/MergeConflictException.hpp"
+#include "com/sun/star/registry/RegistryKeyType.hpp"
+#include "com/sun/star/registry/RegistryValueType.hpp"
+#include "com/sun/star/registry/XRegistryKey.hpp"
+#include "com/sun/star/registry/XSimpleRegistry.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/DeploymentException.hpp"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/Type.hxx"
+#include "com/sun/star/uno/TypeClass.hpp"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "com/sun/star/util/XFlushable.hpp"
+#include "cppu/unotype.hxx"
+#include "cppuhelper/factory.hxx"
+#include "cppuhelper/implbase1.hxx"
+#include "cppuhelper/implbase3.hxx"
+#include "cppuhelper/weak.hxx"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+#include "rtl/unload.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "configurationregistry.hxx"
+
+namespace com { namespace sun { namespace star { namespace util {
+ class XFlushListener;
+} } } }
+
+namespace configmgr { namespace configuration_registry {
+
+namespace {
+
+namespace css = com::sun::star;
+
+class Service:
+ public cppu::WeakImplHelper3<
+ css::lang::XServiceInfo, css::registry::XSimpleRegistry,
+ css::util::XFlushable >,
+ 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 configuration_registry::getImplementationName(); }
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
+ throw (css::uno::RuntimeException)
+ { return ServiceName == getSupportedServiceNames()[0]; } //TODO
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL
+ getSupportedServiceNames() throw (css::uno::RuntimeException)
+ { return configuration_registry::getSupportedServiceNames(); }
+
+ virtual rtl::OUString SAL_CALL getURL() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL open(
+ rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL isValid() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL close()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual void SAL_CALL destroy()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL
+ getRootKey()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL isReadOnly() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL mergeKey(rtl::OUString const &, rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::MergeConflictException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL flush() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL addFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const &)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL removeFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const &)
+ throw (css::uno::RuntimeException);
+
+ void checkValid();
+
+ void checkValid_RuntimeException();
+
+ void doClose();
+
+ css::uno::Reference< css::lang::XMultiServiceFactory > provider_;
+ osl::Mutex mutex_;
+ css::uno::Reference< css::uno::XInterface > access_;
+ rtl::OUString url_;
+ bool readOnly_;
+
+ friend class RegistryKey;
+};
+
+class RegistryKey:
+ public cppu::WeakImplHelper1< css::registry::XRegistryKey >,
+ private boost::noncopyable
+{
+public:
+ RegistryKey(Service & service, css::uno::Any const & value):
+ service_(service), value_(value) {}
+
+private:
+ virtual ~RegistryKey() {}
+
+ virtual rtl::OUString SAL_CALL getKeyName()
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL isReadOnly()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL isValid() throw (css::uno::RuntimeException);
+
+ virtual css::registry::RegistryKeyType SAL_CALL getKeyType(
+ rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::registry::RegistryValueType SAL_CALL getValueType()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual sal_Int32 SAL_CALL getLongValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setLongValue(sal_Int32)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< sal_Int32 > SAL_CALL getLongListValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setLongListValue(
+ css::uno::Sequence< sal_Int32 > const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getAsciiValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setAsciiValue(rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL getAsciiListValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setAsciiListValue(
+ css::uno::Sequence< rtl::OUString > const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getStringValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setStringValue(rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL getStringListValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setStringListValue(
+ css::uno::Sequence< rtl::OUString > const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBinaryValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL setBinaryValue(css::uno::Sequence< sal_Int8 > const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL openKey(
+ rtl::OUString const & aKeyName)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL
+ createKey(rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual void SAL_CALL closeKey()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual void SAL_CALL deleteKey(rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual
+ css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
+ SAL_CALL openKeys()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL getKeyNames()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL createLink(
+ rtl::OUString const &, rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual void SAL_CALL deleteLink(rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getLinkTarget(rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ virtual rtl::OUString SAL_CALL getResolvedName(
+ rtl::OUString const & aKeyName)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::uno::RuntimeException);
+
+ Service & service_;
+ css::uno::Any value_;
+};
+
+Service::Service(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+{
+ OSL_ASSERT(context.is());
+ try {
+ provider_ = css::uno::Reference< css::lang::XMultiServiceFactory >(
+ (css::uno::Reference< css::lang::XMultiComponentFactory >(
+ context->getServiceManager(), css::uno::UNO_SET_THROW)->
+ createInstanceWithContext(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.DefaultProvider")),
+ context)),
+ css::uno::UNO_QUERY_THROW);
+ } catch (css::uno::RuntimeException &) {
+ throw;
+ } catch (css::uno::Exception & e) {
+ throw css::uno::DeploymentException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "component context fails to supply service"
+ " com.sun.star.configuration.DefaultProvider of type"
+ " com.sun.star.lang.XMultiServiceFactory: ")) +
+ e.Message),
+ context);
+ }
+}
+
+rtl::OUString Service::getURL() throw (css::uno::RuntimeException) {
+ osl::MutexGuard g(mutex_);
+ checkValid_RuntimeException();
+ return url_;
+}
+
+void Service::open(rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ //TODO: bCreate
+ osl::MutexGuard g(mutex_);
+ if (access_.is()) {
+ doClose();
+ }
+ css::uno::Sequence< css::uno::Any > args(1);
+ args[0] <<= css::beans::NamedValue(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath")),
+ css::uno::makeAny(rURL));
+ try {
+ access_ = provider_->createInstanceWithArguments(
+ (bReadOnly
+ ? rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationAccess"))
+ : rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationUpdateAccess"))),
+ args);
+ } catch (css::uno::RuntimeException &) {
+ throw;
+ } catch (css::uno::Exception & e) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: open"
+ " failed: ")) +
+ e.Message),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ url_ = rURL;
+ readOnly_ = bReadOnly;
+}
+
+sal_Bool Service::isValid() throw (css::uno::RuntimeException) {
+ osl::MutexGuard g(mutex_);
+ return access_.is();
+}
+
+void Service::close()
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(mutex_);
+ checkValid();
+ doClose();
+}
+
+void Service::destroy()
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Reference< css::registry::XRegistryKey > Service::getRootKey()
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(mutex_);
+ checkValid();
+ return new RegistryKey(*this, css::uno::makeAny(access_));
+}
+
+sal_Bool Service::isReadOnly() throw (css::uno::RuntimeException) {
+ osl::MutexGuard g(mutex_);
+ checkValid_RuntimeException();
+ return readOnly_;
+}
+
+void Service::mergeKey(rtl::OUString const &, rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::MergeConflictException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void Service::flush() throw (css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void Service::addFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const &)
+ throw (css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void Service::removeFlushListener(
+ css::uno::Reference< css::util::XFlushListener > const &)
+ throw (css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void Service::checkValid() {
+ if (!access_.is()) {
+ throw css::registry::InvalidRegistryException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " valid")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+void Service::checkValid_RuntimeException() {
+ if (!access_.is()) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " valid")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+void Service::doClose() {
+ access_.clear();
+}
+
+rtl::OUString RegistryKey::getKeyName() throw (css::uno::RuntimeException) {
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+ css::uno::Reference< css::container::XNamed > named;
+ if (value_ >>= named) {
+ return named->getName();
+ }
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Bool RegistryKey::isReadOnly()
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+ return service_.readOnly_; //TODO: read-only sub-nodes in update access?
+}
+
+sal_Bool RegistryKey::isValid() throw (css::uno::RuntimeException) {
+ return service_.isValid();
+}
+
+css::registry::RegistryKeyType RegistryKey::getKeyType(rtl::OUString const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ return css::registry::RegistryKeyType_KEY;
+}
+
+css::registry::RegistryValueType RegistryKey::getValueType()
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ css::uno::Type t(value_.getValueType());
+ switch (t.getTypeClass()) {
+ case css::uno::TypeClass_LONG:
+ return css::registry::RegistryValueType_LONG;
+ case css::uno::TypeClass_STRING:
+ return css::registry::RegistryValueType_STRING;
+ case css::uno::TypeClass_SEQUENCE:
+ if (t == cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()) {
+ return css::registry::RegistryValueType_BINARY;
+ } else if (t == cppu::UnoType< css::uno::Sequence< sal_Int32 > >::get())
+ {
+ return css::registry::RegistryValueType_LONGLIST;
+ } else if (t ==
+ cppu::UnoType< css::uno::Sequence< rtl::OUString > >::get())
+ {
+ return css::registry::RegistryValueType_STRINGLIST;
+ }
+ // fall through
+ default:
+ return css::registry::RegistryValueType_NOT_DEFINED;
+ }
+}
+
+sal_Int32 RegistryKey::getLongValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ sal_Int32 v = 0;
+ if (value_ >>= v) {
+ return v;
+ }
+ throw css::registry::InvalidValueException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::setLongValue(sal_Int32)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Sequence< sal_Int32 > RegistryKey::getLongListValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ css::uno::Sequence< sal_Int32 > v;
+ if (value_ >>= v) {
+ return v;
+ }
+ throw css::registry::InvalidValueException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::setLongListValue(css::uno::Sequence< sal_Int32 > const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+rtl::OUString RegistryKey::getAsciiValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ rtl::OUString v;
+ if (value_ >>= v) {
+ return v;
+ }
+ throw css::registry::InvalidValueException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::setAsciiValue(rtl::OUString const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Sequence< rtl::OUString > RegistryKey::getAsciiListValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ css::uno::Sequence< rtl::OUString > v;
+ if (value_ >>= v) {
+ return v;
+ }
+ throw css::registry::InvalidValueException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::setAsciiListValue(css::uno::Sequence< rtl::OUString > const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+rtl::OUString RegistryKey::getStringValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ rtl::OUString v;
+ if (value_ >>= v) {
+ return v;
+ }
+ throw css::registry::InvalidValueException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::setStringValue(rtl::OUString const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Sequence< rtl::OUString > RegistryKey::getStringListValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ css::uno::Sequence< rtl::OUString > v;
+ if (value_ >>= v) {
+ return v;
+ }
+ throw css::registry::InvalidValueException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::setStringListValue(
+ css::uno::Sequence< rtl::OUString > const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Sequence< sal_Int8 > RegistryKey::getBinaryValue()
+ throw (
+ css::registry::InvalidRegistryException,
+ css::registry::InvalidValueException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid();
+ css::uno::Sequence< sal_Int8 > v;
+ if (value_ >>= v) {
+ return v;
+ }
+ throw css::registry::InvalidValueException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::setBinaryValue(css::uno::Sequence< sal_Int8 > const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Reference< css::registry::XRegistryKey > RegistryKey::openKey(
+ rtl::OUString const & aKeyName)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+ css::uno::Reference< css::container::XHierarchicalNameAccess > access;
+ if (value_ >>= access) {
+ try {
+ return new RegistryKey(
+ service_, access->getByHierarchicalName(aKeyName));
+ } catch (css::container::NoSuchElementException &) {}
+ }
+ return css::uno::Reference< css::registry::XRegistryKey >();
+}
+
+css::uno::Reference< css::registry::XRegistryKey > RegistryKey::createKey(
+ rtl::OUString const &)
+ throw (
+ css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void RegistryKey::closeKey()
+ throw (
+ css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+}
+
+void RegistryKey::deleteKey(rtl::OUString const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
+RegistryKey::openKeys()
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Sequence< rtl::OUString > RegistryKey::getKeyNames()
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry: not"
+ " implemented")),
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Bool RegistryKey::createLink(rtl::OUString const &, rtl::OUString const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+ return false;
+}
+
+void RegistryKey::deleteLink(rtl::OUString const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+}
+
+rtl::OUString RegistryKey::getLinkTarget(rtl::OUString const &)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+ return rtl::OUString();
+}
+
+rtl::OUString RegistryKey::getResolvedName(rtl::OUString const & aKeyName)
+ throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(service_.mutex_);
+ service_.checkValid_RuntimeException();
+ return aKeyName;
+}
+
+class Factory:
+ public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >,
+ private boost::noncopyable
+{
+public:
+ Factory() {}
+
+private:
+ virtual ~Factory() {}
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+};
+
+css::uno::Reference< css::uno::XInterface > Factory::createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ return createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any >(), Context);
+}
+
+css::uno::Reference< css::uno::XInterface >
+Factory::createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ if (Arguments.getLength() != 0) {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry must be"
+ " instantiated without arguments")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return static_cast< cppu::OWeakObject * >(new Service(Context));
+}
+
+}
+
+rtl::OUString getImplementationName() {
+ return rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.configuration.ConfigurationRegistry"));
+}
+
+css::uno::Sequence< rtl::OUString > getSupportedServiceNames() {
+ rtl::OUString name(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationRegistry"));
+ return css::uno::Sequence< rtl::OUString >(&name, 1);
+}
+
+css::uno::Reference< css::lang::XSingleComponentFactory > createFactory(
+ cppu::ComponentFactoryFunc, rtl::OUString const &,
+ css::uno::Sequence< rtl::OUString > const &, rtl_ModuleCount *)
+ SAL_THROW(())
+{
+ return new Factory;
+}
+
+} }
diff --git a/configmgr/source/configurationregistry.hxx b/configmgr/source/configurationregistry.hxx
new file mode 100644
index 000000000000..6cba122188b1
--- /dev/null
+++ b/configmgr/source/configurationregistry.hxx
@@ -0,0 +1,57 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_CONFIGURATIONREGISTRY_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_CONFIGURATIONREGISTRY_HXX
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "cppuhelper/factory.hxx"
+#include "rtl/unload.h"
+#include "sal/types.h"
+
+namespace com { namespace sun { namespace star { namespace lang {
+ class XSingleComponentFactory;
+} } } }
+namespace rtl { class OUString; }
+
+namespace configmgr { namespace configuration_registry {
+
+rtl::OUString SAL_CALL getImplementationName();
+
+com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
+getSupportedServiceNames();
+
+com::sun::star::uno::Reference< com::sun::star::lang::XSingleComponentFactory >
+SAL_CALL createFactory(
+ cppu::ComponentFactoryFunc, rtl::OUString const &,
+ com::sun::star::uno::Sequence< rtl::OUString > const &, rtl_ModuleCount *)
+ SAL_THROW(());
+
+} }
+
+#endif
diff --git a/configmgr/source/data.cxx b/configmgr/source/data.cxx
new file mode 100644
index 000000000000..5540a40fd5f4
--- /dev/null
+++ b/configmgr/source/data.cxx
@@ -0,0 +1,318 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "rtl/string.h"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "data.hxx"
+#include "groupnode.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "setnode.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+bool decode(
+ rtl::OUString const & encoded, sal_Int32 begin, sal_Int32 end,
+ rtl::OUString * decoded)
+{
+ OSL_ASSERT(
+ begin >= 0 && begin <= end && end <= encoded.getLength() &&
+ decoded != 0);
+ rtl::OUStringBuffer buf;
+ while (begin != end) {
+ sal_Unicode c = encoded[begin++];
+ if (c == '&') {
+ if (encoded.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("amp;"), begin))
+ {
+ buf.append(sal_Unicode('&'));
+ begin += RTL_CONSTASCII_LENGTH("amp;");
+ } else if (encoded.matchAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("quot;"), begin))
+ {
+ buf.append(sal_Unicode('"'));
+ begin += RTL_CONSTASCII_LENGTH("quot;");
+ } else if (encoded.matchAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("apos;"), begin))
+ {
+ buf.append(sal_Unicode('\''));
+ begin += RTL_CONSTASCII_LENGTH("apos;");
+ } else {
+ return false;
+ }
+ OSL_ASSERT(begin <= end);
+ } else {
+ buf.append(c);
+ }
+ }
+ *decoded = buf.makeStringAndClear();
+ return true;
+}
+
+}
+
+rtl::OUString Data::createSegment(
+ rtl::OUString const & templateName, rtl::OUString const & name)
+{
+ if (templateName.getLength() == 0) {
+ return name;
+ }
+ rtl::OUStringBuffer buf(templateName);
+ //TODO: verify template name contains no bad chars?
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("['"));
+ for (sal_Int32 i = 0; i < name.getLength(); ++i) {
+ sal_Unicode c = name[i];
+ switch (c) {
+ case '&':
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("&amp;"));
+ break;
+ case '"':
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("&quot;"));
+ break;
+ case '\'':
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("&apos;"));
+ break;
+ default:
+ buf.append(c);
+ break;
+ }
+ }
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("']"));
+ return buf.makeStringAndClear();
+}
+
+sal_Int32 Data::parseSegment(
+ rtl::OUString const & path, sal_Int32 index, rtl::OUString * name,
+ bool * setElement, rtl::OUString * templateName)
+{
+ OSL_ASSERT(
+ index >= 0 && index <= path.getLength() && name != 0 &&
+ setElement != 0);
+ sal_Int32 i = index;
+ while (i < path.getLength() && path[i] != '/' && path[i] != '[') {
+ ++i;
+ }
+ if (i == path.getLength() || path[i] == '/') {
+ *name = path.copy(index, i - index);
+ *setElement = false;
+ return i;
+ }
+ if (templateName != 0) {
+ if (i - index == 1 && path[index] == '*') {
+ *templateName = rtl::OUString();
+ } else {
+ *templateName = path.copy(index, i - index);
+ }
+ }
+ if (++i == path.getLength()) {
+ return -1;
+ }
+ sal_Unicode del = path[i++];
+ if (del != '\'' && del != '"') {
+ return -1;
+ }
+ sal_Int32 j = path.indexOf(del, i);
+ if (j == -1 || j + 1 == path.getLength() || path[j + 1] != ']' ||
+ !decode(path, i, j, name))
+ {
+ return -1;
+ }
+ *setElement = true;
+ return j + 2;
+}
+
+rtl::OUString Data::fullTemplateName(
+ rtl::OUString const & component, rtl::OUString const & name)
+{
+ if (component.indexOf(':') != -1 || name.indexOf(':') != -1) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad component/name pair containing colon ")) +
+ component + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
+ name),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ rtl::OUStringBuffer buf(component);
+ buf.append(sal_Unicode(':'));
+ buf.append(name);
+ return buf.makeStringAndClear();
+}
+
+bool Data::equalTemplateNames(
+ rtl::OUString const & shortName, rtl::OUString const & longName)
+{
+ if (shortName.indexOf(':') == -1) {
+ sal_Int32 i = longName.indexOf(':') + 1;
+ OSL_ASSERT(i > 0);
+ return
+ rtl_ustr_compare_WithLength(
+ shortName.getStr(), shortName.getLength(),
+ longName.getStr() + i, longName.getLength() - i) ==
+ 0;
+ } else {
+ return shortName == longName;
+ }
+}
+
+rtl::Reference< Node > Data::findNode(
+ int layer, NodeMap const & map, rtl::OUString const & name)
+{
+ NodeMap::const_iterator i(map.find(name));
+ return i == map.end() || i->second->getLayer() > layer
+ ? rtl::Reference< Node >() : i->second;
+}
+
+rtl::Reference< Node > Data::resolvePathRepresentation(
+ rtl::OUString const & pathRepresentation, Path * path, int * finalizedLayer)
+ const
+{
+ if (pathRepresentation.getLength() == 0 || pathRepresentation[0] != '/') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ rtl::OUString seg;
+ bool setElement;
+ sal_Int32 n = parseSegment(pathRepresentation, 1, &seg, &setElement, 0);
+ if (n == -1 || setElement)
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ NodeMap::const_iterator i(components.find(seg));
+ if (path != 0) {
+ path->clear();
+ }
+ rtl::Reference< Node > parent;
+ int finalized = NO_LAYER;
+ for (rtl::Reference< Node > p(i == components.end() ? 0 : i->second);;) {
+ if (!p.is()) {
+ return p;
+ }
+ if (path != 0) {
+ path->push_back(seg);
+ }
+ finalized = std::min(finalized, p->getFinalized());
+ if (n != pathRepresentation.getLength() &&
+ pathRepresentation[n++] != '/')
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ // for backwards compatibility, ignore a final slash
+ if (n == pathRepresentation.getLength()) {
+ if (finalizedLayer != 0) {
+ *finalizedLayer = finalized;
+ }
+ return p;
+ }
+ parent = p;
+ rtl::OUString templateName;
+ n = parseSegment(
+ pathRepresentation, n, &seg, &setElement, &templateName);
+ if (n == -1) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ // For backwards compatibility, allow set members to be accessed with
+ // simple path segments, like group members:
+ p = p->getMember(seg);
+ if (setElement) {
+ switch (parent->kind()) {
+ case Node::KIND_LOCALIZED_PROPERTY:
+ if (templateName.getLength() != 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ break;
+ case Node::KIND_SET:
+ if (templateName.getLength() != 0 &&
+ !dynamic_cast< SetNode * >(parent.get())->isValidTemplate(
+ templateName))
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (templateName.getLength() != 0 && p != 0) {
+ OSL_ASSERT(p->getTemplateName().getLength() != 0);
+ if (!equalTemplateNames(templateName, p->getTemplateName())) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
+ pathRepresentation),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ }
+ }
+}
+
+rtl::Reference< Node > Data::getTemplate(
+ int layer, rtl::OUString const & fullName) const
+{
+ return findNode(layer, templates, fullName);
+}
+
+}
diff --git a/configmgr/source/data.hxx b/configmgr/source/data.hxx
new file mode 100644
index 000000000000..495ca1233878
--- /dev/null
+++ b/configmgr/source/data.hxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_DATA_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_DATA_HXX
+
+#include "sal/config.h"
+
+#include <climits>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "rtl/ref.hxx"
+#include "sal/types.h"
+
+#include "modifications.hxx"
+#include "nodemap.hxx"
+#include "path.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Node;
+
+struct Data: private boost::noncopyable {
+ enum { NO_LAYER = INT_MAX };
+
+ NodeMap templates;
+
+ NodeMap components;
+
+ Modifications modifications;
+
+ static rtl::OUString createSegment(
+ rtl::OUString const & templateName, rtl::OUString const & name);
+
+ static sal_Int32 parseSegment(
+ rtl::OUString const & path, sal_Int32 index, rtl::OUString * name,
+ bool * setElement, rtl::OUString * templateName);
+
+ static rtl::OUString fullTemplateName(
+ rtl::OUString const & component, rtl::OUString const & name);
+
+ //TODO: better rules under which circumstances a short template name matches
+ static bool equalTemplateNames(
+ rtl::OUString const & shortName, rtl::OUString const & longName);
+
+ static rtl::Reference< Node > findNode(
+ int layer, NodeMap const & map, rtl::OUString const & name);
+
+ rtl::Reference< Node > resolvePathRepresentation(
+ rtl::OUString const & pathRepresentation, Path * path,
+ int * finalizedLayer) const;
+
+ rtl::Reference< Node > getTemplate(
+ int layer, rtl::OUString const & fullName) const;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/defaultprovider.cxx b/configmgr/source/defaultprovider.cxx
new file mode 100644
index 000000000000..d069663290e8
--- /dev/null
+++ b/configmgr/source/defaultprovider.cxx
@@ -0,0 +1,131 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/lang/XSingleComponentFactory.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppuhelper/factory.hxx"
+#include "cppuhelper/implbase1.hxx"
+#include "cppuhelper/weak.hxx"
+#include "sal/types.h"
+#include "rtl/unload.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "configurationprovider.hxx"
+#include "lock.hxx"
+
+namespace configmgr { namespace default_provider {
+
+namespace {
+
+namespace css = com::sun::star;
+
+class Factory:
+ public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >,
+ private boost::noncopyable
+{
+public:
+ Factory() {}
+
+private:
+ virtual ~Factory() {}
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+};
+
+css::uno::Reference< css::uno::XInterface > Factory::createInstanceWithContext(
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ return createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any >(), Context);
+}
+
+css::uno::Reference< css::uno::XInterface >
+Factory::createInstanceWithArgumentsAndContext(
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ if (Arguments.getLength() != 0) {
+ throw css::uno::Exception(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.DefaultProvider must be"
+ " instantiated without arguments")),
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ osl::MutexGuard guard(lock);
+ static css::uno::Reference< css::uno::XInterface > singleton(
+ configuration_provider::createDefault(Context));
+ return singleton;
+}
+
+}
+
+rtl::OUString getImplementationName() {
+ return rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.configuration.DefaultProvider"));
+}
+
+css::uno::Sequence< rtl::OUString > getSupportedServiceNames() {
+ rtl::OUString name(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.DefaultProvider"));
+ return css::uno::Sequence< rtl::OUString >(&name, 1);
+}
+
+css::uno::Reference< css::lang::XSingleComponentFactory >
+SAL_CALL createFactory(
+ cppu::ComponentFactoryFunc, rtl::OUString const &,
+ css::uno::Sequence< rtl::OUString > const &, rtl_ModuleCount *)
+ SAL_THROW(())
+{
+ return new Factory;
+}
+
+} }
diff --git a/configmgr/source/defaultprovider.hxx b/configmgr/source/defaultprovider.hxx
new file mode 100644
index 000000000000..7b267a80b42e
--- /dev/null
+++ b/configmgr/source/defaultprovider.hxx
@@ -0,0 +1,59 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_DEFAULTPROVIDER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_DEFAULTPROVIDER_HXX
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "cppuhelper/factory.hxx"
+#include "rtl/unload.h"
+#include "sal/types.h"
+
+namespace com { namespace sun { namespace star { namespace lang {
+ class XSingleComponentFactory;
+} } } }
+namespace rtl { class OUString; }
+
+namespace configmgr { namespace default_provider {
+
+rtl::OUString SAL_CALL getImplementationName();
+
+com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
+getSupportedServiceNames();
+
+com::sun::star::uno::Reference< com::sun::star::lang::XSingleComponentFactory >
+SAL_CALL createFactory(
+ cppu::ComponentFactoryFunc, rtl::OUString const &,
+ com::sun::star::uno::Sequence< rtl::OUString > const &, rtl_ModuleCount *)
+ SAL_THROW(());
+
+} }
+
+#endif
diff --git a/configmgr/source/groupnode.cxx b/configmgr/source/groupnode.cxx
new file mode 100644
index 000000000000..60d825451d69
--- /dev/null
+++ b/configmgr/source/groupnode.cxx
@@ -0,0 +1,88 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "data.hxx"
+#include "groupnode.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+
+namespace configmgr {
+
+GroupNode::GroupNode(
+ int layer, bool extensible, rtl::OUString const & templateName):
+ Node(layer), extensible_(extensible), templateName_(templateName),
+ mandatory_(Data::NO_LAYER)
+{}
+
+rtl::Reference< Node > GroupNode::clone() const {
+ return new GroupNode(*this);
+}
+
+NodeMap & GroupNode::getMembers() {
+ return members_;
+}
+
+rtl::OUString GroupNode::getTemplateName() const {
+ return templateName_;
+}
+
+void GroupNode::setMandatory(int layer) {
+ mandatory_ = layer;
+}
+
+int GroupNode::getMandatory() const {
+ return mandatory_;
+}
+
+bool GroupNode::isExtensible() const {
+ return extensible_;
+}
+
+GroupNode::GroupNode(GroupNode const & other):
+ Node(other), extensible_(other.extensible_),
+ templateName_(other.templateName_), mandatory_(other.mandatory_)
+{
+ cloneNodeMap(other.members_, &members_);
+}
+
+GroupNode::~GroupNode() {}
+
+Node::Kind GroupNode::kind() const {
+ return KIND_GROUP;
+}
+
+void GroupNode::clear() {
+ members_.clear();
+}
+
+}
diff --git a/configmgr/source/groupnode.hxx b/configmgr/source/groupnode.hxx
new file mode 100644
index 000000000000..be4907b86ce3
--- /dev/null
+++ b/configmgr/source/groupnode.hxx
@@ -0,0 +1,75 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_GROUPNODE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_GROUPNODE_HXX
+
+#include "sal/config.h"
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "node.hxx"
+#include "nodemap.hxx"
+
+namespace configmgr {
+
+class GroupNode: public Node {
+public:
+ GroupNode(int layer, bool extensible, rtl::OUString const & templateName);
+
+ virtual rtl::Reference< Node > clone() const;
+
+ virtual NodeMap & getMembers();
+
+ virtual rtl::OUString getTemplateName() const;
+
+ virtual void setMandatory(int layer);
+
+ virtual int getMandatory() const;
+
+ bool isExtensible() const;
+
+private:
+ GroupNode(GroupNode const & other);
+
+ virtual ~GroupNode();
+
+ virtual Kind kind() const;
+
+ virtual void clear();
+
+ bool extensible_;
+ NodeMap members_;
+ rtl::OUString templateName_;
+ // non-empty iff this node is a template, free node, or set member
+ int mandatory_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/localizedpropertynode.cxx b/configmgr/source/localizedpropertynode.cxx
new file mode 100644
index 000000000000..9c5fa3328a58
--- /dev/null
+++ b/configmgr/source/localizedpropertynode.cxx
@@ -0,0 +1,87 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Any.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "localizedpropertynode.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "type.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+LocalizedPropertyNode::LocalizedPropertyNode(
+ int layer, Type staticType, bool nillable):
+ Node(layer), staticType_(staticType), nillable_(nillable)
+{}
+
+rtl::Reference< Node > LocalizedPropertyNode::clone() const {
+ return new LocalizedPropertyNode(*this);
+}
+
+NodeMap & LocalizedPropertyNode::getMembers() {
+ return members_;
+}
+
+Type LocalizedPropertyNode::getStaticType() const {
+ return staticType_;
+}
+
+bool LocalizedPropertyNode::isNillable() const {
+ return nillable_;
+}
+
+LocalizedPropertyNode::LocalizedPropertyNode(
+ LocalizedPropertyNode const & other):
+ Node(other), staticType_(other.staticType_), nillable_(other.nillable_)
+{
+ cloneNodeMap(other.members_, &members_);
+}
+
+LocalizedPropertyNode::~LocalizedPropertyNode() {}
+
+Node::Kind LocalizedPropertyNode::kind() const {
+ return KIND_LOCALIZED_PROPERTY;
+}
+
+void LocalizedPropertyNode::clear() {
+ members_.clear();
+}
+
+}
diff --git a/configmgr/source/localizedpropertynode.hxx b/configmgr/source/localizedpropertynode.hxx
new file mode 100644
index 000000000000..d5a16af0e54d
--- /dev/null
+++ b/configmgr/source/localizedpropertynode.hxx
@@ -0,0 +1,76 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_LOCALIZEDPROPERTYNODE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_LOCALIZEDPROPERTYNODE_HXX
+
+#include "sal/config.h"
+
+#include "rtl/ref.hxx"
+
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "type.hxx"
+
+namespace com { namespace sun { namespace star { namespace uno {
+ class Any;
+} } } }
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class LocalizedPropertyNode: public Node {
+public:
+ LocalizedPropertyNode(int layer, Type staticType, bool nillable);
+
+ virtual rtl::Reference< Node > clone() const;
+
+ virtual NodeMap & getMembers();
+
+ Type getStaticType() const;
+
+ bool isNillable() const;
+
+private:
+ LocalizedPropertyNode(LocalizedPropertyNode const & other);
+
+ virtual ~LocalizedPropertyNode();
+
+ virtual Kind kind() const;
+
+ virtual void clear();
+
+ Type staticType_;
+ // as specified in the component-schema (TYPE_ANY, ...,
+ // TYPE_HEXBINARY_LIST; not TYPE_ERROR or TYPE_NIL)
+ bool nillable_;
+ NodeMap members_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/localizedvaluenode.cxx b/configmgr/source/localizedvaluenode.cxx
new file mode 100644
index 000000000000..f6246106c8fe
--- /dev/null
+++ b/configmgr/source/localizedvaluenode.cxx
@@ -0,0 +1,78 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Any.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "localizedvaluenode.hxx"
+#include "node.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+LocalizedValueNode::LocalizedValueNode(int layer, css::uno::Any const & value):
+ Node(layer), value_(value)
+{}
+
+rtl::Reference< Node > LocalizedValueNode::clone() const {
+ return new LocalizedValueNode(*this);
+}
+
+rtl::OUString LocalizedValueNode::getTemplateName() const {
+ return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*"));
+}
+
+css::uno::Any LocalizedValueNode::getValue() const {
+ return value_;
+}
+
+void LocalizedValueNode::setValue(int layer, css::uno::Any const & value) {
+ setLayer(layer);
+ value_ = value;
+}
+
+LocalizedValueNode::LocalizedValueNode(LocalizedValueNode const & other):
+ Node(other), value_(other.value_)
+{}
+
+LocalizedValueNode::~LocalizedValueNode() {}
+
+Node::Kind LocalizedValueNode::kind() const {
+ return KIND_LOCALIZED_VALUE;
+}
+
+}
diff --git a/configmgr/source/localizedvaluenode.hxx b/configmgr/source/localizedvaluenode.hxx
new file mode 100644
index 000000000000..7f8a5dd987ce
--- /dev/null
+++ b/configmgr/source/localizedvaluenode.hxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_LOCALIZEDVALUENODE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_LOCALIZEDVALUENODE_HXX
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Any.hxx"
+#include "rtl/ref.hxx"
+
+#include "node.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class LocalizedValueNode: public Node {
+public:
+ LocalizedValueNode(int layer, com::sun::star::uno::Any const & value);
+
+ virtual rtl::Reference< Node > clone() const;
+
+ virtual rtl::OUString getTemplateName() const;
+
+ com::sun::star::uno::Any getValue() const;
+
+ void setValue(int layer, com::sun::star::uno::Any const & value);
+
+private:
+ LocalizedValueNode(LocalizedValueNode const & other);
+
+ virtual ~LocalizedValueNode();
+
+ virtual Kind kind() const;
+
+ com::sun::star::uno::Any value_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/lock.cxx b/configmgr/source/lock.cxx
new file mode 100644
index 000000000000..dc7f26a34e73
--- /dev/null
+++ b/configmgr/source/lock.cxx
@@ -0,0 +1,39 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "osl/mutex.hxx"
+
+#include "lock.hxx"
+
+namespace configmgr {
+
+osl::Mutex lock;
+
+}
diff --git a/configmgr/source/lock.hxx b/configmgr/source/lock.hxx
new file mode 100644
index 000000000000..b541f48fbe77
--- /dev/null
+++ b/configmgr/source/lock.hxx
@@ -0,0 +1,41 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_LOCK_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_LOCK_HXX
+
+#include "sal/config.h"
+
+#include "osl/mutex.hxx"
+
+namespace configmgr {
+
+extern osl::Mutex lock;
+
+}
+
+#endif
diff --git a/configmgr/source/makefile.mk b/configmgr/source/makefile.mk
new file mode 100644
index 000000000000..317e08bdf49c
--- /dev/null
+++ b/configmgr/source/makefile.mk
@@ -0,0 +1,84 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#***********************************************************************/
+
+PRJ = ..
+PRJNAME = configmgr
+TARGET = configmgr
+
+ENABLE_EXCEPTIONS = TRUE
+VISIBILITY_HIDDEN = TRUE
+
+.INCLUDE: settings.mk
+
+CDEFS += -DOOO_DLLIMPLEMENTATION_CONFIGMGR
+
+SLOFILES = \
+ $(SLO)/access.obj \
+ $(SLO)/broadcaster.obj \
+ $(SLO)/childaccess.obj \
+ $(SLO)/components.obj \
+ $(SLO)/configurationprovider.obj \
+ $(SLO)/configurationregistry.obj \
+ $(SLO)/data.obj \
+ $(SLO)/defaultprovider.obj \
+ $(SLO)/groupnode.obj \
+ $(SLO)/localizedpropertynode.obj \
+ $(SLO)/localizedvaluenode.obj \
+ $(SLO)/lock.obj \
+ $(SLO)/modifications.obj \
+ $(SLO)/node.obj \
+ $(SLO)/nodemap.obj \
+ $(SLO)/pad.obj \
+ $(SLO)/parsemanager.obj \
+ $(SLO)/partial.obj \
+ $(SLO)/propertynode.obj \
+ $(SLO)/rootaccess.obj \
+ $(SLO)/services.obj \
+ $(SLO)/setnode.obj \
+ $(SLO)/type.obj \
+ $(SLO)/update.obj \
+ $(SLO)/valueparser.obj \
+ $(SLO)/writemodfile.obj \
+ $(SLO)/xcdparser.obj \
+ $(SLO)/xcsparser.obj \
+ $(SLO)/xcuparser.obj \
+ $(SLO)/xmldata.obj \
+ $(SLO)/xmlreader.obj
+
+SHL1IMPLIB = i$(SHL1TARGET)
+SHL1OBJS = $(SLOFILES)
+SHL1STDLIBS = \
+ $(COMPHELPERLIB) \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(SALHELPERLIB) \
+ $(SALLIB)
+SHL1TARGET = configmgr
+SHL1USE_EXPORTS = name
+DEF1NAME = $(SHL1TARGET)
+
+.INCLUDE: target.mk
diff --git a/configmgr/source/modifications.cxx b/configmgr/source/modifications.cxx
new file mode 100644
index 000000000000..2ad3b5ef8bd1
--- /dev/null
+++ b/configmgr/source/modifications.cxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "rtl/ustring.hxx"
+
+#include "modifications.hxx"
+#include "path.hxx"
+
+namespace configmgr {
+
+Modifications::Modifications() {}
+
+Modifications::~Modifications() {}
+
+void Modifications::add(Path const & path) {
+ Node * p = &root_;
+ bool wasPresent = false;
+ for (Path::const_iterator i(path.begin()); i != path.end(); ++i) {
+ Node::Children::iterator j(p->children.find(*i));
+ if (j == p->children.end()) {
+ if (wasPresent && p->children.empty()) {
+ return;
+ }
+ j = p->children.insert(Node::Children::value_type(*i, Node())).
+ first;
+ wasPresent = false;
+ } else {
+ wasPresent = true;
+ }
+ p = &j->second;
+ }
+ p->children.clear();
+}
+
+Modifications::Node const & Modifications::getRoot() const {
+ return root_;
+}
+
+}
diff --git a/configmgr/source/modifications.hxx b/configmgr/source/modifications.hxx
new file mode 100644
index 000000000000..e29a10150148
--- /dev/null
+++ b/configmgr/source/modifications.hxx
@@ -0,0 +1,65 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_MODIFICATIONS_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_MODIFICATIONS_HXX
+
+#include "sal/config.h"
+
+#include <map>
+
+#include "boost/noncopyable.hpp"
+
+#include "path.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Modifications: private boost::noncopyable {
+public:
+ struct Node {
+ typedef std::map< rtl::OUString, Node > Children;
+
+ Children children;
+ };
+
+ Modifications();
+
+ ~Modifications();
+
+ void add(Path const & path);
+
+ Node const & getRoot() const;
+
+private:
+ Node root_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/node.cxx b/configmgr/source/node.cxx
new file mode 100644
index 000000000000..a5a089106b2a
--- /dev/null
+++ b/configmgr/source/node.cxx
@@ -0,0 +1,108 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "data.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+NodeMap & Node::getMembers() {
+ OSL_ASSERT(false);
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+rtl::OUString Node::getTemplateName() const {
+ return rtl::OUString();
+}
+
+void Node::setMandatory(int layer) {
+ (void) layer; // avoid warnings
+ OSL_ASSERT(layer == Data::NO_LAYER);
+}
+
+int Node::getMandatory() const {
+ return Data::NO_LAYER;
+}
+
+void Node::setLayer(int layer) {
+ OSL_ASSERT(layer >= layer_);
+ layer_ = layer;
+}
+
+int Node::getLayer() const {
+ return layer_;
+}
+
+void Node::setFinalized(int layer) {
+ finalized_ = layer;
+}
+
+int Node::getFinalized() const {
+ return finalized_;
+}
+
+rtl::Reference< Node > Node::getMember(rtl::OUString const & name) {
+ NodeMap & members = getMembers();
+ NodeMap::iterator i(members.find(name));
+ return i == members.end() ? rtl::Reference< Node >() : i->second;
+}
+
+Node::Node(int layer): layer_(layer), finalized_(Data::NO_LAYER) {}
+
+Node::Node(const Node & other):
+ SimpleReferenceObject(), layer_(other.layer_), finalized_(other.finalized_)
+{}
+
+Node::~Node() {}
+
+void Node::clear() {}
+
+rtl::Reference< Node > Node::findMember(rtl::OUString const &) {
+ return rtl::Reference< Node >();
+}
+
+}
diff --git a/configmgr/source/node.hxx b/configmgr/source/node.hxx
new file mode 100644
index 000000000000..10f168520595
--- /dev/null
+++ b/configmgr/source/node.hxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_NODE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_NODE_HXX
+
+#include "sal/config.h"
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "salhelper/simplereferenceobject.hxx"
+
+#include "nodemap.hxx"
+
+namespace configmgr {
+
+class Node: public salhelper::SimpleReferenceObject {
+public:
+ enum Kind {
+ KIND_PROPERTY, KIND_LOCALIZED_PROPERTY, KIND_LOCALIZED_VALUE,
+ KIND_GROUP, KIND_SET };
+
+ virtual Kind kind() const = 0;
+
+ virtual rtl::Reference< Node > clone() const = 0;
+
+ virtual NodeMap & getMembers();
+
+ virtual rtl::OUString getTemplateName() const;
+
+ virtual void setMandatory(int layer);
+
+ virtual int getMandatory() const;
+
+ void setLayer(int layer);
+
+ int getLayer() const;
+
+ void setFinalized(int layer);
+
+ int getFinalized() const;
+
+ rtl::Reference< Node > getMember(rtl::OUString const & name);
+
+protected:
+ explicit Node(int layer);
+
+ Node(const Node & other);
+
+ virtual ~Node();
+
+ virtual void clear();
+
+ virtual rtl::Reference< Node > findMember(rtl::OUString const & name);
+
+ int layer_;
+ int finalized_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/nodemap.cxx b/configmgr/source/nodemap.cxx
new file mode 100644
index 000000000000..6b22863b5672
--- /dev/null
+++ b/configmgr/source/nodemap.cxx
@@ -0,0 +1,50 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+
+#include "osl/diagnose.h"
+#include "rtl/ustring.hxx"
+
+#include "node.hxx"
+#include "nodemap.hxx"
+
+namespace configmgr {
+
+void cloneNodeMap(NodeMap const & source, NodeMap * target) {
+ OSL_ASSERT(target != 0 && target->empty());
+ NodeMap clone(source);
+ for (NodeMap::iterator i(clone.begin()); i != clone.end(); ++i) {
+ i->second = i->second->clone();
+ }
+ std::swap(clone, *target);
+}
+
+}
diff --git a/configmgr/source/nodemap.hxx b/configmgr/source/nodemap.hxx
new file mode 100644
index 000000000000..92ea324091cd
--- /dev/null
+++ b/configmgr/source/nodemap.hxx
@@ -0,0 +1,49 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_NODEMAP_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_NODEMAP_HXX
+
+#include "sal/config.h"
+
+#include <map>
+
+#include "rtl/ref.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Node;
+
+typedef std::map< rtl::OUString, rtl::Reference< Node > > NodeMap;
+
+void cloneNodeMap(NodeMap const & source, NodeMap * target);
+
+}
+
+#endif
diff --git a/configmgr/source/pad.cxx b/configmgr/source/pad.cxx
new file mode 100644
index 000000000000..c8c7218b6da6
--- /dev/null
+++ b/configmgr/source/pad.cxx
@@ -0,0 +1,91 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "osl/diagnose.h"
+#include "rtl/string.h"
+#include "sal/types.h"
+
+#include "pad.hxx"
+#include "span.hxx"
+
+namespace configmgr {
+
+void Pad::add(char const * begin, sal_Int32 length) {
+ OSL_ASSERT(
+ begin != 0 && length >= 0 && !(span_.is() && buffer_.getLength() != 0));
+ if (length != 0) {
+ flushSpan();
+ if (buffer_.getLength() == 0) {
+ span_ = Span(begin, length);
+ } else {
+ buffer_.append(begin, length);
+ }
+ }
+}
+
+void Pad::addEphemeral(char const * begin, sal_Int32 length) {
+ OSL_ASSERT(
+ begin != 0 && length >= 0 && !(span_.is() && buffer_.getLength() != 0));
+ if (length != 0) {
+ flushSpan();
+ buffer_.append(begin, length);
+ }
+}
+
+void Pad::clear() {
+ OSL_ASSERT(!(span_.is() && buffer_.getLength() != 0));
+ span_.clear();
+ buffer_.setLength(0);
+}
+
+bool Pad::is() const {
+ OSL_ASSERT(!(span_.is() && buffer_.getLength() != 0));
+ return span_.is() || buffer_.getLength() != 0;
+}
+
+Span Pad::get() const {
+ OSL_ASSERT(!(span_.is() && buffer_.getLength() != 0));
+ if (span_.is()) {
+ return span_;
+ } else if (buffer_.getLength() == 0) {
+ return Span(RTL_CONSTASCII_STRINGPARAM(""));
+ } else {
+ return Span(buffer_.getStr(), buffer_.getLength());
+ }
+}
+
+void Pad::flushSpan() {
+ if (span_.is()) {
+ buffer_.append(span_.begin, span_.length);
+ span_.clear();
+ }
+}
+
+}
diff --git a/configmgr/source/pad.hxx b/configmgr/source/pad.hxx
new file mode 100644
index 000000000000..66a51f480023
--- /dev/null
+++ b/configmgr/source/pad.hxx
@@ -0,0 +1,61 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_PAD_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_PAD_HXX
+
+#include "sal/config.h"
+
+#include "rtl/strbuf.hxx"
+#include "sal/types.h"
+
+#include "span.hxx"
+
+namespace configmgr {
+
+class Pad {
+public:
+ void add(char const * begin, sal_Int32 length);
+
+ void addEphemeral(char const * begin, sal_Int32 length);
+
+ void clear();
+
+ bool is() const;
+
+ Span get() const;
+
+private:
+ void flushSpan();
+
+ Span span_;
+ rtl::OStringBuffer buffer_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/parsemanager.cxx b/configmgr/source/parsemanager.cxx
new file mode 100644
index 000000000000..69a5515b977c
--- /dev/null
+++ b/configmgr/source/parsemanager.cxx
@@ -0,0 +1,85 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/container/NoSuchElementException.hpp"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "osl/diagnose.h"
+#include "sal/types.h"
+
+#include "parsemanager.hxx"
+#include "parser.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+ParseManager::ParseManager(
+ rtl::OUString const & url, rtl::Reference< Parser > const & parser)
+ SAL_THROW((
+ css::container::NoSuchElementException, css::uno::RuntimeException)):
+ reader_(url), parser_(parser)
+{
+ OSL_ASSERT(parser.is());
+}
+
+bool ParseManager::parse() {
+ for (;;) {
+ switch (itemData_.is()
+ ? XmlReader::RESULT_BEGIN
+ : reader_.nextItem(
+ parser_->getTextMode(), &itemData_, &itemNamespace_))
+ {
+ case XmlReader::RESULT_BEGIN:
+ if (!parser_->startElement(reader_, itemNamespace_, itemData_))
+ {
+ return false;
+ }
+ break;
+ case XmlReader::RESULT_END:
+ parser_->endElement(reader_);
+ break;
+ case XmlReader::RESULT_TEXT:
+ parser_->characters(itemData_);
+ break;
+ case XmlReader::RESULT_DONE:
+ return true;
+ }
+ itemData_.clear();
+ }
+}
+
+ParseManager::~ParseManager() {}
+
+}
diff --git a/configmgr/source/parsemanager.hxx b/configmgr/source/parsemanager.hxx
new file mode 100644
index 000000000000..18292859ab98
--- /dev/null
+++ b/configmgr/source/parsemanager.hxx
@@ -0,0 +1,69 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_PARSEMANAGER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_PARSEMANAGER_HXX
+
+#include "sal/config.h"
+
+#include "com/sun/star/container/NoSuchElementException.hpp"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "rtl/ref.hxx"
+#include "sal/types.h"
+#include "salhelper/simplereferenceobject.hxx"
+
+#include "span.hxx"
+#include "xmlreader.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Parser;
+
+class ParseManager: public salhelper::SimpleReferenceObject {
+public:
+ ParseManager(
+ rtl::OUString const & url, rtl::Reference< Parser > const & parser)
+ SAL_THROW((
+ com::sun::star::container::NoSuchElementException,
+ com::sun::star::uno::RuntimeException));
+
+ bool parse();
+
+private:
+ virtual ~ParseManager();
+
+ XmlReader reader_;
+ rtl::Reference< Parser > parser_;
+ Span itemData_;
+ XmlReader::Namespace itemNamespace_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/parser.hxx b/configmgr/source/parser.hxx
new file mode 100644
index 000000000000..da29941953b5
--- /dev/null
+++ b/configmgr/source/parser.hxx
@@ -0,0 +1,62 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_PARSER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_PARSER_HXX
+
+#include "sal/config.h"
+
+#include <memory>
+
+#include "salhelper/simplereferenceobject.hxx"
+
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+struct Span;
+
+class Parser: public salhelper::SimpleReferenceObject {
+public:
+ virtual XmlReader::Text getTextMode() = 0;
+
+ virtual bool startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name) = 0;
+
+ virtual void endElement(XmlReader const & reader) = 0;
+
+ virtual void characters(Span const & text) = 0;
+
+protected:
+ Parser() {}
+
+ virtual ~Parser() {}
+};
+
+}
+
+#endif
diff --git a/configmgr/source/partial.cxx b/configmgr/source/partial.cxx
new file mode 100644
index 000000000000..4c9189ed05c4
--- /dev/null
+++ b/configmgr/source/partial.cxx
@@ -0,0 +1,137 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <map>
+#include <set>
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "data.hxx"
+#include "partial.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+bool parseSegment(
+ rtl::OUString const & path, sal_Int32 * index, rtl::OUString * segment)
+{
+ OSL_ASSERT(
+ index != 0 && *index >= 0 && *index <= path.getLength() &&
+ segment != 0);
+ if (path[(*index)++] == '/') {
+ rtl::OUString name;
+ bool setElement;
+ rtl::OUString templateName;
+ *index = Data::parseSegment(
+ path, *index, &name, &setElement, &templateName);
+ if (*index != -1) {
+ *segment = Data::createSegment(templateName, name);
+ return *index == path.getLength();
+ }
+ }
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) + path,
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+}
+
+Partial::Partial(
+ std::set< rtl::OUString > const & includedPaths,
+ std::set< rtl::OUString > const & excludedPaths)
+{
+ for (std::set< rtl::OUString >::const_iterator i(includedPaths.begin());
+ i != includedPaths.end(); ++i)
+ {
+ sal_Int32 n = 0;
+ for (Node * p = &root_;;) {
+ rtl::OUString seg;
+ bool end = parseSegment(*i, &n, &seg);
+ p = &p->children[seg];
+ if (p->startInclude) {
+ break;
+ }
+ if (end) {
+ p->children.clear();
+ p->startInclude = true;
+ break;
+ }
+ }
+ }
+ for (std::set< rtl::OUString >::const_iterator i(excludedPaths.begin());
+ i != excludedPaths.end(); ++i)
+ {
+ sal_Int32 n = 0;
+ for (Node * p = &root_;;) {
+ rtl::OUString seg;
+ bool end = parseSegment(*i, &n, &seg);
+ if (end) {
+ p->children[seg] = Node();
+ break;
+ }
+ Node::Children::iterator j(p->children.find(seg));
+ if (j == p->children.end()) {
+ break;
+ }
+ p = &j->second;
+ }
+ }
+}
+
+Partial::~Partial() {}
+
+Partial::Containment Partial::contains(Path const & path) const {
+ //TODO: For set elements, the segment names recorded in the node tree need
+ // not match the corresponding path segments, so this function can fail.
+ Node const * p = &root_;
+ bool includes = false;
+ for (Path::const_iterator i(path.begin()); i != path.end(); ++i) {
+ Node::Children::const_iterator j(p->children.find(*i));
+ if (j == p->children.end()) {
+ break;
+ }
+ p = &j->second;
+ includes |= p->startInclude;
+ }
+ return p->children.empty() && !p->startInclude
+ ? CONTAINS_NOT
+ : includes ? CONTAINS_NODE : CONTAINS_SUBNODES;
+}
+
+}
diff --git a/configmgr/source/partial.hxx b/configmgr/source/partial.hxx
new file mode 100644
index 000000000000..39931448c66d
--- /dev/null
+++ b/configmgr/source/partial.hxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_PARTIAL_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_PARTIAL_HXX
+
+#include "sal/config.h"
+
+#include <map>
+#include <set>
+
+#include "boost/noncopyable.hpp"
+
+#include "path.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Partial: private boost::noncopyable {
+public:
+ enum Containment { CONTAINS_NOT, CONTAINS_SUBNODES, CONTAINS_NODE };
+
+ Partial(
+ std::set< rtl::OUString > const & includedPaths,
+ std::set< rtl::OUString > const & excludedPaths);
+
+ ~Partial();
+
+ Containment contains(Path const & path) const;
+
+private:
+ struct Node {
+ typedef std::map< rtl::OUString, Node > Children;
+
+ Node(): startInclude(false) {}
+
+ Children children;
+ bool startInclude;
+ };
+
+ Node root_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/path.hxx b/configmgr/source/path.hxx
new file mode 100644
index 000000000000..fc70287dfe7b
--- /dev/null
+++ b/configmgr/source/path.hxx
@@ -0,0 +1,43 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_PATH_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_PATH_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+typedef std::vector< rtl::OUString > Path;
+
+}
+
+#endif
diff --git a/configmgr/source/propertynode.cxx b/configmgr/source/propertynode.cxx
new file mode 100644
index 000000000000..070b56d9be9a
--- /dev/null
+++ b/configmgr/source/propertynode.cxx
@@ -0,0 +1,110 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/beans/Optional.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "components.hxx"
+#include "node.hxx"
+#include "propertynode.hxx"
+#include "type.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+PropertyNode::PropertyNode(
+ int layer, Type staticType, bool nillable, css::uno::Any const & value,
+ bool extension):
+ Node(layer), staticType_(staticType), nillable_(nillable), value_(value),
+ extension_(extension)
+{}
+
+rtl::Reference< Node > PropertyNode::clone() const {
+ return new PropertyNode(*this);
+}
+
+Type PropertyNode::getStaticType() const {
+ return staticType_;
+}
+
+bool PropertyNode::isNillable() const {
+ return nillable_;
+}
+
+css::uno::Any PropertyNode::getValue(Components & components) {
+ if (externalDescriptor_.getLength() != 0) {
+ css::beans::Optional< css::uno::Any > val(
+ components.getExternalValue(externalDescriptor_));
+ if (val.IsPresent) {
+ value_ = val.Value; //TODO: check value type
+ }
+ externalDescriptor_ = rtl::OUString(); // must not throw
+ }
+ return value_;
+}
+
+void PropertyNode::setValue(int layer, css::uno::Any const & value) {
+ setLayer(layer);
+ value_ = value;
+ externalDescriptor_ = rtl::OUString();
+}
+
+void PropertyNode::setExternal(int layer, rtl::OUString const & descriptor) {
+ OSL_ASSERT(descriptor.getLength() != 0);
+ setLayer(layer);
+ externalDescriptor_ = descriptor;
+}
+
+bool PropertyNode::isExtension() const {
+ return extension_;
+}
+
+PropertyNode::PropertyNode(PropertyNode const & other):
+ Node(other), staticType_(other.staticType_), nillable_(other.nillable_),
+ value_(other.value_), externalDescriptor_(other.externalDescriptor_),
+ extension_(other.extension_)
+{}
+
+PropertyNode::~PropertyNode() {}
+
+Node::Kind PropertyNode::kind() const {
+ return KIND_PROPERTY;
+}
+
+}
diff --git a/configmgr/source/propertynode.hxx b/configmgr/source/propertynode.hxx
new file mode 100644
index 000000000000..1566cbf72dbe
--- /dev/null
+++ b/configmgr/source/propertynode.hxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_PROPERTYNODE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_PROPERTYNODE_HXX
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Any.hxx"
+#include "rtl/ref.hxx"
+
+#include "node.hxx"
+#include "type.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Components;
+
+class PropertyNode: public Node {
+public:
+ PropertyNode(
+ int layer, Type staticType, bool nillable,
+ com::sun::star::uno::Any const & value, bool extension);
+
+ virtual rtl::Reference< Node > clone() const;
+
+ Type getStaticType() const;
+
+ bool isNillable() const;
+
+ com::sun::star::uno::Any getValue(Components & components);
+
+ void setValue(int layer, com::sun::star::uno::Any const & value);
+
+ void setExternal(int layer, rtl::OUString const & descriptor);
+
+ bool isExtension() const;
+
+private:
+ PropertyNode(PropertyNode const & other);
+
+ virtual ~PropertyNode();
+
+ virtual Kind kind() const;
+
+ Type staticType_;
+ // as specified in the component-schema (TYPE_ANY, ...,
+ // TYPE_HEXBINARY_LIST; not TYPE_ERROR or TYPE_NIL)
+ bool nillable_;
+ com::sun::star::uno::Any value_;
+ rtl::OUString externalDescriptor_;
+ bool extension_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/rootaccess.cxx b/configmgr/source/rootaccess.cxx
new file mode 100644
index 000000000000..f8ccc6a31546
--- /dev/null
+++ b/configmgr/source/rootaccess.cxx
@@ -0,0 +1,319 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <vector>
+
+#include "com/sun/star/lang/DisposedException.hpp"
+#include "com/sun/star/lang/EventObject.hpp"
+#include "com/sun/star/lang/WrappedTargetException.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Type.hxx"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "com/sun/star/util/ChangesEvent.hpp"
+#include "com/sun/star/util/ChangesSet.hpp"
+#include "com/sun/star/util/ElementChange.hpp"
+#include "com/sun/star/util/XChangesBatch.hpp"
+#include "com/sun/star/util/XChangesListener.hpp"
+#include "com/sun/star/util/XChangesNotifier.hpp"
+#include "comphelper/sequenceasvector.hxx"
+#include "cppu/unotype.hxx"
+#include "cppuhelper/queryinterface.hxx"
+#include "cppuhelper/weak.hxx"
+#include "osl/diagnose.h"
+#include "osl/mutex.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "broadcaster.hxx"
+#include "childaccess.hxx"
+#include "components.hxx"
+#include "data.hxx"
+#include "lock.hxx"
+#include "modifications.hxx"
+#include "node.hxx"
+#include "path.hxx"
+#include "rootaccess.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+RootAccess::RootAccess(
+ Components & components, rtl::OUString const & pathRepresentation,
+ rtl::OUString const & locale, bool update):
+ Access(components), pathRepresentation_(pathRepresentation),
+ locale_(locale), update_(update)
+{}
+
+Path RootAccess::getAbsolutePath() {
+ getNode();
+ return path_;
+}
+
+void RootAccess::initBroadcaster(
+ Modifications::Node const & modifications, Broadcaster * broadcaster)
+{
+ OSL_ASSERT(broadcaster != 0);
+ comphelper::SequenceAsVector< css::util::ElementChange > changes;
+ initBroadcasterAndChanges(
+ modifications, broadcaster, changesListeners_.empty() ? 0 : &changes);
+ if (!changes.empty()) {
+ css::util::ChangesSet set(changes.getAsConstList());
+ for (ChangesListeners::iterator i(changesListeners_.begin());
+ i != changesListeners_.end(); ++i)
+ {
+ broadcaster->addChangesNotification(
+ *i,
+ css::util::ChangesEvent(
+ static_cast< cppu::OWeakObject * >(this),
+ css::uno::makeAny(pathRepresentation_), set));
+ }
+ }
+}
+
+void RootAccess::acquire() throw () {
+ Access::acquire();
+}
+
+void RootAccess::release() throw () {
+ Access::release();
+}
+
+rtl::OUString RootAccess::getLocale() const {
+ return locale_;
+}
+
+bool RootAccess::isUpdate() const {
+ return update_;
+}
+
+RootAccess::~RootAccess() {
+ osl::MutexGuard g(lock);
+ getComponents().removeRootAccess(this);
+}
+
+Path RootAccess::getRelativePath() {
+ return Path();
+}
+
+rtl::OUString RootAccess::getRelativePathRepresentation() {
+ return rtl::OUString();
+}
+
+rtl::Reference< Node > RootAccess::getNode() {
+ if (!node_.is()) {
+ int finalizedLayer;
+ node_ = getComponents().resolvePathRepresentation(
+ pathRepresentation_, &path_, &finalizedLayer);
+ if (!node_.is()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot find ")) +
+ pathRepresentation_),
+ 0);
+ // RootAccess::queryInterface indirectly calls
+ // RootAccess::getNode, so if this RootAccess were passed out in
+ // RuntimeException.Context, client code that called
+ // queryInterface on it would cause trouble; therefore,
+ // RuntimeException.Context is left null here
+ }
+ OSL_ASSERT(!path_.empty());
+ name_ = path_.back();
+ finalized_ = finalizedLayer != Data::NO_LAYER;
+ }
+ return node_;
+}
+
+bool RootAccess::isFinalized() {
+ getNode();
+ return finalized_;
+}
+
+rtl::OUString RootAccess::getNameInternal() {
+ getNode();
+ return name_;
+}
+
+rtl::Reference< RootAccess > RootAccess::getRootAccess() {
+ return this;
+}
+
+rtl::Reference< Access > RootAccess::getParentAccess() {
+ return rtl::Reference< Access >();
+}
+
+void RootAccess::addTypes(std::vector< css::uno::Type > * types) const {
+ OSL_ASSERT(types != 0);
+ types->push_back(cppu::UnoType< css::util::XChangesNotifier >::get());
+ types->push_back(cppu::UnoType< css::util::XChangesBatch >::get());
+}
+
+void RootAccess::addSupportedServiceNames(
+ std::vector< rtl::OUString > * services)
+{
+ OSL_ASSERT(services != 0);
+ services->push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.AccessRootElement")));
+ if (update_) {
+ services->push_back(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.UpdateRootElement")));
+ }
+}
+
+void RootAccess::initDisposeBroadcaster(Broadcaster * broadcaster) {
+ OSL_ASSERT(broadcaster != 0);
+ for (ChangesListeners::iterator i(changesListeners_.begin());
+ i != changesListeners_.end(); ++i)
+ {
+ broadcaster->addDisposeNotification(
+ i->get(),
+ css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
+ }
+ Access::initDisposeBroadcaster(broadcaster);
+}
+
+void RootAccess::clearListeners() throw() {
+ changesListeners_.clear();
+ Access::clearListeners();
+}
+
+css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType)
+ throw (css::uno::RuntimeException)
+{
+ OSL_ASSERT(thisIs(IS_ANY));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ css::uno::Any res(Access::queryInterface(aType));
+ if (res.hasValue()) {
+ return res;
+ }
+ res = cppu::queryInterface(
+ aType, static_cast< css::util::XChangesNotifier * >(this));
+ if (res.hasValue()) {
+ return res;
+ }
+ if (!res.hasValue() && update_) {
+ res = cppu::queryInterface(
+ aType, static_cast< css::util::XChangesBatch * >(this));
+ }
+ return res;
+}
+
+void RootAccess::addChangesListener(
+ css::uno::Reference< css::util::XChangesListener > const & aListener)
+ throw (css::uno::RuntimeException)
+{
+ OSL_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)
+{
+ OSL_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)
+{
+ OSL_ASSERT(thisIs(IS_UPDATE));
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ int finalizedLayer;
+ Modifications globalMods;
+ commitChildChanges(
+ ((getComponents().resolvePathRepresentation(
+ pathRepresentation_, 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) {
+ OSL_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)
+{
+ OSL_ASSERT(thisIs(IS_UPDATE));
+ osl::MutexGuard g(lock);
+ checkLocalizedPropertyAccess();
+ comphelper::SequenceAsVector< css::util::ElementChange > changes;
+ reportChildChanges(&changes);
+ return changes.getAsConstList();
+}
+
+}
diff --git a/configmgr/source/rootaccess.hxx b/configmgr/source/rootaccess.hxx
new file mode 100644
index 000000000000..45d4193d70de
--- /dev/null
+++ b/configmgr/source/rootaccess.hxx
@@ -0,0 +1,155 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_ROOTACCESS_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_ROOTACCESS_HXX
+
+#include "sal/config.h"
+
+#include <set>
+#include <vector>
+
+#include "com/sun/star/lang/WrappedTargetException.hpp"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/util/ChangesSet.hpp"
+#include "com/sun/star/util/XChangesBatch.hpp"
+#include "com/sun/star/util/XChangesNotifier.hpp"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "access.hxx"
+#include "modifications.hxx"
+#include "path.hxx"
+
+namespace com { namespace sun { namespace star {
+ namespace uno {
+ class Any;
+ class Type;
+ }
+ namespace util { class XChangesListener; }
+} } }
+
+namespace configmgr {
+
+class Broadcaster;
+class Components;
+class Node;
+
+class RootAccess:
+ public Access, public com::sun::star::util::XChangesNotifier,
+ public com::sun::star::util::XChangesBatch
+{
+public:
+ RootAccess(
+ Components & components, rtl::OUString const & pathRepresenation,
+ rtl::OUString const & locale, bool update);
+
+ virtual Path getAbsolutePath();
+
+ virtual void initBroadcaster(
+ Modifications::Node const & modifications, Broadcaster * broadcaster);
+
+ virtual void SAL_CALL acquire() throw ();
+
+ virtual void SAL_CALL release() throw ();
+
+ rtl::OUString getLocale() const;
+
+ bool isUpdate() const;
+
+private:
+ virtual ~RootAccess();
+
+ virtual Path getRelativePath();
+
+ virtual rtl::OUString getRelativePathRepresentation();
+
+ virtual rtl::Reference< Node > getNode();
+
+ virtual bool isFinalized();
+
+ virtual rtl::OUString getNameInternal();
+
+ virtual rtl::Reference< RootAccess > getRootAccess();
+
+ virtual rtl::Reference< Access > getParentAccess();
+
+ virtual void addTypes(std::vector< com::sun::star::uno::Type > * types)
+ const;
+
+ virtual void addSupportedServiceNames(
+ std::vector< rtl::OUString > * services);
+
+ 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);
+
+ 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()
+ throw (com::sun::star::uno::RuntimeException);
+
+ typedef
+ std::multiset<
+ com::sun::star::uno::Reference<
+ com::sun::star::util::XChangesListener > >
+ ChangesListeners;
+
+ rtl::OUString pathRepresentation_;
+ rtl::OUString locale_;
+ bool update_;
+ Path path_;
+ rtl::Reference< Node > node_;
+ rtl::OUString name_;
+ bool finalized_;
+ ChangesListeners changesListeners_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/services.cxx b/configmgr/source/services.cxx
new file mode 100644
index 000000000000..3a009b3cee15
--- /dev/null
+++ b/configmgr/source/services.cxx
@@ -0,0 +1,118 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/registry/XRegistryKey.hpp"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppuhelper/implementationentry.hxx"
+#include "osl/diagnose.h"
+#include "uno/lbnames.h"
+#include "rtl/textenc.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "configurationprovider.hxx"
+#include "configurationregistry.hxx"
+#include "defaultprovider.hxx"
+
+namespace {
+
+namespace css = com::sun::star;
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL dummy(
+ css::uno::Reference< css::uno::XComponentContext > const &)
+ SAL_THROW((css::uno::Exception))
+{
+ OSL_ASSERT(false);
+ return css::uno::Reference< css::uno::XInterface >();
+}
+
+static cppu::ImplementationEntry const services[] = {
+ { &dummy, &configmgr::configuration_provider::getImplementationName,
+ &configmgr::configuration_provider::getSupportedServiceNames,
+ &configmgr::configuration_provider::createFactory, 0, 0 },
+ { &dummy, &configmgr::default_provider::getImplementationName,
+ &configmgr::default_provider::getSupportedServiceNames,
+ &configmgr::default_provider::createFactory, 0, 0 },
+ { &dummy, &configmgr::configuration_registry::getImplementationName,
+ &configmgr::configuration_registry::getSupportedServiceNames,
+ &configmgr::configuration_registry::createFactory, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
+ char const * pImplName, void * pServiceManager, void * pRegistryKey)
+{
+ return cppu::component_getFactoryHelper(
+ pImplName, pServiceManager, pRegistryKey, services);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL
+component_getImplementationEnvironment(
+ char const ** ppEnvTypeName, uno_Environment **)
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(
+ void * pServiceManager, void * pRegistryKey)
+{
+ if (!component_writeInfoHelper(pServiceManager, pRegistryKey, services)) {
+ return false;
+ }
+ try {
+ css::uno::Reference< css::registry::XRegistryKey >(
+ (css::uno::Reference< css::registry::XRegistryKey >(
+ static_cast< css::registry::XRegistryKey * >(pRegistryKey))->
+ createKey(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "/com.sun.star.comp.configuration.DefaultProvider/UNO/"
+ "SINGLETONS/"
+ "com.sun.star.configuration.theDefaultProvider")))),
+ css::uno::UNO_SET_THROW)->
+ setStringValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.DefaultProvider")));
+ } catch (css::uno::Exception & e) {
+ (void) e;
+ OSL_TRACE(
+ "configmgr component_writeInfo exception: %s",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ return false;
+ }
+ return true;
+}
diff --git a/configmgr/source/setnode.cxx b/configmgr/source/setnode.cxx
new file mode 100644
index 000000000000..f19c36c0bba5
--- /dev/null
+++ b/configmgr/source/setnode.cxx
@@ -0,0 +1,126 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "data.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "setnode.hxx"
+
+namespace configmgr {
+
+namespace {
+
+// Work around some compilers' failure to accept
+// std::binder1st(std::ptr_fun(&Data::equalTemplateNames), ...):
+class EqualTemplateNames:
+ public std::unary_function< rtl::OUString const &, bool >
+{
+public:
+ inline explicit EqualTemplateNames(rtl::OUString const & shortName):
+ shortName_(shortName) {}
+
+ inline bool operator ()(rtl::OUString const & longName) const
+ { return Data::equalTemplateNames(shortName_, longName); }
+
+private:
+ rtl::OUString const & shortName_;
+};
+
+}
+
+SetNode::SetNode(
+ int layer, rtl::OUString const & defaultTemplateName,
+ rtl::OUString const & templateName):
+ Node(layer), defaultTemplateName_(defaultTemplateName),
+ templateName_(templateName), mandatory_(Data::NO_LAYER)
+{}
+
+rtl::Reference< Node > SetNode::clone() const {
+ return new SetNode(*this);
+}
+
+NodeMap & SetNode::getMembers() {
+ return members_;
+}
+
+rtl::OUString SetNode::getTemplateName() const {
+ return templateName_;
+}
+
+void SetNode::setMandatory(int layer) {
+ mandatory_ = layer;
+}
+
+int SetNode::getMandatory() const {
+ return mandatory_;
+}
+
+rtl::OUString const & SetNode::getDefaultTemplateName() const {
+ return defaultTemplateName_;
+}
+
+std::vector< rtl::OUString > & SetNode::getAdditionalTemplateNames() {
+ return additionalTemplateNames_;
+}
+
+bool SetNode::isValidTemplate(rtl::OUString const & templateName) const {
+ return Data::equalTemplateNames(templateName, defaultTemplateName_) ||
+ (std::find_if(
+ additionalTemplateNames_.begin(),
+ additionalTemplateNames_.end(), EqualTemplateNames(templateName)) !=
+ additionalTemplateNames_.end());
+}
+
+SetNode::SetNode(SetNode const & other):
+ Node(other), defaultTemplateName_(other.defaultTemplateName_),
+ additionalTemplateNames_(other.additionalTemplateNames_),
+ templateName_(other.templateName_), mandatory_(other.mandatory_)
+{
+ cloneNodeMap(other.members_, &members_);
+}
+
+SetNode::~SetNode() {}
+
+Node::Kind SetNode::kind() const {
+ return KIND_SET;
+}
+
+void SetNode::clear() {
+ members_.clear();
+}
+
+}
diff --git a/configmgr/source/setnode.hxx b/configmgr/source/setnode.hxx
new file mode 100644
index 000000000000..7bf1ab0a199e
--- /dev/null
+++ b/configmgr/source/setnode.hxx
@@ -0,0 +1,84 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_SETNODE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_SETNODE_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "node.hxx"
+#include "nodemap.hxx"
+
+namespace configmgr {
+
+class SetNode: public Node {
+public:
+ SetNode(
+ int layer, rtl::OUString const & defaultTemplateName,
+ rtl::OUString const & templateName);
+
+ virtual rtl::Reference< Node > clone() const;
+
+ virtual NodeMap & getMembers();
+
+ virtual rtl::OUString getTemplateName() const;
+
+ virtual void setMandatory(int layer);
+
+ virtual int getMandatory() const;
+
+ rtl::OUString const & getDefaultTemplateName() const;
+
+ std::vector< rtl::OUString > & getAdditionalTemplateNames();
+
+ bool isValidTemplate(rtl::OUString const & templateName) const;
+
+private:
+ SetNode(SetNode const & other);
+
+ virtual ~SetNode();
+
+ virtual Kind kind() const;
+
+ virtual void clear();
+
+ rtl::OUString defaultTemplateName_;
+ std::vector< rtl::OUString > additionalTemplateNames_;
+ NodeMap members_;
+ rtl::OUString templateName_;
+ // non-empty iff this node is a template, free node, or set member
+ int mandatory_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/span.hxx b/configmgr/source/span.hxx
new file mode 100644
index 000000000000..689618613700
--- /dev/null
+++ b/configmgr/source/span.hxx
@@ -0,0 +1,64 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_SPAN_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_SPAN_HXX
+
+#include "sal/config.h"
+
+#include "rtl/string.h"
+#include "sal/types.h"
+
+namespace configmgr {
+
+struct Span {
+ char const * begin;
+ sal_Int32 length;
+
+ inline Span(): begin(0), length(0) {}
+ // init length to avoid compiler warnings
+
+ inline Span(char const * theBegin, sal_Int32 theLength):
+ begin(theBegin), length(theLength) {}
+
+ inline void clear() throw() { begin = 0; }
+
+ inline bool is() const { return begin != 0; }
+
+ inline bool equals(Span const & text) const {
+ return rtl_str_compare_WithLength(
+ begin, length, text.begin, text.length) == 0;
+ }
+
+ inline bool equals(char const * textBegin, sal_Int32 textLength) const {
+ return equals(Span(textBegin, textLength));
+ }
+};
+
+}
+
+#endif
diff --git a/configmgr/source/type.cxx b/configmgr/source/type.cxx
new file mode 100644
index 000000000000..e1b8a95859ef
--- /dev/null
+++ b/configmgr/source/type.cxx
@@ -0,0 +1,187 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/Type.hxx"
+#include "com/sun/star/uno/TypeClass.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "cppu/unotype.hxx"
+#include "osl/diagnose.h"
+#include "rtl/string.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "type.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+bool isListType(Type type) {
+ return type >= TYPE_BOOLEAN_LIST;
+}
+
+Type elementType(Type type) {
+ switch (type) {
+ case TYPE_BOOLEAN_LIST:
+ return TYPE_BOOLEAN;
+ case TYPE_SHORT_LIST:
+ return TYPE_SHORT;
+ case TYPE_INT_LIST:
+ return TYPE_INT;
+ case TYPE_LONG_LIST:
+ return TYPE_LONG;
+ case TYPE_DOUBLE_LIST:
+ return TYPE_DOUBLE;
+ case TYPE_STRING_LIST:
+ return TYPE_STRING;
+ case TYPE_HEXBINARY_LIST:
+ return TYPE_HEXBINARY;
+ default:
+ OSL_ASSERT(false);
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+css::uno::Type mapType(Type type) {
+ switch (type) {
+ case TYPE_ANY:
+ return cppu::UnoType< css::uno::Any >::get();
+ case TYPE_BOOLEAN:
+ return cppu::UnoType< sal_Bool >::get();
+ case TYPE_SHORT:
+ return cppu::UnoType< sal_Int16 >::get();
+ case TYPE_INT:
+ return cppu::UnoType< sal_Int32 >::get();
+ case TYPE_LONG:
+ return cppu::UnoType< sal_Int64 >::get();
+ case TYPE_DOUBLE:
+ return cppu::UnoType< double >::get();
+ case TYPE_STRING:
+ return cppu::UnoType< rtl::OUString >::get();
+ case TYPE_HEXBINARY:
+ return cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get();
+ case TYPE_BOOLEAN_LIST:
+ return cppu::UnoType< css::uno::Sequence< sal_Bool > >::get();
+ case TYPE_SHORT_LIST:
+ return cppu::UnoType< css::uno::Sequence< sal_Int16 > >::get();
+ case TYPE_INT_LIST:
+ return cppu::UnoType< css::uno::Sequence< sal_Int32 > >::get();
+ case TYPE_LONG_LIST:
+ return cppu::UnoType< css::uno::Sequence< sal_Int64 > >::get();
+ case TYPE_DOUBLE_LIST:
+ return cppu::UnoType< css::uno::Sequence< double > >::get();
+ case TYPE_STRING_LIST:
+ return cppu::UnoType< css::uno::Sequence< rtl::OUString > >::get();
+ case TYPE_HEXBINARY_LIST:
+ return cppu::UnoType<
+ css::uno::Sequence< css::uno::Sequence< sal_Int8 > > >::get();
+ default:
+ OSL_ASSERT(false);
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+Type getDynamicType(css::uno::Any const & value) {
+ switch (value.getValueType().getTypeClass()) {
+ case css::uno::TypeClass_VOID:
+ return TYPE_NIL;
+ case css::uno::TypeClass_BOOLEAN:
+ return TYPE_BOOLEAN;
+ case css::uno::TypeClass_BYTE:
+ return TYPE_SHORT;
+ case css::uno::TypeClass_SHORT:
+ return TYPE_SHORT;
+ case css::uno::TypeClass_UNSIGNED_SHORT:
+ return value.has< sal_Int16 >() ? TYPE_SHORT : TYPE_INT;
+ case css::uno::TypeClass_LONG:
+ return TYPE_INT;
+ case css::uno::TypeClass_UNSIGNED_LONG:
+ return value.has< sal_Int32 >() ? TYPE_INT : TYPE_LONG;
+ case css::uno::TypeClass_HYPER:
+ return TYPE_LONG;
+ case css::uno::TypeClass_UNSIGNED_HYPER:
+ return value.has< sal_Int64 >() ? TYPE_LONG : TYPE_ERROR;
+ case css::uno::TypeClass_FLOAT:
+ case css::uno::TypeClass_DOUBLE:
+ return TYPE_DOUBLE;
+ case css::uno::TypeClass_STRING:
+ return TYPE_STRING;
+ case css::uno::TypeClass_SEQUENCE: //TODO
+ {
+ rtl::OUString name(value.getValueType().getTypeName());
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("[]byte"))) {
+ return TYPE_HEXBINARY;
+ } else if (name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("[]boolean")))
+ {
+ return TYPE_BOOLEAN_LIST;
+ } else if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("[]short")))
+ {
+ return TYPE_SHORT_LIST;
+ } else if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("[]long")))
+ {
+ return TYPE_INT_LIST;
+ } else if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("[]hyper")))
+ {
+ return TYPE_LONG_LIST;
+ } else if (name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("[]double")))
+ {
+ return TYPE_DOUBLE_LIST;
+ } else if (name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("[]string")))
+ {
+ return TYPE_STRING_LIST;
+ } else if (name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("[][]byte")))
+ {
+ return TYPE_HEXBINARY_LIST;
+ }
+ }
+ // fall through
+ default:
+ return TYPE_ERROR;
+ }
+}
+
+}
diff --git a/configmgr/source/type.hxx b/configmgr/source/type.hxx
new file mode 100644
index 000000000000..85edc9b5e9cd
--- /dev/null
+++ b/configmgr/source/type.hxx
@@ -0,0 +1,56 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_TYPE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_TYPE_HXX
+
+#include "sal/config.h"
+
+namespace com { namespace sun { namespace star { namespace uno {
+ class Any;
+ class Type;
+} } } }
+
+namespace configmgr {
+
+enum Type {
+ TYPE_ERROR, TYPE_NIL, TYPE_ANY, TYPE_BOOLEAN, TYPE_SHORT, TYPE_INT,
+ TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_HEXBINARY, TYPE_BOOLEAN_LIST,
+ TYPE_SHORT_LIST, TYPE_INT_LIST, TYPE_LONG_LIST, TYPE_DOUBLE_LIST,
+ TYPE_STRING_LIST, TYPE_HEXBINARY_LIST };
+
+bool isListType(Type type);
+
+Type elementType(Type type);
+
+com::sun::star::uno::Type mapType(Type type);
+
+Type getDynamicType(com::sun::star::uno::Any const & value);
+
+}
+
+#endif
diff --git a/configmgr/source/update.cxx b/configmgr/source/update.cxx
new file mode 100644
index 000000000000..57f45068d954
--- /dev/null
+++ b/configmgr/source/update.cxx
@@ -0,0 +1,85 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <set>
+
+#include "configmgr/update.hxx"
+#include "osl/mutex.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "broadcaster.hxx"
+#include "components.hxx"
+#include "lock.hxx"
+#include "modifications.hxx"
+#include "rootaccess.hxx"
+
+namespace configmgr {
+
+namespace update {
+
+void insertExtensionXcsFile(bool shared, rtl::OUString const & fileUri) {
+ osl::MutexGuard g(lock);
+ Components::getSingleton().insertExtensionXcsFile(shared, fileUri);
+}
+
+void insertExtensionXcuFile(bool shared, rtl::OUString const & fileUri) {
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ Modifications mods;
+ Components::getSingleton().insertExtensionXcuFile(
+ shared, fileUri, &mods);
+ Components::getSingleton().initGlobalBroadcaster(
+ mods, rtl::Reference< RootAccess >(), &bc);
+ }
+ bc.send();
+}
+
+void insertModificationXcuFile(
+ rtl::OUString const & fileUri,
+ std::set< rtl::OUString > const & includedPaths,
+ std::set< rtl::OUString > const & excludedPaths)
+{
+ Broadcaster bc;
+ {
+ osl::MutexGuard g(lock);
+ Modifications mods;
+ Components::getSingleton().insertModificationXcuFile(
+ fileUri, includedPaths, excludedPaths, &mods);
+ Components::getSingleton().initGlobalBroadcaster(
+ mods, rtl::Reference< RootAccess >(), &bc);
+ }
+ bc.send();
+}
+
+}
+
+}
diff --git a/configmgr/source/valueparser.cxx b/configmgr/source/valueparser.cxx
new file mode 100644
index 000000000000..4adf452c409b
--- /dev/null
+++ b/configmgr/source/valueparser.cxx
@@ -0,0 +1,470 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "com/sun/star/uno/Any.hxx"
+#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/XInterface.hpp"
+#include "comphelper/sequenceasvector.hxx"
+#include "osl/diagnose.h"
+#include "rtl/string.h"
+#include "rtl/string.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "localizedvaluenode.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "propertynode.hxx"
+#include "span.hxx"
+#include "type.hxx"
+#include "valueparser.hxx"
+#include "xmldata.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+bool parseHexDigit(char c, int * value) {
+ OSL_ASSERT(value != 0);
+ if (c >= '0' && c <= '9') {
+ *value = c - '0';
+ return true;
+ }
+ if (c >= 'A' && c <= 'F') {
+ *value = c - 'A' + 10;
+ return true;
+ }
+ if (c >= 'a' && c <= 'f') {
+ *value = c - 'a' + 10;
+ return true;
+ }
+ return false;
+}
+
+bool parseValue(Span const & text, sal_Bool * value) {
+ OSL_ASSERT(text.is() && value != 0);
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("true")) ||
+ text.equals(RTL_CONSTASCII_STRINGPARAM("1")))
+ {
+ *value = true;
+ return true;
+ }
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("false")) ||
+ text.equals(RTL_CONSTASCII_STRINGPARAM("0")))
+ {
+ *value = false;
+ return true;
+ }
+ return false;
+}
+
+bool parseValue(Span const & text, sal_Int16 * value) {
+ OSL_ASSERT(text.is() && value != 0);
+ // For backwards compatibility, support hexadecimal values:
+ sal_Int32 n =
+ rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ text.begin, text.length, RTL_CONSTASCII_STRINGPARAM("0X"),
+ RTL_CONSTASCII_LENGTH("0X")) == 0 ?
+ rtl::OString(
+ text.begin + RTL_CONSTASCII_LENGTH("0X"),
+ text.length - RTL_CONSTASCII_LENGTH("0X")).toInt32(16) :
+ rtl::OString(text.begin, text.length).toInt32();
+ //TODO: check valid lexical representation
+ if (n >= SAL_MIN_INT16 && n <= SAL_MAX_INT16) {
+ *value = static_cast< sal_Int16 >(n);
+ return true;
+ }
+ return false;
+}
+
+bool parseValue(Span const & text, sal_Int32 * value) {
+ OSL_ASSERT(text.is() && value != 0);
+ // For backwards compatibility, support hexadecimal values:
+ *value =
+ rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ text.begin, text.length, RTL_CONSTASCII_STRINGPARAM("0X"),
+ RTL_CONSTASCII_LENGTH("0X")) == 0 ?
+ rtl::OString(
+ text.begin + RTL_CONSTASCII_LENGTH("0X"),
+ text.length - RTL_CONSTASCII_LENGTH("0X")).toInt32(16) :
+ rtl::OString(text.begin, text.length).toInt32();
+ //TODO: check valid lexical representation
+ return true;
+}
+
+bool parseValue(Span const & text, sal_Int64 * value) {
+ OSL_ASSERT(text.is() && value != 0);
+ // For backwards compatibility, support hexadecimal values:
+ *value =
+ rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ text.begin, text.length, RTL_CONSTASCII_STRINGPARAM("0X"),
+ RTL_CONSTASCII_LENGTH("0X")) == 0 ?
+ rtl::OString(
+ text.begin + RTL_CONSTASCII_LENGTH("0X"),
+ text.length - RTL_CONSTASCII_LENGTH("0X")).toInt64(16) :
+ rtl::OString(text.begin, text.length).toInt64();
+ //TODO: check valid lexical representation
+ return true;
+}
+
+bool parseValue(Span const & text, double * value) {
+ OSL_ASSERT(text.is() && value != 0);
+ *value = rtl::OString(text.begin, text.length).toDouble();
+ //TODO: check valid lexical representation
+ return true;
+}
+
+bool parseValue(Span const & text, rtl::OUString * value) {
+ OSL_ASSERT(text.is() && value != 0);
+ *value = xmldata::convertFromUtf8(text);
+ return true;
+}
+
+bool parseValue(Span const & text, css::uno::Sequence< sal_Int8 > * value) {
+ OSL_ASSERT(text.is() && value != 0);
+ if ((text.length & 1) != 0) {
+ return false;
+ }
+ comphelper::SequenceAsVector< sal_Int8 > seq;
+ for (sal_Int32 i = 0; i != text.length;) {
+ int n1;
+ int n2;
+ if (!parseHexDigit(text.begin[i++], &n1) ||
+ !parseHexDigit(text.begin[i++], &n2))
+ {
+ return false;
+ }
+ seq.push_back(static_cast< sal_Int8 >((n1 << 4) | n2));
+ }
+ *value = seq.getAsConstList();
+ return true;
+}
+
+template< typename T > css::uno::Any parseSingleValue(Span const & text) {
+ T val;
+ if (!parseValue(text, &val)) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid value")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return css::uno::makeAny(val);
+}
+
+template< typename T > css::uno::Any parseListValue(
+ rtl::OString const & separator, Span const & text)
+{
+ comphelper::SequenceAsVector< T > seq;
+ Span sep;
+ if (separator.getLength() == 0) {
+ sep = Span(RTL_CONSTASCII_STRINGPARAM(" "));
+ } else {
+ sep = Span(separator.getStr(), separator.getLength());
+ }
+ if (text.length != 0) {
+ for (Span t(text);;) {
+ sal_Int32 i = rtl_str_indexOfStr_WithLength(
+ t.begin, t.length, sep.begin, sep.length);
+ T val;
+ if (!parseValue(Span(t.begin, i == -1 ? t.length : i), &val)) {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid value")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ seq.push_back(val);
+ if (i < 0) {
+ break;
+ }
+ t.begin += i + sep.length;
+ t.length -= i + sep.length;
+ }
+ }
+ return css::uno::makeAny(seq.getAsConstList());
+}
+
+css::uno::Any parseValue(
+ rtl::OString const & separator, Span const & text, Type type)
+{
+ switch (type) {
+ case TYPE_ANY:
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("invalid value of type any")),
+ css::uno::Reference< css::uno::XInterface >());
+ case TYPE_BOOLEAN:
+ return parseSingleValue< sal_Bool >(text);
+ case TYPE_SHORT:
+ return parseSingleValue< sal_Int16 >(text);
+ case TYPE_INT:
+ return parseSingleValue< sal_Int32 >(text);
+ case TYPE_LONG:
+ return parseSingleValue< sal_Int64 >(text);
+ case TYPE_DOUBLE:
+ return parseSingleValue< double >(text);
+ case TYPE_STRING:
+ return parseSingleValue< rtl::OUString >(text);
+ case TYPE_HEXBINARY:
+ return parseSingleValue< css::uno::Sequence< sal_Int8 > >(text);
+ case TYPE_BOOLEAN_LIST:
+ return parseListValue< sal_Bool >(separator, text);
+ case TYPE_SHORT_LIST:
+ return parseListValue< sal_Int16 >(separator, text);
+ case TYPE_INT_LIST:
+ return parseListValue< sal_Int32 >(separator, text);
+ case TYPE_LONG_LIST:
+ return parseListValue< sal_Int64 >(separator, text);
+ case TYPE_DOUBLE_LIST:
+ return parseListValue< double >(separator, text);
+ case TYPE_STRING_LIST:
+ return parseListValue< rtl::OUString >(separator, text);
+ case TYPE_HEXBINARY_LIST:
+ return parseListValue< css::uno::Sequence< sal_Int8 > >(
+ separator, text);
+ default:
+ OSL_ASSERT(false);
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+}
+
+ValueParser::ValueParser(int layer): layer_(layer) {}
+
+ValueParser::~ValueParser() {}
+
+XmlReader::Text ValueParser::getTextMode() const {
+ if (node_.is()) {
+ switch (state_) {
+ case STATE_TEXT:
+ if (!items_.empty()) {
+ break;
+ }
+ // fall through
+ case STATE_IT:
+ return
+ (type_ == TYPE_STRING || type_ == TYPE_STRING_LIST ||
+ separator_.getLength() != 0)
+ ? XmlReader::TEXT_RAW : XmlReader::TEXT_NORMALIZED;
+ default:
+ break;
+ }
+ }
+ return XmlReader::TEXT_NONE;
+}
+
+bool ValueParser::startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name)
+{
+ if (!node_.is()) {
+ return false;
+ }
+ switch (state_) {
+ case STATE_TEXT:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("it")) &&
+ isListType(type_) && separator_.getLength() == 0)
+ {
+ pad_.clear();
+ // before first <it>, characters are not ignored; assume they
+ // are only whitespace
+ state_ = STATE_IT;
+ return true;
+ }
+ // fall through
+ case STATE_IT:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("unicode")) &&
+ (type_ == TYPE_STRING || type_ == TYPE_STRING_LIST))
+ {
+ sal_Int32 scalar = -1;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("scalar")))
+ {
+ if (!parseValue(reader.getAttributeValue(true), &scalar)) {
+ scalar = -1;
+ }
+ break;
+ }
+ }
+ if (scalar >= 0 && scalar < 0x20 && scalar != 0x09 &&
+ scalar != 0x0A && scalar != 0x0D)
+ {
+ char c = static_cast< char >(scalar);
+ pad_.add(&c, 1);
+ } else if (scalar == 0xFFFE) {
+ pad_.add(RTL_CONSTASCII_STRINGPARAM("\xEF\xBF\xBE"));
+ } else if (scalar == 0xFFFF) {
+ pad_.add(RTL_CONSTASCII_STRINGPARAM("\xEF\xBF\xBF"));
+ } else {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad unicode scalar attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ state_ = State(state_ + 1);
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) + reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+bool ValueParser::endElement() {
+ if (!node_.is()) {
+ return false;
+ }
+ switch (state_) {
+ case STATE_TEXT:
+ {
+ css::uno::Any value;
+ if (items_.empty()) {
+ value = parseValue(separator_, pad_.get(), type_);
+ pad_.clear();
+ } else {
+ switch (type_) {
+ case TYPE_BOOLEAN_LIST:
+ value = convertItems< sal_Bool >();
+ break;
+ case TYPE_SHORT_LIST:
+ value = convertItems< sal_Int16 >();
+ break;
+ case TYPE_INT_LIST:
+ value = convertItems< sal_Int32 >();
+ break;
+ case TYPE_LONG_LIST:
+ value = convertItems< sal_Int64 >();
+ break;
+ case TYPE_DOUBLE_LIST:
+ value = convertItems< double >();
+ break;
+ case TYPE_STRING_LIST:
+ value = convertItems< rtl::OUString >();
+ break;
+ case TYPE_HEXBINARY_LIST:
+ value = convertItems< css::uno::Sequence< sal_Int8 > >();
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ items_.clear();
+ }
+ switch (node_->kind()) {
+ case Node::KIND_PROPERTY:
+ dynamic_cast< PropertyNode * >(node_.get())->setValue(
+ layer_, value);
+ break;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ {
+ NodeMap::iterator i(
+ node_->getMembers().find(localizedName_));
+ if (i == node_->getMembers().end()) {
+ node_->getMembers().insert(
+ NodeMap::value_type(
+ localizedName_,
+ new LocalizedValueNode(layer_, value)));
+ } else {
+ dynamic_cast< LocalizedValueNode * >(i->second.get())->
+ setValue(layer_, value);
+ }
+ }
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ separator_ = rtl::OString();
+ node_.clear();
+ }
+ break;
+ case STATE_TEXT_UNICODE:
+ case STATE_IT_UNICODE:
+ state_ = State(state_ - 1);
+ break;
+ case STATE_IT:
+ items_.push_back(
+ parseValue(rtl::OString(), pad_.get(), elementType(type_)));
+ pad_.clear();
+ state_ = STATE_TEXT;
+ break;
+ }
+ return true;
+}
+
+void ValueParser::characters(Span const & text) {
+ if (node_.is()) {
+ OSL_ASSERT(state_ == STATE_TEXT || state_ == STATE_IT);
+ pad_.add(text.begin, text.length);
+ }
+}
+
+void ValueParser::start(
+ rtl::Reference< Node > const & node, rtl::OUString const & localizedName)
+{
+ OSL_ASSERT(node.is() && !node_.is());
+ node_ = node;
+ localizedName_ = localizedName;
+ state_ = STATE_TEXT;
+}
+
+int ValueParser::getLayer() const {
+ return layer_;
+}
+
+template< typename T > css::uno::Any ValueParser::convertItems() {
+ css::uno::Sequence< T > seq(items_.size());
+ for (sal_Int32 i = 0; i < seq.getLength(); ++i) {
+ OSL_VERIFY(items_[i] >>= seq[i]);
+ }
+ return css::uno::makeAny(seq);
+}
+
+}
diff --git a/configmgr/source/valueparser.hxx b/configmgr/source/valueparser.hxx
new file mode 100644
index 000000000000..4e899f4632dd
--- /dev/null
+++ b/configmgr/source/valueparser.hxx
@@ -0,0 +1,92 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_VALUEPARSER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_VALUEPARSER_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "rtl/ref.hxx"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+
+#include "pad.hxx"
+#include "type.hxx"
+#include "xmlreader.hxx"
+
+namespace com { namespace sun { namespace star { namespace uno {
+ class Any;
+} } } }
+
+namespace configmgr {
+
+class Node;
+struct Span;
+
+class ValueParser: private boost::noncopyable {
+public:
+ ValueParser(int layer);
+
+ ~ValueParser();
+
+ XmlReader::Text getTextMode() const;
+
+ bool startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name);
+
+ bool endElement();
+
+ void characters(Span const & text);
+
+ void start(
+ rtl::Reference< Node > const & property,
+ rtl::OUString const & localizedName = rtl::OUString());
+
+ int getLayer() const;
+
+ Type type_;
+ rtl::OString separator_;
+
+private:
+ template< typename T > com::sun::star::uno::Any convertItems();
+
+ enum State { STATE_TEXT, STATE_TEXT_UNICODE, STATE_IT, STATE_IT_UNICODE };
+
+ int layer_;
+ rtl::Reference< Node > node_;
+ rtl::OUString localizedName_;
+ State state_;
+ Pad pad_;
+ std::vector< com::sun::star::uno::Any > items_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/writemodfile.cxx b/configmgr/source/writemodfile.cxx
new file mode 100644
index 000000000000..c2573ab67439
--- /dev/null
+++ b/configmgr/source/writemodfile.cxx
@@ -0,0 +1,601 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#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/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/file.h"
+#include "osl/file.hxx"
+#include "rtl/string.h"
+#include "rtl/string.hxx"
+#include "rtl/textcvt.h"
+#include "rtl/textenc.h"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "data.hxx"
+#include "groupnode.hxx"
+#include "localizedpropertynode.hxx"
+#include "localizedvaluenode.hxx"
+#include "modifications.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "propertynode.hxx"
+#include "span.hxx"
+#include "type.hxx"
+#include "writemodfile.hxx"
+
+namespace configmgr {
+
+class Components;
+
+namespace {
+
+namespace css = com::sun::star;
+
+rtl::OString convertToUtf8(
+ rtl::OUString const & text, sal_Int32 offset, sal_Int32 length)
+{
+ OSL_ASSERT(
+ offset <= text.getLength() && text.getLength() - offset >= length);
+ rtl::OString s;
+ if (!rtl_convertUStringToString(
+ &s.pData, text.pData->buffer + offset, length,
+ RTL_TEXTENCODING_UTF8,
+ (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
+ {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot convert to UTF-8")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return s;
+}
+
+struct TempFile: public boost::noncopyable {
+ rtl::OUString url;
+ oslFileHandle handle;
+ bool closed;
+
+ TempFile(): handle(0), closed(false) {}
+
+ ~TempFile();
+};
+
+TempFile::~TempFile() {
+ if (handle != 0) {
+ if (!closed) {
+ oslFileError e = osl_closeFile(handle);
+ if (e != osl_File_E_None) {
+ OSL_TRACE(
+ "osl_closeFile failed with %ld", static_cast< long >(e));
+ }
+ }
+ osl::FileBase::RC e = osl::File::remove(url);
+ if (e != osl::FileBase::E_None) {
+ OSL_TRACE("osl_removeFile failed with %ld", static_cast< long >(e));
+ }
+ }
+}
+
+void writeData(oslFileHandle handle, char const * begin, sal_Int32 length) {
+ OSL_ASSERT(length >= 0);
+ sal_uInt64 n;
+ if ((osl_writeFile(handle, begin, static_cast< sal_uInt32 >(length), &n) !=
+ osl_File_E_None) ||
+ n != static_cast< sal_uInt32 >(length))
+ {
+ throw css::uno::RuntimeException(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("write failure")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void writeData(oslFileHandle handle, rtl::OString const & text) {
+ writeData(handle, text.getStr(), text.getLength());
+}
+
+void writeAttributeValue(oslFileHandle handle, rtl::OUString const & value) {
+ sal_Int32 i = 0;
+ sal_Int32 j = i;
+ for (; j < value.getLength(); ++j) {
+ OSL_ASSERT(
+ value[j] == 0x0009 || value[j] == 0x000A || value[j] == 0x000D ||
+ (value[j] >= 0x0020 && value[j] != 0xFFFE && value[j] != 0xFFFF));
+ switch(value[j]) {
+ case '\x09':
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#9;"));
+ i = j + 1;
+ break;
+ case '\x0A':
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#xA;"));
+ i = j + 1;
+ break;
+ case '\x0D':
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#xD;"));
+ i = j + 1;
+ break;
+ case '"':
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&quot;"));
+ i = j + 1;
+ break;
+ case '&':
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&amp;"));
+ i = j + 1;
+ break;
+ case '<':
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&lt;"));
+ i = j + 1;
+ break;
+ default:
+ break;
+ }
+ }
+ writeData(handle, convertToUtf8(value, i, j - i));
+}
+
+void writeValueContent(oslFileHandle handle, sal_Bool value) {
+ if (value) {
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("true"));
+ } else {
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("false"));
+ }
+}
+
+void writeValueContent(oslFileHandle handle, sal_Int16 value) {
+ writeData(handle, rtl::OString::valueOf(static_cast< sal_Int32 >(value)));
+}
+
+void writeValueContent(oslFileHandle handle, sal_Int32 value) {
+ writeData(handle, rtl::OString::valueOf(value));
+}
+
+void writeValueContent(oslFileHandle handle, sal_Int64 value) {
+ writeData(handle, rtl::OString::valueOf(value));
+}
+
+void writeValueContent(oslFileHandle handle, double value) {
+ writeData(handle, rtl::OString::valueOf(value));
+}
+
+void writeValueContent(oslFileHandle handle, rtl::OUString const & value) {
+ sal_Int32 i = 0;
+ sal_Int32 j = i;
+ for (; j < value.getLength(); ++j) {
+ sal_Unicode c = value[j];
+ if ((c < 0x0020 && c != 0x0009 && c != 0x000A && c != 0x000D) ||
+ c == 0xFFFE || c == 0xFFFF)
+ {
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM("<unicode oor:scalar=\""));
+ writeData(
+ handle, rtl::OString::valueOf(static_cast< sal_Int32 >(c)));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\"/>"));
+ i = j + 1;
+ } else if (c == '\x0D') {
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&#xD;"));
+ i = j + 1;
+ } else if (c == '&') {
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&amp;"));
+ i = j + 1;
+ } else if (c == '<') {
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&lt;"));
+ i = j + 1;
+ } else if (c == '>') {
+ // "MUST, for compatibility, be escaped [...] when it appears in the
+ // string ']]>'":
+ writeData(handle, convertToUtf8(value, i, j - i));
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("&gt;"));
+ i = j + 1;
+ }
+ }
+ writeData(handle, convertToUtf8(value, i, j - i));
+}
+
+void writeValueContent(
+ oslFileHandle handle, css::uno::Sequence< sal_Int8 > const & value)
+{
+ for (sal_Int32 i = 0; i < value.getLength(); ++i) {
+ static char const hexDigit[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
+ 'D', 'E', 'F' };
+ writeData(handle, hexDigit + ((value[i] >> 4) & 0xF), 1);
+ writeData(handle, hexDigit + (value[i] & 0xF), 1);
+ }
+}
+
+template< typename T > void writeSingleValue(
+ oslFileHandle handle, css::uno::Any const & value)
+{
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
+ T val = T();
+ value >>= val;
+ writeValueContent(handle, val);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
+}
+
+template< typename T > void writeListValue(
+ oslFileHandle handle, css::uno::Any const & value)
+{
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
+ css::uno::Sequence< T > val;
+ value >>= val;
+ for (sal_Int32 i = 0; i < val.getLength(); ++i) {
+ if (i != 0) {
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM(" "));
+ }
+ writeValueContent(handle, val[i]);
+ }
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
+}
+
+template< typename T > void writeItemListValue(
+ oslFileHandle handle, css::uno::Any const & value)
+{
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM(">"));
+ css::uno::Sequence< T > val;
+ value >>= val;
+ for (sal_Int32 i = 0; i < val.getLength(); ++i) {
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("<it>"));
+ writeValueContent(handle, val[i]);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("</it>"));
+ }
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
+}
+
+void writeValue(oslFileHandle handle, Type type, css::uno::Any const & value) {
+ switch (type) {
+ case TYPE_BOOLEAN:
+ writeSingleValue< sal_Bool >(handle, value);
+ break;
+ case TYPE_SHORT:
+ writeSingleValue< sal_Int16 >(handle, value);
+ break;
+ case TYPE_INT:
+ writeSingleValue< sal_Int32 >(handle, value);
+ break;
+ case TYPE_LONG:
+ writeSingleValue< sal_Int64 >(handle, value);
+ break;
+ case TYPE_DOUBLE:
+ writeSingleValue< double >(handle, value);
+ break;
+ case TYPE_STRING:
+ writeSingleValue< rtl::OUString >(handle, value);
+ break;
+ case TYPE_HEXBINARY:
+ writeSingleValue< css::uno::Sequence< sal_Int8 > >(handle, value);
+ break;
+ case TYPE_BOOLEAN_LIST:
+ writeListValue< sal_Bool >(handle, value);
+ break;
+ case TYPE_SHORT_LIST:
+ writeListValue< sal_Int16 >(handle, value);
+ break;
+ case TYPE_INT_LIST:
+ writeListValue< sal_Int32 >(handle, value);
+ break;
+ case TYPE_LONG_LIST:
+ writeListValue< sal_Int64 >(handle, value);
+ break;
+ case TYPE_DOUBLE_LIST:
+ writeListValue< double >(handle, value);
+ break;
+ case TYPE_STRING_LIST:
+ writeItemListValue< rtl::OUString >(handle, value);
+ break;
+ case TYPE_HEXBINARY_LIST:
+ writeItemListValue< css::uno::Sequence< sal_Int8 > >(handle, value);
+ break;
+ default: // TYPE_ERROR, TYPE_NIL, TYPE_ANY
+ OSL_ASSERT(false); // this cannot happen
+ }
+}
+
+void writeNode(
+ Components & components, oslFileHandle handle,
+ rtl::Reference< Node > const & parent, rtl::OUString const & name,
+ rtl::Reference< Node > const & node)
+{
+ static Span const typeNames[] = {
+ Span(), Span(), Span(), // TYPE_ERROR, TYPE_NIL, TYPE_ANY
+ Span(RTL_CONSTASCII_STRINGPARAM("xs:boolean")),
+ Span(RTL_CONSTASCII_STRINGPARAM("xs:short")),
+ Span(RTL_CONSTASCII_STRINGPARAM("xs:int")),
+ Span(RTL_CONSTASCII_STRINGPARAM("xs:long")),
+ Span(RTL_CONSTASCII_STRINGPARAM("xs:double")),
+ Span(RTL_CONSTASCII_STRINGPARAM("xs:string")),
+ Span(RTL_CONSTASCII_STRINGPARAM("xs:hexBinary")),
+ Span(RTL_CONSTASCII_STRINGPARAM("oor:boolean-list")),
+ Span(RTL_CONSTASCII_STRINGPARAM("oor:short-list")),
+ Span(RTL_CONSTASCII_STRINGPARAM("oor:int-list")),
+ Span(RTL_CONSTASCII_STRINGPARAM("oor:long-list")),
+ Span(RTL_CONSTASCII_STRINGPARAM("oor:double-list")),
+ Span(RTL_CONSTASCII_STRINGPARAM("oor:string-list")),
+ Span(RTL_CONSTASCII_STRINGPARAM("oor:hexBinary-list")) };
+ switch (node->kind()) {
+ case Node::KIND_PROPERTY:
+ {
+ PropertyNode * prop = dynamic_cast< PropertyNode * >(node.get());
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
+ writeAttributeValue(handle, name);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\""));
+ Type type = prop->getStaticType();
+ Type dynType = getDynamicType(prop->getValue(components));
+ OSL_ASSERT(dynType != TYPE_ERROR);
+ if (type == TYPE_ANY) {
+ type = dynType;
+ if (type != TYPE_NIL) {
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
+ writeData(
+ handle, typeNames[type].begin, typeNames[type].length);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ }
+ }
+ writeData(handle, "><value");
+ if (dynType == TYPE_NIL) {
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
+ } else {
+ writeValue(handle, type, prop->getValue(components));
+ }
+ writeData(handle, "</prop>");
+ }
+ break;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ 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());
+ i != node->getMembers().end(); ++i)
+ {
+ writeNode(components, handle, node, i->first, i->second);
+ }
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("</prop>"));
+ break;
+ case Node::KIND_LOCALIZED_VALUE:
+ {
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
+ if (name.getLength() != 0) {
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
+ writeAttributeValue(handle, name);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ }
+ Type type = dynamic_cast< LocalizedPropertyNode * >(parent.get())->
+ getStaticType();
+ css::uno::Any value(
+ dynamic_cast< LocalizedValueNode * >(node.get())->getValue());
+ Type dynType = getDynamicType(value);
+ OSL_ASSERT(dynType != TYPE_ERROR);
+ if (type == TYPE_ANY) {
+ type = dynType;
+ if (type != TYPE_NIL) {
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
+ writeData(
+ handle, typeNames[type].begin, typeNames[type].length);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ }
+ }
+ if (dynType == TYPE_NIL) {
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
+ } else {
+ writeValue(handle, type, value);
+ }
+ }
+ break;
+ case Node::KIND_GROUP:
+ case Node::KIND_SET:
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
+ writeAttributeValue(handle, name);
+ if (node->getTemplateName().getLength() != 0) { // set member
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"replace"));
+ }
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
+ for (NodeMap::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;
+ }
+}
+
+void writeModifications(
+ Components & components, oslFileHandle handle,
+ rtl::OUString const & parentPathRepresentation,
+ rtl::Reference< Node > const & parent, rtl::OUString const & nodeName,
+ rtl::Reference< Node > const & node,
+ Modifications::Node const & modifications)
+{
+ // It is never necessary to write oor:finalized or oor:mandatory attributes,
+ // as they cannot be set via the UNO API.
+ if (modifications.children.empty()) {
+ OSL_ASSERT(parent.is());
+ // components themselves have no parent but must have children
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\""));
+ writeAttributeValue(handle, parentPathRepresentation);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
+ if (node.is()) {
+ writeNode(components, handle, parent, nodeName, node);
+ } else {
+ switch (parent->kind()) {
+ case Node::KIND_LOCALIZED_PROPERTY:
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
+ if (nodeName.getLength() != 0) {
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
+ writeAttributeValue(handle, nodeName);
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ }
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM(" oor:op=\"remove\"/>"));
+ break;
+ case Node::KIND_GROUP:
+ OSL_ASSERT(
+ dynamic_cast< GroupNode * >(parent.get())->isExtensible());
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
+ writeAttributeValue(handle, nodeName);
+ writeData(
+ handle,
+ RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
+ break;
+ case Node::KIND_SET:
+ writeData(
+ handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
+ writeAttributeValue(handle, nodeName);
+ writeData(
+ handle,
+ RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ }
+ writeData(handle, RTL_CONSTASCII_STRINGPARAM("</item>"));
+ } else {
+ OSL_ASSERT(node.is());
+ rtl::OUString pathRep(
+ parentPathRepresentation +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
+ Data::createSegment(node->getTemplateName(), nodeName));
+ for (Modifications::Node::Children::const_iterator i(
+ modifications.children.begin());
+ i != modifications.children.end(); ++i)
+ {
+ writeModifications(
+ components, handle, pathRep, node, i->first,
+ node->getMember(i->first), i->second);
+ }
+ }
+}
+
+}
+
+void writeModFile(
+ Components & components, rtl::OUString const & url, Data const & data)
+{
+ sal_Int32 i = url.lastIndexOf('/');
+ OSL_ASSERT(i != -1);
+ rtl::OUString dir(url.copy(0, i));
+ switch (osl::Directory::createPath(dir)) {
+ case osl::FileBase::E_None:
+ case osl::FileBase::E_EXIST:
+ break;
+ case osl::FileBase::E_ACCES:
+ OSL_TRACE(
+ "cannot create registrymodifications.xcu path (E_ACCES); changes"
+ " will be lost");
+ return;
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot create directory ")) +
+ dir),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ TempFile tmp;
+ switch (osl::FileBase::createTempFile(&dir, &tmp.handle, &tmp.url)) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_ACCES:
+ OSL_TRACE(
+ "cannot create temp registrymodifications.xcu (E_ACCES); changes"
+ " will be lost");
+ return;
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "cannot create temporary file in ")) +
+ dir),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ writeData(
+ tmp.handle,
+ RTL_CONSTASCII_STRINGPARAM(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><oor:items"
+ " xmlns:oor=\"http://openoffice.org/2001/registry\""
+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"));
+ //TODO: Do not write back information about those removed items that did not
+ // come from the .xcs/.xcu files, anyway (but had been added dynamically
+ // instead):
+ for (Modifications::Node::Children::const_iterator j(
+ data.modifications.getRoot().children.begin());
+ j != data.modifications.getRoot().children.end(); ++j)
+ {
+ writeModifications(
+ components, tmp.handle, rtl::OUString(), rtl::Reference< Node >(),
+ j->first, Data::findNode(Data::NO_LAYER, data.components, j->first),
+ j->second);
+ }
+ writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("</oor:items>"));
+ oslFileError e = osl_closeFile(tmp.handle);
+ tmp.closed = true;
+ if (e != osl_File_E_None) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot close ")) +
+ tmp.url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (osl::File::move(tmp.url, url) != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot move ")) +
+ tmp.url),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ tmp.handle = 0;
+}
+
+}
diff --git a/configmgr/source/writemodfile.hxx b/configmgr/source/writemodfile.hxx
new file mode 100644
index 000000000000..250edfd095af
--- /dev/null
+++ b/configmgr/source/writemodfile.hxx
@@ -0,0 +1,45 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_WRITEMODFILE_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_WRITEMODFILE_HXX
+
+#include "sal/config.h"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class Components;
+struct Data;
+
+void writeModFile(
+ Components & components, rtl::OUString const & url, Data const & data);
+
+}
+
+#endif
diff --git a/configmgr/source/xcdparser.cxx b/configmgr/source/xcdparser.cxx
new file mode 100644
index 000000000000..498254b35644
--- /dev/null
+++ b/configmgr/source/xcdparser.cxx
@@ -0,0 +1,183 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <climits>
+
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.hxx"
+#include "rtl/string.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "span.hxx"
+#include "xcdparser.hxx"
+#include "xcsparser.hxx"
+#include "xcuparser.hxx"
+#include "xmldata.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+XcdParser::XcdParser(int layer, Dependencies const & dependencies, Data & data):
+ layer_(layer), dependencies_(dependencies), data_(data), state_(STATE_START)
+{}
+
+XcdParser::~XcdParser() {}
+
+XmlReader::Text XcdParser::getTextMode() {
+ return nestedParser_.is()
+ ? nestedParser_->getTextMode() : XmlReader::TEXT_NONE;
+}
+
+bool XcdParser::startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name)
+{
+ if (nestedParser_.is()) {
+ OSL_ASSERT(nesting_ != LONG_MAX);
+ ++nesting_;
+ return nestedParser_->startElement(reader, ns, name);
+ }
+ switch (state_) {
+ case STATE_START:
+ if (ns == XmlReader::NAMESPACE_OOR &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("data")))
+ {
+ state_ = STATE_DEPENDENCIES;
+ return true;
+ }
+ break;
+ case STATE_DEPENDENCIES:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("dependency")))
+ {
+ if (dependency_.getLength() == 0) {
+ Span attrFile;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_NONE && //TODO: _OOR
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("file")))
+ {
+ attrFile = reader.getAttributeValue(false);
+ }
+ }
+ if (!attrFile.is()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "no dependency file attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ dependency_ = xmldata::convertFromUtf8(attrFile);
+ if (dependency_.getLength() == 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad dependency file attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ if (dependencies_.find(dependency_) == dependencies_.end()) {
+ return false;
+ }
+ state_ = STATE_DEPENDENCY;
+ dependency_ = rtl::OUString();
+ return true;
+ }
+ state_ = STATE_COMPONENTS;
+ // fall through
+ case STATE_COMPONENTS:
+ if (ns == XmlReader::NAMESPACE_OOR &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("component-schema")))
+ {
+ nestedParser_ = new XcsParser(layer_, data_);
+ nesting_ = 1;
+ return nestedParser_->startElement(reader, ns, name);
+ }
+ if (ns == XmlReader::NAMESPACE_OOR &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("component-data")))
+ {
+ nestedParser_ = new XcuParser(layer_ + 1, data_, 0, 0);
+ nesting_ = 1;
+ return nestedParser_->startElement(reader, ns, name);
+ }
+ break;
+ default: // STATE_DEPENDENCY
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) + reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+void XcdParser::endElement(XmlReader const & reader) {
+ if (nestedParser_.is()) {
+ nestedParser_->endElement(reader);
+ if (--nesting_ == 0) {
+ nestedParser_.clear();
+ }
+ } else {
+ switch (state_) {
+ case STATE_DEPENDENCY:
+ state_ = STATE_DEPENDENCIES;
+ break;
+ case STATE_DEPENDENCIES:
+ case STATE_COMPONENTS:
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ }
+}
+
+void XcdParser::characters(Span const & text) {
+ if (nestedParser_.is()) {
+ nestedParser_->characters(text);
+ }
+}
+
+}
diff --git a/configmgr/source/xcdparser.hxx b/configmgr/source/xcdparser.hxx
new file mode 100644
index 000000000000..2ad8ecea7f93
--- /dev/null
+++ b/configmgr/source/xcdparser.hxx
@@ -0,0 +1,78 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_XCDPARSER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_XCDPARSER_HXX
+
+#include "sal/config.h"
+
+#include <set>
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "parser.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+struct Data;
+struct Span;
+
+class XcdParser: public Parser {
+public:
+ typedef std::set< rtl::OUString > Dependencies;
+
+ XcdParser(int layer, Dependencies const & dependencies, Data & data);
+
+private:
+ virtual ~XcdParser();
+
+ virtual XmlReader::Text getTextMode();
+
+ virtual bool startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name);
+
+ virtual void endElement(XmlReader const & reader);
+
+ virtual void characters(Span const & text);
+
+ enum State {
+ STATE_START, STATE_DEPENDENCIES, STATE_DEPENDENCY, STATE_COMPONENTS };
+
+ int layer_;
+ Dependencies const & dependencies_;
+ Data & data_;
+ State state_;
+ rtl::OUString dependency_;
+ rtl::Reference< Parser > nestedParser_;
+ long nesting_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/xcsparser.cxx b/configmgr/source/xcsparser.cxx
new file mode 100644
index 000000000000..12e64ebbe171
--- /dev/null
+++ b/configmgr/source/xcsparser.cxx
@@ -0,0 +1,669 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <cstddef>
+
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "rtl/strbuf.hxx"
+#include "rtl/string.h"
+#include "rtl/string.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "data.hxx"
+#include "localizedpropertynode.hxx"
+#include "groupnode.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "propertynode.hxx"
+#include "setnode.hxx"
+#include "span.hxx"
+#include "xcsparser.hxx"
+#include "xmldata.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+// Conservatively merge a template or component (and its recursive parts) into
+// an existing instance:
+void merge(
+ rtl::Reference< Node > const & original,
+ rtl::Reference< Node > const & update)
+{
+ OSL_ASSERT(
+ original.is() && update.is() && original->kind() == update->kind() &&
+ update->getFinalized() == Data::NO_LAYER);
+ if (update->getLayer() >= original->getLayer() &&
+ update->getLayer() <= original->getFinalized())
+ {
+ switch (original->kind()) {
+ case Node::KIND_PROPERTY:
+ case Node::KIND_LOCALIZED_PROPERTY:
+ case Node::KIND_LOCALIZED_VALUE:
+ break; //TODO: merge certain parts?
+ case Node::KIND_GROUP:
+ if (dynamic_cast< GroupNode * >(original.get())->isExtensible()) {
+ for (NodeMap::iterator i2(update->getMembers().begin());
+ i2 != update->getMembers().end(); ++i2)
+ {
+ NodeMap::iterator i1(
+ original->getMembers().find(i2->first));
+ if (i1 == original->getMembers().end()) {
+ if (i2->second->kind() == Node::KIND_PROPERTY) {
+ original->getMembers().insert(*i2);
+ }
+ } else if (i2->second->kind() == i1->second->kind()) {
+ merge(i1->second, i2->second);
+ }
+ }
+ }
+ break;
+ case Node::KIND_SET:
+ for (NodeMap::iterator i2(update->getMembers().begin());
+ i2 != update->getMembers().end(); ++i2)
+ {
+ NodeMap::iterator i1(original->getMembers().find(i2->first));
+ if (i1 == original->getMembers().end()) {
+ if (dynamic_cast< SetNode * >(original.get())->
+ isValidTemplate(i2->second->getTemplateName()))
+ {
+ original->getMembers().insert(*i2);
+ }
+ } else if (i2->second->kind() == i1->second->kind() &&
+ (i2->second->getTemplateName() ==
+ i1->second->getTemplateName()))
+ {
+ merge(i1->second, i2->second);
+ }
+ }
+ break;
+ }
+ }
+}
+
+}
+
+XcsParser::XcsParser(int layer, Data & data):
+ valueParser_(layer), data_(data), state_(STATE_START)
+{}
+
+XcsParser::~XcsParser() {}
+
+XmlReader::Text XcsParser::getTextMode() {
+ return valueParser_.getTextMode();
+}
+
+bool XcsParser::startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name)
+{
+ if (valueParser_.startElement(reader, ns, name)) {
+ return true;
+ }
+ if (state_ == STATE_START) {
+ if (ns == XmlReader::NAMESPACE_OOR &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("component-schema"))) {
+ handleComponentSchema(reader);
+ state_ = STATE_COMPONENT_SCHEMA;
+ ignoring_ = 0;
+ return true;
+ }
+ } else {
+ //TODO: ignoring component-schema import, component-schema uses, and
+ // prop constraints; accepting all four at illegal places (and with
+ // illegal content):
+ if (ignoring_ > 0 ||
+ (ns == XmlReader::NAMESPACE_NONE &&
+ (name.equals(RTL_CONSTASCII_STRINGPARAM("info")) ||
+ name.equals(RTL_CONSTASCII_STRINGPARAM("import")) ||
+ name.equals(RTL_CONSTASCII_STRINGPARAM("uses")) ||
+ name.equals(RTL_CONSTASCII_STRINGPARAM("constraints")))))
+ {
+ OSL_ASSERT(ignoring_ < LONG_MAX);
+ ++ignoring_;
+ return true;
+ }
+ switch (state_) {
+ case STATE_COMPONENT_SCHEMA:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("templates")))
+ {
+ state_ = STATE_TEMPLATES;
+ return true;
+ }
+ // fall through
+ case STATE_TEMPLATES_DONE:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
+ {
+ state_ = STATE_COMPONENT;
+ OSL_ASSERT(elements_.empty());
+ elements_.push(
+ Element(
+ new GroupNode(
+ valueParser_.getLayer(), false, rtl::OUString()),
+ componentName_));
+ return true;
+ }
+ break;
+ case STATE_TEMPLATES:
+ if (elements_.empty()) {
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("group")))
+ {
+ handleGroup(reader, true);
+ return true;
+ }
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("set")))
+ {
+ handleSet(reader, true);
+ return true;
+ }
+ break;
+ }
+ // fall through
+ case STATE_COMPONENT:
+ OSL_ASSERT(!elements_.empty());
+ switch (elements_.top().node->kind()) {
+ case Node::KIND_PROPERTY:
+ case Node::KIND_LOCALIZED_PROPERTY:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
+ {
+ handlePropValue(reader, elements_.top().node);
+ return true;
+ }
+ break;
+ case Node::KIND_GROUP:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("prop")))
+ {
+ handleProp(reader);
+ return true;
+ }
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("node-ref")))
+ {
+ handleNodeRef(reader);
+ return true;
+ }
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("group")))
+ {
+ handleGroup(reader, false);
+ return true;
+ }
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("set")))
+ {
+ handleSet(reader, false);
+ return true;
+ }
+ break;
+ case Node::KIND_SET:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("item")))
+ {
+ handleSetItem(
+ reader,
+ dynamic_cast< SetNode * >(elements_.top().node.get()));
+ return true;
+ }
+ break;
+ default: // Node::KIND_LOCALIZED_VALUE
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ break;
+ case STATE_COMPONENT_DONE:
+ break;
+ default: // STATE_START
+ OSL_ASSERT(false); // this cannot happen
+ break;
+ }
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) + reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+void XcsParser::endElement(XmlReader const & reader) {
+ if (valueParser_.endElement()) {
+ return;
+ }
+ if (ignoring_ > 0) {
+ --ignoring_;
+ } else if (!elements_.empty()) {
+ Element top(elements_.top());
+ elements_.pop();
+ if (top.node.is()) {
+ if (elements_.empty()) {
+ switch (state_) {
+ case STATE_TEMPLATES:
+ {
+ NodeMap::iterator i(data_.templates.find(top.name));
+ if (i == data_.templates.end()) {
+ data_.templates.insert(
+ NodeMap::value_type(top.name, top.node));
+ } else {
+ merge(i->second, top.node);
+ }
+ }
+ break;
+ case STATE_COMPONENT:
+ {
+ NodeMap::iterator i(data_.components.find(top.name));
+ if (i == data_.components.end()) {
+ data_.components.insert(
+ NodeMap::value_type(top.name, top.node));
+ } else {
+ merge(i->second, top.node);
+ }
+ state_ = STATE_COMPONENT_DONE;
+ }
+ break;
+ default:
+ OSL_ASSERT(false);
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ 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 {
+ switch (state_) {
+ case STATE_COMPONENT_SCHEMA:
+ case STATE_TEMPLATES_DONE:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no component element in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ case STATE_TEMPLATES:
+ state_ = STATE_TEMPLATES_DONE;
+ break;
+ case STATE_COMPONENT_DONE:
+ break;
+ default:
+ OSL_ASSERT(false); // this cannot happen
+ }
+ }
+}
+
+void XcsParser::characters(Span const & text) {
+ valueParser_.characters(text);
+}
+
+void XcsParser::handleComponentSchema(XmlReader & reader) {
+ //TODO: oor:version, xml:lang attributes
+ rtl::OStringBuffer buf;
+ buf.append('.');
+ bool hasPackage = false;
+ bool hasName = false;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("package")))
+ {
+ if (hasPackage) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "multiple component-schema package attributes"
+ " in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ hasPackage = true;
+ Span s(reader.getAttributeValue(false));
+ buf.insert(0, s.begin, s.length);
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ if (hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "multiple component-schema name attributes in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ hasName = true;
+ Span s(reader.getAttributeValue(false));
+ buf.append(s.begin, s.length);
+ }
+ }
+ if (!hasPackage) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "no component-schema package attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "no component-schema name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ componentName_ = xmldata::convertFromUtf8(
+ Span(buf.getStr(), buf.getLength()));
+}
+
+void XcsParser::handleNodeRef(XmlReader & reader) {
+ bool hasName = false;
+ rtl::OUString name;
+ rtl::OUString component(componentName_);
+ bool hasNodeType = false;
+ rtl::OUString nodeType;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ hasName = true;
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
+ {
+ component = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
+ {
+ hasNodeType = true;
+ nodeType = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ }
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no node-ref name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ rtl::Reference< Node > tmpl(
+ data_.getTemplate(
+ valueParser_.getLayer(),
+ xmldata::parseTemplateReference(
+ component, hasNodeType, nodeType, 0)));
+ if (!tmpl.is()) {
+ //TODO: this can erroneously happen as long as import/uses attributes
+ // are not correctly processed
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown node-ref ")) +
+ name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ rtl::Reference< Node > node(tmpl->clone());
+ node->setLayer(valueParser_.getLayer());
+ elements_.push(Element(node, name));
+}
+
+void XcsParser::handleProp(XmlReader & reader) {
+ bool hasName = false;
+ rtl::OUString name;
+ valueParser_.type_ = TYPE_ERROR;
+ bool localized = false;
+ bool nillable = true;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ hasName = true;
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
+ {
+ valueParser_.type_ = xmldata::parseType(
+ reader, reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("localized")))
+ {
+ localized = xmldata::parseBoolean(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nillable")))
+ {
+ nillable = xmldata::parseBoolean(reader.getAttributeValue(true));
+ }
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no prop name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (valueParser_.type_ == TYPE_ERROR) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no prop type attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ elements_.push(
+ Element(
+ (localized
+ ? rtl::Reference< Node >(
+ new LocalizedPropertyNode(
+ valueParser_.getLayer(), valueParser_.type_, nillable))
+ : rtl::Reference< Node >(
+ new PropertyNode(
+ valueParser_.getLayer(), valueParser_.type_, nillable,
+ css::uno::Any(), false))),
+ name));
+}
+
+void XcsParser::handlePropValue(
+ XmlReader & reader, rtl::Reference< Node > const & property)
+{
+ Span attrSeparator;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
+ {
+ attrSeparator = reader.getAttributeValue(false);
+ if (attrSeparator.length == 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad oor:separator attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ }
+ valueParser_.separator_ = rtl::OString(
+ attrSeparator.begin, attrSeparator.length);
+ valueParser_.start(property);
+}
+
+void XcsParser::handleGroup(XmlReader & reader, bool isTemplate) {
+ bool hasName = false;
+ rtl::OUString name;
+ bool extensible = false;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ hasName = true;
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("extensible")))
+ {
+ extensible = xmldata::parseBoolean(reader.getAttributeValue(true));
+ }
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no group name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (isTemplate) {
+ name = Data::fullTemplateName(componentName_, name);
+ }
+ elements_.push(
+ Element(
+ new GroupNode(
+ valueParser_.getLayer(), extensible,
+ isTemplate ? name : rtl::OUString()),
+ name));
+}
+
+void XcsParser::handleSet(XmlReader & reader, bool isTemplate) {
+ bool hasName = false;
+ rtl::OUString name;
+ rtl::OUString component(componentName_);
+ bool hasNodeType = false;
+ rtl::OUString nodeType;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ hasName = true;
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
+ {
+ component = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
+ {
+ hasNodeType = true;
+ nodeType = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ }
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no set name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (isTemplate) {
+ name = Data::fullTemplateName(componentName_, name);
+ }
+ elements_.push(
+ Element(
+ new SetNode(
+ valueParser_.getLayer(),
+ xmldata::parseTemplateReference(
+ component, hasNodeType, nodeType, 0),
+ isTemplate ? name : rtl::OUString()),
+ name));
+}
+
+void XcsParser::handleSetItem(XmlReader & reader, SetNode * set) {
+ rtl::OUString component(componentName_);
+ bool hasNodeType = false;
+ rtl::OUString nodeType;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
+ {
+ component = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
+ {
+ hasNodeType = true;
+ nodeType = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ }
+ }
+ set->getAdditionalTemplateNames().push_back(
+ xmldata::parseTemplateReference(component, hasNodeType, nodeType, 0));
+ elements_.push(Element(rtl::Reference< Node >(), rtl::OUString()));
+}
+
+}
diff --git a/configmgr/source/xcsparser.hxx b/configmgr/source/xcsparser.hxx
new file mode 100644
index 000000000000..196add9a826a
--- /dev/null
+++ b/configmgr/source/xcsparser.hxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_XCSPARSER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_XCSPARSER_HXX
+
+#include "sal/config.h"
+
+#include <stack>
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "node.hxx"
+#include "parser.hxx"
+#include "valueparser.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+class SetNode;
+struct Data;
+struct Span;
+
+class XcsParser: public Parser {
+public:
+ XcsParser(int layer, Data & data);
+
+private:
+ virtual ~XcsParser();
+
+ virtual XmlReader::Text getTextMode();
+
+ virtual bool startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name);
+
+ virtual void endElement(XmlReader const & reader);
+
+ virtual void characters(Span const & text);
+
+ void handleComponentSchema(XmlReader & reader);
+
+ void handleNodeRef(XmlReader & reader);
+
+ void handleProp(XmlReader & reader);
+
+ void handlePropValue(
+ XmlReader & reader, rtl::Reference< Node > const & property);
+
+ void handleGroup(XmlReader & reader, bool isTemplate);
+
+ void handleSet(XmlReader & reader, bool isTemplate);
+
+ void handleSetItem(XmlReader & reader, SetNode * set);
+
+ enum State {
+ STATE_START, STATE_COMPONENT_SCHEMA, STATE_TEMPLATES,
+ STATE_TEMPLATES_DONE, STATE_COMPONENT, STATE_COMPONENT_DONE };
+
+ struct Element {
+ rtl::Reference< Node > node;
+ rtl::OUString name;
+
+ inline Element(
+ rtl::Reference< Node > const & theNode,
+ rtl::OUString const & theName):
+ node(theNode), name(theName) {}
+ };
+
+ typedef std::stack< Element > ElementStack;
+
+ ValueParser valueParser_;
+ Data & data_;
+ rtl::OUString componentName_;
+ State state_;
+ long ignoring_;
+ ElementStack elements_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/xcuparser.cxx b/configmgr/source/xcuparser.cxx
new file mode 100644
index 000000000000..77b0f747f313
--- /dev/null
+++ b/configmgr/source/xcuparser.cxx
@@ -0,0 +1,1112 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <algorithm>
+
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "rtl/ref.hxx"
+#include "rtl/strbuf.hxx"
+#include "rtl/string.h"
+#include "rtl/string.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+
+#include "data.hxx"
+#include "localizedpropertynode.hxx"
+#include "localizedvaluenode.hxx"
+#include "groupnode.hxx"
+#include "modifications.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "partial.hxx"
+#include "path.hxx"
+#include "propertynode.hxx"
+#include "setnode.hxx"
+#include "span.hxx"
+#include "xcuparser.hxx"
+#include "xmldata.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+XcuParser::XcuParser(
+ int layer, Data & data, Partial const * partial,
+ Modifications * broadcastModifications):
+ valueParser_(layer), data_(data),
+ partial_(partial), broadcastModifications_(broadcastModifications),
+ recordModifications_(layer == Data::NO_LAYER),
+ trackPath_(
+ partial_ != 0 || broadcastModifications_ != 0 || recordModifications_)
+{}
+
+XcuParser::~XcuParser() {}
+
+XmlReader::Text XcuParser::getTextMode() {
+ return valueParser_.getTextMode();
+}
+
+bool XcuParser::startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name)
+{
+ if (valueParser_.startElement(reader, ns, name)) {
+ return true;
+ }
+ if (state_.empty()) {
+ if (ns == XmlReader::NAMESPACE_OOR &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("component-data")))
+ {
+ handleComponentData(reader);
+ } else if (ns == XmlReader::NAMESPACE_OOR &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("items")))
+ {
+ state_.push(State(rtl::Reference< Node >(), false));
+ } else {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad root element <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else if (state_.top().ignore) {
+ state_.push(State(false));
+ } else if (!state_.top().node.is()) {
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("item")))
+ {
+ handleItem(reader);
+ } else {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad items node member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else {
+ switch (state_.top().node->kind()) {
+ case Node::KIND_PROPERTY:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
+ {
+ handlePropValue(
+ reader,
+ dynamic_cast< PropertyNode * >(state_.top().node.get()));
+ } else {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad property node member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ break;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
+ {
+ handleLocpropValue(
+ reader,
+ dynamic_cast< LocalizedPropertyNode * >(
+ state_.top().node.get()));
+ } else {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad localized property node member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ break;
+ case Node::KIND_LOCALIZED_VALUE:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ case Node::KIND_GROUP:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("prop")))
+ {
+ handleGroupProp(
+ reader,
+ dynamic_cast< GroupNode * >(state_.top().node.get()));
+ } else if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("node")))
+ {
+ handleGroupNode(reader, state_.top().node);
+ } else {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad group node member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ break;
+ case Node::KIND_SET:
+ if (ns == XmlReader::NAMESPACE_NONE &&
+ name.equals(RTL_CONSTASCII_STRINGPARAM("node")))
+ {
+ handleSetNode(
+ reader, dynamic_cast< SetNode * >(state_.top().node.get()));
+ } else {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad set node member <")) +
+ xmldata::convertFromUtf8(name) +
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+void XcuParser::endElement(XmlReader const &) {
+ if (valueParser_.endElement()) {
+ return;
+ }
+ OSL_ASSERT(!state_.empty());
+ bool pop = state_.top().pop;
+ rtl::Reference< Node > insert;
+ rtl::OUString name;
+ if (state_.top().insert) {
+ insert = state_.top().node;
+ OSL_ASSERT(insert.is());
+ name = state_.top().name;
+ }
+ state_.pop();
+ if (insert.is()) {
+ OSL_ASSERT(!state_.empty() && state_.top().node.is());
+ state_.top().node->getMembers()[name] = insert;
+ }
+ if (pop && !path_.empty()) {
+ path_.pop_back();
+ // </item> will pop less than <item> pushed, but that is harmless,
+ // as the next <item> will reset path_
+ }
+}
+
+void XcuParser::characters(Span const & text) {
+ valueParser_.characters(text);
+}
+
+XcuParser::Operation XcuParser::parseOperation(Span const & text) {
+ OSL_ASSERT(text.is());
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("modify"))) {
+ return OPERATION_MODIFY;
+ }
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("replace"))) {
+ return OPERATION_REPLACE;
+ }
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("fuse"))) {
+ return OPERATION_FUSE;
+ }
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("remove"))) {
+ return OPERATION_REMOVE;
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid op ")) +
+ xmldata::convertFromUtf8(text)),
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+void XcuParser::handleComponentData(XmlReader & reader) {
+ rtl::OStringBuffer buf;
+ buf.append('.');
+ bool hasPackage = false;
+ bool hasName = false;
+ Operation op = OPERATION_MODIFY;
+ bool finalized = false;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("package")))
+ {
+ if (hasPackage) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "multiple component-update package attributes"
+ " in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ hasPackage = true;
+ Span s(reader.getAttributeValue(false));
+ buf.insert(0, s.begin, s.length);
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ if (hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "multiple component-update name attributes in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ hasName = true;
+ Span s(reader.getAttributeValue(false));
+ buf.append(s.begin, s.length);
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
+ {
+ op = parseOperation(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
+ {
+ finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
+ }
+ }
+ if (!hasPackage) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "no component-data package attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "no component-data name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ componentName_ = xmldata::convertFromUtf8(
+ Span(buf.getStr(), buf.getLength()));
+ if (trackPath_) {
+ OSL_ASSERT(path_.empty());
+ path_.push_back(componentName_);
+ if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
+ {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ }
+ rtl::Reference< Node > node(
+ Data::findNode(
+ valueParser_.getLayer(), data_.components, componentName_));
+ if (!node.is()) {
+ OSL_TRACE(
+ "configmgr unknown component %s in %s",
+ rtl::OUStringToOString(
+ componentName_, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(
+ reader.getUrl(), RTL_TEXTENCODING_UTF8).getStr());
+ state_.push(State(true)); // ignored
+ return;
+ }
+ switch (op) {
+ case OPERATION_MODIFY:
+ case OPERATION_FUSE:
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "invalid operation on root node in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ int finalizedLayer = std::min(
+ finalized ? valueParser_.getLayer() : Data::NO_LAYER,
+ node->getFinalized());
+ node->setFinalized(finalizedLayer);
+ state_.push(State(node, finalizedLayer < valueParser_.getLayer()));
+}
+
+void XcuParser::handleItem(XmlReader & reader) {
+ Span attrPath;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("path")))
+ {
+ attrPath = reader.getAttributeValue(false);
+ }
+ }
+ if (!attrPath.is()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("missing path attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ rtl::OUString path(xmldata::convertFromUtf8(attrPath));
+ int finalizedLayer;
+ rtl::Reference< Node > node(
+ data_.resolvePathRepresentation(path, &path_, &finalizedLayer));
+ if (!node.is()) {
+ OSL_TRACE(
+ "configmgr unknown item %s in %s",
+ rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(
+ reader.getUrl(), RTL_TEXTENCODING_UTF8).getStr());
+ state_.push(State(true)); // ignored
+ return;
+ }
+ OSL_ASSERT(!path_.empty());
+ componentName_ = path_.front();
+ if (trackPath_) {
+ if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
+ {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ } else {
+ path_.clear();
+ }
+ switch (node->kind()) {
+ case Node::KIND_PROPERTY:
+ case Node::KIND_LOCALIZED_VALUE:
+ OSL_TRACE(
+ "configmgr item of bad type %s in %s",
+ rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(
+ reader.getUrl(), RTL_TEXTENCODING_UTF8).getStr());
+ state_.push(State(true)); // ignored
+ return;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ valueParser_.type_ = dynamic_cast< LocalizedPropertyNode * >(
+ node.get())->getStaticType();
+ break;
+ default:
+ break;
+ }
+ state_.push(State(node, finalizedLayer < valueParser_.getLayer()));
+}
+
+void XcuParser::handlePropValue(XmlReader & reader, PropertyNode * prop) {
+ bool nil = false;
+ rtl::OString separator;
+ rtl::OUString external;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_XSI &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nil")))
+ {
+ nil = xmldata::parseBoolean(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
+ {
+ Type type = xmldata::parseType(
+ reader, reader.getAttributeValue(true));
+ if (valueParser_.type_ != TYPE_ANY && type != valueParser_.type_) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("invalid value type in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ valueParser_.type_ = type;
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
+ {
+ Span s(reader.getAttributeValue(false));
+ if (s.length == 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad oor:separator attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ separator = rtl::OString(s.begin, s.length);
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("external")))
+ {
+ external = xmldata::convertFromUtf8(reader.getAttributeValue(true));
+ if (external.getLength() == 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad oor:external attribute value in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ }
+ if (nil) {
+ if (!prop->isNillable()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "xsi:nil attribute for non-nillable prop in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (external.getLength() != 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "xsi:nil and oor:external attributes for prop in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ prop->setValue(valueParser_.getLayer(), css::uno::Any());
+ state_.push(State(false));
+ } else if (external.getLength() == 0) {
+ valueParser_.separator_ = separator;
+ valueParser_.start(prop);
+ } else {
+ prop->setExternal(valueParser_.getLayer(), external);
+ state_.push(State(false));
+ }
+}
+
+void XcuParser::handleLocpropValue(
+ XmlReader & reader, LocalizedPropertyNode * locprop)
+{
+ rtl::OUString name;
+ bool nil = false;
+ rtl::OString separator;
+ Operation op = OPERATION_FUSE;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_XML &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("lang")))
+ {
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_XSI &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nil")))
+ {
+ nil = xmldata::parseBoolean(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
+ {
+ Type type = xmldata::parseType(
+ reader, reader.getAttributeValue(true));
+ if (valueParser_.type_ != TYPE_ANY && type != valueParser_.type_) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("invalid value type in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ valueParser_.type_ = type;
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
+ {
+ Span s(reader.getAttributeValue(false));
+ if (s.length == 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad oor:separator attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ separator = rtl::OString(s.begin, s.length);
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
+ {
+ op = parseOperation(reader.getAttributeValue(true));
+ }
+ }
+ if (trackPath_) {
+ path_.push_back(name);
+ if (partial_ != 0 &&
+ partial_->contains(path_) != Partial::CONTAINS_NODE)
+ {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ }
+ NodeMap::iterator i(locprop->getMembers().find(name));
+ if (i != locprop->getMembers().end() &&
+ i->second->getLayer() > valueParser_.getLayer())
+ {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ if (nil && !locprop->isNillable()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "xsi:nil attribute for non-nillable prop in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ switch (op) {
+ case OPERATION_FUSE:
+ {
+ bool pop = false;
+ if (nil) {
+ if (i == locprop->getMembers().end()) {
+ locprop->getMembers()[name] = new LocalizedValueNode(
+ valueParser_.getLayer(), css::uno::Any());
+ } else {
+ dynamic_cast< LocalizedValueNode * >(
+ i->second.get())->setValue(
+ valueParser_.getLayer(), css::uno::Any());
+ }
+ state_.push(State(true));
+ } else {
+ valueParser_.separator_ = separator;
+ valueParser_.start(locprop, name);
+ pop = true;
+ }
+ if (trackPath_) {
+ recordModification();
+ if (pop) {
+ path_.pop_back();
+ }
+ }
+ }
+ break;
+ 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);
+ }
+ state_.push(State(true));
+ recordModification();
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "bad op attribute for value element in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void XcuParser::handleGroupProp(XmlReader & reader, GroupNode * group) {
+ bool hasName = false;
+ rtl::OUString name;
+ Type type = TYPE_ERROR;
+ Operation op = OPERATION_MODIFY;
+ bool finalized = false;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ hasName = true;
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
+ {
+ type = xmldata::parseType(reader, reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
+ {
+ op = parseOperation(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
+ {
+ finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
+ }
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no prop name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (trackPath_) {
+ path_.push_back(name);
+ //TODO: This ignores locprop values for which specific include paths
+ // exist (i.e., for which contains(locprop path) = CONTAINS_SUBNODES):
+ if (partial_ != 0 &&
+ partial_->contains(path_) != Partial::CONTAINS_NODE)
+ {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ }
+ NodeMap::iterator i(group->getMembers().find(name));
+ if (i == group->getMembers().end()) {
+ handleUnknownGroupProp(reader, group, name, type, op, finalized);
+ } else {
+ switch (i->second->kind()) {
+ case Node::KIND_PROPERTY:
+ handlePlainGroupProp(reader, group, i, name, type, op, finalized);
+ break;
+ case Node::KIND_LOCALIZED_PROPERTY:
+ handleLocalizedGroupProp(
+ reader,
+ dynamic_cast< LocalizedPropertyNode * >(i->second.get()), name,
+ type, op, finalized);
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("inappropriate prop ")) +
+ name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+}
+
+void XcuParser::handleUnknownGroupProp(
+ XmlReader const & reader, GroupNode * group, rtl::OUString const & name,
+ Type type, Operation operation, bool finalized)
+{
+ switch (operation) {
+ case OPERATION_REPLACE:
+ case OPERATION_FUSE:
+ if (group->isExtensible()) {
+ if (type == TYPE_ERROR) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "missing type attribute for prop ")) +
+ name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ valueParser_.type_ = type;
+ rtl::Reference< Node > prop(
+ new PropertyNode(
+ valueParser_.getLayer(), TYPE_ANY, true, css::uno::Any(),
+ true));
+ if (finalized) {
+ prop->setFinalized(valueParser_.getLayer());
+ }
+ state_.push(State(prop, name, state_.top().locked));
+ recordModification();
+ break;
+ }
+ // fall through
+ default:
+ OSL_TRACE(
+ "configmgr unknown property %s in %s",
+ rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(
+ reader.getUrl(), RTL_TEXTENCODING_UTF8).getStr());
+ state_.push(State(true)); // ignored
+ break;
+ }
+}
+
+void XcuParser::handlePlainGroupProp(
+ XmlReader const & reader, GroupNode * group,
+ NodeMap::iterator const & propertyIndex, rtl::OUString const & name,
+ Type type, Operation operation, bool finalized)
+{
+ PropertyNode * property = dynamic_cast< PropertyNode * >(
+ propertyIndex->second.get());
+ if (property->getLayer() > valueParser_.getLayer()) {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ int finalizedLayer = std::min(
+ finalized ? valueParser_.getLayer() : Data::NO_LAYER,
+ property->getFinalized());
+ property->setFinalized(finalizedLayer);
+ if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
+ type != property->getStaticType())
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("invalid type for prop ")) +
+ name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
+ switch (operation) {
+ case OPERATION_MODIFY:
+ case OPERATION_REPLACE:
+ case OPERATION_FUSE:
+ state_.push(
+ State(
+ property,
+ (state_.top().locked ||
+ finalizedLayer < valueParser_.getLayer())));
+ recordModification();
+ break;
+ case OPERATION_REMOVE:
+ if (!property->isExtension()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "invalid remove of non-extension prop ")) +
+ name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ group->getMembers().erase(propertyIndex);
+ state_.push(State(true)); // ignore children
+ recordModification();
+ break;
+ }
+}
+
+void XcuParser::handleLocalizedGroupProp(
+ XmlReader const & reader, LocalizedPropertyNode * property,
+ rtl::OUString const & name, Type type, Operation operation, bool finalized)
+{
+ if (property->getLayer() > valueParser_.getLayer()) {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ int finalizedLayer = std::min(
+ finalized ? valueParser_.getLayer() : Data::NO_LAYER,
+ property->getFinalized());
+ property->setFinalized(finalizedLayer);
+ if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
+ type != property->getStaticType())
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("invalid type for prop ")) +
+ name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
+ switch (operation) {
+ case OPERATION_MODIFY:
+ case OPERATION_FUSE:
+ state_.push(
+ State(
+ property,
+ (state_.top().locked ||
+ finalizedLayer < valueParser_.getLayer())));
+ break;
+ case OPERATION_REPLACE:
+ {
+ rtl::Reference< Node > replacement(
+ new LocalizedPropertyNode(
+ valueParser_.getLayer(), property->getStaticType(),
+ property->isNillable()));
+ replacement->setFinalized(property->getFinalized());
+ state_.push(
+ State(
+ replacement, name,
+ (state_.top().locked ||
+ finalizedLayer < valueParser_.getLayer())));
+ recordModification();
+ }
+ break;
+ case OPERATION_REMOVE:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "invalid remove of non-extension prop ")) +
+ name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void XcuParser::handleGroupNode(
+ XmlReader & reader, rtl::Reference< Node > const & group)
+{
+ bool hasName = false;
+ rtl::OUString name;
+ Operation op = OPERATION_MODIFY;
+ bool finalized = false;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ hasName = true;
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
+ {
+ op = parseOperation(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
+ {
+ finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
+ }
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no node name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (trackPath_) {
+ path_.push_back(name);
+ if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
+ {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ }
+ rtl::Reference< Node > child(
+ Data::findNode(valueParser_.getLayer(), group->getMembers(), name));
+ if (!child.is()) {
+ OSL_TRACE(
+ "configmgr unknown node %s in %s",
+ rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString(
+ reader.getUrl(), RTL_TEXTENCODING_UTF8).getStr());
+ state_.push(State(true)); // ignored
+ return;
+ }
+ if (op != OPERATION_MODIFY && op != OPERATION_FUSE) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "invalid operation on group node in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ int finalizedLayer = std::min(
+ finalized ? valueParser_.getLayer() : Data::NO_LAYER,
+ child->getFinalized());
+ child->setFinalized(finalizedLayer);
+ state_.push(
+ State(
+ child,
+ state_.top().locked || finalizedLayer < valueParser_.getLayer()));
+}
+
+void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) {
+ bool hasName = false;
+ rtl::OUString name;
+ rtl::OUString component(componentName_);
+ bool hasNodeType = false;
+ rtl::OUString nodeType;
+ Operation op = OPERATION_MODIFY;
+ bool finalized = false;
+ bool mandatory = false;
+ for (;;) {
+ XmlReader::Namespace attrNs;
+ Span attrLn;
+ if (!reader.nextAttribute(&attrNs, &attrLn)) {
+ break;
+ }
+ if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ hasName = true;
+ name = xmldata::convertFromUtf8(reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
+ {
+ component = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
+ {
+ hasNodeType = true;
+ nodeType = xmldata::convertFromUtf8(
+ reader.getAttributeValue(false));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
+ {
+ op = parseOperation(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
+ {
+ finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
+ } else if (attrNs == XmlReader::NAMESPACE_OOR &&
+ attrLn.equals(RTL_CONSTASCII_STRINGPARAM("mandatory")))
+ {
+ mandatory = xmldata::parseBoolean(reader.getAttributeValue(true));
+ }
+ }
+ if (!hasName) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("no node name attribute in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (trackPath_) {
+ path_.push_back(name);
+ if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
+ {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ }
+ rtl::OUString templateName(
+ xmldata::parseTemplateReference(
+ component, hasNodeType, nodeType, &set->getDefaultTemplateName()));
+ if (!set->isValidTemplate(templateName)) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("set member node ")) +
+ name +
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(" references invalid template ")) +
+ templateName + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ rtl::Reference< Node > tmpl(
+ data_.getTemplate(valueParser_.getLayer(), templateName));
+ if (!tmpl.is()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("set member node ")) +
+ name +
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ " references undefined template ")) +
+ templateName + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
+ reader.getUrl()),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ 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()) {
+ finalizedLayer = std::min(finalizedLayer, i->second->getFinalized());
+ i->second->setFinalized(finalizedLayer);
+ mandatoryLayer = std::min(mandatoryLayer, i->second->getMandatory());
+ i->second->setMandatory(mandatoryLayer);
+ if (i->second->getLayer() > valueParser_.getLayer()) {
+ state_.push(State(true)); // ignored
+ return;
+ }
+ }
+ switch (op) {
+ case OPERATION_MODIFY:
+ if (i == set->getMembers().end()) {
+ OSL_TRACE("ignoring modify of unknown set member node");
+ state_.push(State(true)); // ignored
+ } else {
+ state_.push(
+ State(
+ i->second,
+ (state_.top().locked ||
+ finalizedLayer < valueParser_.getLayer())));
+ }
+ break;
+ case OPERATION_REPLACE:
+ if (state_.top().locked || finalizedLayer < valueParser_.getLayer()) {
+ state_.push(State(true)); // ignored
+ } else {
+ rtl::Reference< Node > member(tmpl->clone());
+ member->setLayer(valueParser_.getLayer());
+ member->setFinalized(finalizedLayer);
+ member->setMandatory(mandatoryLayer);
+ state_.push(State(member, name, false));
+ recordModification();
+ }
+ break;
+ case OPERATION_FUSE:
+ if (i == set->getMembers().end()) {
+ if (state_.top().locked || finalizedLayer < valueParser_.getLayer())
+ {
+ state_.push(State(true)); // ignored
+ } else {
+ rtl::Reference< Node > member(tmpl->clone());
+ member->setLayer(valueParser_.getLayer());
+ member->setFinalized(finalizedLayer);
+ member->setMandatory(mandatoryLayer);
+ state_.push(State(member, name, false));
+ recordModification();
+ }
+ } else {
+ state_.push(
+ State(
+ i->second,
+ (state_.top().locked ||
+ finalizedLayer < valueParser_.getLayer())));
+ }
+ break;
+ case OPERATION_REMOVE:
+ // Ignore removal of unknown members, members finalized in a lower
+ // layer, and members made mandatory in this or a lower layer:
+ if (i != set->getMembers().end() && !state_.top().locked &&
+ finalizedLayer >= valueParser_.getLayer() &&
+ mandatoryLayer > valueParser_.getLayer())
+ {
+ set->getMembers().erase(i);
+ }
+ state_.push(State(true));
+ recordModification();
+ break;
+ }
+}
+
+void XcuParser::recordModification() {
+ if (broadcastModifications_ != 0) {
+ broadcastModifications_->add(path_);
+ }
+ if (recordModifications_) {
+ data_.modifications.add(path_);
+ }
+}
+
+}
diff --git a/configmgr/source/xcuparser.hxx b/configmgr/source/xcuparser.hxx
new file mode 100644
index 000000000000..64108451b4ef
--- /dev/null
+++ b/configmgr/source/xcuparser.hxx
@@ -0,0 +1,153 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_XCUPARSER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_XCUPARSER_HXX
+
+#include "sal/config.h"
+
+#include <stack>
+
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "parser.hxx"
+#include "path.hxx"
+#include "type.hxx"
+#include "valueparser.hxx"
+#include "xmldata.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+class GroupNode;
+class LocalizedPropertyNode;
+class Modifications;
+class Partial;
+class PropertyNode;
+class SetNode;
+struct Data;
+struct Span;
+
+class XcuParser: public Parser {
+public:
+ XcuParser(
+ int layer, Data & data, Partial const * partial,
+ Modifications * broadcastModifications);
+
+private:
+ virtual ~XcuParser();
+
+ virtual XmlReader::Text getTextMode();
+
+ virtual bool startElement(
+ XmlReader & reader, XmlReader::Namespace ns, Span const & name);
+
+ virtual void endElement(XmlReader const & reader);
+
+ virtual void characters(Span const & span);
+
+ enum Operation {
+ OPERATION_MODIFY, OPERATION_REPLACE, OPERATION_FUSE, OPERATION_REMOVE };
+
+ static Operation parseOperation(Span const & text);
+
+ void handleComponentData(XmlReader & reader);
+
+ void handleItem(XmlReader & reader);
+
+ void handlePropValue(XmlReader & reader, PropertyNode * prop);
+
+ void handleLocpropValue(
+ XmlReader & reader, LocalizedPropertyNode * locprop);
+
+ void handleGroupProp(XmlReader & reader, GroupNode * group);
+
+ void handleUnknownGroupProp(
+ XmlReader const & reader, GroupNode * group, rtl::OUString const & name,
+ Type type, Operation operation, bool finalized);
+
+ void handlePlainGroupProp(
+ XmlReader const & reader, GroupNode * group,
+ NodeMap::iterator const & propertyIndex, rtl::OUString const & name,
+ Type type, Operation operation, bool finalized);
+
+ void handleLocalizedGroupProp(
+ XmlReader const & reader, LocalizedPropertyNode * property,
+ rtl::OUString const & name, Type type, Operation operation,
+ bool finalized);
+
+ void handleGroupNode(
+ XmlReader & reader, rtl::Reference< Node > const & group);
+
+ void handleSetNode(XmlReader & reader, SetNode * set);
+
+ void recordModification();
+
+ struct State {
+ rtl::Reference< Node > node; // empty iff ignore or <items>
+ rtl::OUString name; // empty and ignored if !insert
+ bool ignore;
+ bool insert;
+ bool locked;
+ bool pop;
+
+ inline State(bool thePop):
+ ignore(true), insert(false), locked(false), pop(thePop)
+ {}
+
+ inline State(rtl::Reference< Node > const & theNode, bool theLocked):
+ node(theNode), ignore(false), insert(false), locked(theLocked),
+ pop(true)
+ {}
+
+ inline State(
+ rtl::Reference< Node > const & theNode,
+ rtl::OUString const & theName, bool theLocked):
+ node(theNode), name(theName), ignore(false), insert(true),
+ locked(theLocked), pop(true)
+ {}
+ };
+
+ typedef std::stack< State > StateStack;
+
+ ValueParser valueParser_;
+ Data & data_;
+ Partial const * partial_;
+ Modifications * broadcastModifications_;
+ bool recordModifications_;
+ bool trackPath_;
+ rtl::OUString componentName_;
+ StateStack state_;
+ Path path_;
+};
+
+}
+
+#endif
diff --git a/configmgr/source/xmldata.cxx b/configmgr/source/xmldata.cxx
new file mode 100644
index 000000000000..07ad4d17a345
--- /dev/null
+++ b/configmgr/source/xmldata.cxx
@@ -0,0 +1,204 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <climits>
+#include <stack>
+
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/file.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/strbuf.hxx"
+#include "rtl/string.h"
+#include "rtl/textcvt.h"
+#include "rtl/textenc.h"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "data.hxx"
+#include "groupnode.hxx"
+#include "localizedpropertynode.hxx"
+#include "localizedvaluenode.hxx"
+#include "node.hxx"
+#include "nodemap.hxx"
+#include "parsemanager.hxx"
+#include "parser.hxx"
+#include "propertynode.hxx"
+#include "setnode.hxx"
+#include "span.hxx"
+#include "type.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+namespace xmldata {
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+rtl::OUString convertFromUtf8(Span const & text) {
+ OSL_ASSERT(text.is());
+ rtl_uString * s = 0;
+ if (!rtl_convertStringToUString(
+ &s, text.begin, text.length, RTL_TEXTENCODING_UTF8,
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+ {
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("cannot convert from UTF-8")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return rtl::OUString(s, SAL_NO_ACQUIRE);
+}
+
+Type parseType(XmlReader const & reader, Span const & text) {
+ OSL_ASSERT(text.is());
+ sal_Int32 i = rtl_str_indexOfChar_WithLength(text.begin, text.length, ':');
+ if (i >= 0) {
+ switch (reader.getNamespace(Span(text.begin, i))) {
+ case XmlReader::NAMESPACE_OOR:
+ if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("any")))
+ {
+ return TYPE_ANY;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("boolean-list")))
+ {
+ return TYPE_BOOLEAN_LIST;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("short-list")))
+ {
+ return TYPE_SHORT_LIST;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("int-list")))
+ {
+ return TYPE_INT_LIST;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("long-list")))
+ {
+ return TYPE_LONG_LIST;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("double-list")))
+ {
+ return TYPE_DOUBLE_LIST;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("string-list")))
+ {
+ return TYPE_STRING_LIST;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("hexBinary-list")))
+ {
+ return TYPE_HEXBINARY_LIST;
+ }
+ break;
+ case XmlReader::NAMESPACE_XS:
+ if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("boolean")))
+ {
+ return TYPE_BOOLEAN;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("short")))
+ {
+ return TYPE_SHORT;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("int")))
+ {
+ return TYPE_INT;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("long")))
+ {
+ return TYPE_LONG;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("double")))
+ {
+ return TYPE_DOUBLE;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("string")))
+ {
+ return TYPE_STRING;
+ } else if (Span(text.begin + i + 1, text.length - (i + 1)).equals(
+ RTL_CONSTASCII_STRINGPARAM("hexBinary")))
+ {
+ return TYPE_HEXBINARY;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid type ")) +
+ convertFromUtf8(text)),
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+bool parseBoolean(Span const & text) {
+ OSL_ASSERT(text.is());
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("true"))) {
+ return true;
+ }
+ if (text.equals(RTL_CONSTASCII_STRINGPARAM("false"))) {
+ return false;
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("invalid boolean ")) +
+ convertFromUtf8(text)),
+ css::uno::Reference< css::uno::XInterface >());
+}
+
+rtl::OUString parseTemplateReference(
+ rtl::OUString const & component, bool hasNodeType,
+ rtl::OUString const & nodeType, rtl::OUString const * defaultTemplateName)
+{
+ if (!hasNodeType) {
+ if (defaultTemplateName != 0) {
+ return *defaultTemplateName;
+ }
+ throw css::uno::RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("missing node-type attribute")),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return Data::fullTemplateName(component, nodeType);
+}
+
+}
+
+}
diff --git a/configmgr/source/xmldata.hxx b/configmgr/source/xmldata.hxx
new file mode 100644
index 000000000000..15a0a36336ad
--- /dev/null
+++ b/configmgr/source/xmldata.hxx
@@ -0,0 +1,58 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_XMLDATA_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_XMLDATA_HXX
+
+#include "sal/config.h"
+
+#include "type.hxx"
+
+namespace rtl { class OUString; }
+
+namespace configmgr {
+
+class XmlReader;
+struct Span;
+
+namespace xmldata {
+
+rtl::OUString convertFromUtf8(Span const & text);
+
+Type parseType(XmlReader const & reader, Span const & text);
+
+bool parseBoolean(Span const & text);
+
+rtl::OUString parseTemplateReference(
+ rtl::OUString const & component, bool hasNodeType,
+ rtl::OUString const & nodeType, rtl::OUString const * defaultTemplateName);
+
+}
+
+}
+
+#endif
diff --git a/configmgr/source/xmlreader.cxx b/configmgr/source/xmlreader.cxx
new file mode 100644
index 000000000000..ac6a08d18604
--- /dev/null
+++ b/configmgr/source/xmlreader.cxx
@@ -0,0 +1,1054 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "precompiled_configmgr.hxx"
+#include "sal/config.h"
+
+#include <cstddef>
+
+#include "com/sun/star/container/NoSuchElementException.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/diagnose.h"
+#include "osl/file.h"
+#include "rtl/string.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "pad.hxx"
+#include "span.hxx"
+#include "xmlreader.hxx"
+
+namespace configmgr {
+
+namespace {
+
+namespace css = com::sun::star;
+
+bool isSpace(char c) {
+ switch (c) {
+ case '\x09':
+ case '\x0A':
+ case '\x0D':
+ case ' ':
+ return true;
+ default:
+ return false;
+ }
+}
+
+}
+
+XmlReader::XmlReader(rtl::OUString const & fileUrl)
+ SAL_THROW((
+ css::container::NoSuchElementException, css::uno::RuntimeException)):
+ fileUrl_(fileUrl)
+{
+ switch (osl_openFile(fileUrl_.pData, &fileHandle_, osl_File_OpenFlag_Read))
+ {
+ case osl_File_E_None:
+ break;
+ case osl_File_E_NOENT:
+ throw css::container::NoSuchElementException(
+ fileUrl_, css::uno::Reference< css::uno::XInterface >());
+ default:
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot open ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ oslFileError e = osl_getFileSize(fileHandle_, &fileSize_);
+ if (e == osl_File_E_None) {
+ e = osl_mapFile(
+ fileHandle_, &fileAddress_, fileSize_, 0,
+ osl_File_MapFlag_WillNeed);
+ }
+ if (e != osl_File_E_None) {
+ e = osl_closeFile(fileHandle_);
+ if (e != osl_File_E_None) {
+ OSL_TRACE("osl_closeFile failed with %ld", static_cast< long >(e));
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot mmap ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ namespaces_.push_back(
+ NamespaceData(Span(RTL_CONSTASCII_STRINGPARAM("xml")), NAMESPACE_XML));
+ namespaces_.push_back(
+ NamespaceData(Span(RTL_CONSTASCII_STRINGPARAM("xsi")), NAMESPACE_XSI));
+ // old user layer .xcu files used the xsi namespace prefix without
+ // declaring a corresponding namespace binding, see issue 77174; reading
+ // those files during migration would fail without this hack that can be
+ // removed once migration is no longer relevant (see
+ // Components::parseModificationLayer)
+ pos_ = static_cast< char * >(fileAddress_);
+ end_ = pos_ + fileSize_;
+ state_ = STATE_CONTENT;
+}
+
+XmlReader::~XmlReader() {
+ oslFileError e = osl_unmapFile(fileAddress_, fileSize_);
+ if (e != osl_File_E_None) {
+ OSL_TRACE("osl_unmapFile failed with %ld", static_cast< long >(e));
+ }
+ e = osl_closeFile(fileHandle_);
+ if (e != osl_File_E_None) {
+ OSL_TRACE("osl_closeFile failed with %ld", static_cast< long >(e));
+ }
+}
+
+XmlReader::Result XmlReader::nextItem(
+ Text reportText, Span * data, Namespace * ns)
+{
+ switch (state_) {
+ case STATE_CONTENT:
+ switch (reportText) {
+ case TEXT_NONE:
+ return handleSkippedText(data, ns);
+ case TEXT_RAW:
+ return handleRawText(data);
+ case TEXT_NORMALIZED:
+ return handleNormalizedText(data);
+ }
+ case STATE_START_TAG:
+ return handleStartTag(ns, data);
+ case STATE_END_TAG:
+ return handleEndTag();
+ case STATE_EMPTY_ELEMENT_TAG:
+ handleElementEnd();
+ return RESULT_END;
+ default: // STATE_DONE
+ return RESULT_DONE;
+ }
+}
+
+bool XmlReader::nextAttribute(Namespace * ns, Span * localName) {
+ OSL_ASSERT(ns != 0 && localName != 0);
+ if (firstAttribute_) {
+ currentAttribute_ = attributes_.begin();
+ firstAttribute_ = false;
+ } else {
+ ++currentAttribute_;
+ }
+ if (currentAttribute_ == attributes_.end()) {
+ return false;
+ }
+ if (currentAttribute_->nameColon == 0) {
+ *ns = NAMESPACE_NONE;
+ *localName = Span(
+ currentAttribute_->nameBegin,
+ currentAttribute_->nameEnd - currentAttribute_->nameBegin);
+ } else {
+ *ns = getNamespace(
+ Span(
+ currentAttribute_->nameBegin,
+ currentAttribute_->nameColon - currentAttribute_->nameBegin));
+ *localName = Span(
+ currentAttribute_->nameColon + 1,
+ currentAttribute_->nameEnd - (currentAttribute_->nameColon + 1));
+ }
+ return true;
+}
+
+Span XmlReader::getAttributeValue(bool fullyNormalize) {
+ return handleAttributeValue(
+ currentAttribute_->valueBegin, currentAttribute_->valueEnd,
+ fullyNormalize);
+}
+
+XmlReader::Namespace XmlReader::getNamespace(Span const & prefix) const {
+ for (NamespaceList::const_reverse_iterator i(namespaces_.rbegin());
+ i != namespaces_.rend(); ++i)
+ {
+ if (prefix.equals(i->prefix)) {
+ return i->ns;
+ }
+ }
+ return NAMESPACE_OTHER;
+}
+
+rtl::OUString XmlReader::getUrl() const {
+ return fileUrl_;
+}
+
+void XmlReader::normalizeLineEnds(Span const & text) {
+ char const * p = text.begin;
+ sal_Int32 n = text.length;
+ for (;;) {
+ sal_Int32 i = rtl_str_indexOfChar_WithLength(p, n, '\x0D');
+ if (i < 0) {
+ break;
+ }
+ pad_.add(p, i);
+ p += i + 1;
+ n -= i + 1;
+ if (n == 0 || *p != '\x0A') {
+ pad_.add(RTL_CONSTASCII_STRINGPARAM("\x0A"));
+ }
+ }
+ pad_.add(p, n);
+}
+
+void XmlReader::skipSpace() {
+ while (isSpace(peek())) {
+ ++pos_;
+ }
+}
+
+bool XmlReader::skipComment() {
+ if (rtl_str_shortenedCompare_WithLength(
+ pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("--"),
+ RTL_CONSTASCII_LENGTH("--")) !=
+ 0)
+ {
+ return false;
+ }
+ pos_ += RTL_CONSTASCII_LENGTH("--");
+ sal_Int32 i = rtl_str_indexOfStr_WithLength(
+ pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("--"));
+ if (i < 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "premature end (within comment) of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ pos_ += i + RTL_CONSTASCII_LENGTH("--");
+ if (read() != '>') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "illegal \"--\" within comment in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return true;
+}
+
+void XmlReader::skipProcessingInstruction() {
+ sal_Int32 i = rtl_str_indexOfStr_WithLength(
+ pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("?>"));
+ if (i < 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad '<?' in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ pos_ += i + RTL_CONSTASCII_LENGTH("?>");
+}
+
+void XmlReader::skipDocumentTypeDeclaration() {
+ // Neither is it checked that the doctypedecl is at the correct position in
+ // the document, nor that it is well-formed:
+ for (;;) {
+ char c = read();
+ switch (c) {
+ case '\0': // i.e., EOF
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "premature end (within DTD) of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ case '"':
+ case '\'':
+ {
+ sal_Int32 i = rtl_str_indexOfChar_WithLength(
+ pos_, end_ - pos_, c);
+ if (i < 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "premature end (within DTD) of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ pos_ += i + 1;
+ }
+ break;
+ case '>':
+ return;
+ case '[':
+ for (;;) {
+ c = read();
+ switch (c) {
+ case '\0': // i.e., EOF
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "premature end (within DTD) of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ case '"':
+ case '\'':
+ {
+ sal_Int32 i = rtl_str_indexOfChar_WithLength(
+ pos_, end_ - pos_, c);
+ if (i < 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "premature end (within DTD) of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ pos_ += i + 1;
+ }
+ break;
+ case '<':
+ switch (read()) {
+ case '\0': // i.e., EOF
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "premature end (within DTD) of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ case '!':
+ skipComment();
+ break;
+ case '?':
+ skipProcessingInstruction();
+ break;
+ default:
+ break;
+ }
+ break;
+ case ']':
+ skipSpace();
+ if (read() != '>') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "missing \">\" of DTD in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return;
+ default:
+ break;
+ }
+ }
+ default:
+ break;
+ }
+ }
+}
+
+Span XmlReader::scanCdataSection() {
+ if (rtl_str_shortenedCompare_WithLength(
+ pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("[CDATA["),
+ RTL_CONSTASCII_LENGTH("[CDATA[")) !=
+ 0)
+ {
+ return Span();
+ }
+ pos_ += RTL_CONSTASCII_LENGTH("[CDATA[");
+ char const * begin = pos_;
+ sal_Int32 i = rtl_str_indexOfStr_WithLength(
+ pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("]]>"));
+ if (i < 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "premature end (within CDATA section) of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ pos_ += i + RTL_CONSTASCII_LENGTH("]]>");
+ return Span(begin, i);
+}
+
+bool XmlReader::scanName(char const ** nameColon) {
+ OSL_ASSERT(nameColon != 0 && *nameColon == 0);
+ for (char const * begin = pos_;; ++pos_) {
+ switch (peek()) {
+ case '\0': // i.e., EOF
+ case '\x09':
+ case '\x0A':
+ case '\x0D':
+ case ' ':
+ case '/':
+ case '=':
+ case '>':
+ return pos_ != begin;
+ case ':':
+ *nameColon = pos_;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+XmlReader::Namespace XmlReader::scanNamespaceIri(
+ char const * begin, char const * end)
+{
+ OSL_ASSERT(begin != 0 && begin <= end);
+ Span iri(handleAttributeValue(begin, end, false));
+ struct Iri {
+ char const * begin;
+ sal_Int32 length;
+ XmlReader::Namespace ns;
+ };
+ static Iri const iris[] = {
+ { RTL_CONSTASCII_STRINGPARAM("http://openoffice.org/2001/registry"),
+ XmlReader::NAMESPACE_OOR },
+ { RTL_CONSTASCII_STRINGPARAM("http://www.w3.org/2001/XMLSchema"),
+ XmlReader::NAMESPACE_XS },
+ { RTL_CONSTASCII_STRINGPARAM(
+ "http://www.w3.org/2001/XMLSchema-instance"),
+ XmlReader::NAMESPACE_XSI },
+ { RTL_CONSTASCII_STRINGPARAM("http://www.w3.org/XML/1998/namespace"),
+ XmlReader::NAMESPACE_XML } };
+ for (std::size_t i = 0; i < sizeof iris / sizeof iris[0]; ++i) {
+ if (rtl_str_compare_WithLength(
+ iri.begin, iri.length, iris[i].begin, iris[i].length) ==
+ 0)
+ {
+ return iris[i].ns;
+ }
+ }
+ return XmlReader::NAMESPACE_OTHER;
+}
+
+char const * XmlReader::handleReference(char const * position, char const * end)
+{
+ OSL_ASSERT(position != 0 && *position == '&' && position < end);
+ ++position;
+ if (*position == '#') {
+ ++position;
+ sal_Int32 val = 0;
+ char const * p;
+ if (*position == 'x') {
+ ++position;
+ p = position;
+ for (;; ++position) {
+ char c = *position;
+ if (c >= '0' && c <= '9') {
+ val = 16 * val + (c - '0');
+ } else if (c >= 'A' && c <= 'F') {
+ val = 16 * val + (c - 'A') + 10;
+ } else if (c >= 'a' && c <= 'f') {
+ val = 16 * val + (c - 'a') + 10;
+ } else {
+ break;
+ }
+ if (val > 0x10FFFF) { // avoid overflow
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "'&#x...' too large in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ } else {
+ p = position;
+ for (;; ++position) {
+ char c = *position;
+ if (c >= '0' && c <= '9') {
+ val = 10 * val + (c - '0');
+ } else {
+ break;
+ }
+ if (val > 0x10FFFF) { // avoid overflow
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "'&#...' too large in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ }
+ if (position == p || *position++ != ';') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("'&#...' missing ';' in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ OSL_ASSERT(val >= 0 && val <= 0x10FFFF);
+ if ((val < 0x20 && val != 0x9 && val != 0xA && val != 0xD) ||
+ (val >= 0xD800 && val <= 0xDFFF) || val == 0xFFFE || val == 0xFFFF)
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "character reference denoting invalid character in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ char buf[4];
+ sal_Int32 len;
+ if (val < 0x80) {
+ buf[0] = static_cast< char >(val);
+ len = 1;
+ } else if (val < 0x800) {
+ buf[0] = static_cast< char >((val >> 6) | 0xC0);
+ buf[1] = static_cast< char >((val & 0x3F) | 0x80);
+ len = 2;
+ } else if (val < 0x10000) {
+ buf[0] = static_cast< char >((val >> 12) | 0xE0);
+ buf[1] = static_cast< char >(((val >> 6) & 0x3F) | 0x80);
+ buf[2] = static_cast< char >((val & 0x3F) | 0x80);
+ len = 3;
+ } else {
+ buf[0] = static_cast< char >((val >> 18) | 0xF0);
+ buf[1] = static_cast< char >(((val >> 12) & 0x3F) | 0x80);
+ buf[2] = static_cast< char >(((val >> 6) & 0x3F) | 0x80);
+ buf[3] = static_cast< char >((val & 0x3F) | 0x80);
+ len = 4;
+ }
+ pad_.addEphemeral(buf, len);
+ return position;
+ } else {
+ struct EntityRef {
+ char const * inBegin;
+ sal_Int32 inLength;
+ char const * outBegin;
+ sal_Int32 outLength;
+ };
+ static EntityRef const refs[] = {
+ { RTL_CONSTASCII_STRINGPARAM("amp;"),
+ RTL_CONSTASCII_STRINGPARAM("&") },
+ { RTL_CONSTASCII_STRINGPARAM("lt;"),
+ RTL_CONSTASCII_STRINGPARAM("<") },
+ { RTL_CONSTASCII_STRINGPARAM("gt;"),
+ RTL_CONSTASCII_STRINGPARAM(">") },
+ { RTL_CONSTASCII_STRINGPARAM("apos;"),
+ RTL_CONSTASCII_STRINGPARAM("'") },
+ { RTL_CONSTASCII_STRINGPARAM("quot;"),
+ RTL_CONSTASCII_STRINGPARAM("\"") } };
+ for (std::size_t i = 0; i < sizeof refs / sizeof refs[0]; ++i) {
+ if (rtl_str_shortenedCompare_WithLength(
+ position, end - position, refs[i].inBegin, refs[i].inLength,
+ refs[i].inLength) ==
+ 0)
+ {
+ position += refs[i].inLength;
+ pad_.add(refs[i].outBegin, refs[i].outLength);
+ return position;
+ }
+ }
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("unknown entity reference in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+Span XmlReader::handleAttributeValue(
+ char const * begin, char const * end, bool fullyNormalize)
+{
+ pad_.clear();
+ if (fullyNormalize) {
+ while (begin != end && isSpace(*begin)) {
+ ++begin;
+ }
+ while (end != begin && isSpace(end[-1])) {
+ --end;
+ }
+ char const * p = begin;
+ enum Space { SPACE_NONE, SPACE_SPAN, SPACE_BREAK };
+ // a single true space character can go into the current span,
+ // everything else breaks the span
+ Space space = SPACE_NONE;
+ while (p != end) {
+ switch (*p) {
+ case '\x09':
+ case '\x0A':
+ case '\x0D':
+ switch (space) {
+ case SPACE_NONE:
+ pad_.add(begin, p - begin);
+ pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
+ space = SPACE_BREAK;
+ break;
+ case SPACE_SPAN:
+ pad_.add(begin, p - begin);
+ space = SPACE_BREAK;
+ break;
+ case SPACE_BREAK:
+ break;
+ }
+ begin = ++p;
+ break;
+ case ' ':
+ switch (space) {
+ case SPACE_NONE:
+ ++p;
+ space = SPACE_SPAN;
+ break;
+ case SPACE_SPAN:
+ pad_.add(begin, p - begin);
+ begin = ++p;
+ space = SPACE_BREAK;
+ break;
+ case SPACE_BREAK:
+ begin = ++p;
+ break;
+ }
+ break;
+ case '&':
+ pad_.add(begin, p - begin);
+ p = handleReference(p, end);
+ begin = p;
+ space = SPACE_NONE;
+ break;
+ default:
+ ++p;
+ space = SPACE_NONE;
+ break;
+ }
+ }
+ pad_.add(begin, p - begin);
+ } else {
+ char const * p = begin;
+ while (p != end) {
+ switch (*p) {
+ case '\x09':
+ case '\x0A':
+ pad_.add(begin, p - begin);
+ begin = ++p;
+ pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
+ break;
+ case '\x0D':
+ pad_.add(begin, p - begin);
+ ++p;
+ if (peek() == '\x0A') {
+ ++p;
+ }
+ begin = p;
+ pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
+ break;
+ case '&':
+ pad_.add(begin, p - begin);
+ p = handleReference(p, end);
+ begin = p;
+ break;
+ default:
+ ++p;
+ break;
+ }
+ }
+ pad_.add(begin, p - begin);
+ }
+ return pad_.get();
+}
+
+XmlReader::Result XmlReader::handleStartTag(Namespace * ns, Span * localName) {
+ OSL_ASSERT(ns != 0 && localName);
+ char const * nameBegin = pos_;
+ char const * nameColon = 0;
+ if (!scanName(&nameColon)) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad tag name in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ char const * nameEnd = pos_;
+ NamespaceList::size_type inheritedNamespaces = namespaces_.size();
+ bool hasDefaultNs = false;
+ Namespace defaultNs = NAMESPACE_NONE;
+ attributes_.clear();
+ for (;;) {
+ char const * p = pos_;
+ skipSpace();
+ if (peek() == '/' || peek() == '>') {
+ break;
+ }
+ if (pos_ == p) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "missing whitespace before attribute in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ char const * attrNameBegin = pos_;
+ char const * attrNameColon = 0;
+ if (!scanName(&attrNameColon)) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad attribute name in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ char const * attrNameEnd = pos_;
+ skipSpace();
+ if (read() != '=') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("missing '=' in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ skipSpace();
+ char del = read();
+ if (del != '\'' && del != '"') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("bad attribute value in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ char const * valueBegin = pos_;
+ sal_Int32 i = rtl_str_indexOfChar_WithLength(pos_, end_ - pos_, del);
+ if (i < 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "unterminated attribute value in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ char const * valueEnd = pos_ + i;
+ pos_ += i + 1;
+ if (attrNameColon == 0 &&
+ Span(attrNameBegin, attrNameEnd - attrNameBegin).equals(
+ RTL_CONSTASCII_STRINGPARAM("xmlns")))
+ {
+ hasDefaultNs = true;
+ defaultNs = scanNamespaceIri(valueBegin, valueEnd);
+ } else if (attrNameColon != 0 &&
+ Span(attrNameBegin, attrNameColon - attrNameBegin).equals(
+ RTL_CONSTASCII_STRINGPARAM("xmlns")))
+ {
+ namespaces_.push_back(
+ NamespaceData(
+ Span(attrNameColon + 1, attrNameEnd - (attrNameColon + 1)),
+ scanNamespaceIri(valueBegin, valueEnd)));
+ } else {
+ attributes_.push_back(
+ AttributeData(
+ attrNameBegin, attrNameEnd, attrNameColon, valueBegin,
+ valueEnd));
+ }
+ }
+ if (!hasDefaultNs && !elements_.empty()) {
+ defaultNs = elements_.top().defaultNamespace;
+ }
+ firstAttribute_ = true;
+ if (peek() == '/') {
+ state_ = STATE_EMPTY_ELEMENT_TAG;
+ ++pos_;
+ } else {
+ state_ = STATE_CONTENT;
+ }
+ if (peek() != '>') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("missing '>' in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ ++pos_;
+ elements_.push(
+ ElementData(
+ Span(nameBegin, nameEnd - nameBegin), inheritedNamespaces,
+ defaultNs));
+ if (nameColon == 0) {
+ *ns = defaultNs;
+ *localName = Span(nameBegin, nameEnd - nameBegin);
+ } else {
+ *ns = getNamespace(Span(nameBegin, nameColon - nameBegin));
+ *localName = Span(nameColon + 1, nameEnd - (nameColon + 1));
+ }
+ return RESULT_BEGIN;
+}
+
+XmlReader::Result XmlReader::handleEndTag() {
+ if (elements_.empty()) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("spurious end tag in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ char const * nameBegin = pos_;
+ char const * nameColon = 0;
+ if (!scanName(&nameColon) ||
+ !elements_.top().name.equals(nameBegin, pos_ - nameBegin))
+ {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("tag mismatch in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ handleElementEnd();
+ skipSpace();
+ if (peek() != '>') {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("missing '>' in ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ ++pos_;
+ return RESULT_END;
+}
+
+void XmlReader::handleElementEnd() {
+ OSL_ASSERT(!elements_.empty());
+ namespaces_.resize(elements_.top().inheritedNamespaces);
+ elements_.pop();
+ state_ = elements_.empty() ? STATE_DONE : STATE_CONTENT;
+}
+
+XmlReader::Result XmlReader::handleSkippedText(Span * data, Namespace * ns) {
+ for (;;) {
+ sal_Int32 i = rtl_str_indexOfChar_WithLength(pos_, end_ - pos_, '<');
+ if (i < 0) {
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("premature end of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ pos_ += i + 1;
+ switch (peek()) {
+ case '!':
+ ++pos_;
+ if (!skipComment() && !scanCdataSection().is()) {
+ skipDocumentTypeDeclaration();
+ }
+ break;
+ case '/':
+ ++pos_;
+ return handleEndTag();
+ case '?':
+ ++pos_;
+ skipProcessingInstruction();
+ break;
+ default:
+ return handleStartTag(ns, data);
+ }
+ }
+}
+
+XmlReader::Result XmlReader::handleRawText(Span * text) {
+ pad_.clear();
+ for (char const * begin = pos_;;) {
+ switch (peek()) {
+ case '\0': // i.e., EOF
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("premature end of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ case '\x0D':
+ pad_.add(begin, pos_ - begin);
+ ++pos_;
+ if (peek() != '\x0A') {
+ pad_.add(RTL_CONSTASCII_STRINGPARAM("\x0A"));
+ }
+ begin = pos_;
+ break;
+ case '&':
+ pad_.add(begin, pos_ - begin);
+ pos_ = handleReference(pos_, end_);
+ begin = pos_;
+ break;
+ case '<':
+ pad_.add(begin, pos_ - begin);
+ ++pos_;
+ switch (peek()) {
+ case '!':
+ ++pos_;
+ if (!skipComment()) {
+ Span cdata(scanCdataSection());
+ if (cdata.is()) {
+ normalizeLineEnds(cdata);
+ } else {
+ skipDocumentTypeDeclaration();
+ }
+ }
+ begin = pos_;
+ break;
+ case '/':
+ *text = pad_.get();
+ ++pos_;
+ state_ = STATE_END_TAG;
+ return RESULT_TEXT;
+ case '?':
+ ++pos_;
+ skipProcessingInstruction();
+ begin = pos_;
+ break;
+ default:
+ *text = pad_.get();
+ state_ = STATE_START_TAG;
+ return RESULT_TEXT;
+ }
+ break;
+ default:
+ ++pos_;
+ break;
+ }
+ }
+}
+
+XmlReader::Result XmlReader::handleNormalizedText(Span * text) {
+ pad_.clear();
+ char const * flowBegin = pos_;
+ char const * flowEnd = pos_;
+ enum Space { SPACE_START, SPACE_NONE, SPACE_SPAN, SPACE_BREAK };
+ // a single true space character can go into the current flow,
+ // everything else breaks the flow
+ Space space = SPACE_START;
+ for (;;) {
+ switch (peek()) {
+ case '\0': // i.e., EOF
+ throw css::uno::RuntimeException(
+ (rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("premature end of ")) +
+ fileUrl_),
+ css::uno::Reference< css::uno::XInterface >());
+ case '\x09':
+ case '\x0A':
+ case '\x0D':
+ switch (space) {
+ case SPACE_START:
+ case SPACE_BREAK:
+ break;
+ case SPACE_NONE:
+ case SPACE_SPAN:
+ space = SPACE_BREAK;
+ break;
+ }
+ ++pos_;
+ break;
+ case ' ':
+ switch (space) {
+ case SPACE_START:
+ case SPACE_BREAK:
+ break;
+ case SPACE_NONE:
+ space = SPACE_SPAN;
+ break;
+ case SPACE_SPAN:
+ space = SPACE_BREAK;
+ break;
+ }
+ ++pos_;
+ break;
+ case '&':
+ switch (space) {
+ case SPACE_START:
+ break;
+ case SPACE_NONE:
+ case SPACE_SPAN:
+ pad_.add(flowBegin, pos_ - flowBegin);
+ break;
+ case SPACE_BREAK:
+ pad_.add(flowBegin, flowEnd - flowBegin);
+ pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
+ break;
+ }
+ pos_ = handleReference(pos_, end_);
+ flowBegin = pos_;
+ flowEnd = pos_;
+ space = SPACE_NONE;
+ break;
+ case '<':
+ ++pos_;
+ switch (peek()) {
+ case '!':
+ ++pos_;
+ if (skipComment()) {
+ space = SPACE_BREAK;
+ } else {
+ Span cdata(scanCdataSection());
+ if (cdata.is()) {
+ // CDATA is not normalized (similar to character
+ // references; it keeps the code simple), but it might
+ // arguably be better to normalize it:
+ switch (space) {
+ case SPACE_START:
+ break;
+ case SPACE_NONE:
+ case SPACE_SPAN:
+ pad_.add(flowBegin, pos_ - flowBegin);
+ break;
+ case SPACE_BREAK:
+ pad_.add(flowBegin, flowEnd - flowBegin);
+ pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
+ break;
+ }
+ normalizeLineEnds(cdata);
+ flowBegin = pos_;
+ flowEnd = pos_;
+ space = SPACE_NONE;
+ } else {
+ skipDocumentTypeDeclaration();
+ }
+ }
+ break;
+ case '/':
+ ++pos_;
+ pad_.add(flowBegin, flowEnd - flowBegin);
+ *text = pad_.get();
+ state_ = STATE_END_TAG;
+ return RESULT_TEXT;
+ case '?':
+ ++pos_;
+ skipProcessingInstruction();
+ space = SPACE_BREAK;
+ break;
+ default:
+ pad_.add(flowBegin, flowEnd - flowBegin);
+ *text = pad_.get();
+ state_ = STATE_START_TAG;
+ return RESULT_TEXT;
+ }
+ break;
+ default:
+ switch (space) {
+ case SPACE_START:
+ flowBegin = pos_;
+ break;
+ case SPACE_NONE:
+ case SPACE_SPAN:
+ break;
+ case SPACE_BREAK:
+ pad_.add(flowBegin, flowEnd - flowBegin);
+ pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
+ flowBegin = pos_;
+ break;
+ }
+ flowEnd = ++pos_;
+ space = SPACE_NONE;
+ break;
+ }
+ }
+}
+
+}
diff --git a/configmgr/source/xmlreader.hxx b/configmgr/source/xmlreader.hxx
new file mode 100644
index 000000000000..83ccac148cd4
--- /dev/null
+++ b/configmgr/source/xmlreader.hxx
@@ -0,0 +1,186 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#ifndef INCLUDED_CONFIGMGR_SOURCE_XMLREADER_HXX
+#define INCLUDED_CONFIGMGR_SOURCE_XMLREADER_HXX
+
+#include "sal/config.h"
+
+#include <stack>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/container/NoSuchElementException.hpp"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "osl/file.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "pad.hxx"
+#include "span.hxx"
+
+namespace configmgr {
+
+class XmlReader: private boost::noncopyable {
+public:
+ explicit XmlReader(rtl::OUString const & fileUrl)
+ SAL_THROW((
+ com::sun::star::container::NoSuchElementException,
+ com::sun::star::uno::RuntimeException));
+
+ ~XmlReader();
+
+ enum Namespace {
+ NAMESPACE_NONE, NAMESPACE_XML, NAMESPACE_OOR, NAMESPACE_XS,
+ NAMESPACE_XSI, NAMESPACE_OTHER };
+
+ enum Text { TEXT_NONE, TEXT_RAW, TEXT_NORMALIZED };
+
+ enum Result { RESULT_BEGIN, RESULT_END, RESULT_TEXT, RESULT_DONE };
+
+ // RESULT_BEGIN: data = localName, ns = ns
+ // RESULT_END: data, ns unused
+ // RESULT_TEXT: data = text, ns unused
+ Result nextItem(Text reportText, Span * data, Namespace * ns);
+
+ bool nextAttribute(Namespace * ns, Span * localName);
+
+ // the span returned by getAttributeValue is only valid until the next call
+ // to nextItem or getAttributeValue
+ Span getAttributeValue(bool fullyNormalize);
+
+ Namespace getNamespace(Span const & prefix) const;
+
+ rtl::OUString getUrl() const;
+
+private:
+ inline char read() { return pos_ == end_ ? '\0' : *pos_++; }
+
+ inline char peek() { return pos_ == end_ ? '\0' : *pos_; }
+
+ void normalizeLineEnds(Span const & text);
+
+ void skipSpace();
+
+ bool skipComment();
+
+ void skipProcessingInstruction();
+
+ void skipDocumentTypeDeclaration();
+
+ Span scanCdataSection();
+
+ bool scanName(char const ** nameColon);
+
+ Namespace scanNamespaceIri(char const * begin, char const * end);
+
+ char const * handleReference(char const * position, char const * end);
+
+ Span handleAttributeValue(
+ char const * begin, char const * end, bool fullyNormalize);
+
+ Result handleStartTag(Namespace * ns, Span * localName);
+
+ Result handleEndTag();
+
+ void handleElementEnd();
+
+ Result handleSkippedText(Span * data, Namespace * ns);
+
+ Result handleRawText(Span * text);
+
+ Result handleNormalizedText(Span * text);
+
+ struct NamespaceData {
+ Span prefix;
+ Namespace ns;
+
+ NamespaceData() {}
+
+ NamespaceData(Span const & thePrefix, Namespace theNs):
+ prefix(thePrefix), ns(theNs) {}
+ };
+
+ typedef std::vector< NamespaceData > NamespaceList;
+
+ struct ElementData {
+ Span name;
+ NamespaceList::size_type inheritedNamespaces;
+ Namespace defaultNamespace;
+
+ ElementData(
+ Span const & theName,
+ NamespaceList::size_type theInheritedNamespaces,
+ Namespace theDefaultNamespace):
+ name(theName), inheritedNamespaces(theInheritedNamespaces),
+ defaultNamespace(theDefaultNamespace)
+ {}
+ };
+
+ typedef std::stack< ElementData > ElementStack;
+
+ struct AttributeData {
+ char const * nameBegin;
+ char const * nameEnd;
+ char const * nameColon;
+ char const * valueBegin;
+ char const * valueEnd;
+
+ AttributeData(
+ char const * theNameBegin, char const * theNameEnd,
+ char const * theNameColon, char const * theValueBegin,
+ char const * theValueEnd):
+ nameBegin(theNameBegin), nameEnd(theNameEnd),
+ nameColon(theNameColon), valueBegin(theValueBegin),
+ valueEnd(theValueEnd)
+ {}
+ };
+
+ typedef std::vector< AttributeData > Attributes;
+
+ enum State {
+ STATE_CONTENT, STATE_START_TAG, STATE_END_TAG, STATE_EMPTY_ELEMENT_TAG,
+ STATE_DONE };
+
+ rtl::OUString fileUrl_;
+ oslFileHandle fileHandle_;
+ sal_uInt64 fileSize_;
+ void * fileAddress_;
+ NamespaceList namespaces_;
+ ElementStack elements_;
+ char const * pos_;
+ char const * end_;
+ State state_;
+ Attributes attributes_;
+ Attributes::iterator currentAttribute_;
+ bool firstAttribute_;
+ Pad pad_;
+};
+
+}
+
+#endif