diff options
Diffstat (limited to 'configmgr/source/components.cxx')
-rw-r--r-- | configmgr/source/components.cxx | 138 |
1 files changed, 117 insertions, 21 deletions
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index 04e6317c959d..33b0eca3f65f 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 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()) { + case Node::KIND_LOCALIZED_PROPERTY: + case Node::KIND_GROUP: + for (NodeMap::iterator i(node->getMembers().begin()); + i != node->getMembers().end(); ++i) + { + 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; + } +} + 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,58 @@ 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 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 + // 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. + OSL_ASSERT(modifications != 0); + 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(Data::NO_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 (canRemoveFromLayer(item->layer, node)) { + parent->getMembers().erase(i->back()); + data_.modifications.remove(*i); + modifications->add(*i); + } + } + } + } + writeModifications(); + } +} + void Components::insertModificationXcuFile( rtl::OUString const & fileUri, std::set< rtl::OUString > const & includedPaths, @@ -254,7 +336,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 +459,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 +469,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 +480,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 +490,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 +557,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 +573,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 +704,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 +746,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, |