From 1423da554b361a3aa020c17469972861a02dcac1 Mon Sep 17 00:00:00 2001 From: sb Date: Thu, 12 Aug 2010 10:22:02 +0200 Subject: sb130: #i113096# introduced com.sun.star.configuration.XUpdate.removeExtensionXcuFile --- configmgr/source/components.cxx | 134 +++++++++++++++++++++++++++++++++------- 1 file changed, 113 insertions(+), 21 deletions(-) (limited to 'configmgr/source/components.cxx') diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index 04e6317c959d..733ca05bc147 100644 --- a/configmgr/source/components.cxx +++ b/configmgr/source/components.cxx @@ -54,10 +54,12 @@ #include "rtl/ustring.hxx" #include "sal/types.h" +#include "additions.hxx" #include "components.hxx" #include "data.hxx" #include "modifications.hxx" #include "node.hxx" +#include "nodemap.hxx" #include "parsemanager.hxx" #include "partial.hxx" #include "rootaccess.hxx" @@ -86,12 +88,12 @@ typedef std::list< UnresolvedListItem > UnresolvedList; void parseXcsFile( rtl::OUString const & url, int layer, Data & data, Partial const * partial, - Modifications * modifications) + Modifications * modifications, Additions * additions) SAL_THROW(( css::container::NoSuchElementException, css::uno::RuntimeException)) { - OSL_ASSERT(partial == 0 && modifications == 0); - (void) partial; (void) modifications; + OSL_ASSERT(partial == 0 && modifications == 0 && additions == 0); + (void) partial; (void) modifications; (void) additions; OSL_VERIFY( rtl::Reference< ParseManager >( new ParseManager(url, new XcsParser(layer, data)))->parse()); @@ -99,14 +101,16 @@ void parseXcsFile( void parseXcuFile( rtl::OUString const & url, int layer, Data & data, Partial const * partial, - Modifications * modifications) + Modifications * modifications, Additions * additions) SAL_THROW(( css::container::NoSuchElementException, css::uno::RuntimeException)) { OSL_VERIFY( rtl::Reference< ParseManager >( new ParseManager( - url, new XcuParser(layer, data, partial, modifications)))-> + url, + new XcuParser( + layer, data, partial, modifications, additions)))-> parse()); } @@ -116,6 +120,29 @@ rtl::OUString expand(rtl::OUString const & str) { return s; } +bool hasOnlyEmptySets(rtl::Reference< Node > const & node) { + OSL_ASSERT(node.is()); + switch (node->kind()) { + default: // Node::KIND_LOCALIZED_VALUE + OSL_ASSERT(false); + // fall through + case Node::KIND_PROPERTY: + case Node::KIND_LOCALIZED_PROPERTY: + return true; + case Node::KIND_GROUP: + for (NodeMap::iterator i(node->getMembers().begin()); + i != node->getMembers().end(); ++i) + { + if (!hasOnlyEmptySets(i->second)) { + return false; + } + } + return true; + case Node::KIND_SET: + return node->getMembers().empty(); + } +} + static bool singletonCreated = false; static Components * singleton = 0; @@ -218,7 +245,7 @@ void Components::insertExtensionXcsFile( bool shared, rtl::OUString const & fileUri) { try { - parseXcsFile(fileUri, shared ? 9 : 13, data_, 0, 0); + parseXcsFile(fileUri, shared ? 9 : 13, data_, 0, 0, 0); } catch (css::container::NoSuchElementException & e) { throw css::uno::RuntimeException( (rtl::OUString( @@ -233,9 +260,12 @@ void Components::insertExtensionXcuFile( bool shared, rtl::OUString const & fileUri, Modifications * modifications) { OSL_ASSERT(modifications != 0); + int layer = shared ? 10 : 14; + Additions * adds = data_.addExtensionXcuAdditions(fileUri, layer); try { - parseXcuFile(fileUri, shared ? 10 : 14, data_, 0, modifications); + parseXcuFile(fileUri, layer, data_, 0, modifications, adds); } catch (css::container::NoSuchElementException & e) { + data_.removeExtensionXcuAdditions(fileUri); throw css::uno::RuntimeException( (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( @@ -245,6 +275,54 @@ void Components::insertExtensionXcuFile( } } +void Components::removeExtensionXcuFile( + rtl::OUString const & fileUri, Modifications * modifications) +{ + //TODO: Ideally, exactly the data coming from the specified xcu file would + // be removed. However, not enough information is recorded in the in-memory + // data structures to do so. So, as a workaround, all those set elements + // that were freshly added by the xcu and have afterwards been left + // unchanged are removed (and nothing else). The heuristic to determine + // whether a node has been left unchanged is to check the layer ID (as + // usual) and additionally to check that the node does not recursively + // contain any non-empty sets (multiple extension xcu files are merged into + // one layer, so checking layer ID alone is not enough). Since + // item->additions records all additions of set members in textual order, + // the latter check works well when iterating through item->additions in + // reverse order. + rtl::Reference< Data::ExtensionXcu > item( + data_.removeExtensionXcuAdditions(fileUri)); + if (item.is()) { + for (Additions::reverse_iterator i(item->additions.rbegin()); + i != item->additions.rend(); ++i) + { + rtl::Reference< Node > parent; + NodeMap const * map = &data_.components; + rtl::Reference< Node > node; + for (Path::const_iterator j(i->begin()); j != i->end(); ++j) { + parent = node; + node = Data::findNode(item->layer, *map, *j); + if (!node.is()) { + break; + } + map = &node->getMembers(); + } + if (node.is()) { + OSL_ASSERT(parent.is()); + if (parent->kind() == Node::KIND_SET) { + OSL_ASSERT( + node->kind() == Node::KIND_GROUP || + node->kind() == Node::KIND_SET); + if (hasOnlyEmptySets(node)) { + parent->getMembers().erase(i->back()); + modifications->add(*i); + } + } + } + } + } +} + void Components::insertModificationXcuFile( rtl::OUString const & fileUri, std::set< rtl::OUString > const & includedPaths, @@ -254,7 +332,7 @@ void Components::insertModificationXcuFile( OSL_ASSERT(modifications != 0); try { Partial part(includedPaths, excludedPaths); - parseXcuFile(fileUri, Data::NO_LAYER, data_, &part, modifications); + parseXcuFile(fileUri, Data::NO_LAYER, data_, &part, modifications, 0); } catch (css::uno::Exception & e) { //TODO: more specific exception catching OSL_TRACE( "configmgr error inserting %s: %s", @@ -377,7 +455,8 @@ Components::Components( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno") ":BUNDLED_EXTENSIONS_USER}/registry/" "com.sun.star.comp.deployment.configuration." - "PackageRegistryBackend/configmgr.ini")))); + "PackageRegistryBackend/configmgr.ini"))), + false); parseXcsXcuIniLayer( 9, expand( @@ -386,8 +465,9 @@ Components::Components( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno") ":SHARED_EXTENSIONS_USER}/registry/" "com.sun.star.comp.deployment.configuration." - "PackageRegistryBackend/configmgr.ini")))); - parseXcsXcuLayer( //TODO: migrate + "PackageRegistryBackend/configmgr.ini"))), + true); + parseXcsXcuLayer( 11, expand( rtl::OUString( @@ -396,6 +476,8 @@ Components::Components( ":UNO_USER_PACKAGES_CACHE}/registry/" "com.sun.star.comp.deployment.configuration." "PackageRegistryBackend/registry")))); + // can be dropped once old UserInstallation format can no longer exist + // (probably OOo 4) parseXcsXcuIniLayer( 13, expand( @@ -404,7 +486,8 @@ Components::Components( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno") ":UNO_USER_PACKAGES_CACHE}/registry/" "com.sun.star.comp.deployment.configuration." - "PackageRegistryBackend/configmgr.ini")))); + "PackageRegistryBackend/configmgr.ini"))), + true); try { parseModificationLayer(); } catch (css::uno::Exception & e) { //TODO: more specific exception catching @@ -470,7 +553,7 @@ void Components::parseFiles( file.match(extension, file.getLength() - extension.getLength())) { try { - (*parseFile)(stat.getFileURL(), layer, data_, 0, 0); + (*parseFile)(stat.getFileURL(), layer, data_, 0, 0, 0); } catch (css::container::NoSuchElementException & e) { throw css::uno::RuntimeException( (rtl::OUString( @@ -486,19 +569,26 @@ void Components::parseFiles( void Components::parseFileList( int layer, FileParser * parseFile, rtl::OUString const & urls, - rtl::Bootstrap const & ini) + rtl::Bootstrap const & ini, bool recordAdditions) { for (sal_Int32 i = 0;;) { rtl::OUString url(urls.getToken(0, ' ', i)); if (url.getLength() != 0) { ini.expandMacrosFrom(url); //TODO: detect failure + Additions * adds = 0; + if (recordAdditions) { + adds = data_.addExtensionXcuAdditions(url, layer); + } try { - (*parseFile)(url, layer, data_, 0, 0); + (*parseFile)(url, layer, data_, 0, 0, adds); } catch (css::container::NoSuchElementException & e) { OSL_TRACE( "configmgr file does not exist: %s", rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8).getStr()); + if (adds != 0) { + data_.removeExtensionXcuAdditions(url); + } } } if (i == -1) { @@ -610,18 +700,20 @@ void Components::parseXcsXcuLayer(int layer, rtl::OUString const & url) { url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/data")), false); } -void Components::parseXcsXcuIniLayer(int layer, rtl::OUString const & url) { +void Components::parseXcsXcuIniLayer( + int layer, rtl::OUString const & url, bool recordAdditions) +{ //TODO: rtl::Bootstrap::getFrom "first trie[s] to retrieve the value via the // global function" rtl::Bootstrap ini(url); rtl::OUString urls; if (ini.getFrom(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SCHEMA")), urls)) { - parseFileList(layer, &parseXcsFile, urls, ini); + parseFileList(layer, &parseXcsFile, urls, ini, false); } if (ini.getFrom(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DATA")), urls)) { - parseFileList(layer + 1, &parseXcuFile, urls, ini); + parseFileList(layer + 1, &parseXcuFile, urls, ini, recordAdditions); } } @@ -650,13 +742,13 @@ rtl::OUString Components::getModificationFileUrl() const { void Components::parseModificationLayer() { try { - parseXcuFile(getModificationFileUrl(), Data::NO_LAYER, data_, 0, 0); + parseXcuFile(getModificationFileUrl(), Data::NO_LAYER, data_, 0, 0, 0); } catch (css::container::NoSuchElementException &) { OSL_TRACE( "configmgr user registrymodifications.xcu does not (yet) exist"); // Migrate old user layer data (can be removed once migration is no - // longer relevant; also see hack for xsi namespace in XmlReader - // constructor): + // longer relevant, probably OOo 4; also see hack for xsi namespace in + // XmlReader constructor): parseFiles( Data::NO_LAYER, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")), &parseXcuFile, -- cgit From d7fd47ed54f42d353c375d171350cfe81c307414 Mon Sep 17 00:00:00 2001 From: sb Date: Thu, 26 Aug 2010 13:26:56 +0200 Subject: sb130: #i113096# previous change contained an error in configmgr::Components::removeExtensionXcuFile --- configmgr/source/components.cxx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'configmgr/source/components.cxx') diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index 733ca05bc147..e76460de5b64 100644 --- a/configmgr/source/components.cxx +++ b/configmgr/source/components.cxx @@ -290,6 +290,7 @@ void Components::removeExtensionXcuFile( // item->additions records all additions of set members in textual order, // the latter check works well when iterating through item->additions in // reverse order. + OSL_ASSERT(modifications != 0); rtl::Reference< Data::ExtensionXcu > item( data_.removeExtensionXcuAdditions(fileUri)); if (item.is()) { @@ -315,6 +316,7 @@ void Components::removeExtensionXcuFile( node->kind() == Node::KIND_SET); if (hasOnlyEmptySets(node)) { parent->getMembers().erase(i->back()); + addModification(*i); modifications->add(*i); } } -- cgit From 4ea577d0efe22e5785c8ae72c86f517fd2cf9194 Mon Sep 17 00:00:00 2001 From: sb Date: Thu, 26 Aug 2010 17:11:05 +0200 Subject: sb130: #i113096# previous configmgr::Components::removeExtensionXcuFile changes were still not good --- configmgr/source/components.cxx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'configmgr/source/components.cxx') diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index e76460de5b64..33b0eca3f65f 100644 --- a/configmgr/source/components.cxx +++ b/configmgr/source/components.cxx @@ -120,26 +120,26 @@ rtl::OUString expand(rtl::OUString const & str) { return s; } -bool hasOnlyEmptySets(rtl::Reference< Node > const & node) { +bool canRemoveFromLayer(int layer, rtl::Reference< Node > const & node) { OSL_ASSERT(node.is()); + if (node->getLayer() > layer && node->getLayer() < Data::NO_LAYER) { + return false; + } switch (node->kind()) { - default: // Node::KIND_LOCALIZED_VALUE - OSL_ASSERT(false); - // fall through - case Node::KIND_PROPERTY: case Node::KIND_LOCALIZED_PROPERTY: - return true; case Node::KIND_GROUP: for (NodeMap::iterator i(node->getMembers().begin()); i != node->getMembers().end(); ++i) { - if (!hasOnlyEmptySets(i->second)) { + if (!canRemoveFromLayer(layer, i->second)) { return false; } } return true; case Node::KIND_SET: return node->getMembers().empty(); + default: // Node::KIND_PROPERTY, Node::KIND_LOCALIZED_VALUE + return true; } } @@ -282,7 +282,8 @@ void Components::removeExtensionXcuFile( // be removed. However, not enough information is recorded in the in-memory // data structures to do so. So, as a workaround, all those set elements // that were freshly added by the xcu and have afterwards been left - // unchanged are removed (and nothing else). The heuristic to determine + // unchanged or have only had their properties changed in the user layer are + // removed (and nothing else). The heuristic to determine // whether a node has been left unchanged is to check the layer ID (as // usual) and additionally to check that the node does not recursively // contain any non-empty sets (multiple extension xcu files are merged into @@ -302,7 +303,7 @@ void Components::removeExtensionXcuFile( rtl::Reference< Node > node; for (Path::const_iterator j(i->begin()); j != i->end(); ++j) { parent = node; - node = Data::findNode(item->layer, *map, *j); + node = Data::findNode(Data::NO_LAYER, *map, *j); if (!node.is()) { break; } @@ -314,14 +315,15 @@ void Components::removeExtensionXcuFile( OSL_ASSERT( node->kind() == Node::KIND_GROUP || node->kind() == Node::KIND_SET); - if (hasOnlyEmptySets(node)) { + if (canRemoveFromLayer(item->layer, node)) { parent->getMembers().erase(i->back()); - addModification(*i); + data_.modifications.remove(*i); modifications->add(*i); } } } } + writeModifications(); } } -- cgit