diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /filter/source/config/cache/basecontainer.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'filter/source/config/cache/basecontainer.cxx')
-rw-r--r-- | filter/source/config/cache/basecontainer.cxx | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/filter/source/config/cache/basecontainer.cxx b/filter/source/config/cache/basecontainer.cxx new file mode 100644 index 000000000..0dee9d4ba --- /dev/null +++ b/filter/source/config/cache/basecontainer.cxx @@ -0,0 +1,476 @@ +/* -*- 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 "basecontainer.hxx" + +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/uno/Type.h> +#include <comphelper/enumhelper.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <osl/diagnose.h> + +#define LOAD_IMPLICIT + +namespace filter::config{ + +BaseContainer::BaseContainer() + : m_eType() + , m_lListener (m_aMutex) +{ + GetTheFilterCache().load(FilterCache::E_CONTAINS_STANDARD); +} + + +BaseContainer::~BaseContainer() +{ +} + + +void BaseContainer::init(const OUString& sImplementationName, + const css::uno::Sequence< OUString >& lServiceNames , + FilterCache::EItemType eType ) +{ + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + + m_sImplementationName = sImplementationName; + m_lServiceNames = lServiceNames ; + m_eType = eType ; + // <- SAFE +} + + +void BaseContainer::impl_loadOnDemand() +{ +#ifdef LOAD_IMPLICIT + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + + // A generic container needs all items of a set of our cache! + // Of course it can block for a while, till the cache is really filled. + // Note: don't load all sets supported by the cache here! + + FilterCache::EFillState eRequiredState = FilterCache::E_CONTAINS_NOTHING; + switch(m_eType) + { + case FilterCache::E_TYPE : + eRequiredState = FilterCache::E_CONTAINS_TYPES; + break; + + case FilterCache::E_FILTER : + eRequiredState = FilterCache::E_CONTAINS_FILTERS; + break; + + case FilterCache::E_FRAMELOADER : + eRequiredState = FilterCache::E_CONTAINS_FRAMELOADERS; + break; + + case FilterCache::E_CONTENTHANDLER : + eRequiredState = FilterCache::E_CONTAINS_CONTENTHANDLERS; + break; + } + + GetTheFilterCache().load(eRequiredState); + // <- SAFE +#endif +} + + +void BaseContainer::impl_initFlushMode() +{ + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + if (!m_pFlushCache) + m_pFlushCache = GetTheFilterCache().clone(); + if (!m_pFlushCache) + throw css::uno::RuntimeException( "Can not create write copy of internal used cache on demand.", + static_cast< OWeakObject* >(this)); + // <- SAFE +} + + +FilterCache* BaseContainer::impl_getWorkingCache() const +{ + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + if (m_pFlushCache) + return m_pFlushCache.get(); + else + return &GetTheFilterCache(); + // <- SAFE +} + + +OUString SAL_CALL BaseContainer::getImplementationName() +{ + return m_sImplementationName; +} + + +sal_Bool SAL_CALL BaseContainer::supportsService(const OUString& sServiceName) +{ + return cppu::supportsService(this, sServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL BaseContainer::getSupportedServiceNames() +{ + return m_lServiceNames; +} + + +void SAL_CALL BaseContainer::insertByName(const OUString& sItem , + const css::uno::Any& aValue) +{ + if (sItem.isEmpty()) + throw css::lang::IllegalArgumentException("empty value not allowed as item name.", + static_cast< css::container::XNameContainer* >(this), + 1); + + CacheItem aItem; + try + { + aItem << aValue; + } + catch(const css::uno::Exception& ex) + { + throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2); + } + + impl_loadOnDemand(); + + // SAFE -> ---------------------------------- + osl::MutexGuard aLock(m_aMutex); + + // create write copy of used cache on demand ... + impl_initFlushMode(); + + FilterCache* pCache = impl_getWorkingCache(); + if (pCache->hasItem(m_eType, sItem)) + throw css::container::ElementExistException(OUString(), static_cast< css::container::XNameContainer* >(this)); + pCache->setItem(m_eType, sItem, aItem); + // <- SAFE ---------------------------------- +} + + +void SAL_CALL BaseContainer::removeByName(const OUString& sItem) +{ + impl_loadOnDemand(); + + // SAFE -> ---------------------------------- + osl::MutexGuard aLock(m_aMutex); + + // create write copy of used cache on demand ... + impl_initFlushMode(); + + FilterCache* pCache = impl_getWorkingCache(); + pCache->removeItem(m_eType, sItem); // throw exceptions automatically + // <- SAFE ---------------------------------- +} + + +void SAL_CALL BaseContainer::replaceByName(const OUString& sItem , + const css::uno::Any& aValue) +{ + if (sItem.isEmpty()) + throw css::lang::IllegalArgumentException("empty value not allowed as item name.", + static_cast< css::container::XNameContainer* >(this), + 1); + + CacheItem aItem; + try + { + aItem << aValue; + } + catch(const css::uno::Exception& ex) + { + throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2); + } + + impl_loadOnDemand(); + + // SAFE -> ---------------------------------- + osl::MutexGuard aLock(m_aMutex); + + // create write copy of used cache on demand ... + impl_initFlushMode(); + + FilterCache* pCache = impl_getWorkingCache(); + if (!pCache->hasItem(m_eType, sItem)) + throw css::container::NoSuchElementException(OUString(), static_cast< css::container::XNameContainer* >(this)); + pCache->setItem(m_eType, sItem, aItem); + // <- SAFE ---------------------------------- +} + + +css::uno::Any SAL_CALL BaseContainer::getByName(const OUString& sItem) +{ + if (sItem.isEmpty()) + throw css::container::NoSuchElementException( "An empty item can't be part of this cache!", + static_cast< css::container::XNameAccess* >(this)); + + css::uno::Any aValue; + + impl_loadOnDemand(); + + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + + try + { + FilterCache* pCache = impl_getWorkingCache(); + aValue = pCache->getItemWithStateProps(m_eType, sItem); + } + catch(const css::container::NoSuchElementException&) + { + throw; + } + catch(const css::uno::Exception&) + { + // TODO invalid cache!? How should it be handled right? + } + + // <- SAFE + + return aValue; +} + + +css::uno::Sequence< OUString > SAL_CALL BaseContainer::getElementNames() +{ + css::uno::Sequence< OUString > lNames; + + impl_loadOnDemand(); + + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + + try + { + FilterCache* pCache = impl_getWorkingCache(); + std::vector<OUString> lKeys = pCache->getItemNames(m_eType); + lNames = comphelper::containerToSequence(lKeys); + } + catch(const css::uno::Exception&) + { + // invalid cache!? + lNames.realloc(0); + } + + // <- SAFE + + return lNames; +} + + +sal_Bool SAL_CALL BaseContainer::hasByName(const OUString& sItem) +{ + bool bHasOne = false; + + impl_loadOnDemand(); + + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + + try + { + FilterCache* pCache = impl_getWorkingCache(); + bHasOne = pCache->hasItem(m_eType, sItem); + } + catch(const css::uno::Exception&) + { + // invalid cache!? + bHasOne = false; + } + + // <- SAFE + + return bHasOne; +} + + +css::uno::Type SAL_CALL BaseContainer::getElementType() +{ + // no lock necessary - because the type of our items + // is fix! no internal call or member needed ... + return cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get(); +} + + +sal_Bool SAL_CALL BaseContainer::hasElements() +{ + bool bHasSome = false; + + impl_loadOnDemand(); + + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + + try + { + FilterCache* pCache = impl_getWorkingCache(); + bHasSome = pCache->hasItems(m_eType); + } + catch(const css::uno::Exception&) + { + // invalid cache?! + bHasSome = false; + } + + // <- SAFE + + return bHasSome; +} + + +css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const OUString& /* sQuery */ ) +{ + OSL_FAIL("not pure virtual ... but not really implemented .-)"); + + return new ::comphelper::OEnumerationByName(this, {}); +} + + +css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) +{ + std::vector<OUString> lKeys; + + impl_loadOnDemand(); + + // SAFE -> + osl::MutexGuard aLock(m_aMutex); + + try + { + // search the key names of all items, where its properties match + // the given ones in its minimum + FilterCache* pCache = impl_getWorkingCache(); + lKeys = pCache->getMatchingItemsByProps(m_eType, o3tl::span<const css::beans::NamedValue>( lProperties.getConstArray(), lProperties.getLength() )); + } + catch(const css::uno::Exception&) + { + // invalid cache, internal failure, wrong conversion ...!? + // doesn't matter + lKeys.clear(); + } + + // <- SAFE + + // create a specialized enumeration helper, which + // provides the collected information outside. + // It hold a reference to us ... and call our container interface directly. + // be aware of some direct callbacks if it will be created :-) + + /* Note: It's not allowed to return NULL. Because an empty enumeration + transport the same information but make no trouble outside. + Further its easier to work directly with the return value + instead of checking of NULL returns! */ + + return new ::comphelper::OEnumerationByName(this, std::move(lKeys)); +} + + +void SAL_CALL BaseContainer::flush() +{ + // SAFE -> + osl::ClearableMutexGuard aLock(m_aMutex); + + if (!m_pFlushCache) + throw css::lang::WrappedTargetRuntimeException( + "Can not guarantee cache consistency. Special flush container does not exists!", + static_cast< OWeakObject* >(this), + css::uno::Any()); + + try + { + m_pFlushCache->flush(); + // Take over all changes into the global cache and + // forget the clone. + /* TODO + -think about me + If the global cache gets this information via listener, + we should remove this method! + */ + GetTheFilterCache().takeOver(*m_pFlushCache); + } + catch(const css::uno::Exception& ex) + { + // Don't remove the clone. May be the outside + // user wish to repair it now and calls flush() + // later again ... + + throw css::lang::WrappedTargetRuntimeException( "Flush rejected by internal container.", + static_cast< OWeakObject* >(this), + css::uno::Any(ex)); + } + + m_pFlushCache.reset(); + + aLock.clear(); + // <- SAFE + + // notify listener outside the lock! + // The used listener helper lives if we live + // and is threadsafe by itself. + // Further it's not a good idea to hold the own lock + // if an outside object is called :-) + css::lang::EventObject aSource (static_cast< css::util::XFlushable* >(this)); + comphelper::OInterfaceContainerHelper2* pContainer = m_lListener.getContainer(cppu::UnoType<css::util::XFlushListener>::get()); + if (!pContainer) + return; + + comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + // ... this pointer can be interesting to find out, where will be called as listener + // Don't optimize it to a direct iterator cast :-) + css::util::XFlushListener* pListener = static_cast<css::util::XFlushListener*>(pIterator.next()); + pListener->flushed(aSource); + } + catch(const css::uno::Exception&) + { + // ignore any "damaged" flush listener! + // May its remote reference is broken ... + pIterator.remove(); + } + } +} + + +void SAL_CALL BaseContainer::addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) +{ + // no locks necessary + // used helper lives if we live and is threadsafe by itself ... + m_lListener.addInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener); +} + + +void SAL_CALL BaseContainer::removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) +{ + // no locks necessary + // used helper lives if we live and is threadsafe by itself ... + m_lListener.removeInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener); +} + +} // namespace filter::config + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |