/**************************************************************
 * 
 * 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);
    }
}

}
