diff options
Diffstat (limited to 'filter/source/config/cache/basecontainer.cxx')
-rw-r--r-- | filter/source/config/cache/basecontainer.cxx | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/filter/source/config/cache/basecontainer.cxx b/filter/source/config/cache/basecontainer.cxx new file mode 100644 index 000000000000..800876ce1abd --- /dev/null +++ b/filter/source/config/cache/basecontainer.cxx @@ -0,0 +1,638 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include "basecontainer.hxx" +#include "constant.hxx" + +//_______________________________________________ +// includes +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/uno/Type.h> +#include <comphelper/enumhelper.hxx> +#include <osl/diagnose.h> + +//_______________________________________________ +// namespace + +#define LOAD_IMPLICIT + +namespace css = ::com::sun::star; + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +::salhelper::SingletonRef< FilterCache >* BaseContainer::m_pPerformanceOptimizer = 0; + +/*----------------------------------------------- + 03.03.2004 11:37 +-----------------------------------------------*/ +BaseContainer::BaseContainer() + : BaseLock ( ) + , m_rCache ( ) + , m_pFlushCache(NULL ) + , m_lListener (m_aLock) +{ + m_rCache->load(FilterCache::E_CONTAINS_STANDARD); + + // GLOBAL SAFE (!) -> ----------------------- + // TODO use rtl pattern to create it realy threadsafe! + ::osl::ResettableMutexGuard aGlobalLock(::osl::Mutex::getGlobalMutex()); + if (!m_pPerformanceOptimizer) + m_pPerformanceOptimizer = new ::salhelper::SingletonRef< FilterCache >(); + aGlobalLock.clear(); + // <- GLOBAL SAFE (!) ----------------------- +} + +/*----------------------------------------------- + 02.07.2003 10:16 +-----------------------------------------------*/ +BaseContainer::~BaseContainer() +{ +} + +/*----------------------------------------------- + 03.07.2003 11:16 +-----------------------------------------------*/ +void BaseContainer::init(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , + const ::rtl::OUString& sImplementationName, + const css::uno::Sequence< ::rtl::OUString >& lServiceNames , + FilterCache::EItemType eType ) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + m_sImplementationName = sImplementationName; + m_lServiceNames = lServiceNames ; + m_xSMGR = xSMGR ; + m_eType = eType ; + m_xRefreshBroadcaster = css::uno::Reference< css::util::XRefreshable >( + xSMGR->createInstance(SERVICE_FILTERCONFIGREFRESH), + css::uno::UNO_QUERY); + // <- SAFE +} + +/*----------------------------------------------- + 28.10.2003 09:04 +-----------------------------------------------*/ +void BaseContainer::impl_loadOnDemand() +{ +#ifdef LOAD_IMPLICIT + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // A generic container needs all items of a set of our cache! + // Of course it can block for a while, till the cache is realy filled. + // Note: dont 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_DETECTSERVICE : + eRequiredState = FilterCache::E_CONTAINS_DETECTSERVICES; + break; + + case FilterCache::E_FRAMELOADER : + eRequiredState = FilterCache::E_CONTAINS_FRAMELOADERS; + break; + + case FilterCache::E_CONTENTHANDLER : + eRequiredState = FilterCache::E_CONTAINS_CONTENTHANDLERS; + break; + } + + m_rCache->load(eRequiredState); + // <- SAFE +#endif +} + +/*----------------------------------------------- + 03.03.2004 12:18 +-----------------------------------------------*/ +void BaseContainer::impl_initFlushMode() + throw (css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + if (!m_pFlushCache) + m_pFlushCache = m_rCache->clone(); + if (!m_pFlushCache) + throw css::uno::RuntimeException( + ::rtl::OUString::createFromAscii("Cant create write copy of internal used cache on demand."), + dynamic_cast< css::container::XNameAccess* >(this)); + // <- SAFE +} + +/*----------------------------------------------- + 03.03.2004 12:11 +-----------------------------------------------*/ +FilterCache* BaseContainer::impl_getWorkingCache() const +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + if (m_pFlushCache) + return m_pFlushCache; + else + return &(*m_rCache); + // <- SAFE +} + +/*----------------------------------------------- + 03.07.2003 11:12 +-----------------------------------------------*/ +::rtl::OUString SAL_CALL BaseContainer::getImplementationName() + throw (css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + return m_sImplementationName; + // <- SAFE +} + +/*----------------------------------------------- + 03.07.2003 11:14 +-----------------------------------------------*/ +sal_Bool SAL_CALL BaseContainer::supportsService(const ::rtl::OUString& sServiceName) + throw (css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + sal_Int32 c = m_lServiceNames.getLength(); + const ::rtl::OUString* pNames = m_lServiceNames.getConstArray(); + for (sal_Int32 i=0; i<c; ++i) + { + if (pNames[i].equals(sServiceName)) + return sal_True; + } + return sal_False; + // <- SAFE +} + +/*----------------------------------------------- + 03.07.2003 11:12 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > SAL_CALL BaseContainer::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + return m_lServiceNames; + // <- SAFE +} + +/*----------------------------------------------- + 20.10.2003 11:39 +-----------------------------------------------*/ +void SAL_CALL BaseContainer::insertByName(const ::rtl::OUString& sItem , + const css::uno::Any& aValue) + throw (css::lang::IllegalArgumentException , + css::container::ElementExistException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ) +{ + if (!sItem.getLength()) + throw css::lang::IllegalArgumentException( + ::rtl::OUString::createFromAscii("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::ResettableMutexGuard aLock(m_aLock); + + // create write copy of used cache on demand ... + impl_initFlushMode(); + + FilterCache* pCache = impl_getWorkingCache(); + if (pCache->hasItem(m_eType, sItem)) + throw css::container::ElementExistException(::rtl::OUString(), static_cast< css::container::XNameContainer* >(this)); + pCache->setItem(m_eType, sItem, aItem); + + aLock.clear(); + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 03.03.2004 11:40 +-----------------------------------------------*/ +void SAL_CALL BaseContainer::removeByName(const ::rtl::OUString& sItem) + throw (css::container::NoSuchElementException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ) +{ + impl_loadOnDemand(); + + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + // create write copy of used cache on demand ... + impl_initFlushMode(); + + FilterCache* pCache = impl_getWorkingCache(); + pCache->removeItem(m_eType, sItem); // throw exceptions automaticly + + aLock.clear(); + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 03.03.2004 11:41 +-----------------------------------------------*/ +void SAL_CALL BaseContainer::replaceByName(const ::rtl::OUString& sItem , + const css::uno::Any& aValue) + throw (css::lang::IllegalArgumentException , + css::container::NoSuchElementException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ) +{ + if (!sItem.getLength()) + throw css::lang::IllegalArgumentException( + ::rtl::OUString::createFromAscii("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::ResettableMutexGuard aLock(m_aLock); + + // create write copy of used cache on demand ... + impl_initFlushMode(); + + FilterCache* pCache = impl_getWorkingCache(); + if (!pCache->hasItem(m_eType, sItem)) + throw css::container::NoSuchElementException(::rtl::OUString(), static_cast< css::container::XNameContainer* >(this)); + pCache->setItem(m_eType, sItem, aItem); + + aLock.clear(); + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 03.03.2004 11:44 +-----------------------------------------------*/ +css::uno::Any SAL_CALL BaseContainer::getByName(const ::rtl::OUString& sItem) + throw (css::container::NoSuchElementException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ) +{ + if (!sItem.getLength()) + throw css::container::NoSuchElementException( + ::rtl::OUString::createFromAscii("An empty item cant be part of this cache!"), + css::uno::Reference< css::uno::XInterface >(static_cast< css::container::XNameAccess* >(this), css::uno::UNO_QUERY)); + + css::uno::Any aValue; + + impl_loadOnDemand(); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + CacheItem aItem; + try + { + FilterCache* pCache = impl_getWorkingCache(); + aItem = pCache->getItem(m_eType, sItem); + pCache->addStatePropsToItem(m_eType, sItem, aItem); // add implicit props "Finalized"/"Mandatory" + } + catch(const css::container::NoSuchElementException& exNotExist) + { + throw exNotExist; + } + catch(const css::uno::Exception&) + { + // TODO invalid cache!? How should it be handled right? + aItem.clear(); + } + + aValue <<= aItem.getAsPackedPropertyValueList(); + // <- SAFE + + return aValue; +} + +/*----------------------------------------------- + 03.03.2004 11:46 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > SAL_CALL BaseContainer::getElementNames() + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< ::rtl::OUString > lNames; + + impl_loadOnDemand(); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + try + { + FilterCache* pCache = impl_getWorkingCache(); + OUStringList lKeys = pCache->getItemNames(m_eType); + lKeys >> lNames; + } + catch(const css::uno::Exception&) + { + // invalid cache!? + lNames.realloc(0); + } + + // <- SAFE + + return lNames; +} + +/*----------------------------------------------- + 03.03.2004 11:47 +-----------------------------------------------*/ +sal_Bool SAL_CALL BaseContainer::hasByName(const ::rtl::OUString& sItem) + throw (css::uno::RuntimeException) +{ + sal_Bool bHasOne = sal_False; + + impl_loadOnDemand(); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + try + { + FilterCache* pCache = impl_getWorkingCache(); + bHasOne = pCache->hasItem(m_eType, sItem); + } + catch(const css::uno::Exception&) + { + // invalid cache!? + bHasOne = sal_False; + } + + // <- SAFE + + return bHasOne; +} + +/*----------------------------------------------- + 02.07.2003 10:18 +-----------------------------------------------*/ +css::uno::Type SAL_CALL BaseContainer::getElementType() + throw (css::uno::RuntimeException) +{ + // no lock neccessary - because the type of our items + // is fix! no internal call or member needed ... + return ::getCppuType(static_cast< css::uno::Sequence< css::beans::PropertyValue >* >(NULL)); +} + +/*----------------------------------------------- + 03.03.2004 11:48 +-----------------------------------------------*/ +sal_Bool SAL_CALL BaseContainer::hasElements() + throw (css::uno::RuntimeException) +{ + sal_Bool bHasSome = sal_False; + + impl_loadOnDemand(); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + try + { + FilterCache* pCache = impl_getWorkingCache(); + bHasSome = pCache->hasItems(m_eType); + } + catch(const css::uno::Exception&) + { + // invalid cache?! + bHasSome = sal_False; + } + + // <- SAFE + + return bHasSome; +} + +/*----------------------------------------------- + 15.07.2003 09:21 +-----------------------------------------------*/ +css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const ::rtl::OUString& /* sQuery */ ) + throw (css::uno::RuntimeException) +{ + OSL_ENSURE(sal_False, "not pure virtual ... but not realy implemented .-)"); + + ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, css::uno::Sequence< ::rtl::OUString >()); + return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY); +} + +/*----------------------------------------------- + 15.07.2003 10:15 +-----------------------------------------------*/ +css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::container::XEnumeration > xEnum; + OUStringList lKeys; + + impl_loadOnDemand(); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + try + { + // convert the given properties first to our internal representation + CacheItem lProps; + lProps << lProperties; + + // 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, lProps); + } + catch(const css::uno::Exception&) + { + // invalid cache, internal failure, wrong conversion ...!? + // doesnt matter + lKeys.clear(); + } + + // <- SAFE + + // create a specialized enumeration helper, which + // provides the collected informations 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: Its not allowed to return NULL. Because an empty enumeration + transport the same information but make no trouble outside. + Further its easiear to work directly with the return value + instaed of checking of NULL returns! */ + + css::uno::Sequence< ::rtl::OUString > lSubSet; + lKeys >> lSubSet; + ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, lSubSet); + return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY); +} + +/*----------------------------------------------- + 07.03.2004 10:48 +-----------------------------------------------*/ +void SAL_CALL BaseContainer::flush() + throw (css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + if (!m_pFlushCache) + throw css::lang::WrappedTargetRuntimeException( + ::rtl::OUString::createFromAscii("Cant guarantee cache consistency. Special flush container does not exists!"), + dynamic_cast< css::container::XNameAccess* >(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! + */ + m_rCache->takeOver(*m_pFlushCache); + } + catch(const css::uno::Exception& ex) + { + // Dont remove the clone. May be the outside + // user whish to repair it now and calls flush() + // later again ... + + throw css::lang::WrappedTargetRuntimeException( + ::rtl::OUString::createFromAscii("Flush rejected by internal container."), + dynamic_cast< css::container::XNameAccess* >(this), + css::uno::makeAny(ex)); + } + + delete m_pFlushCache; + m_pFlushCache = NULL; + + css::uno::Reference< css::util::XRefreshable > xRefreshBroadcaster = m_xRefreshBroadcaster; + + aLock.clear(); + // <- SAFE + + if (xRefreshBroadcaster.is()) + xRefreshBroadcaster->refresh(); + + // notify listener outside the lock! + // The used listener helper lives if we live + // and is threadsafe by itself. + // Further its 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)); + ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL))); + if (pContainer) + { + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + // ... this pointer can be interesting to find out, where will be called as listener + // Dont optimize it to a direct iterator cast :-) + css::util::XFlushListener* pListener = (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(); + } + } + } +} + +/*----------------------------------------------- + 02.07.2003 12:16 +-----------------------------------------------*/ +void SAL_CALL BaseContainer::addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) + throw (css::uno::RuntimeException) +{ + // no locks neccessary + // used helper lives if we live and is threadsafe by itself ... + m_lListener.addInterface(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)), + xListener ); +} + +/*----------------------------------------------- + 02.07.2003 12:18 +-----------------------------------------------*/ +void SAL_CALL BaseContainer::removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) + throw (css::uno::RuntimeException) +{ + // no locks neccessary + // used helper lives if we live and is threadsafe by itself ... + m_lListener.removeInterface(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)), + xListener ); +} + + } // namespace config +} // namespace filter |