diff options
Diffstat (limited to 'configmgr/source/rootaccess.cxx')
-rw-r--r-- | configmgr/source/rootaccess.cxx | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/configmgr/source/rootaccess.cxx b/configmgr/source/rootaccess.cxx new file mode 100644 index 000000000..ff7adddef --- /dev/null +++ b/configmgr/source/rootaccess.cxx @@ -0,0 +1,313 @@ +/* -*- 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 <cassert> +#include <utility> +#include <vector> + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/util/ChangesEvent.hpp> +#include <com/sun/star/util/ChangesSet.hpp> +#include <com/sun/star/util/ElementChange.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/util/XChangesListener.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <comphelper/sequence.hxx> +#include <cppu/unotype.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <osl/mutex.hxx> +#include <rtl/ref.hxx> +#include <rtl/ustring.hxx> + +#include "broadcaster.hxx" +#include "components.hxx" +#include "data.hxx" +#include "lock.hxx" +#include "modifications.hxx" +#include "node.hxx" +#include "rootaccess.hxx" + +namespace configmgr { + +RootAccess::RootAccess( + Components & components, OUString pathRepresentation, + OUString locale, bool update): + Access(components), pathRepresentation_(std::move(pathRepresentation)), + locale_(std::move(locale)), + lock_( lock() ), + update_(update), finalized_(false), alive_(true) +{ +} + +std::vector<OUString> RootAccess::getAbsolutePath() { + getNode(); + return path_; +} + +void RootAccess::initBroadcaster( + Modifications::Node const & modifications, Broadcaster * broadcaster) +{ + assert(broadcaster != nullptr); + std::vector< css::util::ElementChange > changes; + initBroadcasterAndChanges( + modifications, broadcaster, changesListeners_.empty() ? nullptr : &changes); + if (changes.empty()) + return; + + css::util::ChangesSet set(comphelper::containerToSequence(changes)); + for (auto const& changesListener : changesListeners_) + { + cppu::OWeakObject* pSource = this; + css::uno::Reference< css::uno::XInterface > xBase( pSource, css::uno::UNO_QUERY ); + broadcaster->addChangesNotification( + changesListener, + css::util::ChangesEvent( + pSource, css::uno::Any( xBase ), set)); + } +} + +void RootAccess::acquire() noexcept { + Access::acquire(); +} + +void RootAccess::release() noexcept { + Access::release(); +} + +OUString const & RootAccess::getAbsolutePathRepresentation() { + getNode(); // turn pathRepresentation_ into canonic form + return pathRepresentation_; +} + + +void RootAccess::setAlive(bool b) { + alive_ = b; +} + +void RootAccess::addChangesListener( + css::uno::Reference< css::util::XChangesListener > const & aListener) +{ + assert(thisIs(IS_ANY)); + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + if (!aListener.is()) { + throw css::uno::RuntimeException( + "null listener", static_cast< cppu::OWeakObject * >(this)); + } + if (!isDisposed()) { + changesListeners_.insert(aListener); + return; + } + } + try { + aListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} +} + +void RootAccess::removeChangesListener( + css::uno::Reference< css::util::XChangesListener > const & aListener) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + ChangesListeners::iterator i(changesListeners_.find(aListener)); + if (i != changesListeners_.end()) { + changesListeners_.erase(i); + } +} + +void RootAccess::commitChanges() +{ + assert(thisIs(IS_UPDATE)); + if (!alive_) + { + return; + } + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + + checkLocalizedPropertyAccess(); + int finalizedLayer; + Modifications globalMods; + commitChildChanges( + ((getComponents().resolvePathRepresentation( + pathRepresentation_, nullptr, nullptr, &finalizedLayer) + == node_) && + finalizedLayer == Data::NO_LAYER), + &globalMods); + getComponents().writeModifications(); + getComponents().initGlobalBroadcaster(globalMods, this, &bc); + } + bc.send(); +} + +sal_Bool RootAccess::hasPendingChanges() { + assert(thisIs(IS_UPDATE)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + //TODO: Optimize: + std::vector< css::util::ElementChange > changes; + reportChildChanges(&changes); + return !changes.empty(); +} + +css::uno::Sequence< ::css::util::ElementChange > RootAccess::getPendingChanges() +{ + assert(thisIs(IS_UPDATE)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + std::vector< css::util::ElementChange > changes; + reportChildChanges(&changes); + return comphelper::containerToSequence(changes); +} + +RootAccess::~RootAccess() +{ + osl::MutexGuard g(*lock_); + if (alive_) + getComponents().removeRootAccess(this); +} + +std::vector<OUString> RootAccess::getRelativePath() { + return std::vector<OUString>(); +} + +OUString RootAccess::getRelativePathRepresentation() { + return OUString(); +} + +rtl::Reference< Node > RootAccess::getNode() { + if (!node_.is()) { + OUString canonic; + int finalizedLayer; + node_ = getComponents().resolvePathRepresentation( + pathRepresentation_, &canonic, &path_, &finalizedLayer); + if (!node_.is()) { + throw css::uno::RuntimeException( + "cannot find " + pathRepresentation_, nullptr); + // RootAccess::queryInterface indirectly calls + // RootAccess::getNode, so if this RootAccess were passed out in + // RuntimeException.Context, client code that called + // queryInterface on it would cause trouble; therefore, + // RuntimeException.Context is left null here + } + pathRepresentation_ = canonic; + assert(!path_.empty() || node_->kind() == Node::KIND_ROOT); + if (!path_.empty()) { + name_ = path_.back(); + } + finalized_ = finalizedLayer != Data::NO_LAYER; + } + return node_; +} + +bool RootAccess::isFinalized() { + getNode(); + return finalized_; +} + +const OUString & RootAccess::getNameInternal() { + getNode(); + return name_; +} + +rtl::Reference< RootAccess > RootAccess::getRootAccess() { + return this; +} + +rtl::Reference< Access > RootAccess::getParentAccess() { + return rtl::Reference< Access >(); +} + +void RootAccess::addTypes(std::vector< css::uno::Type > * types) const { + assert(types != nullptr); + types->push_back(cppu::UnoType< css::util::XChangesNotifier >::get()); + types->push_back(cppu::UnoType< css::util::XChangesBatch >::get()); +} + +void RootAccess::addSupportedServiceNames( + std::vector<OUString> * services) +{ + assert(services != nullptr); + services->push_back("com.sun.star.configuration.AccessRootElement"); + if (update_) { + services->push_back("com.sun.star.configuration.UpdateRootElement"); + } +} + +void RootAccess::initDisposeBroadcaster(Broadcaster * broadcaster) { + assert(broadcaster != nullptr); + for (auto const& changesListener : changesListeners_) + { + broadcaster->addDisposeNotification( + changesListener, + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } + Access::initDisposeBroadcaster(broadcaster); +} + +void RootAccess::clearListeners() noexcept { + changesListeners_.clear(); + Access::clearListeners(); +} + +css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + css::uno::Any res(Access::queryInterface(aType)); + if (res.hasValue()) { + return res; + } + res = cppu::queryInterface( + aType, static_cast< css::util::XChangesNotifier * >(this)); + if (res.hasValue()) { + return res; + } + if (!res.hasValue() && update_) { + res = cppu::queryInterface( + aType, static_cast< css::util::XChangesBatch * >(this)); + } + return res; +} + +OUString RootAccess::getImplementationName() +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return "configmgr.RootAccess"; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |