blob: 98367dff962ccb6e8ec1cfe14f0d44363f590ac2 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "precompiled_configmgr.hxx"
#include "sal/config.h"
#include <algorithm>
#include <cstddef>
#include <list>
#include "com/sun/star/beans/Optional.hpp"
#include "com/sun/star/beans/UnknownPropertyException.hpp"
#include "com/sun/star/beans/XPropertySet.hpp"
#include "com/sun/star/container/NoSuchElementException.hpp"
#include "com/sun/star/lang/WrappedTargetException.hpp"
#include "com/sun/star/lang/XMultiComponentFactory.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/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hpp"
#include "osl/conditn.hxx"
#include "osl/diagnose.h"
#include "osl/file.hxx"
#include "osl/mutex.hxx"
#include "osl/thread.hxx"
#include "rtl/bootstrap.hxx"
#include "rtl/logfile.h"
#include "rtl/ref.hxx"
#include "rtl/string.h"
#include "rtl/textenc.h"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "salhelper/simplereferenceobject.hxx"
#include "additions.hxx"
#include "components.hxx"
#include "data.hxx"
#include "lock.hxx"
#include "modifications.hxx"
#include "node.hxx"
#include "nodemap.hxx"
#include "parsemanager.hxx"
#include "partial.hxx"
#include "rootaccess.hxx"
#include "writemodfile.hxx"
#include "xcdparser.hxx"
#include "xcuparser.hxx"
#include "xcsparser.hxx"
namespace configmgr {
namespace {
namespace css = com::sun::star;
struct UnresolvedListItem {
rtl::OUString name;
rtl::Reference< ParseManager > manager;
UnresolvedListItem(
rtl::OUString const & theName,
rtl::Reference< ParseManager > theManager):
name(theName), manager(theManager) {}
};
typedef std::list< UnresolvedListItem > UnresolvedList;
void parseXcsFile(
rtl::OUString const & url, int layer, Data & data, Partial const * partial,
Modifications * modifications, Additions * additions)
SAL_THROW((
css::container::NoSuchElementException, css::uno::RuntimeException))
{
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());
}
void parseXcuFile(
rtl::OUString const & url, int layer, Data & data, Partial const * partial,
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, additions)))->
parse());
}
rtl::OUString expand(rtl::OUString const & str) {
rtl::OUString s(str);
rtl::Bootstrap::expandMacros(s); //TODO: detect failure
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;
}
class Components::WriteThread:
public osl::Thread, public salhelper::SimpleReferenceObject
{
public:
static void * operator new(std::size_t size)
{ return Thread::operator new(size); }
static void operator delete(void * pointer)
{ Thread::operator delete(pointer); }
WriteThread(
rtl::Reference< WriteThread > * reference, Components & components,
rtl::OUString const & url, Data const & data);
void flush() { delay_.set(); }
private:
virtual ~WriteThread() {}
virtual void SAL_CALL run();
virtual void SAL_CALL onTerminated() { release(); }
rtl::Reference< WriteThread > * reference_;
Components & components_;
rtl::OUString url_;
Data const & data_;
osl::Condition delay_;
};
Components::WriteThread::WriteThread(
rtl::Reference< WriteThread > * reference, Components & components,
rtl::OUString const & url, Data const & data):
reference_(reference), components_(components), url_(url), data_(data)
{
OSL_ASSERT(reference != 0);
acquire();
}
void Components::WriteThread::run() {
TimeValue t = { 1, 0 }; // 1 sec
delay_.wait(&t); // must not throw; result_error is harmless and ignored
osl::MutexGuard g(lock); // must not throw
try {
try {
writeModFile(components_, url_, data_);
} catch (css::uno::RuntimeException & e) {
// Silently ignore write errors, instead of aborting:
OSL_TRACE(
"configmgr error writing modifications: %s",
rtl::OUStringToOString(
e.Message, RTL_TEXTENCODING_UTF8).getStr());
}
} catch (...) {
reference_->clear();
throw;
}
reference_->clear();
}
Components & Components::getSingleton(
css::uno::Reference< css::uno::XComponentContext > const & context)
{
OSL_ASSERT(context.is());
if (!singletonCreated) {
singletonCreated = true;
static Components theSingleton(context);
singleton = &theSingleton;
}
if (singleton == 0) {
throw css::uno::RuntimeException(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"configmgr no Components singleton")),
css::uno::Reference< css::uno::XInterface >());
}
return *singleton;
}
bool Components::allLocales(rtl::OUString const & locale) {
return locale.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("*"));
}
rtl::Reference< Node > Components::resolvePathRepresentation(
rtl::OUString const & pathRepresentation,
rtl::OUString * canonicRepresentation, Path * path, int * finalizedLayer)
const
{
return data_.resolvePathRepresentation(
pathRepresentation, canonicRepresentation, path, finalizedLayer);
}
rtl::Reference< Node > Components::getTemplate(
int layer, rtl::OUString const & fullName) const
{
return data_.getTemplate(layer, fullName);
}
void Components::addRootAccess(rtl::Reference< RootAccess > const & access) {
roots_.insert(access.get());
}
void Components::removeRootAccess(RootAccess * access) {
roots_.erase(access);
}
void Components::initGlobalBroadcaster(
Modifications const & modifications,
rtl::Reference< RootAccess > const & exclude, Broadcaster * broadcaster)
{
//TODO: Iterate only over roots w/ listeners:
for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) {
rtl::Reference< RootAccess > root;
if ((*i)->acquireCounting() > 1) {
root.set(*i); // must not throw
}
(*i)->releaseNondeleting();
if (root.is()) {
if (root != exclude) {
Path path(root->getAbsolutePath());
Modifications::Node const * mods = &modifications.getRoot();
for (Path::iterator j(path.begin()); j != path.end(); ++j) {
Modifications::Node::Children::const_iterator k(
mods->children.find(*j));
if (k == mods->children.end()) {
mods = 0;
break;
}
mods = &k->second;
}
//TODO: If the complete tree of which root is a part is deleted,
// or replaced, mods will be null, but some of the listeners
// from within root should probably fire nonetheless:
if (mods != 0) {
root->initBroadcaster(*mods, broadcaster);
}
}
}
}
}
void Components::addModification(Path const & path) {
data_.modifications.add(path);
}
void Components::writeModifications() {
if (!writeThread_.is()) {
writeThread_ = new WriteThread(
&writeThread_, *this, getModificationFileUrl(), data_);
writeThread_->create();
}
}
void Components::flushModifications() {
rtl::Reference< WriteThread > thread;
{
osl::MutexGuard g(lock);
thread = writeThread_;
}
if (thread.is()) {
thread->flush();
thread->join();
}
}
void Components::insertExtensionXcsFile(
bool shared, rtl::OUString const & fileUri)
{
try {
parseXcsFile(fileUri, shared ? 9 : 13, data_, 0, 0, 0);
} catch (css::container::NoSuchElementException & e) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"insertExtensionXcsFile does not exist: ")) +
e.Message),
css::uno::Reference< css::uno::XInterface >());
}
}
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, layer, data_, 0, modifications, adds);
} catch (css::container::NoSuchElementException & e) {
data_.removeExtensionXcuAdditions(fileUri);
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"insertExtensionXcuFile does not exist: ")) +
e.Message),
css::uno::Reference< css::uno::XInterface >());
}
}
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,
std::set< rtl::OUString > const & excludedPaths,
Modifications * modifications)
{
OSL_ASSERT(modifications != 0);
Partial part(includedPaths, excludedPaths);
try {
parseFileLeniently(
&parseXcuFile, fileUri, Data::NO_LAYER, data_, &part, modifications,
0);
} catch (css::container::NoSuchElementException & e) {
OSL_TRACE(
"configmgr error inserting non-existing %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)
{
sal_Int32 i = descriptor.indexOf(' ');
if (i <= 0) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("bad external value descriptor ")) +
descriptor),
css::uno::Reference< css::uno::XInterface >());
}
//TODO: Do not make calls with mutex locked:
rtl::OUString name(descriptor.copy(0, i));
ExternalServices::iterator j(externalServices_.find(name));
if (j == externalServices_.end()) {
css::uno::Reference< css::uno::XInterface > service;
try {
service = css::uno::Reference< css::lang::XMultiComponentFactory >(
context_->getServiceManager(), css::uno::UNO_SET_THROW)->
createInstanceWithContext(name, context_);
} catch (css::uno::RuntimeException &) {
// Assuming these exceptions are real errors:
throw;
} catch (css::uno::Exception & e) {
// Assuming these exceptions indicate that the service is not
// installed:
OSL_TRACE(
"createInstance(%s) failed with %s",
rtl::OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr(),
rtl::OUStringToOString(
e.Message, RTL_TEXTENCODING_UTF8).getStr());
}
css::uno::Reference< css::beans::XPropertySet > propset;
if (service.is()) {
propset = css::uno::Reference< css::beans::XPropertySet >(
service, css::uno::UNO_QUERY_THROW);
}
j = externalServices_.insert(
ExternalServices::value_type(name, propset)).first;
}
css::beans::Optional< css::uno::Any > value;
if (j->second.is()) {
try {
if (!(j->second->getPropertyValue(descriptor.copy(i + 1)) >>=
value))
{
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"cannot obtain external value through ")) +
descriptor),
css::uno::Reference< css::uno::XInterface >());
}
} catch (css::beans::UnknownPropertyException & e) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"unknwon external value descriptor ID: ")) +
e.Message),
css::uno::Reference< css::uno::XInterface >());
} catch (css::lang::WrappedTargetException & e) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"cannot obtain external value: ")) +
e.Message),
css::uno::Reference< css::uno::XInterface >());
}
}
return value;
}
Components::Components(
css::uno::Reference< css::uno::XComponentContext > const & context):
context_(context)
{
OSL_ASSERT(context.is());
RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "begin parsing");
parseXcsXcuLayer(
0,
expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))));
parseModuleLayer(
2,
expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"$OOO_BASE_DIR/share/registry/modules"))));
parseResLayer(
3,
expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/registry"))));
parseXcsXcuIniLayer(
7,
expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
":BUNDLED_EXTENSIONS_USER}/registry/"
"com.sun.star.comp.deployment.configuration."
"PackageRegistryBackend/configmgr.ini"))),
false);
parseXcsXcuIniLayer(
9,
expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
":SHARED_EXTENSIONS_USER}/registry/"
"com.sun.star.comp.deployment.configuration."
"PackageRegistryBackend/configmgr.ini"))),
true);
parseXcsXcuLayer(
11,
expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
":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(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")
":UNO_USER_PACKAGES_CACHE}/registry/"
"com.sun.star.comp.deployment.configuration."
"PackageRegistryBackend/configmgr.ini"))),
true);
parseModificationLayer();
RTL_LOGFILE_TRACE_AUTHOR("configmgr", "sb", "end parsing");
}
Components::~Components() {}
void Components::parseFileLeniently(
FileParser * parseFile, rtl::OUString const & url, int layer, Data & data,
Partial const * partial, Modifications * modifications,
Additions * additions)
{
OSL_ASSERT(parseFile != 0);
try {
(*parseFile)(url, layer, data, partial, modifications, additions);
} catch (css::container::NoSuchElementException &) {
throw;
} catch (css::uno::Exception & e) { //TODO: more specific exception catching
// Silently ignore invalid XML files, instead of completely preventing
// OOo from starting:
OSL_TRACE(
"configmgr error reading %s: %s",
rtl::OUStringToOString(url, RTL_TEXTENCODING_UTF8).getStr(),
rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
}
}
void Components::parseFiles(
int layer, rtl::OUString const & extension, FileParser * parseFile,
rtl::OUString const & url, bool recursive)
{
osl::Directory dir(url);
switch (dir.open()) {
case osl::FileBase::E_None:
break;
case osl::FileBase::E_NOENT:
if (!recursive) {
return;
}
// fall through
default:
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
url),
css::uno::Reference< css::uno::XInterface >());
}
for (;;) {
osl::DirectoryItem i;
osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
if (rc == osl::FileBase::E_NOENT) {
break;
}
if (rc != osl::FileBase::E_None) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
url),
css::uno::Reference< css::uno::XInterface >());
}
osl::FileStatus stat(
FileStatusMask_Type | FileStatusMask_FileName |
FileStatusMask_FileURL);
if (i.getFileStatus(stat) != osl::FileBase::E_None) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
url),
css::uno::Reference< css::uno::XInterface >());
}
if (stat.getFileType() == osl::FileStatus::Directory) { //TODO: symlinks
parseFiles(layer, extension, parseFile, stat.getFileURL(), true);
} else {
rtl::OUString file(stat.getFileName());
if (file.getLength() >= extension.getLength() &&
file.match(extension, file.getLength() - extension.getLength()))
{
try {
parseFileLeniently(
parseFile, stat.getFileURL(), layer, data_, 0, 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 >());
}
}
}
}
}
void Components::parseFileList(
int layer, FileParser * parseFile, rtl::OUString const & urls,
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 {
parseFileLeniently(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) {
break;
}
}
}
void Components::parseXcdFiles(int layer, rtl::OUString const & url) {
osl::Directory dir(url);
switch (dir.open()) {
case osl::FileBase::E_None:
break;
case osl::FileBase::E_NOENT:
return;
default:
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
url),
css::uno::Reference< css::uno::XInterface >());
}
UnresolvedList unres;
XcdParser::Dependencies deps;
for (;;) {
osl::DirectoryItem i;
osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
if (rc == osl::FileBase::E_NOENT) {
break;
}
if (rc != osl::FileBase::E_None) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
url),
css::uno::Reference< css::uno::XInterface >());
}
osl::FileStatus stat(
FileStatusMask_Type | FileStatusMask_FileName |
FileStatusMask_FileURL);
if (i.getFileStatus(stat) != osl::FileBase::E_None) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
url),
css::uno::Reference< css::uno::XInterface >());
}
if (stat.getFileType() != osl::FileStatus::Directory) { //TODO: symlinks
rtl::OUString file(stat.getFileName());
if (file.getLength() >= RTL_CONSTASCII_LENGTH(".xcd") &&
file.matchAsciiL(
RTL_CONSTASCII_STRINGPARAM(".xcd"),
file.getLength() - RTL_CONSTASCII_LENGTH(".xcd")))
{
rtl::OUString name(
file.copy(
0, file.getLength() - RTL_CONSTASCII_LENGTH(".xcd")));
rtl::Reference< ParseManager > manager;
try {
manager = new ParseManager(
stat.getFileURL(), new XcdParser(layer, deps, data_));
} 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 >());
}
if (manager->parse()) {
deps.insert(name);
} else {
unres.push_back(UnresolvedListItem(name, manager));
}
}
}
}
while (!unres.empty()) {
bool resolved = false;
for (UnresolvedList::iterator i(unres.begin()); i != unres.end();) {
if (i->manager->parse()) {
deps.insert(i->name);
unres.erase(i++);
resolved = true;
} else {
++i;
}
}
if (!resolved) {
throw css::uno::RuntimeException(
(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"xcd: unresolved dependencies in ")) +
url),
css::uno::Reference< css::uno::XInterface >());
}
}
}
void Components::parseXcsXcuLayer(int layer, rtl::OUString const & url) {
parseXcdFiles(layer, url);
parseFiles(
layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcs")),
&parseXcsFile,
url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/schema")), false);
parseFiles(
layer + 1, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
&parseXcuFile,
url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/data")), false);
}
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, false);
}
if (ini.getFrom(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DATA")), urls))
{
parseFileList(layer + 1, &parseXcuFile, urls, ini, recordAdditions);
}
}
void Components::parseModuleLayer(int layer, rtl::OUString const & url) {
parseFiles(
layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
&parseXcuFile, url, false);
}
void Components::parseResLayer(int layer, rtl::OUString const & url) {
rtl::OUString resUrl(
url + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/res")));
parseXcdFiles(layer, resUrl);
parseFiles(
layer, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
&parseXcuFile, resUrl, false);
}
rtl::OUString Components::getModificationFileUrl() const {
return expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
":UserInstallation}/user/registrymodifications.xcu")));
}
void Components::parseModificationLayer() {
try {
parseFileLeniently(
&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, probably OOo 4; also see hack for xsi namespace in
// xmlreader::XmlReader::registerNamespaceIri):
parseFiles(
Data::NO_LAYER, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".xcu")),
&parseXcuFile,
expand(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap")
":UserInstallation}/user/registry/data"))),
false);
}
}
}