summaryrefslogtreecommitdiff
path: root/configmgr
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr')
-rw-r--r--configmgr/inc/configmgr/update.hxx7
-rw-r--r--configmgr/source/README1
-rw-r--r--configmgr/source/components.cxx65
-rw-r--r--configmgr/source/components.hxx18
-rw-r--r--configmgr/source/makefile.mk1
-rw-r--r--configmgr/source/partial.cxx137
-rw-r--r--configmgr/source/partial.hxx71
-rw-r--r--configmgr/source/update.cxx19
-rw-r--r--configmgr/source/valueparser.cxx22
-rw-r--r--configmgr/source/valueparser.hxx4
-rw-r--r--configmgr/source/writemodfile.cxx70
-rw-r--r--configmgr/source/xcdparser.cxx4
-rw-r--r--configmgr/source/xcdparser.hxx4
-rw-r--r--configmgr/source/xcsparser.cxx93
-rw-r--r--configmgr/source/xcsparser.hxx4
-rw-r--r--configmgr/source/xcuparser.cxx305
-rw-r--r--configmgr/source/xcuparser.hxx27
17 files changed, 598 insertions, 254 deletions
diff --git a/configmgr/inc/configmgr/update.hxx b/configmgr/inc/configmgr/update.hxx
index b27a32487400..3a152959342b 100644
--- a/configmgr/inc/configmgr/update.hxx
+++ b/configmgr/inc/configmgr/update.hxx
@@ -30,6 +30,8 @@
#include "sal/config.h"
+#include <set>
+
#include "configmgr/detail/configmgrdllapi.hxx"
namespace rtl { class OUString; }
@@ -44,6 +46,11 @@ OOO_DLLPUBLIC_CONFIGMGR void insertExtensionXcsFile(
OOO_DLLPUBLIC_CONFIGMGR void insertExtensionXcuFile(
bool shared, rtl::OUString const & fileUri);
+OOO_DLLPUBLIC_CONFIGMGR void insertModificationXcuFile(
+ rtl::OUString const & fileUri,
+ std::set< rtl::OUString > const & includedPaths,
+ std::set< rtl::OUString > const & excludedPaths);
+
}
}
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/components.cxx b/configmgr/source/components.cxx
index 51a1a6547d9b..6d97971e1a2c 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;
}
}
@@ -211,7 +217,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(
@@ -227,7 +233,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(
@@ -238,6 +244,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)
{
@@ -315,7 +339,7 @@ Components::Components(
context_(context)
{
OSL_ASSERT(context.is());
-/*SB*/try{
+ RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "begin parsing");
parseXcsXcuLayer(
0,
expand(
@@ -380,24 +404,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);
@@ -447,7 +469,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(
@@ -462,16 +484,15 @@ 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(
@@ -539,7 +560,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(
@@ -630,7 +651,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 8523b02cbbaf..a78ed325969d 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 {
@@ -96,10 +97,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);
@@ -107,14 +117,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/makefile.mk b/configmgr/source/makefile.mk
index d6972e12b9d8..317e08bdf49c 100644
--- a/configmgr/source/makefile.mk
+++ b/configmgr/source/makefile.mk
@@ -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 \
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/update.cxx b/configmgr/source/update.cxx
index ab711c3bec10..57f45068d954 100644
--- a/configmgr/source/update.cxx
+++ b/configmgr/source/update.cxx
@@ -28,6 +28,8 @@
#include "precompiled_configmgr.hxx"
#include "sal/config.h"
+#include <set>
+
#include "configmgr/update.hxx"
#include "osl/mutex.hxx"
#include "rtl/ref.hxx"
@@ -61,6 +63,23 @@ void insertExtensionXcuFile(bool shared, rtl::OUString const & fileUri) {
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
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..12e64ebbe171 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:
+ 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):
+}
+
+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)));
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 220168c62725..77b0f747f313 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, &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());
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());
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_;
};
}