diff options
author | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-06-03 14:33:05 +0200 |
---|---|---|
committer | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-06-03 14:33:05 +0200 |
commit | 41b43f2fc66a490780d4751ed64f663fe1c548d7 (patch) | |
tree | bc4c07f29cea406016a10445103b39d0aac598e1 /configmgr/source | |
parent | 05a463c55182efc777e1fee5f708fc36de6eda92 (diff) | |
parent | f8e7afbac976ca862a801b9648fd95b2107757b2 (diff) |
slidecopy: merged latest DEV300.m80 changes
Diffstat (limited to 'configmgr/source')
31 files changed, 833 insertions, 292 deletions
diff --git a/configmgr/source/README b/configmgr/source/README index 6d19a3b78610..b731043d34ed 100644 --- a/configmgr/source/README +++ b/configmgr/source/README @@ -76,6 +76,7 @@ update.cxx data.cxx lock.cxx nodemap.cxx +partial.cxx path.hxx type.cxx Utilities. diff --git a/configmgr/source/access.cxx b/configmgr/source/access.cxx index e8c6f835e83b..190db364cdfe 100644 --- a/configmgr/source/access.cxx +++ b/configmgr/source/access.cxx @@ -1929,7 +1929,7 @@ css::uno::Reference< css::uno::XInterface > Access::createInstance() tmplName), static_cast< cppu::OWeakObject * >(this)); } - rtl::Reference< Node > node(tmpl->clone()); + rtl::Reference< Node > node(tmpl->clone(true)); node->setLayer(Data::NO_LAYER); return static_cast< cppu::OWeakObject * >( new ChildAccess(components_, getRootAccess(), node)); diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index 187eeee2e45c..5b30e9491eb4 100644 --- a/configmgr/source/components.cxx +++ b/configmgr/source/components.cxx @@ -46,6 +46,7 @@ #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" @@ -58,6 +59,7 @@ #include "modifications.hxx" #include "node.hxx" #include "parsemanager.hxx" +#include "partial.hxx" #include "rootaccess.hxx" #include "writemodfile.hxx" #include "xcdparser.hxx" @@ -82,26 +84,29 @@ struct UnresolvedListItem { typedef std::list< UnresolvedListItem > UnresolvedList; -void parseXcsFile(rtl::OUString const & url, int layer, Data * data, +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(modifications == 0); (void) modifications; + 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, + 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, modifications)))-> + new ParseManager( + url, new XcuParser(layer, data, partial, modifications)))-> parse()); } @@ -112,7 +117,7 @@ rtl::OUString expand(rtl::OUString const & str) { } static bool singletonCreated = false; -static Components * singleton; // leaks +static Components * singleton = 0; } @@ -122,7 +127,8 @@ void Components::initSingleton( OSL_ASSERT(context.is()); if (!singletonCreated) { singletonCreated = true; - singleton = new Components(context); + static Components theSingleton(context); + singleton = &theSingleton; } } @@ -212,7 +218,7 @@ void Components::insertExtensionXcsFile( bool shared, rtl::OUString const & fileUri) { try { - parseXcsFile(fileUri, shared ? 9 : 13, &data_, 0); + parseXcsFile(fileUri, shared ? 9 : 13, data_, 0, 0); } catch (css::container::NoSuchElementException & e) { throw css::uno::RuntimeException( (rtl::OUString( @@ -228,7 +234,7 @@ void Components::insertExtensionXcuFile( { OSL_ASSERT(modifications != 0); try { - parseXcuFile(fileUri, shared ? 10 : 14, &data_, modifications); + parseXcuFile(fileUri, shared ? 10 : 14, data_, 0, modifications); } catch (css::container::NoSuchElementException & e) { throw css::uno::RuntimeException( (rtl::OUString( @@ -239,6 +245,24 @@ void Components::insertExtensionXcuFile( } } +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) { @@ -316,7 +340,7 @@ Components::Components( context_(context) { OSL_ASSERT(context.is()); -/*SB*/try{ + RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "begin parsing"); parseXcsXcuLayer( 0, expand( @@ -381,24 +405,22 @@ Components::Components( ":UNO_USER_PACKAGES_CACHE}/registry/" "com.sun.star.comp.deployment.configuration." "PackageRegistryBackend/configmgr.ini")))); -/*SB*/}catch(css::uno::Exception&e){fprintf(stderr,"caught <%s>\n",rtl::OUStringToOString(e.Message,RTL_TEXTENCODING_UTF8).getStr());throw;} try { parseModificationLayer(); } catch (css::uno::Exception & e) { //TODO: more specific exception catching - // Silently ignore unreadable parts of a corrupted - // registrymodifications.xcu file, instead of completely preventing OOo - // from starting: + // 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, - void (* parseFile)(rtl::OUString const &, int, Data *, Modifications *), + int layer, rtl::OUString const & extension, FileParser * parseFile, rtl::OUString const & url, bool recursive) { osl::Directory dir(url); @@ -448,7 +470,7 @@ void Components::parseFiles( file.match(extension, file.getLength() - extension.getLength())) { try { - (*parseFile)(stat.getFileURL(), layer, &data_, 0); + (*parseFile)(stat.getFileURL(), layer, data_, 0, 0); } catch (css::container::NoSuchElementException & e) { throw css::uno::RuntimeException( (rtl::OUString( @@ -463,23 +485,20 @@ void Components::parseFiles( } void Components::parseFileList( - int layer, - void (* parseFile)(rtl::OUString const &, int, Data *, Modifications *), - rtl::OUString const & urls, rtl::Bootstrap const & ini) + 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); + (*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 >()); + OSL_TRACE( + "configmgr file does not exist: %s", + rtl::OUStringToOString( + e.Message, RTL_TEXTENCODING_UTF8).getStr()); } } if (i == -1) { @@ -540,7 +559,7 @@ void Components::parseXcdFiles(int layer, rtl::OUString const & url) { rtl::Reference< ParseManager > manager; try { manager = new ParseManager( - stat.getFileURL(), new XcdParser(layer, deps, &data_)); + stat.getFileURL(), new XcdParser(layer, deps, data_)); } catch (css::container::NoSuchElementException & e) { throw css::uno::RuntimeException( (rtl::OUString( @@ -631,7 +650,7 @@ rtl::OUString Components::getModificationFileUrl() const { void Components::parseModificationLayer() { try { - parseXcuFile(getModificationFileUrl(), Data::NO_LAYER, &data_, 0); + parseXcuFile(getModificationFileUrl(), Data::NO_LAYER, data_, 0, 0); } catch (css::container::NoSuchElementException &) { OSL_TRACE( "configmgr user registrymodifications.xcu does not (yet) exist"); diff --git a/configmgr/source/components.hxx b/configmgr/source/components.hxx index cdf4bdbaeb8f..2e635680c1ce 100644 --- a/configmgr/source/components.hxx +++ b/configmgr/source/components.hxx @@ -58,6 +58,7 @@ namespace configmgr { class Broadcaster; class Modifications; class Node; +class Partial; class RootAccess; class Components: private boost::noncopyable { @@ -97,10 +98,19 @@ public: 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); @@ -108,14 +118,12 @@ private: ~Components(); void parseFiles( - int layer, rtl::OUString const & extension, - void (* parseFile)(rtl::OUString const &, int, Data *, Modifications *), + int layer, rtl::OUString const & extension, FileParser * parseFile, rtl::OUString const & url, bool recursive); void parseFileList( - int layer, - void (* parseFile)(rtl::OUString const &, int, Data *, Modifications *), - rtl::OUString const & urls, rtl::Bootstrap const & ini); + int layer, FileParser * parseFile, rtl::OUString const & urls, + rtl::Bootstrap const & ini); void parseXcdFiles(int layer, rtl::OUString const & url); diff --git a/configmgr/source/groupnode.cxx b/configmgr/source/groupnode.cxx index 60d825451d69..59c0f89df5d1 100644 --- a/configmgr/source/groupnode.cxx +++ b/configmgr/source/groupnode.cxx @@ -44,8 +44,8 @@ GroupNode::GroupNode( mandatory_(Data::NO_LAYER) {} -rtl::Reference< Node > GroupNode::clone() const { - return new GroupNode(*this); +rtl::Reference< Node > GroupNode::clone(bool keepTemplateName) const { + return new GroupNode(*this, keepTemplateName); } NodeMap & GroupNode::getMembers() { @@ -68,11 +68,13 @@ bool GroupNode::isExtensible() const { return extensible_; } -GroupNode::GroupNode(GroupNode const & other): - Node(other), extensible_(other.extensible_), - templateName_(other.templateName_), mandatory_(other.mandatory_) +GroupNode::GroupNode(GroupNode const & other, bool keepTemplateName): + Node(other), extensible_(other.extensible_), mandatory_(other.mandatory_) { cloneNodeMap(other.members_, &members_); + if (keepTemplateName) { + templateName_ = other.templateName_; + } } GroupNode::~GroupNode() {} diff --git a/configmgr/source/groupnode.hxx b/configmgr/source/groupnode.hxx index be4907b86ce3..9d7bbbafa5b3 100644 --- a/configmgr/source/groupnode.hxx +++ b/configmgr/source/groupnode.hxx @@ -42,7 +42,7 @@ class GroupNode: public Node { public: GroupNode(int layer, bool extensible, rtl::OUString const & templateName); - virtual rtl::Reference< Node > clone() const; + virtual rtl::Reference< Node > clone(bool keepTemplateName) const; virtual NodeMap & getMembers(); @@ -55,7 +55,7 @@ public: bool isExtensible() const; private: - GroupNode(GroupNode const & other); + GroupNode(GroupNode const & other, bool keepTemplateName); virtual ~GroupNode(); diff --git a/configmgr/source/localizedpropertynode.cxx b/configmgr/source/localizedpropertynode.cxx index 9c5fa3328a58..54560d7aded4 100644 --- a/configmgr/source/localizedpropertynode.cxx +++ b/configmgr/source/localizedpropertynode.cxx @@ -51,7 +51,7 @@ LocalizedPropertyNode::LocalizedPropertyNode( Node(layer), staticType_(staticType), nillable_(nillable) {} -rtl::Reference< Node > LocalizedPropertyNode::clone() const { +rtl::Reference< Node > LocalizedPropertyNode::clone(bool) const { return new LocalizedPropertyNode(*this); } diff --git a/configmgr/source/localizedpropertynode.hxx b/configmgr/source/localizedpropertynode.hxx index d5a16af0e54d..4ebcf8e243da 100644 --- a/configmgr/source/localizedpropertynode.hxx +++ b/configmgr/source/localizedpropertynode.hxx @@ -47,7 +47,7 @@ class LocalizedPropertyNode: public Node { public: LocalizedPropertyNode(int layer, Type staticType, bool nillable); - virtual rtl::Reference< Node > clone() const; + virtual rtl::Reference< Node > clone(bool keepTemplateName) const; virtual NodeMap & getMembers(); diff --git a/configmgr/source/localizedvaluenode.cxx b/configmgr/source/localizedvaluenode.cxx index f6246106c8fe..c0e3bc333187 100644 --- a/configmgr/source/localizedvaluenode.cxx +++ b/configmgr/source/localizedvaluenode.cxx @@ -48,7 +48,7 @@ LocalizedValueNode::LocalizedValueNode(int layer, css::uno::Any const & value): Node(layer), value_(value) {} -rtl::Reference< Node > LocalizedValueNode::clone() const { +rtl::Reference< Node > LocalizedValueNode::clone(bool) const { return new LocalizedValueNode(*this); } diff --git a/configmgr/source/localizedvaluenode.hxx b/configmgr/source/localizedvaluenode.hxx index 7f8a5dd987ce..bfcbdea1de51 100644 --- a/configmgr/source/localizedvaluenode.hxx +++ b/configmgr/source/localizedvaluenode.hxx @@ -43,7 +43,7 @@ class LocalizedValueNode: public Node { public: LocalizedValueNode(int layer, com::sun::star::uno::Any const & value); - virtual rtl::Reference< Node > clone() const; + virtual rtl::Reference< Node > clone(bool keepTemplateName) const; virtual rtl::OUString getTemplateName() const; diff --git a/configmgr/source/makefile.mk b/configmgr/source/makefile.mk index d6972e12b9d8..777fed3323d8 100644 --- a/configmgr/source/makefile.mk +++ b/configmgr/source/makefile.mk @@ -34,7 +34,7 @@ VISIBILITY_HIDDEN = TRUE .INCLUDE: settings.mk -CDEFS += -DOOO_DLLIMPLEMENTATION_CONFIGMGR +DLLPRE = SLOFILES = \ $(SLO)/access.obj \ @@ -54,6 +54,7 @@ SLOFILES = \ $(SLO)/nodemap.obj \ $(SLO)/pad.obj \ $(SLO)/parsemanager.obj \ + $(SLO)/partial.obj \ $(SLO)/propertynode.obj \ $(SLO)/rootaccess.obj \ $(SLO)/services.obj \ @@ -76,7 +77,7 @@ SHL1STDLIBS = \ $(CPPULIB) \ $(SALHELPERLIB) \ $(SALLIB) -SHL1TARGET = configmgr +SHL1TARGET = configmgr.uno SHL1USE_EXPORTS = name DEF1NAME = $(SHL1TARGET) diff --git a/configmgr/source/node.hxx b/configmgr/source/node.hxx index 10f168520595..7c9417e68ea9 100644 --- a/configmgr/source/node.hxx +++ b/configmgr/source/node.hxx @@ -46,7 +46,7 @@ public: virtual Kind kind() const = 0; - virtual rtl::Reference< Node > clone() const = 0; + virtual rtl::Reference< Node > clone(bool keepTemplateName) const = 0; virtual NodeMap & getMembers(); diff --git a/configmgr/source/nodemap.cxx b/configmgr/source/nodemap.cxx index 6b22863b5672..8e4d06030bdf 100644 --- a/configmgr/source/nodemap.cxx +++ b/configmgr/source/nodemap.cxx @@ -42,7 +42,7 @@ 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(); + i->second = i->second->clone(true); } std::swap(clone, *target); } 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/propertynode.cxx b/configmgr/source/propertynode.cxx index 070b56d9be9a..f3e459998e7e 100644 --- a/configmgr/source/propertynode.cxx +++ b/configmgr/source/propertynode.cxx @@ -55,7 +55,7 @@ PropertyNode::PropertyNode( extension_(extension) {} -rtl::Reference< Node > PropertyNode::clone() const { +rtl::Reference< Node > PropertyNode::clone(bool) const { return new PropertyNode(*this); } diff --git a/configmgr/source/propertynode.hxx b/configmgr/source/propertynode.hxx index 1566cbf72dbe..506526ffcc1e 100644 --- a/configmgr/source/propertynode.hxx +++ b/configmgr/source/propertynode.hxx @@ -48,7 +48,7 @@ public: int layer, Type staticType, bool nillable, com::sun::star::uno::Any const & value, bool extension); - virtual rtl::Reference< Node > clone() const; + virtual rtl::Reference< Node > clone(bool keepTemplateName) const; Type getStaticType() const; diff --git a/configmgr/source/services.cxx b/configmgr/source/services.cxx index 3a009b3cee15..f8c3289664ef 100644 --- a/configmgr/source/services.cxx +++ b/configmgr/source/services.cxx @@ -44,6 +44,7 @@ #include "configurationprovider.hxx" #include "configurationregistry.hxx" #include "defaultprovider.hxx" +#include "update.hxx" namespace { @@ -67,6 +68,9 @@ static cppu::ImplementationEntry const services[] = { { &dummy, &configmgr::configuration_registry::getImplementationName, &configmgr::configuration_registry::getSupportedServiceNames, &configmgr::configuration_registry::createFactory, 0, 0 }, + { &dummy, &configmgr::update::getImplementationName, + &configmgr::update::getSupportedServiceNames, + &configmgr::update::createFactory, 0, 0 }, { 0, 0, 0, 0, 0, 0 } }; @@ -107,6 +111,19 @@ extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.DefaultProvider"))); + 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.Update/UNO/" + "SINGLETONS/com.sun.star.configuration.Update")))), + css::uno::UNO_SET_THROW)-> + setStringValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.Update_Service"))); } catch (css::uno::Exception & e) { (void) e; OSL_TRACE( diff --git a/configmgr/source/setnode.cxx b/configmgr/source/setnode.cxx index f19c36c0bba5..465345a5f856 100644 --- a/configmgr/source/setnode.cxx +++ b/configmgr/source/setnode.cxx @@ -69,8 +69,8 @@ SetNode::SetNode( templateName_(templateName), mandatory_(Data::NO_LAYER) {} -rtl::Reference< Node > SetNode::clone() const { - return new SetNode(*this); +rtl::Reference< Node > SetNode::clone(bool keepTemplateName) const { + return new SetNode(*this, keepTemplateName); } NodeMap & SetNode::getMembers() { @@ -105,12 +105,15 @@ bool SetNode::isValidTemplate(rtl::OUString const & templateName) const { additionalTemplateNames_.end()); } -SetNode::SetNode(SetNode const & other): +SetNode::SetNode(SetNode const & other, bool keepTemplateName): Node(other), defaultTemplateName_(other.defaultTemplateName_), additionalTemplateNames_(other.additionalTemplateNames_), - templateName_(other.templateName_), mandatory_(other.mandatory_) + mandatory_(other.mandatory_) { cloneNodeMap(other.members_, &members_); + if (keepTemplateName) { + templateName_ = other.templateName_; + } } SetNode::~SetNode() {} diff --git a/configmgr/source/setnode.hxx b/configmgr/source/setnode.hxx index 7bf1ab0a199e..94ce537adda1 100644 --- a/configmgr/source/setnode.hxx +++ b/configmgr/source/setnode.hxx @@ -46,7 +46,7 @@ public: int layer, rtl::OUString const & defaultTemplateName, rtl::OUString const & templateName); - virtual rtl::Reference< Node > clone() const; + virtual rtl::Reference< Node > clone(bool keepTemplateName) const; virtual NodeMap & getMembers(); @@ -63,7 +63,7 @@ public: bool isValidTemplate(rtl::OUString const & templateName) const; private: - SetNode(SetNode const & other); + SetNode(SetNode const & other, bool keepTemplateName); virtual ~SetNode(); diff --git a/configmgr/source/update.cxx b/configmgr/source/update.cxx index ab711c3bec10..4c1d59d5d054 100644 --- a/configmgr/source/update.cxx +++ b/configmgr/source/update.cxx @@ -28,27 +28,86 @@ #include "precompiled_configmgr.hxx" #include "sal/config.h" -#include "configmgr/update.hxx" +#include <set> + +#include "boost/noncopyable.hpp" +#include "com/sun/star/configuration/XUpdate.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 "osl/mutex.hxx" #include "rtl/ref.hxx" +#include "rtl/unload.h" +#include "rtl/ustring.h" #include "rtl/ustring.hxx" +#include "sal/types.h" #include "broadcaster.hxx" #include "components.hxx" #include "lock.hxx" #include "modifications.hxx" #include "rootaccess.hxx" +#include "update.hxx" + +namespace configmgr { namespace update { + +namespace { + +namespace css = com::sun::star; + +std::set< rtl::OUString > seqToSet( + css::uno::Sequence< rtl::OUString > const & sequence) +{ + return std::set< rtl::OUString >( + sequence.getConstArray(), + sequence.getConstArray() + sequence.getLength()); +} + +class Service: + public cppu::WeakImplHelper1< css::configuration::XUpdate >, + private boost::noncopyable +{ +public: + Service() {} + +private: + virtual ~Service() {} + + virtual void SAL_CALL insertExtensionXcsFile( + sal_Bool shared, rtl::OUString const & fileUri) + throw (css::uno::RuntimeException); -namespace configmgr { + virtual void SAL_CALL insertExtensionXcuFile( + sal_Bool shared, rtl::OUString const & fileUri) + throw (css::uno::RuntimeException); -namespace update { + virtual void SAL_CALL insertModificationXcuFile( + rtl::OUString const & fileUri, + css::uno::Sequence< rtl::OUString > const & includedPaths, + css::uno::Sequence< rtl::OUString > const & excludedPaths) + throw (css::uno::RuntimeException); +}; -void insertExtensionXcsFile(bool shared, rtl::OUString const & fileUri) { +void Service::insertExtensionXcsFile( + sal_Bool shared, rtl::OUString const & fileUri) + throw (css::uno::RuntimeException) +{ osl::MutexGuard g(lock); Components::getSingleton().insertExtensionXcsFile(shared, fileUri); } -void insertExtensionXcuFile(bool shared, rtl::OUString const & fileUri) { +void Service::insertExtensionXcuFile( + sal_Bool shared, rtl::OUString const & fileUri) + throw (css::uno::RuntimeException) +{ Broadcaster bc; { osl::MutexGuard g(lock); @@ -61,6 +120,91 @@ void insertExtensionXcuFile(bool shared, rtl::OUString const & fileUri) { bc.send(); } +void Service::insertModificationXcuFile( + rtl::OUString const & fileUri, + css::uno::Sequence< rtl::OUString > const & includedPaths, + css::uno::Sequence< rtl::OUString > const & excludedPaths) + throw (css::uno::RuntimeException) +{ + Broadcaster bc; + { + osl::MutexGuard g(lock); + Modifications mods; + Components::getSingleton().insertModificationXcuFile( + fileUri, seqToSet(includedPaths), seqToSet(excludedPaths), &mods); + Components::getSingleton().initGlobalBroadcaster( + mods, rtl::Reference< RootAccess >(), &bc); + } + bc.send(); } +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 &) + throw (css::uno::Exception, css::uno::RuntimeException) +{ + if (Arguments.getLength() != 0) { + throw css::uno::Exception( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.configuration.Update must be" + " instantiated without arguments")), + static_cast< cppu::OWeakObject * >(this)); + } + return static_cast< cppu::OWeakObject * >(new Service); +} + +} + +rtl::OUString getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.configuration.Update")); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.Update_Service")); + 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/update.hxx b/configmgr/source/update.hxx new file mode 100644 index 000000000000..faa5c86b15fa --- /dev/null +++ b/configmgr/source/update.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_UPDATE_HXX +#define INCLUDED_CONFIGMGR_SOURCE_UPDATE_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 update { + +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/valueparser.cxx b/configmgr/source/valueparser.cxx index f951aac5ca01..4adf452c409b 100644 --- a/configmgr/source/valueparser.cxx +++ b/configmgr/source/valueparser.cxx @@ -270,6 +270,10 @@ 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 || @@ -294,7 +298,9 @@ bool ValueParser::startElement( name.equals(RTL_CONSTASCII_STRINGPARAM("it")) && isListType(type_) && separator_.getLength() == 0) { - checkEmptyPad(reader); + pad_.clear(); + // before first <it>, characters are not ignored; assume they + // are only whitespace state_ = STATE_IT; return true; } @@ -351,7 +357,7 @@ bool ValueParser::startElement( css::uno::Reference< css::uno::XInterface >()); } -bool ValueParser::endElement(XmlReader const & reader) { +bool ValueParser::endElement() { if (!node_.is()) { return false; } @@ -363,7 +369,6 @@ bool ValueParser::endElement(XmlReader const & reader) { value = parseValue(separator_, pad_.get(), type_); pad_.clear(); } else { - checkEmptyPad(reader); switch (type_) { case TYPE_BOOLEAN_LIST: value = convertItems< sal_Bool >(); @@ -454,17 +459,6 @@ int ValueParser::getLayer() const { return layer_; } -void ValueParser::checkEmptyPad(XmlReader const & reader) const { - if (pad_.is()) { - throw css::uno::RuntimeException( - (rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "mixed text and <it> elements in ")) + - reader.getUrl()), - css::uno::Reference< css::uno::XInterface >()); - } -} - template< typename T > css::uno::Any ValueParser::convertItems() { css::uno::Sequence< T > seq(items_.size()); for (sal_Int32 i = 0; i < seq.getLength(); ++i) { diff --git a/configmgr/source/valueparser.hxx b/configmgr/source/valueparser.hxx index c328fe7eddce..4e899f4632dd 100644 --- a/configmgr/source/valueparser.hxx +++ b/configmgr/source/valueparser.hxx @@ -61,7 +61,7 @@ public: bool startElement( XmlReader & reader, XmlReader::Namespace ns, Span const & name); - bool endElement(XmlReader const & reader); + bool endElement(); void characters(Span const & text); @@ -75,8 +75,6 @@ public: rtl::OString separator_; private: - void checkEmptyPad(XmlReader const & reader) const; - template< typename T > com::sun::star::uno::Any convertItems(); enum State { STATE_TEXT, STATE_TEXT_UNICODE, STATE_IT, STATE_IT_UNICODE }; diff --git a/configmgr/source/writemodfile.cxx b/configmgr/source/writemodfile.cxx index a8e0f77cbd2e..c2573ab67439 100644 --- a/configmgr/source/writemodfile.cxx +++ b/configmgr/source/writemodfile.cxx @@ -451,9 +451,9 @@ void writeNode( void writeModifications( Components & components, oslFileHandle handle, - rtl::OUString const & grandparentPathRepresentation, - rtl::OUString const & parentName, rtl::Reference< Node > const & parent, - rtl::OUString const & nodeName, rtl::Reference< Node > const & node, + 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, @@ -461,27 +461,15 @@ void writeModifications( 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()) { - writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\"")); - writeAttributeValue( - handle, - (grandparentPathRepresentation + - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + - Data::createSegment(parent->getTemplateName(), parentName))); - writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">")); writeNode(components, handle, parent, nodeName, node); - writeData(handle, RTL_CONSTASCII_STRINGPARAM("</item>")); } else { - writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\"")); switch (parent->kind()) { case Node::KIND_LOCALIZED_PROPERTY: - writeAttributeValue(handle, grandparentPathRepresentation); - writeData( - handle, RTL_CONSTASCII_STRINGPARAM("\"><prop oor:name=\"")); - writeAttributeValue(handle, parentName); - writeData( - handle, - RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\"><value")); + writeData(handle, RTL_CONSTASCII_STRINGPARAM("<value")); if (nodeName.getLength() != 0) { writeData( handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\"")); @@ -489,61 +477,44 @@ void writeModifications( writeData(handle, RTL_CONSTASCII_STRINGPARAM("\"")); } writeData( - handle, - RTL_CONSTASCII_STRINGPARAM( - " oor:op=\"remove\"/></prop></item>")); + handle, RTL_CONSTASCII_STRINGPARAM(" oor:op=\"remove\"/>")); break; case Node::KIND_GROUP: OSL_ASSERT( dynamic_cast< GroupNode * >(parent.get())->isExtensible()); - writeAttributeValue( - handle, - (grandparentPathRepresentation + - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + - Data::createSegment( - parent->getTemplateName(), parentName))); writeData( - handle, RTL_CONSTASCII_STRINGPARAM("\"><prop oor:name=\"")); + handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\"")); writeAttributeValue(handle, nodeName); writeData( handle, - RTL_CONSTASCII_STRINGPARAM( - "\" oor:op=\"remove\"/></item>")); + RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>")); break; case Node::KIND_SET: - writeAttributeValue( - handle, - (grandparentPathRepresentation + - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + - Data::createSegment( - parent->getTemplateName(), parentName))); writeData( - handle, RTL_CONSTASCII_STRINGPARAM("\"><node oor:name=\"")); + handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\"")); writeAttributeValue(handle, nodeName); writeData( handle, - RTL_CONSTASCII_STRINGPARAM( - "\" oor:op=\"remove\"/></item>")); + RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>")); break; default: OSL_ASSERT(false); // this cannot happen break; } } + writeData(handle, RTL_CONSTASCII_STRINGPARAM("</item>")); } else { - rtl::OUString parentPathRep; - if (parent.is()) { // components themselves have no parent - parentPathRep = grandparentPathRepresentation + - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + - Data::createSegment(parent->getTemplateName(), parentName); - } 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, parentPathRep, nodeName, node, i->first, + components, handle, pathRep, node, i->first, node->getMember(i->first), i->second); } } @@ -605,9 +576,8 @@ void writeModFile( j != data.modifications.getRoot().children.end(); ++j) { writeModifications( - components, tmp.handle, rtl::OUString(), rtl::OUString(), - rtl::Reference< Node >(), j->first, - Data::findNode(Data::NO_LAYER, data.components, j->first), + 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>")); diff --git a/configmgr/source/xcdparser.cxx b/configmgr/source/xcdparser.cxx index 8306c692c30f..498254b35644 100644 --- a/configmgr/source/xcdparser.cxx +++ b/configmgr/source/xcdparser.cxx @@ -53,7 +53,7 @@ namespace css = com::sun::star; } -XcdParser::XcdParser(int layer, Dependencies const & dependencies, Data * data): +XcdParser::XcdParser(int layer, Dependencies const & dependencies, Data & data): layer_(layer), dependencies_(dependencies), data_(data), state_(STATE_START) {} @@ -137,7 +137,7 @@ bool XcdParser::startElement( if (ns == XmlReader::NAMESPACE_OOR && name.equals(RTL_CONSTASCII_STRINGPARAM("component-data"))) { - nestedParser_ = new XcuParser(layer_ + 1, data_, 0); + nestedParser_ = new XcuParser(layer_ + 1, data_, 0, 0); nesting_ = 1; return nestedParser_->startElement(reader, ns, name); } diff --git a/configmgr/source/xcdparser.hxx b/configmgr/source/xcdparser.hxx index 2e35b3686e60..2ad8ecea7f93 100644 --- a/configmgr/source/xcdparser.hxx +++ b/configmgr/source/xcdparser.hxx @@ -47,7 +47,7 @@ class XcdParser: public Parser { public: typedef std::set< rtl::OUString > Dependencies; - XcdParser(int layer, Dependencies const & dependencies, Data * data); + XcdParser(int layer, Dependencies const & dependencies, Data & data); private: virtual ~XcdParser(); @@ -66,7 +66,7 @@ private: int layer_; Dependencies const & dependencies_; - Data * data_; + Data & data_; State state_; rtl::OUString dependency_; rtl::Reference< Parser > nestedParser_; diff --git a/configmgr/source/xcsparser.cxx b/configmgr/source/xcsparser.cxx index 15141844a276..79e122759fc8 100644 --- a/configmgr/source/xcsparser.cxx +++ b/configmgr/source/xcsparser.cxx @@ -60,9 +60,66 @@ 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: + 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 && + dynamic_cast< GroupNode * >( + original.get())->isExtensible()) + { + 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): +} + +XcsParser::XcsParser(int layer, Data & data): valueParser_(layer), data_(data), state_(STATE_START) {} @@ -209,7 +266,7 @@ bool XcsParser::startElement( } void XcsParser::endElement(XmlReader const & reader) { - if (valueParser_.endElement(reader)) { + if (valueParser_.endElement()) { return; } if (ignoring_ > 0) { @@ -218,15 +275,30 @@ void XcsParser::endElement(XmlReader const & reader) { Element top(elements_.top()); elements_.pop(); if (top.node.is()) { - NodeMap * map; if (elements_.empty()) { switch (state_) { case STATE_TEMPLATES: - map = &data_->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: - map = &data_->components; - state_ = STATE_COMPONENT_DONE; + { + 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); @@ -235,10 +307,9 @@ void XcsParser::endElement(XmlReader const & reader) { RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), css::uno::Reference< css::uno::XInterface >()); } - } else { - map = &elements_.top().node->getMembers(); - } - if (!map->insert(NodeMap::value_type(top.name, top.node)).second) { + } 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 + @@ -372,7 +443,7 @@ void XcsParser::handleNodeRef(XmlReader & reader) { css::uno::Reference< css::uno::XInterface >()); } rtl::Reference< Node > tmpl( - data_->getTemplate( + data_.getTemplate( valueParser_.getLayer(), xmldata::parseTemplateReference( component, hasNodeType, nodeType, 0))); @@ -385,7 +456,7 @@ void XcsParser::handleNodeRef(XmlReader & reader) { reader.getUrl()), css::uno::Reference< css::uno::XInterface >()); } - rtl::Reference< Node > node(tmpl->clone()); + rtl::Reference< Node > node(tmpl->clone(false)); node->setLayer(valueParser_.getLayer()); elements_.push(Element(node, name)); } diff --git a/configmgr/source/xcsparser.hxx b/configmgr/source/xcsparser.hxx index 21a124945a2e..196add9a826a 100644 --- a/configmgr/source/xcsparser.hxx +++ b/configmgr/source/xcsparser.hxx @@ -48,7 +48,7 @@ struct Span; class XcsParser: public Parser { public: - XcsParser(int layer, Data * data); + XcsParser(int layer, Data & data); private: virtual ~XcsParser(); @@ -94,7 +94,7 @@ private: typedef std::stack< Element > ElementStack; ValueParser valueParser_; - Data * data_; + Data & data_; rtl::OUString componentName_; State state_; long ignoring_; diff --git a/configmgr/source/xcuparser.cxx b/configmgr/source/xcuparser.cxx index 5f0223dde6ee..f9f439c98916 100644 --- a/configmgr/source/xcuparser.cxx +++ b/configmgr/source/xcuparser.cxx @@ -49,6 +49,7 @@ #include "modifications.hxx" #include "node.hxx" #include "nodemap.hxx" +#include "partial.hxx" #include "path.hxx" #include "propertynode.hxx" #include "setnode.hxx" @@ -65,14 +66,15 @@ namespace css = com::sun::star; } -XcuParser::XcuParser(int layer, Data * data, Modifications * modifications): - valueParser_(layer), data_(data), modifications_(modifications) -{ - if (layer == Data::NO_LAYER) { - OSL_ASSERT(modifications_ == 0); - modifications_ = &data_->modifications; - } -} +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() {} @@ -105,7 +107,7 @@ bool XcuParser::startElement( css::uno::Reference< css::uno::XInterface >()); } } else if (state_.top().ignore) { - state_.push(state_.top()); + state_.push(State(false)); } else if (!state_.top().node.is()) { if (ns == XmlReader::NAMESPACE_NONE && name.equals(RTL_CONSTASCII_STRINGPARAM("item"))) @@ -209,12 +211,12 @@ bool XcuParser::startElement( return true; } -void XcuParser::endElement(XmlReader const & reader) { - if (valueParser_.endElement(reader)) { +void XcuParser::endElement(XmlReader const &) { + if (valueParser_.endElement()) { return; } OSL_ASSERT(!state_.empty()); - bool ignore = state_.top().ignore; + bool pop = state_.top().pop; rtl::Reference< Node > insert; rtl::OUString name; if (state_.top().insert) { @@ -227,10 +229,10 @@ void XcuParser::endElement(XmlReader const & reader) { OSL_ASSERT(!state_.empty() && state_.top().node.is()); state_.top().node->getMembers()[name] = insert; } - if (!ignore && !modificationPath_.empty()) { - modificationPath_.pop_back(); + if (pop && !path_.empty()) { + path_.pop_back(); // </item> will pop less than <item> pushed, but that is harmless, - // as the next <item> will reset modificationPath_ + // as the next <item> will reset path_ } } @@ -328,16 +330,27 @@ void XcuParser::handleComponentData(XmlReader & reader) { } 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_)); + valueParser_.getLayer(), data_.components, componentName_)); if (!node.is()) { - throw css::uno::RuntimeException( - (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown component ")) + - componentName_ + - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) + - reader.getUrl()), - css::uno::Reference< css::uno::XInterface >()); + 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: @@ -356,10 +369,6 @@ void XcuParser::handleComponentData(XmlReader & reader) { node->getFinalized()); node->setFinalized(finalizedLayer); state_.push(State(node, finalizedLayer < valueParser_.getLayer())); - if (modifications_ != 0) { - OSL_ASSERT(modificationPath_.empty()); - modificationPath_.push_back(componentName_); - } } void XcuParser::handleItem(XmlReader & reader) { @@ -386,27 +395,43 @@ void XcuParser::handleItem(XmlReader & reader) { rtl::OUString path(xmldata::convertFromUtf8(attrPath)); int finalizedLayer; rtl::Reference< Node > node( - data_->resolvePathRepresentation( - path, 0, &modificationPath_, &finalizedLayer)); + data_.resolvePathRepresentation(path, &path_, &finalizedLayer)); if (!node.is()) { - //TODO: Within Components::parseModificationLayer (but only there) it - // can rightly happen that data is read that does not match a schema - // (that no schema exists, or that the schema specifies a different - // type), namely if the schema was brought along by an extension that - // has been removed or replaced; instead of taking care of that at all - // the relevant places, as a hack, only "top-level" <item>s (that only - // appear in modification layer data) with unknown path are filtered out - // here. OSL_TRACE( - "configmgr unknown <item path=\"%s\">", - rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr()); - state_.push(State()); // ignored + "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(!modificationPath_.empty()); - componentName_ = modificationPath_.front(); - if (modifications_ == 0) { - modificationPath_.clear(); + 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())); } @@ -483,13 +508,13 @@ void XcuParser::handlePropValue(XmlReader & reader, PropertyNode * prop) { css::uno::Reference< css::uno::XInterface >()); } prop->setValue(valueParser_.getLayer(), css::uno::Any()); - state_.push(State()); + state_.push(State(false)); } else if (external.getLength() == 0) { valueParser_.separator_ = separator; valueParser_.start(prop); } else { prop->setExternal(valueParser_.getLayer(), external); - state_.push(State()); + state_.push(State(false)); } } @@ -546,11 +571,20 @@ void XcuParser::handleLocpropValue( 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()); // ignored + state_.push(State(true)); // ignored return; } if (nil && !locprop->isNillable()) { @@ -563,23 +597,29 @@ void XcuParser::handleLocpropValue( } switch (op) { case OPERATION_FUSE: - if (nil) { - if (i == locprop->getMembers().end()) { - locprop->getMembers()[name] = new LocalizedValueNode( - valueParser_.getLayer(), css::uno::Any()); + { + 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 { - dynamic_cast< LocalizedValueNode * >(i->second.get())->setValue( - valueParser_.getLayer(), css::uno::Any()); + valueParser_.separator_ = separator; + valueParser_.start(locprop, name); + pop = true; + } + if (trackPath_) { + recordModification(); + if (pop) { + path_.pop_back(); + } } - state_.push(State()); - } else { - valueParser_.separator_ = separator; - valueParser_.start(locprop, name); - } - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - modificationPath_.pop_back(); } break; case OPERATION_REMOVE: @@ -588,12 +628,8 @@ void XcuParser::handleLocpropValue( if (i != locprop->getMembers().end()) { locprop->getMembers().erase(i); } - state_.push(State()); - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - modificationPath_.pop_back(); - } + state_.push(State(true)); + recordModification(); break; default: throw css::uno::RuntimeException( @@ -643,6 +679,17 @@ void XcuParser::handleGroupProp(XmlReader & reader, GroupNode * group) { 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); @@ -672,17 +719,10 @@ void XcuParser::handleUnknownGroupProp( XmlReader const & reader, GroupNode * group, rtl::OUString const & name, Type type, Operation operation, bool finalized) { - if (!group->isExtensible()) { - throw css::uno::RuntimeException( - (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown prop ")) + - name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) + - reader.getUrl()), - css::uno::Reference< css::uno::XInterface >()); - } switch (operation) { case OPERATION_REPLACE: case OPERATION_FUSE: - { + if (group->isExtensible()) { if (type == TYPE_ERROR) { throw css::uno::RuntimeException( (rtl::OUString( @@ -701,17 +741,17 @@ void XcuParser::handleUnknownGroupProp( prop->setFinalized(valueParser_.getLayer()); } state_.push(State(prop, name, state_.top().locked)); - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - } + recordModification(); + break; } - break; + // fall through default: OSL_TRACE( - "ignoring modify or remove of unknown (presumably extension)" - " property"); - state_.push(State()); + "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; } } @@ -724,7 +764,7 @@ void XcuParser::handlePlainGroupProp( PropertyNode * property = dynamic_cast< PropertyNode * >( propertyIndex->second.get()); if (property->getLayer() > valueParser_.getLayer()) { - state_.push(State()); // ignored + state_.push(State(true)); // ignored return; } int finalizedLayer = std::min( @@ -751,10 +791,7 @@ void XcuParser::handlePlainGroupProp( property, (state_.top().locked || finalizedLayer < valueParser_.getLayer()))); - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - } + recordModification(); break; case OPERATION_REMOVE: if (!property->isExtension()) { @@ -767,12 +804,8 @@ void XcuParser::handlePlainGroupProp( css::uno::Reference< css::uno::XInterface >()); } group->getMembers().erase(propertyIndex); - state_.push(State()); // ignore children - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - modificationPath_.pop_back(); - } + state_.push(State(true)); // ignore children + recordModification(); break; } } @@ -782,7 +815,7 @@ void XcuParser::handleLocalizedGroupProp( rtl::OUString const & name, Type type, Operation operation, bool finalized) { if (property->getLayer() > valueParser_.getLayer()) { - state_.push(State()); // ignored + state_.push(State(true)); // ignored return; } int finalizedLayer = std::min( @@ -808,9 +841,6 @@ void XcuParser::handleLocalizedGroupProp( property, (state_.top().locked || finalizedLayer < valueParser_.getLayer()))); - if (modifications_ != 0) { - modificationPath_.push_back(name); - } break; case OPERATION_REPLACE: { @@ -824,10 +854,7 @@ void XcuParser::handleLocalizedGroupProp( replacement, name, (state_.top().locked || finalizedLayer < valueParser_.getLayer()))); - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - } + recordModification(); } break; case OPERATION_REMOVE: @@ -876,14 +903,24 @@ void XcuParser::handleGroupNode( 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()) { - throw css::uno::RuntimeException( - (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown node ")) + - name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) + - reader.getUrl()), - css::uno::Reference< css::uno::XInterface >()); + 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( @@ -901,9 +938,6 @@ void XcuParser::handleGroupNode( State( child, state_.top().locked || finalizedLayer < valueParser_.getLayer())); - if (modifications_ != 0) { - modificationPath_.push_back(name); - } } void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) { @@ -958,6 +992,14 @@ void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) { 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())); @@ -972,7 +1014,7 @@ void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) { css::uno::Reference< css::uno::XInterface >()); } rtl::Reference< Node > tmpl( - data_->getTemplate(valueParser_.getLayer(), templateName)); + data_.getTemplate(valueParser_.getLayer(), templateName)); if (!tmpl.is()) { throw css::uno::RuntimeException( (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("set member node ")) + @@ -993,7 +1035,7 @@ void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) { mandatoryLayer = std::min(mandatoryLayer, i->second->getMandatory()); i->second->setMandatory(mandatoryLayer); if (i->second->getLayer() > valueParser_.getLayer()) { - state_.push(State()); // ignored + state_.push(State(true)); // ignored return; } } @@ -1001,48 +1043,39 @@ void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) { case OPERATION_MODIFY: if (i == set->getMembers().end()) { OSL_TRACE("ignoring modify of unknown set member node"); - state_.push(State()); + state_.push(State(true)); // ignored } else { state_.push( State( i->second, (state_.top().locked || finalizedLayer < valueParser_.getLayer()))); - if (modifications_ != 0) { - modificationPath_.push_back(name); - } } break; case OPERATION_REPLACE: if (state_.top().locked || finalizedLayer < valueParser_.getLayer()) { - state_.push(State()); // ignored + state_.push(State(true)); // ignored } else { - rtl::Reference< Node > member(tmpl->clone()); + rtl::Reference< Node > member(tmpl->clone(true)); member->setLayer(valueParser_.getLayer()); member->setFinalized(finalizedLayer); member->setMandatory(mandatoryLayer); state_.push(State(member, name, false)); - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - } + recordModification(); } break; case OPERATION_FUSE: if (i == set->getMembers().end()) { if (state_.top().locked || finalizedLayer < valueParser_.getLayer()) { - state_.push(State()); // ignored + state_.push(State(true)); // ignored } else { - rtl::Reference< Node > member(tmpl->clone()); + rtl::Reference< Node > member(tmpl->clone(true)); member->setLayer(valueParser_.getLayer()); member->setFinalized(finalizedLayer); member->setMandatory(mandatoryLayer); state_.push(State(member, name, false)); - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - } + recordModification(); } } else { state_.push( @@ -1050,9 +1083,6 @@ void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) { i->second, (state_.top().locked || finalizedLayer < valueParser_.getLayer()))); - if (modifications_ != 0) { - modificationPath_.push_back(name); - } } break; case OPERATION_REMOVE: @@ -1064,14 +1094,19 @@ void XcuParser::handleSetNode(XmlReader & reader, SetNode * set) { { set->getMembers().erase(i); } - state_.push(State()); - if (modifications_ != 0) { - modificationPath_.push_back(name); - modifications_->add(modificationPath_); - modificationPath_.pop_back(); - } + 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 index 21806edebe9c..64108451b4ef 100644 --- a/configmgr/source/xcuparser.hxx +++ b/configmgr/source/xcuparser.hxx @@ -49,6 +49,7 @@ namespace configmgr { class GroupNode; class LocalizedPropertyNode; class Modifications; +class Partial; class PropertyNode; class SetNode; struct Data; @@ -56,7 +57,9 @@ struct Span; class XcuParser: public Parser { public: - XcuParser(int layer, Data * data, Modifications * modifications); + XcuParser( + int layer, Data & data, Partial const * partial, + Modifications * broadcastModifications); private: virtual ~XcuParser(); @@ -105,36 +108,44 @@ private: 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(): ignore(true), insert(false), locked(false) {} + 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) + 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) + locked(theLocked), pop(true) {} }; typedef std::stack< State > StateStack; ValueParser valueParser_; - Data * data_; - Modifications * modifications_; + Data & data_; + Partial const * partial_; + Modifications * broadcastModifications_; + bool recordModifications_; + bool trackPath_; rtl::OUString componentName_; StateStack state_; - Path modificationPath_; - rtl::OUString path_; + Path path_; }; } |