/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "precompiled_configmgr.hxx" #include "sal/config.h" #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/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_; boost::shared_ptr lock_; }; Components::WriteThread::WriteThread( rtl::Reference< WriteThread > * reference, Components & components, rtl::OUString const & url, Data const & data): reference_(reference), components_(components), url_(url), data_(data) { lock_ = lock(); 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(); } void Components::initSingleton( css::uno::Reference< css::uno::XComponentContext > const & context) { OSL_ASSERT(context.is()); if (!singletonCreated) { static Components theSingleton(context); singleton = &theSingleton; singletonCreated = true; } } Components & Components::getSingleton() { OSL_ASSERT(singletonCreated); 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); } bool Components::hasModifications() const { return data_.modifications.getRoot().children.begin() != data_.modifications.getRoot().children.end(); } void Components::writeModifications() { if (!hasModifications()) return; 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) { lock_ = lock(); 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")))); parseXcsXcuLayer( 4, expand( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$BRAND_BASE_DIR/share/registry")))); parseModuleLayer( 6, expand( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$BRAND_BASE_DIR/share/registry/modules")))); 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() { flushModifications(); } 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( "${$BRAND_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 constructor): 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); } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */