/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include "sal/config.h" #include #include #include #include #include #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/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/file.hxx" #include "osl/mutex.hxx" #include "rtl/bootstrap.hxx" #include "rtl/logfile.h" #include "rtl/ref.hxx" #include "rtl/string.h" #include "rtl/ustrbuf.hxx" #include "rtl/ustring.h" #include "rtl/ustring.hxx" #include "rtl/instance.hxx" #include "sal/log.hxx" #include "sal/types.h" #include "salhelper/thread.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 { 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)) { assert(partial == 0 && modifications == 0 && additions == 0); (void) partial; (void) modifications; (void) additions; bool ok = rtl::Reference< ParseManager >( new ParseManager(url, new XcsParser(layer, data)))->parse(0); assert(ok); (void) ok; // avoid warnings } 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)) { bool ok = rtl::Reference< ParseManager >( new ParseManager( url, new XcuParser(layer, data, partial, modifications, additions)))-> parse(0); assert(ok); (void) ok; // avoid warnings } 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) { 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::const_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; } } } class Components::WriteThread: public salhelper::Thread { public: WriteThread( rtl::Reference< WriteThread > * reference, Components & components, rtl::OUString const & url, Data const & data); void flush() { delay_.set(); } private: virtual ~WriteThread() {} virtual void execute(); rtl::Reference< WriteThread > * reference_; Components & components_; rtl::OUString url_; Data const & data_; osl::Condition delay_; boost::shared_ptr lock_; }; Components::WriteThread::WriteThread( rtl::Reference< WriteThread > * reference, Components & components, rtl::OUString const & url, Data const & data): Thread("configmgrWriter"), reference_(reference), components_(components), url_(url), data_(data) { lock_ = lock(); assert(reference != 0); } void Components::WriteThread::execute() { 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) { // Ignore write errors, instead of aborting: SAL_WARN( "configmgr", "error writing modifications: \"" << e.Message << '"'); } } catch (...) { reference_->clear(); throw; } reference_->clear(); } class theComponentsSingleton : public rtl::StaticWithArg< Components, css::uno::Reference< css::uno::XComponentContext >, theComponentsSingleton> { }; Components & Components::getSingleton( css::uno::Reference< css::uno::XComponentContext > const & context) { assert(context.is()); return theComponentsSingleton::get(context); } bool Components::allLocales(rtl::OUString const & locale) { return locale == "*"; } 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); } bool Components::hasModifications() const { return data_.modifications.getRoot().children.begin() != data_.modifications.getRoot().children.end(); } void Components::writeModifications() { if (!hasModifications() || modificationFileUrl_.isEmpty()) return; if (!writeThread_.is()) { writeThread_ = new WriteThread( &writeThread_, *this, modificationFileUrl_, data_); writeThread_->launch(); } } 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) { int layer = getExtensionLayer(shared); try { parseXcsFile(fileUri, layer, 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) { assert(modifications != 0); int layer = getExtensionLayer(shared) + 1; 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. 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_.getComponents(); 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()) { assert(parent.is()); if (parent->kind() == Node::KIND_SET) { 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) { assert(modifications != 0); Partial part(includedPaths, excludedPaths); try { parseFileLeniently( &parseXcuFile, fileUri, Data::NO_LAYER, data_, &part, modifications, 0); } catch (css::container::NoSuchElementException & e) { SAL_WARN( "configmgr", "error inserting non-existing \"" << fileUri << "\": \"" << e.Message << '"'); } } 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 = context_->getServiceManager()->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: SAL_WARN( "configmgr", "createInstance(" << name << ") failed with \"" << e.Message << '"'); } 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( "unknown 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), sharedExtensionLayer_(-1), userExtensionLayer_(-1) { assert(context.is()); lock_ = lock(); rtl::OUString conf( expand( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("${CONFIGURATION_LAYERS}")))); RTL_LOGFILE_TRACE("configmgr : begin parsing"); int layer = 0; for (sal_Int32 i = 0;;) { while (i != conf.getLength() && conf[i] == ' ') { ++i; } if (i == conf.getLength()) { break; } if (!modificationFileUrl_.isEmpty()) { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CONFIGURATION_LAYERS: \"user\" followed by further" " layers")), css::uno::Reference< css::uno::XInterface >()); } sal_Int32 c = i; for (;; ++c) { if (c == conf.getLength() || conf[c] == ' ') { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CONFIGURATION_LAYERS: missing \":\"")), css::uno::Reference< css::uno::XInterface >()); } if (conf[c] == ':') { break; } } sal_Int32 n = conf.indexOf(' ', c + 1); if (n == -1) { n = conf.getLength(); } rtl::OUString type(conf.copy(i, c - i)); rtl::OUString url(conf.copy(c + 1, n - c - 1)); if ( type == "xcsxcu" ) { parseXcsXcuLayer(layer, url); layer += 2; //TODO: overflow } else if ( type == "bundledext" ) { parseXcsXcuIniLayer(layer, url, false); layer += 2; //TODO: overflow } else if ( type == "sharedext" ) { if (sharedExtensionLayer_ != -1) { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CONFIGURATION_LAYERS: multiple \"sharedext\"" " layers")), css::uno::Reference< css::uno::XInterface >()); } sharedExtensionLayer_ = layer; parseXcsXcuIniLayer(layer, url, true); layer += 2; //TODO: overflow } else if ( type == "userext" ) { if (userExtensionLayer_ != -1) { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CONFIGURATION_LAYERS: multiple \"userext\"" " layers")), css::uno::Reference< css::uno::XInterface >()); } userExtensionLayer_ = layer; parseXcsXcuIniLayer(layer, url, true); layer += 2; //TODO: overflow } else if ( type == "module" ) { parseModuleLayer(layer, url); ++layer; //TODO: overflow } else if ( type == "res" ) { parseResLayer(layer, url); ++layer; //TODO: overflow } else if ( type == "user" ) { if (url.isEmpty()) { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CONFIGURATION_LAYERS: empty \"user\" URL")), css::uno::Reference< css::uno::XInterface >()); } modificationFileUrl_ = url; parseModificationLayer(url); } else { throw css::uno::RuntimeException( (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CONFIGURATION_LAYERS: unknown layer type \"")) + type + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\""))), css::uno::Reference< css::uno::XInterface >()); } i = n; } RTL_LOGFILE_TRACE("configmgr : end parsing"); } Components::~Components() { flushModifications(); for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) { (*i)->setAlive(false); } } void Components::parseFileLeniently( FileParser * parseFile, rtl::OUString const & url, int layer, Data & data, Partial const * partial, Modifications * modifications, Additions * additions) { 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 // Ignore invalid XML files, instead of completely preventing OOo from // starting: SAL_WARN( "configmgr", "error reading \"" << url << "\": \"" << e.Message << '"'); } } 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( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_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, bool recordAdditions) { for (sal_Int32 i = 0;;) { rtl::OUString url(urls.getToken(0, ' ', i)); if (!url.isEmpty()) { Additions * adds = 0; if (recordAdditions) { adds = data_.addExtensionXcuAdditions(url, layer); } try { parseFileLeniently(parseFile, url, layer, data_, 0, 0, adds); } catch (css::container::NoSuchElementException & e) { SAL_WARN( "configmgr", "file does not exist: \"" << e.Message << '"'); 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; std::set< OUString > existingDeps; std::set< OUString > processedDeps; 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( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_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"))); existingDeps.insert(name); rtl::Reference< ParseManager > manager; try { manager = new ParseManager( stat.getFileURL(), new XcdParser(layer, processedDeps, 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(0)) { processedDeps.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(&existingDeps)) { processedDeps.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) { // Check if ini file exists (otherwise .override would still read global // SCHEMA/DATA variables, which could interfere with unrelated environment // variables): if (rtl::Bootstrap(url).getHandle() != 0) { rtl::OUStringBuffer prefix("${.override:"); for (sal_Int32 i = 0; i != url.getLength(); ++i) { sal_Unicode c = url[i]; switch (c) { case '$': case ':': case '\\': prefix.append('\\'); // fall through default: prefix.append(c); } } prefix.append(':'); rtl::OUString urls(prefix.toString() + rtl::OUString("SCHEMA}")); rtl::Bootstrap::expandMacros(urls); if (!urls.isEmpty()) { parseFileList(layer, &parseXcsFile, urls, false); } urls = prefix.makeStringAndClear() + rtl::OUString("DATA}"); rtl::Bootstrap::expandMacros(urls); if (!urls.isEmpty()) { parseFileList(layer + 1, &parseXcuFile, urls, 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); } void Components::parseModificationLayer(rtl::OUString const & url) { try { parseFileLeniently(&parseXcuFile, url, Data::NO_LAYER, data_, 0, 0, 0); } catch (css::container::NoSuchElementException &) { SAL_INFO( "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( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/user/registry/data"))), false); } } int Components::getExtensionLayer(bool shared) { int layer = shared ? sharedExtensionLayer_ : userExtensionLayer_; if (layer == -1) { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert extension xcs/xcu file into undefined layer")), css::uno::Reference< css::uno::XInterface >()); } return layer; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */