summaryrefslogtreecommitdiff
path: root/configmgr/source/components.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr/source/components.cxx')
-rw-r--r--configmgr/source/components.cxx138
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,