diff options
Diffstat (limited to 'filter/source/config/cache')
31 files changed, 10709 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 diff --git a/filter/source/config/cache/basecontainer.hxx b/filter/source/config/cache/basecontainer.hxx new file mode 100644 index 000000000000..e3730ce662e4 --- /dev/null +++ b/filter/source/config/cache/basecontainer.hxx @@ -0,0 +1,323 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef __FILTER_CONFIG_BASECONTAINER_HXX_ +#define __FILTER_CONFIG_BASECONTAINER_HXX_ + +//_______________________________________________ +// includes + +#include "filtercache.hxx" +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/util/XFlushable.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <salhelper/singletonref.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/weakref.hxx> +#include <rtl/ustring.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements the interface css::container::XNameContainer + on top of a FilterCache reference. + + @descr This class can be used as base for own service implementations, + which must provide read/write access to the filter configuration. + Parameters regulate read/write access, which sub set of informations + should be available etc. + + @attention The base class BaseLock must be the first of declared ones. + Otherwhise we cant be shure, that our own mutex member (which is + present by this base class!) was full initialized inside our own + ctor as first! + */ +class BaseContainer : public BaseLock + , public ::cppu::WeakImplHelper4< css::lang::XServiceInfo , + css::container::XNameContainer , // => XNameReplace => XNameAccess => XElementAccess + css::container::XContainerQuery , + css::util::XFlushable > +{ + //------------------------------------------- + // member + + protected: + + /** @short reference to an uno service manager, which can be used + to create own needed services. */ + css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR; + + // TODO + css::uno::WeakReference< css::util::XRefreshable > m_xRefreshBroadcaster; + + /** @short the implementation name of our derived class, which we provide + at the interface XServiceInfo of our class ... */ + ::rtl::OUString m_sImplementationName; + + /** @short the list of supported uno service names of our derived class, which we provide + at the interface XServiceInfo of our class ... */ + css::uno::Sequence< ::rtl::OUString > m_lServiceNames; + + /** @short reference(!) to a singleton filter cache implementation, + which is used to work with the underlying configuration. */ + ::salhelper::SingletonRef< FilterCache > m_rCache; + + /** @short local filter cache, which is used to collect changes on the + filter configuration first and flush it later. + + @descr Normaly this member isnt used nor initialized. Thats true, + if this container is used for reading only. The first write access + (e.g. by calling insertByName()) creates a copy of the current + global cache m_rCache to initialize the m_pFlushCache member. + + Afterwards only the flush cache copy is used. Inside flush() this + copy will be removed and m_rCache can be used again. + + m_pFlushCache and m_rCache must not be synchronized manually here. + m_rCache listen on the global configuration, where m_pFlushCache + write its data. m_rCache update itself automaticly. + */ + FilterCache* m_pFlushCache; + + /** @short specify, which sub container of the used filter cache + must be wrapped by this container interface. */ + FilterCache::EItemType m_eType; + + /** @short holds all listener, which are registered at this instance. */ + ::cppu::OMultiTypeInterfaceContainerHelper m_lListener; + + /** @short hold at least on filter cache instance alive and + prevent he office from unloading this cache if no filter + is currently used.*/ + static ::salhelper::SingletonRef< FilterCache >* m_pPerformanceOptimizer; + + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short standard ctor. + + @descr Because mostly this class is used as base class for own service + implementations in combination with a ImplInheritanceHelper2 template ... + there is no way to provide some initializing data through the ctor :-( + This base class will be created inside its default ctor and must be + initialized with its needed parameters explicitly by calling: "init()". + + @see init() + */ + BaseContainer(); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~BaseContainer(); + + //--------------------------------------- + + /** @short initialize this generic intsnace with some specialized values + from our derived object. + + @descr Because an outside class must use ImplInheritanceHelper2 template to + use us a base class ... and there is no way to pass such initializing + parameters trough a required default ctor ... we must be initialized + by this special method. Of course this method must be called first before + any other interface method is used. + + @param xSMGR + reference to the uno service manager, which created this service instance. + + @param sImplementationName + the implementation name of our derived class, which we provide + at the interface XServiceInfo of our class ... + + @param lServiceNames + the list of supported uno service names of our derived class, which we provide + at the interface XServiceInfo of our class ... + + @param eType + specify, which sub container of the used filter cache + must be wrapped by this container interface. + */ + virtual void init(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , + const ::rtl::OUString& sImplementationName, + const css::uno::Sequence< ::rtl::OUString >& lServiceNames , + FilterCache::EItemType eType ); + + //------------------------------------------- + // helper + + protected: + + //--------------------------------------- + + /** @short check if the underlying configuration data was already loaded + and do it if neccessary automaticly. + */ + void impl_loadOnDemand(); + + //--------------------------------------- + + /** @short it creates the global instance m_pFilterCache, which is a copy + of the global instance m_rCache, and will be used to change the + configuration. + + @descr If no exception occures, its guaranteed, that the member m_rFlushCache + was initialized right and can be used further. + */ + void impl_initFlushMode() + throw (css::uno::RuntimeException); + + //--------------------------------------- + + /** @short returns a pointer to the current used cache member. + + @descr Its a point to the FilterCache instance behind m_pFlushCache + or m_rCache. + + @note The lifetime of this pointer is restricted to the time, where + the mutex of this BaseContainer instance is locked. + Otherwhise may be the interface method flush() will destroy + m_pFlushCache and the here returned pointer will be invalid! + + Use: + + Guard aLock(m_aLock); + FilterCache* p = impl_getWorkingCache(); + p->doSomething(); + aLock.clear(); + // after this point p cant b e guaranteed any longer! + */ + FilterCache* impl_getWorkingCache() const; + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // XServiceInfo + + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& sServiceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (css::uno::RuntimeException); + + //--------------------------------------- + // XNameContainer + + virtual void SAL_CALL insertByName(const ::rtl::OUString& sItem , + const css::uno::Any& aValue) + throw (css::lang::IllegalArgumentException , + css::container::ElementExistException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ); + + virtual void SAL_CALL removeByName(const ::rtl::OUString& sItem) + throw (css::container::NoSuchElementException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ); + + //--------------------------------------- + // XNameReplace + + virtual void SAL_CALL replaceByName(const ::rtl::OUString& sItem , + const css::uno::Any& aValue) + throw (css::lang::IllegalArgumentException , + css::container::NoSuchElementException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ); + + //--------------------------------------- + // XElementAccess + + virtual css::uno::Any SAL_CALL getByName(const ::rtl::OUString& sItem) + throw (css::container::NoSuchElementException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasByName(const ::rtl::OUString& sItem) + throw (css::uno::RuntimeException); + + virtual css::uno::Type SAL_CALL getElementType() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasElements() + throw (css::uno::RuntimeException); + + //--------------------------------------- + // XContainerQuery + + // must be implemented realy by derived class ... + // We implement return of an empty result here only! + // But we show an assertion :-) + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery(const ::rtl::OUString& sQuery) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) + throw (css::uno::RuntimeException); + + //--------------------------------------- + // XFlushable + + virtual void SAL_CALL flush() + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) + throw (css::uno::RuntimeException); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_BASECONTAINER_HXX_ diff --git a/filter/source/config/cache/cacheitem.cxx b/filter/source/config/cache/cacheitem.cxx new file mode 100644 index 000000000000..c752516df10f --- /dev/null +++ b/filter/source/config/cache/cacheitem.cxx @@ -0,0 +1,443 @@ +/************************************************************************* + * + * 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 "cacheitem.hxx" +#include "macros.hxx" +#include "constant.hxx" + +//_______________________________________________ +// includes +#include <com/sun/star/uno/Sequence.h> + +#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_Hpp_ +#include <com/sun/star/beans/PropertyValue.hpp> +#endif + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 04.11.2003 09:27 +-----------------------------------------------*/ +CacheItem::CacheItem() + : SequenceAsHashMap() +{ +} + +/*----------------------------------------------- + 26.06.2003 11:37 +-----------------------------------------------*/ +void CacheItem::update(const CacheItem& rUpdateItem) +{ + for(const_iterator pItUpdate = rUpdateItem.begin(); + pItUpdate != rUpdateItem.end() ; + ++pItUpdate ) + { + iterator pItThis = this->find(pItUpdate->first); + if (pItThis == this->end()) + (*this)[pItUpdate->first] = pItUpdate->second; // add new prop + else + pItThis->second = pItUpdate->second; // change value of existing prop + } +} + +/*----------------------------------------------- + 26.11.2003 13:27 +-----------------------------------------------*/ +void CacheItem::validateUINames(const ::rtl::OUString& sActLocale) +{ + if (!sActLocale.getLength()) + return; + + // 1) check UINames first + const_iterator pUINames = find(PROPNAME_UINAMES); + const_iterator pUIName = find(PROPNAME_UINAME ); + + ::comphelper::SequenceAsHashMap lUINames; + if (pUINames != end()) + lUINames << pUINames->second; + + ::rtl::OUString sUIName; + if (pUIName != end()) + pUIName->second >>= sUIName; + + if (sUIName.getLength()) + { + // 1a) set UIName inside list of UINames for current locale + lUINames[sActLocale] <<= sUIName; + } + else if (lUINames.size()>0) + { + // 1b) or get it from this list, if it not exist! + lUINames[sActLocale] >>= sUIName; + } + + (*this)[PROPNAME_UINAMES] <<= lUINames.getAsConstPropertyValueList(); + (*this)[PROPNAME_UINAME ] <<= sUIName; +} + +/*----------------------------------------------- + 12.01.2004 13:32 +-----------------------------------------------*/ +css::uno::Sequence< css::beans::PropertyValue > CacheItem::getAsPackedPropertyValueList() +{ + sal_Int32 c = (sal_Int32)size(); + sal_Int32 i = 0; + + css::uno::Sequence< css::beans::PropertyValue > lList(c); + css::beans::PropertyValue* pList = lList.getArray(); + + for (const_iterator pProp = begin(); + pProp != end() ; + ++pProp ) + { + const ::rtl::OUString& rName = pProp->first; + const css::uno::Any& rValue = pProp->second; + + if (!rValue.hasValue()) + continue; + + pList[i].Name = rName ; + pList[i].Value = rValue; + ++i; + } + lList.realloc(i); + + return lList; +} + +/*----------------------------------------------- + 17.07.2003 08:27 +-----------------------------------------------*/ +sal_Bool isSubSet(const css::uno::Any& aSubSet, + const css::uno::Any& aSet ) +{ + css::uno::Type aT1 = aSubSet.getValueType(); + css::uno::Type aT2 = aSet.getValueType(); + + if (!aT1.equals(aT2)) + { + _FILTER_CONFIG_LOG_("isSubSet() ... types of any values are different => return FALSE\n") + return sal_False; + } + + css::uno::TypeClass aTypeClass = aT1.getTypeClass(); + switch(aTypeClass) + { + //--------------------------------------- + case css::uno::TypeClass_BOOLEAN : + case css::uno::TypeClass_BYTE : + case css::uno::TypeClass_SHORT : + case css::uno::TypeClass_UNSIGNED_SHORT : + case css::uno::TypeClass_LONG : + case css::uno::TypeClass_UNSIGNED_LONG : + case css::uno::TypeClass_HYPER : + case css::uno::TypeClass_UNSIGNED_HYPER : + case css::uno::TypeClass_FLOAT : + case css::uno::TypeClass_DOUBLE : + { + sal_Bool bIs = (aSubSet == aSet); + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for atomic types => return %s\n", bIs ? "TRUE" : "FALSE") + return bIs; + } + + //--------------------------------------- + case css::uno::TypeClass_STRING : + { + ::rtl::OUString v1; + ::rtl::OUString v2; + + if ( + (aSubSet >>= v1) && + (aSet >>= v2) + ) + { + sal_Bool bIs = (v1.equals(v2)); + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for string types => return %s\n", bIs ? "TRUE" : "FALSE") + return bIs; + } + } + break; + + //--------------------------------------- + case css::uno::TypeClass_ANY : + { + css::uno::Any v1; + css::uno::Any v2; + + if ( + (aSubSet >>= v1) && + (aSet >>= v2) + ) + { + sal_Bool bIs = (isSubSet(v1, v2)); + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for packed any types => return %s\n", bIs ? "TRUE" : "FALSE") + return bIs; + } + } + break; + + //--------------------------------------- + case css::uno::TypeClass_STRUCT : + { + css::beans::PropertyValue p1; + css::beans::PropertyValue p2; + + if ( + (aSubSet >>= p1) && + (aSet >>= p2) + ) + { + sal_Bool bIs = ( + (p1.Name.equals(p2.Name) ) && + (isSubSet(p1.Value, p2.Value)) + ); + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for structured types [PropertyValue] => return %s\n", bIs ? "TRUE" : "FALSE") + return bIs; + } + + css::beans::NamedValue n1; + css::beans::NamedValue n2; + + if ( + (aSubSet >>= n1) && + (aSet >>= n2) + ) + { + sal_Bool bIs = ( + (n1.Name.equals(n2.Name) ) && + (isSubSet(n1.Value, n2.Value)) + ); + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for structured types [NamedValue] => return %s\n", bIs ? "TRUE" : "FALSE") + return bIs; + } + } + break; + + //--------------------------------------- + case css::uno::TypeClass_SEQUENCE : + { + css::uno::Sequence< ::rtl::OUString > uno_s1; + css::uno::Sequence< ::rtl::OUString > uno_s2; + + if ( + (aSubSet >>= uno_s1) && + (aSet >>= uno_s2) + ) + { + OUStringList stl_s1(uno_s1); + OUStringList stl_s2(uno_s2); + + for (OUStringList::const_iterator it1 = stl_s1.begin(); + it1 != stl_s1.end() ; + ++it1 ) + { + if (::std::find(stl_s2.begin(), stl_s2.end(), *it1) == stl_s2.end()) + { + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [OUString] ... dont found \"%s\" => return FALSE\n", _FILTER_CONFIG_TO_ASCII_(*it1)) + return sal_False; + } + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [OUString] ... found \"%s\" => continue loop\n", _FILTER_CONFIG_TO_ASCII_(*it1)) + } + _FILTER_CONFIG_LOG_("isSubSet() ... check for list types [OUString] => return TRUE\n") + return sal_True; + } + + css::uno::Sequence< css::beans::PropertyValue > uno_p1; + css::uno::Sequence< css::beans::PropertyValue > uno_p2; + + if ( + (aSubSet >>= uno_p1) && + (aSet >>= uno_p2) + ) + { + ::comphelper::SequenceAsHashMap stl_p1(uno_p1); + ::comphelper::SequenceAsHashMap stl_p2(uno_p2); + + for (::comphelper::SequenceAsHashMap::const_iterator it1 = stl_p1.begin(); + it1 != stl_p1.end() ; + ++it1 ) + { + ::comphelper::SequenceAsHashMap::const_iterator it2 = stl_p2.find(it1->first); + if (it2 == stl_p2.end()) + { + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [PropertyValue] ... dont found \"%s\" => return FALSE\n", _FILTER_CONFIG_TO_ASCII_(it1->first)) + return sal_False; + } + if (!isSubSet(it1->second, it2->second)) + { + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [PropertyValue] ... found \"%s\" but has different value => return FALSE\n", _FILTER_CONFIG_TO_ASCII_(it1->first)) + return sal_False; + } + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [PropertyValue] ... found \"%s\" with right value => continue loop\n", _FILTER_CONFIG_TO_ASCII_(it1->first)) + } + _FILTER_CONFIG_LOG_("isSubSet() ... check for list types [PropertyValue] => return TRUE\n") + return sal_True; + } + + css::uno::Sequence< css::beans::NamedValue > uno_n1; + css::uno::Sequence< css::beans::NamedValue > uno_n2; + + if ( + (aSubSet >>= uno_n1) && + (aSet >>= uno_n2) + ) + { + ::comphelper::SequenceAsHashMap stl_n1(uno_n1); + ::comphelper::SequenceAsHashMap stl_n2(uno_n2); + + for (::comphelper::SequenceAsHashMap::const_iterator it1 = stl_n1.begin(); + it1 != stl_n1.end() ; + ++it1 ) + { + ::comphelper::SequenceAsHashMap::const_iterator it2 = stl_n2.find(it1->first); + if (it2 == stl_n2.end()) + { + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [NamedValue] ... dont found \"%s\" => return FALSE\n", _FILTER_CONFIG_TO_ASCII_(it1->first)) + return sal_False; + } + if (!isSubSet(it1->second, it2->second)) + { + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [NamedValue] ... found \"%s\" but has different value => return FALSE\n", _FILTER_CONFIG_TO_ASCII_(it1->first)) + return sal_False; + } + _FILTER_CONFIG_LOG_1_("isSubSet() ... check for list types [NamedValue] ... found \"%s\" with right value => continue loop\n", _FILTER_CONFIG_TO_ASCII_(it1->first)) + } + _FILTER_CONFIG_LOG_("isSubSet() ... check for list types [NamedValue] => return TRUE\n") + return sal_True; + } + } + break; +/* + case css::uno::TypeClass_CHAR : + case css::uno::TypeClass_VOID : + case css::uno::TypeClass_TYPE : + case css::uno::TypeClass_ENUM : + case css::uno::TypeClass_TYPEDEF : + case css::uno::TypeClass_UNION : + case css::uno::TypeClass_EXCEPTION : + case css::uno::TypeClass_ARRAY : + case css::uno::TypeClass_INTERFACE : + case css::uno::TypeClass_SERVICE : + case css::uno::TypeClass_MODULE : + case css::uno::TypeClass_INTERFACE_METHOD : + case css::uno::TypeClass_INTERFACE_ATTRIBUTE : + case css::uno::TypeClass_UNKNOWN : + case css::uno::TypeClass_PROPERTY : + case css::uno::TypeClass_CONSTANT : + case css::uno::TypeClass_CONSTANTS : + case css::uno::TypeClass_SINGLETON : +*/ + default: break; + } + + OSL_ENSURE(sal_False, "isSubSet() ... this point should not be reached!"); + return sal_False; +} + +/*----------------------------------------------- + 14.07.2003 10:24 +-----------------------------------------------*/ +sal_Bool CacheItem::haveProps(const CacheItem& lProps) const +{ + for (const_iterator pIt = lProps.begin(); + pIt != lProps.end() ; + ++pIt ) + { + // i) one required property does not exist at this item => return false + const_iterator pItThis = this->find(pIt->first); + if (pItThis == this->end()) + { + _FILTER_CONFIG_LOG_1_("CacheItem::haveProps() ... dont found \"%s\" => return FALSE\n", _FILTER_CONFIG_TO_ASCII_(pIt->first)) + return sal_False; + } + + // ii) one item does not have the right value => return false + if (!isSubSet(pIt->second, pItThis->second)) + { + _FILTER_CONFIG_LOG_1_("CacheItem::haveProps() ... item \"%s\" has different value => return FALSE\n", _FILTER_CONFIG_TO_ASCII_(pIt->first)) + return sal_False; + } + } + + // this method was not breaked before => + // the given property set seems to match with our + // own properties in its minimum => return TRUE + _FILTER_CONFIG_LOG_("CacheItem::haveProps() ... => return TRUE\n") + return sal_True; +} + +/*----------------------------------------------- + 14.07.2003 10:43 +-----------------------------------------------*/ +sal_Bool CacheItem::dontHaveProps(const CacheItem& lProps) const +{ + for (const_iterator pIt = lProps.begin(); + pIt != lProps.end() ; + ++pIt ) + { + // i) one item does not exists in general + // => continue with next one, because + // "excluding" means ... "dont have it". + // And "not exists" match to "dont have it". + const_iterator pItThis = this->find(pIt->first); + if (pItThis == this->end()) + { + _FILTER_CONFIG_LOG_1_("CacheItem::dontHaveProps() ... not found \"%s\" => continue loop!\n", _FILTER_CONFIG_TO_ASCII_(pIt->first)) + continue; + } + + // ii) one item have the right value => return false + // because this item has the requested property ... + // But we checked for "dont have it" here. + if (isSubSet(pIt->second, pItThis->second)) + { + _FILTER_CONFIG_LOG_1_("CacheItem::dontHaveProps() ... item \"%s\" has same value => return FALSE!\n", _FILTER_CONFIG_TO_ASCII_(pIt->first)) + return sal_False; + } + } + + // this method was not breaked before => + // That means: this item has no matching property + // of the given set. It "dont have" it ... => return true. + _FILTER_CONFIG_LOG_("CacheItem::dontHaveProps() ... => return TRUE\n") + return sal_True; +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/cacheitem.hxx b/filter/source/config/cache/cacheitem.hxx new file mode 100644 index 000000000000..793a5f370cf9 --- /dev/null +++ b/filter/source/config/cache/cacheitem.hxx @@ -0,0 +1,261 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __FILTER_CONFIG_CACHEITEM_HXX_ +#define __FILTER_CONFIG_CACHEITEM_HXX_ + +//_______________________________________________ +// includes + +#include <hash_map> +#include <deque> +#include <list> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <comphelper/sequenceasvector.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <osl/mutex.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/** @short Must be used as first derived base class + to get a full initialized mutex member, + which can be used during the ctor runs too! + */ +struct BaseLock +{ + public: + + // must be mutable to be useable in const environments too! + mutable ::osl::Mutex m_aLock; +}; + + +typedef ::comphelper::SequenceAsVector< ::rtl::OUString > OUStringList; + +//_______________________________________________ + +/** @short represent an item of a FilterCache + instance. + + @descr This class is not threadsafe tp perform + operations, which use many instances of + this class! Synchronizations must be done outside. + */ +class CacheItem : public ::comphelper::SequenceAsHashMap +{ + //------------------------------------------- + public: + + //--------------------------------------- + /** @short creates an empty item. + */ + CacheItem(); + + //--------------------------------------- + + /** @short update only properties, which are given by the + specified rItem. + + @descr Update means: - add new properties + - change existing values + + @param rUpdateItem + another cache item, which contains some special + properties, which should by used for updating + this one. + */ + void update(const CacheItem& rUpdateItem); + + //--------------------------------------- + + /** @short check, if the given properties exists + at this item. + + @descr All properties are compared in its minimum. + E.g: string lists => only the requested items + are checked. Additional existing items are ignored. + + @param lProps + contains all properties, which must exist at this item. + + @return TRUE if all given properties exists + at this item; FALSE otherwhise. + */ + sal_Bool haveProps(const CacheItem& lProps) const; + + //--------------------------------------- + + /** @short check, if the given properties dont exists + at this item. + + @descr All properties are compared in its minimum. + E.g: string lists => only the requested items + are checked. Additional existing items are ignored. + + @param lProps + contains all properties, which should not exists at this item. + + @return FALSE if at least on property exists at this item(!); + TRUE otherwhise. + */ + sal_Bool dontHaveProps(const CacheItem& lProps) const; + + //--------------------------------------- + + /** @short check, if the given properties dont exists + at this item. + + @descr All properties are compared in its minimum. + E.g: string lists => only the specified items + are checked. Additional existing items are ignored. + + @param lProps + contains all properties, which should be checked. + + @return TRUE if all given properties dont exists + at this item; FALSE otherwhise. + */ + sal_Bool excludeProps(const CacheItem& lProps) const; + + //--------------------------------------- + + /** @short because we know two UIName properties + (a list with all locales and the value + for the current locale only), we must be shure + that the correspond together. + + @param sActLocale + must specify the current office locale. + Its needed to adress the UIName property inside + the list of possible ones. + */ + void validateUINames(const ::rtl::OUString& sActLocale); + + //--------------------------------------- + + /** @short convert this structure to a seq< PropertyValue > + and ignore all empty properties! + + @descr Normaly the converter routines of the base class + SequenceAsHashMap do this job already. + But it doesnt provide a "pack" mechanism to + ignore properties with empty (means "void") values. + + @return css::uno::Sequence< css::beans::PropertyValue > + as a list of all properties of this cacheitem, + where empty properties was removed. + */ + css::uno::Sequence< css::beans::PropertyValue > getAsPackedPropertyValueList(); +}; + +//_______________________________________________ + +/** @short represent an item list of a FilterCache + instance. + */ +typedef ::std::hash_map< ::rtl::OUString , + CacheItem , + ::rtl::OUStringHash , + ::std::equal_to< ::rtl::OUString > > CacheItemList; + +//_______________________________________________ + +/** @short supports registration of multiple key to + another string information. + + @descr E.g. a list of internal type names can be registered + to an extension. Organization as an hash makes it + faster then searching inside vectors. + + On the other side e.g. URLPattern cant be realy adressed + by a hash value ... because the use wildcards. But + there we need key-value pairs too, which cant be provided + by a pur vector! + */ +typedef ::std::hash_map< ::rtl::OUString , + OUStringList , + ::rtl::OUStringHash , + ::std::equal_to< ::rtl::OUString > > CacheItemRegistration; + +//_______________________________________________ + +/** @short is used to collect all matching types of an URL + during type detection. + + @descr Every type in this list is combined with an information, + which property matched to the given URL. The user of this + structure can decide then, if a deep detection should be + supressed e.g. if an URLPattern was used. + */ +struct FlatDetectionInfo +{ + // the internal type name + ::rtl::OUString sType; + + // this type was found by a matching the URL extension + sal_Bool bMatchByExtension; + + // this type was found by a matching URL Pattern + sal_Bool bMatchByPattern; + + // the user selected this type explicitly + sal_Bool bPreselectedAsType; + + // the user selected this type implicit by selecting a corresponding filter + sal_Bool bPreselectedByFilter; + + // the user selected this type implicit by selecting a corresponding office module + sal_Bool bPreselectedByDocumentService; + + FlatDetectionInfo() + : sType (::rtl::OUString()) + , bMatchByExtension (sal_False ) + , bMatchByPattern (sal_False ) + , bPreselectedAsType (sal_False ) + , bPreselectedByFilter (sal_False ) + , bPreselectedByDocumentService(sal_False ) + {} +}; + +typedef ::std::list< FlatDetectionInfo > FlatDetection; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_CACHEITEM_HXX_ diff --git a/filter/source/config/cache/cacheupdatelistener.cxx b/filter/source/config/cache/cacheupdatelistener.cxx new file mode 100644 index 000000000000..90bd89c9d864 --- /dev/null +++ b/filter/source/config/cache/cacheupdatelistener.cxx @@ -0,0 +1,246 @@ +/************************************************************************* + * + * 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 "cacheupdatelistener.hxx" +#include "constant.hxx" + +//_______________________________________________ +// includes +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +#include <salhelper/singletonref.hxx> +#include <unotools/configpathes.hxx> +#include <rtl/ustring.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 05.03.2004 08:36 +-----------------------------------------------*/ +CacheUpdateListener::CacheUpdateListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , + const css::uno::Reference< css::uno::XInterface >& xConfigAccess, + FilterCache::EItemType eConfigType ) + : BaseLock ( ) + , m_xSMGR (xSMGR ) + , m_rCache ( ) + , m_xConfig (xConfigAccess) + , m_eConfigType(eConfigType ) +{ +} + +/*----------------------------------------------- + 05.03.2004 08:37 +-----------------------------------------------*/ +CacheUpdateListener::~CacheUpdateListener() +{ +} + +/*----------------------------------------------- + 07.03.2004 07:59 +-----------------------------------------------*/ +void CacheUpdateListener::startListening() +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::util::XChangesNotifier > xNotifier(m_xConfig, css::uno::UNO_QUERY); + aLock.clear(); + // <- SAFE + + if (!xNotifier.is()) + return; + + css::uno::Reference< css::util::XChangesListener > xThis(static_cast< css::util::XChangesListener* >(this), css::uno::UNO_QUERY_THROW); + xNotifier->addChangesListener(xThis); + +/* + css::uno::Reference< css::container::XContainer > xNotifier(xConfigAccess, css::uno::UNO_QUERY); + if (!xNotifier.is()) + return; + + css::uno::Reference< css::container::XContainerListener > xThis(static_cast< css::container::XContainerListener* >(this), css::uno::UNO_QUERY); + xNotifier->addContainerListener(xThis); +*/ +} + +/*----------------------------------------------- + 07.03.2004 07:59 +-----------------------------------------------*/ +void CacheUpdateListener::stopListening() +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::util::XChangesNotifier > xNotifier(m_xConfig, css::uno::UNO_QUERY); + aLock.clear(); + // <- SAFE + + if (!xNotifier.is()) + return; + + css::uno::Reference< css::util::XChangesListener > xThis(static_cast< css::util::XChangesListener* >(this), css::uno::UNO_QUERY); + xNotifier->removeChangesListener(xThis); + +/* + css::uno::Reference< css::container::XContainer > xNotifier(xConfigAccess, css::uno::UNO_QUERY); + if (!xNotifier.is()) + return; + + css::uno::Reference< css::container::XContainerListener > xThis(static_cast< css::container::XContainerListener* >(this), css::uno::UNO_QUERY); + xNotifier->removeContainerListener(xThis); +*/ +} + +/*----------------------------------------------- + 07.03.2004 08:17 +-----------------------------------------------*/ +void SAL_CALL CacheUpdateListener::changesOccurred(const css::util::ChangesEvent& aEvent) + throw(css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // disposed ? + if ( ! m_xConfig.is()) + return; + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + FilterCache::EItemType eType = m_eConfigType; + + aLock.clear(); + // <- SAFE + + OUStringList lChangedItems; + sal_Int32 c = aEvent.Changes.getLength(); + sal_Int32 i = 0; + + for (i=0; i<c; ++i) + { + const css::util::ElementChange& aChange = aEvent.Changes[i]; + + ::rtl::OUString sOrgPath ; + ::rtl::OUString sTempPath; + + ::rtl::OUString sProperty; + ::rtl::OUString sNode ; + ::rtl::OUString sLocale ; + + /* at least we must be able to retrieve 2 path elements + But sometimes the original path can contain 3 of them ... in case + a localized value was changed. + => + 1) Filters/Filter["filtername"]/Property + 2) Filters/Filter["filtername"]/LocalizedProperty/Locale + */ + + aChange.Accessor >>= sOrgPath; + if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sLocale)) + continue; + sOrgPath = sTempPath; + if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sProperty)) + { + sNode = sLocale; + sProperty = ::rtl::OUString(); + sLocale = ::rtl::OUString(); + } + else + { + sOrgPath = sTempPath; + if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sNode)) + { + sNode = sProperty; + sProperty = sLocale; + sLocale = ::rtl::OUString(); + } + } + + if ( ! sNode.getLength() ) + continue; + + OUStringList::const_iterator pIt = ::std::find(lChangedItems.begin(), lChangedItems.end(), sNode); + if (pIt == lChangedItems.end()) + lChangedItems.push_back(sNode); + } + + sal_Bool bNotifyRefresh = sal_False; + OUStringList::const_iterator pIt; + for ( pIt = lChangedItems.begin(); + pIt != lChangedItems.end() ; + ++pIt ) + { + const ::rtl::OUString& sItem = *pIt; + try + { + m_rCache->refreshItem(eType, sItem); + } + catch(const css::container::NoSuchElementException&) + { + // can be ignored! Because we must be aware that + // sItem was removed from the condfiguration and we forced an update of the cache. + // But we know, that the cache is up-to-date know and has thrown this exception afterwards .-) + } + // NO FLUSH! Otherwhise we start a never ending story here .-) + bNotifyRefresh = sal_True; + } + + // notify sfx cache about the changed filter cache .-) + if (bNotifyRefresh) + { + css::uno::Reference< css::util::XRefreshable > xRefreshBroadcaster( + xSMGR->createInstance(SERVICE_FILTERCONFIGREFRESH), + css::uno::UNO_QUERY); + if (xRefreshBroadcaster.is()) + xRefreshBroadcaster->refresh(); + } +} + +/*----------------------------------------------- + 05.03.2004 08:44 +-----------------------------------------------*/ +void SAL_CALL CacheUpdateListener::disposing(const css::lang::EventObject& aEvent) + throw(css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + if (aEvent.Source == m_xConfig) + m_xConfig.clear(); + aLock.clear(); + // <- SAFE +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/cacheupdatelistener.hxx b/filter/source/config/cache/cacheupdatelistener.hxx new file mode 100644 index 000000000000..8e75e4304bf2 --- /dev/null +++ b/filter/source/config/cache/cacheupdatelistener.hxx @@ -0,0 +1,147 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef __FILTER_CONFIG_CACHEUPDATELISTENER_HXX_ +#define __FILTER_CONFIG_CACHEUPDATELISTENER_HXX_ + +//_______________________________________________ +// includes + +#include "filtercache.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/util/XChangesListener.hpp> +#include <salhelper/singletonref.hxx> +#include <cppuhelper/implbase1.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements a listener, which will update the + global filter cache, if the underlying configuration + wa changed by other processes. + */ +class CacheUpdateListener : public BaseLock // must be the first one to guarantee right initialized mutex member! + , public ::cppu::WeakImplHelper1< css::util::XChangesListener > +{ + //------------------------------------------- + // member + + private: + + /** @short reference to an uno service manager, which can be used + to create own needed services. */ + css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR; + + /** @short reference to the singleton(!) filter cache implementation, + which should be updated by this thread. */ + ::salhelper::SingletonRef< FilterCache > m_rCache; + + /** @short holds the configuration access, where we listen alive. */ + css::uno::Reference< css::uno::XInterface > m_xConfig; + + /** @short every instance of this update listener listen on + a special sub set of the filter configuration. + So it should know, which type of configuration entry + it must put into the filter cache, if the configuration notifys changes ... */ + FilterCache::EItemType m_eConfigType; + + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short initialize new instance of this class. + + @descr Listening wont be started here. It can be done + by calling startListening() on this instance. + + @see startListening() + + @param xSMGR + reference to a service manager, which can be used to create + own needed uno services. + + @param xConfigAccess + the configuration access, where this instance should listen for changes. + + @param eConfigType + specify the type of configuration. + */ + CacheUpdateListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR , + const css::uno::Reference< css::uno::XInterface >& xConfigAccess, + FilterCache::EItemType eConfigType ); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~CacheUpdateListener(); + + //--------------------------------------- + + /** @short starts listening. + */ + virtual void startListening(); + + //--------------------------------------- + + /** @short stop listening. + */ + virtual void stopListening(); + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // XChangesListener + + virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent) + throw(css::uno::RuntimeException); + + //--------------------------------------- + // lang.XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) + throw(css::uno::RuntimeException); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_CACHEUPDATELISTENER_HXX_ diff --git a/filter/source/config/cache/configflush.cxx b/filter/source/config/cache/configflush.cxx new file mode 100644 index 000000000000..e97df2a7f40d --- /dev/null +++ b/filter/source/config/cache/configflush.cxx @@ -0,0 +1,168 @@ +/************************************************************************* + * + * 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 "configflush.hxx" +#include "constant.hxx" + +//_______________________________________________ +// includes +#include <osl/diagnose.h> + +//_______________________________________________ +// namespace + +namespace css = ::com::sun::star; + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +//----------------------------------------------- +ConfigFlush::ConfigFlush(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) + : BaseLock ( ) + , m_xSMGR (xSMGR ) + , m_lListener(m_aLock) +{ +} + +//----------------------------------------------- +ConfigFlush::~ConfigFlush() +{ +} + +//----------------------------------------------- +::rtl::OUString SAL_CALL ConfigFlush::getImplementationName() + throw (css::uno::RuntimeException) +{ + return impl_getImplementationName(); + // <- SAFE +} + +//----------------------------------------------- +sal_Bool SAL_CALL ConfigFlush::supportsService(const ::rtl::OUString& sServiceName) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< ::rtl::OUString > lServiceNames = impl_getSupportedServiceNames(); + sal_Int32 c = lServiceNames.getLength(); + const ::rtl::OUString* pNames = lServiceNames.getConstArray(); + for (sal_Int32 i=0; i<c; ++i) + { + if (pNames[i].equals(sServiceName)) + return sal_True; + } + return sal_False; +} + +//----------------------------------------------- +css::uno::Sequence< ::rtl::OUString > SAL_CALL ConfigFlush::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return impl_getSupportedServiceNames(); +} + +//----------------------------------------------- +void SAL_CALL ConfigFlush::refresh() + throw(css::uno::RuntimeException) +{ + // 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::XRefreshable* >(this)); + ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(::getCppuType(static_cast< css::uno::Reference< css::util::XRefreshListener >* >(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::XRefreshListener* pListener = (css::util::XRefreshListener*)pIterator.next(); + pListener->refreshed(aSource); + } + catch(const css::uno::Exception&) + { + // ignore any "damaged" flush listener! + // May its remote reference is broken ... + pIterator.remove(); + } + } + } +} + +//----------------------------------------------- +void SAL_CALL ConfigFlush::addRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& 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::XRefreshListener >* >(NULL)), + xListener); +} + +//----------------------------------------------- +void SAL_CALL ConfigFlush::removeRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& 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::XRefreshListener >* >(NULL)), + xListener); +} + +//----------------------------------------------- +::rtl::OUString ConfigFlush::impl_getImplementationName() +{ + static ::rtl::OUString IMPLNAME = ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.ConfigFlush"); + return IMPLNAME; +} + +//----------------------------------------------- +css::uno::Sequence< ::rtl::OUString > ConfigFlush::impl_getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > lServiceNames(1); + lServiceNames[0] = SERVICE_FILTERCONFIGREFRESH; + return lServiceNames; +} + +//----------------------------------------------- +css::uno::Reference< css::uno::XInterface > ConfigFlush::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + ConfigFlush* pNew = new ConfigFlush(xSMGR); + return css::uno::Reference< css::uno::XInterface >(static_cast< css::util::XRefreshable* >(pNew), css::uno::UNO_QUERY); +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/configflush.hxx b/filter/source/config/cache/configflush.hxx new file mode 100644 index 000000000000..477d7017ca35 --- /dev/null +++ b/filter/source/config/cache/configflush.hxx @@ -0,0 +1,128 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef __FILTER_CONFIG_CONFIGFLUSH_HXX_ +#define __FILTER_CONFIG_CONFIGFLUSH_HXX_ + +//_______________________________________________ +// includes + +#include "cacheitem.hxx" +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/interfacecontainer.h> +#include <cppuhelper/implbase1.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short supports registration of XRefreshListener + on the global filter configuration. + + @descr Such refresh listener will be called in case the + type/filter configuration will be changed at runtime. + */ +class ConfigFlush : public BaseLock + , public ::cppu::WeakImplHelper1< css::util::XRefreshable > +{ + //------------------------------------------- + // member + + protected: + + /** @short reference to an uno service manager, which can be used + to create own needed services. */ + css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR; + + /** @short holds all listener, which are registered at this instance. */ + ::cppu::OMultiTypeInterfaceContainerHelper m_lListener; + + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short standard ctor. + */ + ConfigFlush(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~ConfigFlush(); + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // XServiceInfo + + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService(const ::rtl::OUString& sServiceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (css::uno::RuntimeException); + + //--------------------------------------- + // XRefreshable + + virtual void SAL_CALL refresh() + throw(css::uno::RuntimeException); + + virtual void SAL_CALL addRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& xListener) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL removeRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& xListener) + throw(css::uno::RuntimeException); + + //--------------------------------------- + // interface to register/create this instance as an UNO service + static ::rtl::OUString impl_getImplementationName(); + static css::uno::Sequence< ::rtl::OUString > impl_getSupportedServiceNames(); + static css::uno::Reference< css::uno::XInterface > impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_CONFIGFLUSH_HXX_ diff --git a/filter/source/config/cache/constant.hxx b/filter/source/config/cache/constant.hxx new file mode 100644 index 000000000000..244a78864228 --- /dev/null +++ b/filter/source/config/cache/constant.hxx @@ -0,0 +1,217 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef _FILTER_CONFIG_CONSTANT_HXX_ +#define _FILTER_CONFIG_CONSTANT_HXX_ + +#include "macros.hxx" + +namespace filter { namespace config { +extern rtl::OUString pFilterStrings[]; +} } +#ifndef PROPNAME_IMPL_DECL +# define PROPNAME_DECL(index, str) (pFilterStrings[(index)]) +#else +# define PROPNAME_DECL(index, str) pFilterStrings[(index)] = _FILTER_CONFIG_FROM_ASCII_(str) +#endif + +/* disable impl_loadOnDemand function of BaseContainer for certain + functions, where it the feature "impl_loadItemOnDemand() of class FilterCache + can be used instead of loadAll()!*/ +// #define LOAD_IMPLICIT + +//_______________________________________________ + +/** @short used to identify a some generic item properties against the + configuration API and can be used at all name containers + (based on this filtercache) too. + */ +#define PROPNAME_NAME PROPNAME_DECL(0, "Name") + +/** @short used to identify a type item property against the + configuration API and can be used at all name containers + (based on this filtercache) too. + */ +#define PROPNAME_UINAME PROPNAME_DECL(1, "UIName" ) +#define PROPNAME_UINAMES PROPNAME_DECL(2, "UINames" ) +#define PROPNAME_PREFERRED PROPNAME_DECL(3, "Preferred" ) +#define PROPNAME_PREFERREDFILTER PROPNAME_DECL(4, "PreferredFilter" ) +#define PROPNAME_DETECTSERVICE PROPNAME_DECL(5, "DetectService" ) +#define PROPNAME_MEDIATYPE PROPNAME_DECL(6, "MediaType" ) +#define PROPNAME_CLIPBOARDFORMAT PROPNAME_DECL(7, "ClipboardFormat" ) +#define PROPNAME_URLPATTERN PROPNAME_DECL(8, "URLPattern" ) +#define PROPNAME_EXTENSIONS PROPNAME_DECL(9, "Extensions" ) + +/** @short used to identify a filter item property against the + configuration API and can be used at all name containers + (based on this filtercache) too. + */ +#define PROPNAME_TYPE PROPNAME_DECL(10, "Type" ) +#define PROPNAME_DOCUMENTSERVICE PROPNAME_DECL(11, "DocumentService" ) +#define PROPNAME_FILTERSERVICE PROPNAME_DECL(12, "FilterService" ) +#define PROPNAME_UICOMPONENT PROPNAME_DECL(13, "UIComponent" ) +#define PROPNAME_FLAGS PROPNAME_DECL(14, "Flags" ) +#define PROPNAME_USERDATA PROPNAME_DECL(15, "UserData" ) +#define PROPNAME_TEMPLATENAME PROPNAME_DECL(16, "TemplateName" ) +#define PROPNAME_FILEFORMATVERSION PROPNAME_DECL(17, "FileFormatVersion") + +/** @short used to identify a frame loader or detect service item + property against the configuration API and can be used + at all name containers (based on this filtercache) too. + */ +#define PROPNAME_TYPES PROPNAME_DECL(18, "Types") + +/** @short used to identify the list of sorted filters for a specific + office module + */ +#define PROPNAME_SORTEDFILTERLIST _FILTER_CONFIG_FROM_ASCII_("SortedFilterList") + +/** @short implicit properties. which are used at the container interface only. + */ +#define PROPNAME_FINALIZED _FILTER_CONFIG_FROM_ASCII_("Finalized") +#define PROPNAME_MANDATORY _FILTER_CONFIG_FROM_ASCII_("Mandatory") + +/** @short used to identify a set of items against the configuration API. */ +#define CFGSET_TYPES _FILTER_CONFIG_FROM_ASCII_("Types" ) +#define CFGSET_FILTERS _FILTER_CONFIG_FROM_ASCII_("Filters" ) +#define CFGSET_FRAMELOADERS _FILTER_CONFIG_FROM_ASCII_("FrameLoaders" ) +#define CFGSET_CONTENTHANDLERS _FILTER_CONFIG_FROM_ASCII_("ContentHandlers") + +/** @short used to adress some configuration keys directly. + + @descr Such direct keys should be used with function + FilterCache::impl_getDirectCFGValue() only! + + @TODO define these direct keys ... + */ +#define CFGDIRECTKEY_OFFICELOCALE _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.Setup/L10N/ooLocale" ) +#define CFGDIRECTKEY_DEFAULTFRAMELOADER _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.TypeDetection.Misc/Defaults/DefaultFrameLoader") +#define CFGDIRECTKEY_OFFICELOCALE _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.Setup/L10N/ooLocale" ) +#define CFGDIRECTKEY_FORMATNAME _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.Setup/Product/ooXMLFileFormatName" ) +#define CFGDIRECTKEY_FORMATVERSION _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.Setup/Product/ooXMLFileFormatVersion" ) +#define CFGDIRECTKEY_PRODUCTNAME _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.Setup/Product/ooName" ) + +/** @short names of filter flags, sorted in alphabetical order */ +#define FLAGNAME_3RDPARTYFILTER _FILTER_CONFIG_FROM_ASCII_("3RDPARTYFILTER" ) +#define FLAGNAME_ALIEN _FILTER_CONFIG_FROM_ASCII_("ALIEN" ) +#define FLAGNAME_ASYNCHRON _FILTER_CONFIG_FROM_ASCII_("ASYNCHRON" ) +#define FLAGNAME_BROWSERPREFERRED _FILTER_CONFIG_FROM_ASCII_("BROWSERPREFERRED" ) +#define FLAGNAME_CONSULTSERVICE _FILTER_CONFIG_FROM_ASCII_("CONSULTSERVICE" ) +#define FLAGNAME_DEFAULT _FILTER_CONFIG_FROM_ASCII_("DEFAULT" ) +#define FLAGNAME_ENCRYPTION _FILTER_CONFIG_FROM_ASCII_("ENCRYPTION" ) +#define FLAGNAME_EXPORT _FILTER_CONFIG_FROM_ASCII_("EXPORT" ) +#define FLAGNAME_IMPORT _FILTER_CONFIG_FROM_ASCII_("IMPORT" ) +#define FLAGNAME_INTERNAL _FILTER_CONFIG_FROM_ASCII_("INTERNAL" ) +#define FLAGNAME_NOTINCHOOSER _FILTER_CONFIG_FROM_ASCII_("NOTINCHOOSER" ) +#define FLAGNAME_NOTINFILEDIALOG _FILTER_CONFIG_FROM_ASCII_("NOTINFILEDIALOG" ) +#define FLAGNAME_NOTINSTALLED _FILTER_CONFIG_FROM_ASCII_("NOTINSTALLED" ) +#define FLAGNAME_OWN _FILTER_CONFIG_FROM_ASCII_("OWN" ) +#define FLAGNAME_PACKED _FILTER_CONFIG_FROM_ASCII_("PACKED" ) +#define FLAGNAME_PASSWORDTOMODIFY _FILTER_CONFIG_FROM_ASCII_("PASSWORDTOMODIFY" ) +#define FLAGNAME_PREFERRED _FILTER_CONFIG_FROM_ASCII_("PREFERRED" ) +#define FLAGNAME_READONLY _FILTER_CONFIG_FROM_ASCII_("READONLY" ) +#define FLAGNAME_SILENTEXPORT _FILTER_CONFIG_FROM_ASCII_("SILENTEXPORT" ) +#define FLAGNAME_SUPPORTSSELECTION _FILTER_CONFIG_FROM_ASCII_("SUPPORTSSELECTION") +#define FLAGNAME_TEMPLATE _FILTER_CONFIG_FROM_ASCII_("TEMPLATE" ) +#define FLAGNAME_TEMPLATEPATH _FILTER_CONFIG_FROM_ASCII_("TEMPLATEPATH" ) +#define FLAGNAME_USESOPTIONS _FILTER_CONFIG_FROM_ASCII_("USESOPTIONS" ) +#define FLAGNAME_COMBINED _FILTER_CONFIG_FROM_ASCII_("COMBINED" ) + +/** @short values of filter flags, sorted based on value */ +#define FLAGVAL_IMPORT 0x00000001 // 1 +#define FLAGVAL_EXPORT 0x00000002 // 2 +#define FLAGVAL_TEMPLATE 0x00000004 // 4 +#define FLAGVAL_INTERNAL 0x00000008 // 8 +#define FLAGVAL_TEMPLATEPATH 0x00000010 // 16 +#define FLAGVAL_OWN 0x00000020 // 32 +#define FLAGVAL_ALIEN 0x00000040 // 64 +#define FLAGVAL_USESOPTIONS 0x00000080 // 128 +#define FLAGVAL_DEFAULT 0x00000100 // 256 +#define FLAGVAL_SUPPORTSSELECTION 0x00000400 // 1024 +#define FLAGVAL_NOTINFILEDIALOG 0x00001000 // 4096 +#define FLAGVAL_NOTINCHOOSER 0x00002000 // 8192 +#define FLAGVAL_ASYNCHRON 0x00004000 // 16384 +#define FLAGVAL_READONLY 0x00010000 // 65536 +#define FLAGVAL_NOTINSTALLED 0x00020000 // 131072 +#define FLAGVAL_CONSULTSERVICE 0x00040000 // 262144 +#define FLAGVAL_3RDPARTYFILTER 0x00080000 // 524288 +#define FLAGVAL_PACKED 0x00100000 // 1048576 +#define FLAGVAL_SILENTEXPORT 0x00200000 // 2097152 +#define FLAGVAL_BROWSERPREFERRED 0x00400000 // 4194304 +#define FLAGVAL_COMBINED 0x00800000 // 8388608 +#define FLAGVAL_ENCRYPTION 0x01000000 // 16777216 +#define FLAGVAL_PASSWORDTOMODIFY 0x02000000 // 33554432 +#define FLAGVAL_PREFERRED 0x10000000 // 268435456 +#define FLAGVAL_ALL 0xffffffff // 4294967295 + +/** @short uno service names of our document services + provided by our application modules. + */ +#define DOCUMENTSERVICE_WRITER _FILTER_CONFIG_FROM_ASCII_("com.sun.star.text.TextDocument" ) +#define DOCUMENTSERVICE_WRITER_WEB _FILTER_CONFIG_FROM_ASCII_("com.sun.star.text.WebDocument" ) +#define DOCUMENTSERVICE_WRITER_GLOBAL _FILTER_CONFIG_FROM_ASCII_("com.sun.star.text.GlobalDocument" ) +#define DOCUMENTSERVICE_CALC _FILTER_CONFIG_FROM_ASCII_("com.sun.star.sheet.SpreadsheetDocument" ) +#define DOCUMENTSERVICE_DRAW _FILTER_CONFIG_FROM_ASCII_("com.sun.star.drawing.DrawingDocument" ) +#define DOCUMENTSERVICE_IMPRESS _FILTER_CONFIG_FROM_ASCII_("com.sun.star.presentation.PresentationDocument") +#define DOCUMENTSERVICE_CHART _FILTER_CONFIG_FROM_ASCII_("com.sun.star.chart2.ChartDocument" ) +#define DOCUMENTSERVICE_MATH _FILTER_CONFIG_FROM_ASCII_("com.sun.star.formula.FormulaProperties" ) + +/** @short some uno service names. + */ +#define SERVICE_CONFIGURATIONPROVIDER _FILTER_CONFIG_FROM_ASCII_("com.sun.star.configuration.ConfigurationProvider" ) +#define SERVICE_CONFIGURATIONUPDATEACCESS _FILTER_CONFIG_FROM_ASCII_("com.sun.star.configuration.ConfigurationUpdateAccess" ) +#define SERVICE_CONFIGURATIONACCESS _FILTER_CONFIG_FROM_ASCII_("com.sun.star.configuration.ConfigurationAccess" ) +#define SERVICE_URLTRANSFORMER _FILTER_CONFIG_FROM_ASCII_("com.sun.star.util.URLTransformer" ) +#define SERVICE_FILTERCONFIGREFRESH _FILTER_CONFIG_FROM_ASCII_("com.sun.star.document.FilterConfigRefresh" ) + +/** @short some configuration pathes. + */ +#define CFGPACKAGE_TD_TYPES _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.TypeDetection.Types" ) +#define CFGPACKAGE_TD_FILTERS _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.TypeDetection.Filter") +#define CFGPACKAGE_TD_OTHERS _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.TypeDetection.Misc" ) +#define CFGPACKAGE_TD_UISORT _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.TypeDetection.UISort/ModuleDependendFilterOrder") +#define CFGPACKAGE_TD_OLD _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.Office.TypeDetection") +#define CFGPACKAGE_OOO_MODULES _FILTER_CONFIG_FROM_ASCII_("/org.openoffice.Setup/Office/Factories") + +/** @short some default values. + */ +#define DEFAULT_OFFICELOCALE _FILTER_CONFIG_FROM_ASCII_("en-US") +#define DEFAULT_FORMATNAME _FILTER_CONFIG_FROM_ASCII_("OpenOffice") +#define DEFAULT_FORMATVERSION _FILTER_CONFIG_FROM_ASCII_("1.0") + +/** @short used for the queries of the FilterFactory service. + */ +#define QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE _FILTER_CONFIG_FROM_ASCII_("matchByDocumentService" ) +#define QUERY_IDENTIFIER_GETPREFERREDFILTERFORTYPE _FILTER_CONFIG_FROM_ASCII_("getDefaultFilterForType") +#define QUERY_IDENTIFIER_GET_SORTED_FILTERLIST _FILTER_CONFIG_FROM_ASCII_("getSortedFilterList()" ) + +#define QUERY_PARAM_IFLAGS _FILTER_CONFIG_FROM_ASCII_("iflags") +#define QUERY_PARAM_EFLAGS _FILTER_CONFIG_FROM_ASCII_("eflags") +#define QUERY_PARAM_MODULE _FILTER_CONFIG_FROM_ASCII_("module") +#define QUERY_PARAM_DEFAULTFIRST _FILTER_CONFIG_FROM_ASCII_("default_first") +#define QUERY_CONSTVALUE_ALL _FILTER_CONFIG_FROM_ASCII_("all") + +#endif // _FILTER_CONFIG_CONSTANT_HXX_ diff --git a/filter/source/config/cache/contenthandlerfactory.cxx b/filter/source/config/cache/contenthandlerfactory.cxx new file mode 100644 index 000000000000..3863658d9abb --- /dev/null +++ b/filter/source/config/cache/contenthandlerfactory.cxx @@ -0,0 +1,201 @@ +/************************************************************************* + * + * 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 "contenthandlerfactory.hxx" +#include "querytokenizer.hxx" +#include "macros.hxx" +#include "constant.hxx" +#include "versions.hxx" + +//_______________________________________________ +// includes +#include <com/sun/star/lang/XInitialization.hpp> +#include <comphelper/enumhelper.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +ContentHandlerFactory::ContentHandlerFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + BaseContainer::init(xSMGR , + ContentHandlerFactory::impl_getImplementationName() , + ContentHandlerFactory::impl_getSupportedServiceNames(), + FilterCache::E_CONTENTHANDLER ); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +ContentHandlerFactory::~ContentHandlerFactory() +{ +} + +/*----------------------------------------------- + 16.07.2003 13:38 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL ContentHandlerFactory::createInstance(const ::rtl::OUString& sHandler) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + return createInstanceWithArguments(sHandler, css::uno::Sequence< css::uno::Any >()); +} + +/*----------------------------------------------- + 16.07.2003 13:40 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL ContentHandlerFactory::createInstanceWithArguments(const ::rtl::OUString& sHandler , + const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + css::uno::Reference< css::uno::XInterface > xHandler; + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + ::rtl::OUString sRealHandler = sHandler; + + #ifdef _FILTER_CONFIG_MIGRATION_Q_ + + /* -> TODO - HACK + check if the given handler name realy exist ... + Because our old implementation worked with an internal + type name instead of a handler name. For a small migration time + we must simulate this old feature :-( */ + + if (!m_rCache->hasItem(FilterCache::E_CONTENTHANDLER, sHandler) && m_rCache->hasItem(FilterCache::E_TYPE, sHandler)) + { + _FILTER_CONFIG_LOG_("ContentHandlerFactory::createInstanceWithArguments() ... simulate old type search functionality!\n"); + + css::uno::Sequence< ::rtl::OUString > lTypes(1); + lTypes[0] = sHandler; + + css::uno::Sequence< css::beans::NamedValue > lQuery(1); + lQuery[0].Name = PROPNAME_TYPES; + lQuery[0].Value <<= lTypes; + + css::uno::Reference< css::container::XEnumeration > xSet = createSubSetEnumerationByProperties(lQuery); + while(xSet->hasMoreElements()) + { + ::comphelper::SequenceAsHashMap lHandlerProps(xSet->nextElement()); + if (!(lHandlerProps[PROPNAME_NAME] >>= sRealHandler)) + continue; + } + + // prevent outside code against NoSuchElementException! + // But dont implement such defensive strategy for our new create handling :-) + if (!m_rCache->hasItem(FilterCache::E_CONTENTHANDLER, sRealHandler)) + return css::uno::Reference< css::uno::XInterface>(); + } + + /* <- HACK */ + + #endif // _FILTER_CONFIG_MIGRATION_Q_ + + // search handler on cache + CacheItem aHandler = m_rCache->getItem(FilterCache::E_CONTENTHANDLER, sRealHandler); + + // create service instance + xHandler = m_xSMGR->createInstance(sRealHandler); + + // initialize filter + css::uno::Reference< css::lang::XInitialization > xInit(xHandler, css::uno::UNO_QUERY); + if (xInit.is()) + { + // format: lInitData[0] = seq<PropertyValue>, which contains all configuration properties of this handler + // lInitData[1] = lArguments[0] + // ... + // lInitData[n] = lArguments[n-1] + css::uno::Sequence< css::beans::PropertyValue > lConfig; + aHandler >> lConfig; + + ::comphelper::SequenceAsVector< css::uno::Any > stlArguments(lArguments); + stlArguments.insert(stlArguments.begin(), css::uno::makeAny(lConfig)); + + css::uno::Sequence< css::uno::Any > lInitData; + stlArguments >> lInitData; + + xInit->initialize(lInitData); + } + + return xHandler; + // <- SAFE +} + +/*----------------------------------------------- + 09.07.2003 07:46 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > SAL_CALL ContentHandlerFactory::getAvailableServiceNames() + throw(css::uno::RuntimeException) +{ + // must be the same list as ((XNameAccess*)this)->getElementNames() return! + return getElementNames(); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +::rtl::OUString ContentHandlerFactory::impl_getImplementationName() +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.ContentHandlerFactory"); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > ContentHandlerFactory::impl_getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > lServiceNames(1); + lServiceNames[0] = ::rtl::OUString::createFromAscii("com.sun.star.frame.ContentHandlerFactory"); + return lServiceNames; +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL ContentHandlerFactory::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + ContentHandlerFactory* pNew = new ContentHandlerFactory(xSMGR); + return css::uno::Reference< css::uno::XInterface >(static_cast< css::lang::XMultiServiceFactory* >(pNew), css::uno::UNO_QUERY); +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/contenthandlerfactory.hxx b/filter/source/config/cache/contenthandlerfactory.hxx new file mode 100644 index 000000000000..a50f91c0b61e --- /dev/null +++ b/filter/source/config/cache/contenthandlerfactory.hxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __FILTER_CONFIG_CONTENTHANDLERFACTORY_HXX_ +#define __FILTER_CONFIG_CONTENTHANDLERFACTORY_HXX_ + +//_______________________________________________ +// includes + +#include "basecontainer.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <cppuhelper/implbase1.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements the service <type scope="com.sun.star.document">ContentHandlerFactory</type>. + */ +class ContentHandlerFactory : public ::cppu::ImplInheritanceHelper1< BaseContainer , + css::lang::XMultiServiceFactory > +{ + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short standard ctor to connect this interface wrapper to + the global filter cache instance ... + + @param xSMGR + reference to the uno service manager, which created this service instance. + */ + ContentHandlerFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~ContentHandlerFactory(); + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // XMultiServiceFactory + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const ::rtl::OUString& sHandler) + throw(css::uno::Exception , + css::uno::RuntimeException); + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const ::rtl::OUString& sHandler , + const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames() + throw(css::uno::RuntimeException); + + //------------------------------------------- + // static uno helper! + + public: + + //--------------------------------------- + + /** @short return the uno implementation name of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix uno implementation name of this class. + */ + static ::rtl::OUString impl_getImplementationName(); + + //--------------------------------------- + + /** @short return the list of supported uno services of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix list of uno services supported by this class. + */ + static css::uno::Sequence< ::rtl::OUString > impl_getSupportedServiceNames(); + + //--------------------------------------- + + /** @short return a new intsnace of this class. + + @descr This method is used by the uno service manager, to create + a new instance of this service if needed. + + @param xSMGR + reference to the uno service manager, which require + this new instance. It should be passed to the new object + so it can be used internaly to create own needed uno resources. + + @return The new instance of this service as an uno reference. + */ + static css::uno::Reference< css::uno::XInterface > impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_CONTENTHANDLERFACTORY_HXX_ diff --git a/filter/source/config/cache/filtercache.cxx b/filter/source/config/cache/filtercache.cxx new file mode 100644 index 000000000000..d4435e2182f1 --- /dev/null +++ b/filter/source/config/cache/filtercache.cxx @@ -0,0 +1,2536 @@ +/************************************************************************* + * + * 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 "filtercache.hxx" +#include "lateinitlistener.hxx" +#include "macros.hxx" +#include "constant.hxx" +#include "cacheupdatelistener.hxx" + +/*TODO see using below ... */ +#define AS_ENABLE_FILTER_UINAMES +#define WORKAROUND_EXCEPTION_PROBLEM + +//_______________________________________________ +// includes +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XProperty.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp> +#include <comphelper/sequenceasvector.hxx> +#include <comphelper/locale.hxx> +#include <unotools/processfactory.hxx> + +#ifndef _UNOTOOLS_CONFIGPATHES_HXX_ +#include <unotools/configpathes.hxx> +#endif +#include <rtl/ustrbuf.hxx> +#include <rtl/logfile.hxx> +#include <rtl/uri.hxx> +#include <tools/urlobj.hxx> +#include <tools/wldcrd.hxx> + +#include <comphelper/configurationhelper.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +// Error message in case filter config seems to be corrupted. +// Note: Dont tell user something about "setup -repair"! +// Its no longer supported by using native installers ... +static ::rtl::OUString MESSAGE_CORRUPTED_FILTERCONFIG = ::rtl::OUString::createFromAscii("The filter configuration appears to be defective. Please install the office suite again."); + +/*----------------------------------------------- + 15.03.2004 08:59 +-----------------------------------------------*/ +FilterCache::FilterCache() + : BaseLock ( ) + , m_xSMGR (::comphelper::getProcessServiceFactory()) + , m_eFillState(E_CONTAINS_NOTHING ) +{ + RTL_LOGFILE_TRACE("{ (as96863) FilterCache lifetime"); +} + +/*----------------------------------------------- + 15.03.2004 08:59 +-----------------------------------------------*/ +FilterCache::~FilterCache() +{ + RTL_LOGFILE_TRACE("} (as96863) FilterCache lifetime"); +} + +/*----------------------------------------------- + 03.03.2004 11:27 +-----------------------------------------------*/ +FilterCache* FilterCache::clone() const +{ + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + FilterCache* pClone = new FilterCache(); + + // Dont copy the configuration access points here. + // They will be created on demand inside the cloned instance, + // if they are needed. + + pClone->m_xSMGR = m_xSMGR; + + pClone->m_lTypes = m_lTypes; + pClone->m_lDetectServices = m_lDetectServices; + pClone->m_lFilters = m_lFilters; + pClone->m_lFrameLoaders = m_lFrameLoaders; + pClone->m_lContentHandlers = m_lContentHandlers; + pClone->m_lExtensions2Types = m_lExtensions2Types; + pClone->m_lURLPattern2Types = m_lURLPattern2Types; + + pClone->m_sActLocale = m_sActLocale; + pClone->m_sFormatName = m_sFormatName; + pClone->m_sFormatVersion = m_sFormatVersion; + + pClone->m_eFillState = m_eFillState; + + pClone->m_lChangedTypes = m_lChangedTypes; + pClone->m_lChangedFilters = m_lChangedFilters; + pClone->m_lChangedDetectServices = m_lChangedDetectServices; + pClone->m_lChangedFrameLoaders = m_lChangedFrameLoaders; + pClone->m_lChangedContentHandlers = m_lChangedContentHandlers; + + return pClone; + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 03.03.2004 14:39 +-----------------------------------------------*/ +void FilterCache::takeOver(const FilterCache& rClone) +{ + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + // a) + // Dont copy the configuration access points here! + // We must use our own ones ... + + // b) + // Further we can ignore the uno service manager. + // We should already have a valid instance. + + // c) + // Take over only changed items! + // Otherwhise we risk the following scenario: + // c1) clone_1 contains changed filters + // c2) clone_2 container changed types + // c3) clone_1 take over changed filters and unchanged types + // c4) clone_2 take over unchanged filters(!) and changed types(!) + // c5) c4 overwrites c3! + + if (rClone.m_lChangedTypes.size()>0) + m_lTypes = rClone.m_lTypes; + if (rClone.m_lChangedDetectServices.size()>0) + m_lDetectServices = rClone.m_lDetectServices; + if (rClone.m_lChangedFilters.size()>0) + m_lFilters = rClone.m_lFilters; + if (rClone.m_lChangedFrameLoaders.size()>0) + m_lFrameLoaders = rClone.m_lFrameLoaders; + if (rClone.m_lChangedContentHandlers.size()>0) + m_lContentHandlers = rClone.m_lContentHandlers; + + m_lChangedTypes.clear(); + m_lChangedDetectServices.clear(); + m_lChangedFilters.clear(); + m_lChangedFrameLoaders.clear(); + m_lChangedContentHandlers.clear(); + + m_sActLocale = rClone.m_sActLocale; + m_sFormatName = rClone.m_sFormatName; + m_sFormatVersion = rClone.m_sFormatVersion; + + m_eFillState = rClone.m_eFillState; + + // renew all dependencies and optimizations + // Because we cant be shure, that changed filters on one clone + // and changed types of another clone work together. + // But here we can check against the lates changes ... + impl_validateAndOptimize(); + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 28.10.2003 09:01 +-----------------------------------------------*/ +void FilterCache::load(EFillState eRequired, +#if OSL_DEBUG_LEVEL > 1 + sal_Bool bByThread +#else + sal_Bool +#endif +) + throw(css::uno::Exception) +{ + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + // check if required fill state is already reached ... + // There is nothing to do then. + if ((m_eFillState & eRequired) == eRequired) + return; + +#if OSL_DEBUG_LEVEL > 1 && !defined(OS2) + if ( + (!bByThread) && + ( + ((eRequired & E_CONTAINS_FILTERS) == E_CONTAINS_FILTERS) || + ((eRequired & E_CONTAINS_ALL ) == E_CONTAINS_ALL ) + ) + ) + { + OSL_ENSURE(sal_False, "Who disturb our \"fill cache on demand\" feature and force loading of ALL data during office startup? Please optimize your code, so a full filled filter cache is not realy needed here!"); + } +#endif + + // Otherwhise load the missing items. + + // ------------------------------------------ + // a) load some const values from configration. + // These values are needed there for loading + // config items ... + // Further we load some std items from the + // configuration so we can try to load the first + // office document with a minimal set of values. + if (m_eFillState == E_CONTAINS_NOTHING) + { + impl_getDirectCFGValue(CFGDIRECTKEY_OFFICELOCALE) >>= m_sActLocale; + if (!m_sActLocale.getLength()) + { + _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify office locale => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_OFFICELOCALE)); + m_sActLocale = DEFAULT_OFFICELOCALE; + } + + impl_getDirectCFGValue(CFGDIRECTKEY_FORMATNAME) >>= m_sFormatName; + if (!m_sFormatName.getLength()) + impl_getDirectCFGValue(CFGDIRECTKEY_PRODUCTNAME) >>= m_sFormatName; + + if (!m_sFormatName.getLength()) + { + _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format name => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATNAME)); + m_sFormatName = DEFAULT_FORMATNAME; + } + + impl_getDirectCFGValue(CFGDIRECTKEY_FORMATVERSION) >>= m_sFormatVersion; + if (!m_sFormatVersion.getLength()) + { + _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format version => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATVERSION)); + m_sFormatVersion = DEFAULT_FORMATVERSION; + } + + // Support the old configuration support. Read it only one times during office runtime! + impl_readOldFormat(); + + // enable "loadOnDemand" feature ... + // Create uno listener, which waits for finishing the office startup + // and starts a thread, which calls loadAll() at this filter cache. + // Note: Its not a leak to create this listener with new here. + // It kills itself after working! + /* LateInitListener* pLateInit = */ new LateInitListener(m_xSMGR); + } + + // ------------------------------------------ + // b) If the required fill state was not reached + // but std values was already loaded ... + // we must load some further missing items. + impl_load(eRequired); + // <- SAFE +} + +/*----------------------------------------------- + 28.10.2003 09:50 +-----------------------------------------------*/ +sal_Bool FilterCache::isFillState(FilterCache::EFillState eState) const + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + return ((m_eFillState & eState) == eState); + // <- SAFE +} + +/*----------------------------------------------- + 14.07.2003 10:45 +-----------------------------------------------*/ +OUStringList FilterCache::getMatchingItemsByProps( EItemType eType , + const CacheItem& lIProps, + const CacheItem& lEProps) const + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search for right list + // An exception is thrown �f "eType" is unknown. + // => rList will be valid everytimes next line is reached. + CacheItemList& rList = impl_getItemList(eType); + + OUStringList lKeys; + + // search items, which provides all needed properties of set "lIProps" + // but not of set "lEProps"! + for (CacheItemList::const_iterator pIt = rList.begin(); + pIt != rList.end() ; + ++pIt ) + { + _FILTER_CONFIG_LOG_1_("getMatchingProps for \"%s\" ...\n", + _FILTER_CONFIG_TO_ASCII_(pIt->first)) + if ( + (pIt->second.haveProps(lIProps) ) && + (pIt->second.dontHaveProps(lEProps)) + ) + { + lKeys.push_back(pIt->first); + } + } + + return lKeys; + // <- SAFE +} + +/*----------------------------------------------- + 02.07.2003 09:32 +-----------------------------------------------*/ +sal_Bool FilterCache::hasItems(EItemType eType) const + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search for right list + // An exception is thrown �f "eType" is unknown. + // => rList will be valid everytimes next line is reached. + CacheItemList& rList = impl_getItemList(eType); + + return (rList.size()>0); + // <- SAFE +} + +/*----------------------------------------------- + 02.07.2003 11:48 +-----------------------------------------------*/ +OUStringList FilterCache::getItemNames(EItemType eType) const + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search for right list + // An exception is thrown �f "eType" is unknown. + // => rList will be valid everytimes next line is reached. + CacheItemList& rList = impl_getItemList(eType); + + OUStringList lKeys; + for (CacheItemList::const_iterator pIt = rList.begin(); + pIt != rList.end() ; + ++pIt ) + { + lKeys.push_back(pIt->first); + } + return lKeys; + // <- SAFE +} + +/*----------------------------------------------- + 27.10.2003 08:37 +-----------------------------------------------*/ +sal_Bool FilterCache::hasItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search for right list + // An exception is thrown �f "eType" is unknown. + // => rList will be valid everytimes next line is reached. + CacheItemList& rList = impl_getItemList(eType); + + // if item could not be found - check if it can be loaded + // from the underlying configuration layer. Might it was not already + // loaded into this FilterCache object before. + CacheItemList::const_iterator pIt = rList.find(sItem); + if (pIt != rList.end()) + return sal_True; + + try + { + impl_loadItemOnDemand(eType, sItem); + // no exception => item could be loaded! + return sal_True; + } + catch(const css::container::NoSuchElementException&) + {} + + return sal_False; + // <- SAFE +} + +/*----------------------------------------------- + 17.07.2006 09:15 +-----------------------------------------------*/ +CacheItem FilterCache::getItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search for right list + // An exception is thrown if "eType" is unknown. + // => rList will be valid everytimes next line is reached. + CacheItemList& rList = impl_getItemList(eType); + + // check if item exists ... + CacheItemList::iterator pIt = rList.find(sItem); + if (pIt == rList.end()) + { + // ... or load it on demand from the + // underlying configuration layer. + // Note: NoSuchElementException is thrown automaticly here if + // item could not be loaded! + pIt = impl_loadItemOnDemand(eType, sItem); + } + + /* Workaround for #137955# + Draw types and filters are installed ... but draw was disabled during setup. + We must supress accessing these filters. Otherwise the office can crash. + Solution for the next major release: do not install those filters ! + */ + if (eType == E_FILTER) + { + CacheItem& rFilter = pIt->second; + ::rtl::OUString sDocService; + rFilter[PROPNAME_DOCUMENTSERVICE] >>= sDocService; + + // --> PB 2006-10-18 #142498# + // In Standalone-Impress the module WriterWeb is not installed + // but it is there to load help pages + sal_Bool bIsHelpFilter = sItem.equalsAscii( "writer_web_HTML_help" ); + + if ( !bIsHelpFilter && !impl_isModuleInstalled(sDocService) ) + // <-- + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("The requested filter '" ); + sMsg.append (sItem ); + sMsg.appendAscii("' exists ... but it shouldnt; because the corresponding OOo module was not installed."); + throw css::container::NoSuchElementException(sMsg.makeStringAndClear(), css::uno::Reference< css::uno::XInterface >()); + } + } + + return pIt->second; + // <- SAFE +} + +/*----------------------------------------------- + 03.03.2004 11:28 +-----------------------------------------------*/ +void FilterCache::removeItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search for right list + // An exception is thrown �f "eType" is unknown. + // => rList will be valid everytimes next line is reached. + CacheItemList& rList = impl_getItemList(eType); + + CacheItemList::iterator pItem = rList.find(sItem); + if (pItem == rList.end()) + pItem = impl_loadItemOnDemand(eType, sItem); // throws NoSuchELementException! + rList.erase(pItem); + + impl_addItem2FlushList(eType, sItem); +} + +/*----------------------------------------------- + 26.11.2003 13:28 +-----------------------------------------------*/ +void FilterCache::setItem( EItemType eType , + const ::rtl::OUString& sItem , + const CacheItem& aValue) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search for right list + // An exception is thrown �f "eType" is unknown. + // => rList will be valid everytimes next line is reached. + CacheItemList& rList = impl_getItemList(eType); + + // name must be part of the property set too ... otherwhise our + // container query cant work correctly + CacheItem aItem = aValue; + aItem[PROPNAME_NAME] <<= sItem; + aItem.validateUINames(m_sActLocale); + + // remove implicit properties as e.g. FINALIZED or MANDATORY + // They cant be saved here and must be readed on demand later, if they are needed. + removeStatePropsFromItem(aItem); + + rList[sItem] = aItem; + + impl_addItem2FlushList(eType, sItem); +} + +//----------------------------------------------- +void FilterCache::refreshItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + impl_loadItemOnDemand(eType, sItem); +} + +/*----------------------------------------------- + 27.10.2003 08:14 +-----------------------------------------------*/ +void FilterCache::addStatePropsToItem( EItemType eType, + const ::rtl::OUString& sItem, + CacheItem& rItem) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // Note: Opening of the configuration layer throws some exceptions + // if it failed. So we dont must check any reference here ... + css::uno::Reference< css::container::XNameAccess > xPackage; + css::uno::Reference< css::container::XNameAccess > xSet; + switch(eType) + { + case E_TYPE : + { + xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY); + xPackage->getByName(CFGSET_TYPES) >>= xSet; + } + break; + + case E_FILTER : + { + xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY); + xPackage->getByName(CFGSET_FILTERS) >>= xSet; + } + break; + + case E_FRAMELOADER : + { + /* TODO + Hack --> + The default frame loader cant be located inside te normal set of frame loaders. + Its an atomic property inside the misc cfg package. So we cant retrieve the information + about FINALIZED and MANDATORY very easy ... :-( + => set it to readonly/required everytimes :-) + */ + css::uno::Any aDirectValue = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER); + ::rtl::OUString sDefaultFrameLoader; + if ( + (aDirectValue >>= sDefaultFrameLoader) && + (sDefaultFrameLoader.getLength() ) && + (sItem.equals(sDefaultFrameLoader) ) + ) + { + rItem[PROPNAME_FINALIZED] <<= sal_True; + rItem[PROPNAME_MANDATORY] <<= sal_True; + return; + } + /* <-- HACK */ + + xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY); + xPackage->getByName(CFGSET_FRAMELOADERS) >>= xSet; + } + break; + + case E_CONTENTHANDLER : + { + xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY); + xPackage->getByName(CFGSET_CONTENTHANDLERS) >>= xSet; + } + break; + default: break; + } + + try + { + css::uno::Reference< css::beans::XProperty > xItem; + xSet->getByName(sItem) >>= xItem; + css::beans::Property aDescription = xItem->getAsProperty(); + + sal_Bool bFinalized = ((aDescription.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY ); + sal_Bool bMandatory = ((aDescription.Attributes & css::beans::PropertyAttribute::REMOVEABLE) != css::beans::PropertyAttribute::REMOVEABLE); + + rItem[PROPNAME_FINALIZED] <<= bFinalized; + rItem[PROPNAME_MANDATORY] <<= bMandatory; + } + catch(const css::container::NoSuchElementException&) + { + /* Ignore exceptions for missing elements inside configuration. + May by the following reason exists: + - The item does not exists inside the new configuration package org.openoffice.TypeDetection - but + we got it from the old package org.openoffice.Office/TypeDetection. We dont migrate such items + automaticly to the new format. Because it will disturb e.g. the deinstallation of an external filter + package. Because such external filter can remove the old file - but not the automaticly created new one ... + + => mark item as FINALIZED / MANDATORY, we dont support writing to the old format + */ + rItem[PROPNAME_FINALIZED] <<= sal_True; + rItem[PROPNAME_MANDATORY] <<= sal_True; + } + + // <- SAFE +} + +/*----------------------------------------------- + 05.03.2004 10:36 +-----------------------------------------------*/ +void FilterCache::removeStatePropsFromItem(CacheItem& rItem) + throw(css::uno::Exception) +{ + CacheItem::iterator pIt; + pIt = rItem.find(PROPNAME_FINALIZED); + if (pIt != rItem.end()) + rItem.erase(pIt); + pIt = rItem.find(PROPNAME_MANDATORY); + if (pIt != rItem.end()) + rItem.erase(pIt); +} + +/*----------------------------------------------- + 02.07.2003 09:17 +-----------------------------------------------*/ +void FilterCache::flush() + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // renew all dependencies and optimizations + impl_validateAndOptimize(); + + if (m_lChangedTypes.size() > 0) + { + css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY); + css::uno::Reference< css::container::XNameAccess > xSet ; + + xConfig->getByName(CFGSET_TYPES) >>= xSet; + impl_flushByList(xSet, E_TYPE, m_lTypes, m_lChangedTypes); + + css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY); + xFlush->commitChanges(); + } + + if (m_lChangedFilters.size() > 0) + { + css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY); + css::uno::Reference< css::container::XNameAccess > xSet ; + + xConfig->getByName(CFGSET_FILTERS) >>= xSet; + impl_flushByList(xSet, E_FILTER, m_lFilters, m_lChangedFilters); + + css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY); + xFlush->commitChanges(); + } + + /*TODO FrameLoader/ContentHandler must be flushed here too ... */ +} + +/*----------------------------------------------- + 20.10.2003 09:22 +-----------------------------------------------*/ +void FilterCache::impl_flushByList(const css::uno::Reference< css::container::XNameAccess >& xSet , + EItemType eType , + const CacheItemList& rCache, + const OUStringList& lItems) + throw(css::uno::Exception) +{ + css::uno::Reference< css::container::XNameContainer > xAddRemoveSet = css::uno::Reference< css::container::XNameContainer > (xSet, css::uno::UNO_QUERY); + css::uno::Reference< css::container::XNameReplace > xReplaceeSet = css::uno::Reference< css::container::XNameReplace > (xSet, css::uno::UNO_QUERY); + css::uno::Reference< css::lang::XSingleServiceFactory > xFactory = css::uno::Reference< css::lang::XSingleServiceFactory >(xSet, css::uno::UNO_QUERY); + + for (OUStringList::const_iterator pIt = lItems.begin(); + pIt != lItems.end() ; + ++pIt ) + { + const ::rtl::OUString& sItem = *pIt; + EItemFlushState eState = impl_specifyFlushOperation(xSet, rCache, sItem); + switch(eState) + { + case E_ITEM_REMOVED : + { + xAddRemoveSet->removeByName(sItem); + } + break; + + case E_ITEM_ADDED : + { + css::uno::Reference< css::container::XNameReplace > xItem (xFactory->createInstance(), css::uno::UNO_QUERY); + + // special case. no exception - but not a valid item => set must be finalized or mandatory! + // Reject flush operation by throwing an exception. At least one item couldnt be flushed. + if (!xItem.is()) + throw css::uno::Exception(::rtl::OUString::createFromAscii("Cant add item. Set is finalized or mandatory!"), + css::uno::Reference< css::uno::XInterface >() ); + + CacheItemList::const_iterator pItem = rCache.find(sItem); + impl_saveItem(xItem, eType, pItem->second); + xAddRemoveSet->insertByName(sItem, css::uno::makeAny(xItem)); + } + break; + + case E_ITEM_CHANGED : + { + css::uno::Reference< css::container::XNameReplace > xItem; + xSet->getByName(sItem) >>= xItem; + + // special case. no exception - but not a valid item => it must be finalized or mandatory! + // Reject flush operation by throwing an exception. At least one item couldnt be flushed. + if (!xItem.is()) + throw css::uno::Exception(::rtl::OUString::createFromAscii("Cant change item. Its finalized or mandatory!"), + css::uno::Reference< css::uno::XInterface >() ); + + CacheItemList::const_iterator pItem = rCache.find(sItem); + impl_saveItem(xItem, eType, pItem->second); + } + break; + default: break; + } + } +} + +/*----------------------------------------------- + 03.11.2003 08:38 +-----------------------------------------------*/ +void FilterCache::detectFlatForURL(const css::util::URL& aURL , + FlatDetection& rFlatTypes) const + throw(css::uno::Exception) +{ + // extract extension from URL, so it can be used directly as key into our hash map! + // Note further: It must be converted to lower case, because the optimize hash + // (which maps extensions to types) work with lower case key strings! + INetURLObject aParser (aURL.Main); + ::rtl::OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT , + sal_True , + INetURLObject::DECODE_WITH_CHARSET); + sExtension = sExtension.toAsciiLowerCase(); + + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + //******************************************* + // i) Step over all well known URL pattern + // and add registered types to the return list too + // Do it as first one - because: if a type match by a + // pattern a following deep detection can be supressed! + // Further we can stop after first match ... + for (CacheItemRegistration::const_iterator pPattReg = m_lURLPattern2Types.begin(); + pPattReg != m_lURLPattern2Types.end() ; + ++pPattReg ) + { + WildCard aPatternCheck(pPattReg->first); + if (aPatternCheck.Matches(aURL.Main)) + { + const OUStringList& rTypesForPattern = pPattReg->second; + + FlatDetectionInfo aInfo; + aInfo.sType = *(rTypesForPattern.begin()); + aInfo.bMatchByPattern = sal_True; + + rFlatTypes.push_back(aInfo); +// return; + } + } + + //******************************************* + // ii) search types matching to the given extension. + // Copy every macthing type without changing its order! + // Because preferred types was added as first one during + // loading configuration. + CacheItemRegistration::const_iterator pExtReg = m_lExtensions2Types.find(sExtension); + if (pExtReg != m_lExtensions2Types.end()) + { + const OUStringList& rTypesForExtension = pExtReg->second; + for (OUStringList::const_iterator pIt = rTypesForExtension.begin(); + pIt != rTypesForExtension.end() ; + ++pIt ) + { + FlatDetectionInfo aInfo; + aInfo.sType = *pIt; + aInfo.bMatchByExtension = sal_True; + + rFlatTypes.push_back(aInfo); + } + } + + aLock.clear(); + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 03.11.2003 08:38 +-----------------------------------------------*/ +CacheItemList& FilterCache::impl_getItemList(EItemType eType) const + throw(css::uno::Exception) +{ + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + switch(eType) + { + case E_TYPE : return m_lTypes ; + case E_FILTER : return m_lFilters ; + case E_FRAMELOADER : return m_lFrameLoaders ; + case E_CONTENTHANDLER : return m_lContentHandlers; + case E_DETECTSERVICE : return m_lDetectServices ; + + default : throw css::uno::Exception(::rtl::OUString::createFromAscii("unknown sub container requested."), + css::uno::Reference< css::uno::XInterface >() ); + } + + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 21.10.2003 13:20 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > FilterCache::impl_openConfig(EConfigProvider eProvider) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + ::rtl::OUString sPath ; + css::uno::Reference< css::uno::XInterface >* pConfig = 0; + css::uno::Reference< css::uno::XInterface > xOld ; + ::rtl::OString sRtlLog ; + FilterCache::EItemType eItemType( FilterCache::E_TYPE ) ; + sal_Bool bStartListening = sal_False; + + switch(eProvider) + { + case E_PROVIDER_TYPES : + { + if (m_xConfigTypes.is()) + return m_xConfigTypes; + sPath = CFGPACKAGE_TD_TYPES; + pConfig = &m_xConfigTypes; + eItemType = FilterCache::E_TYPE; + bStartListening = sal_True; + sRtlLog = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_TYPES)"); + } + break; + + case E_PROVIDER_FILTERS : + { + if (m_xConfigFilters.is()) + return m_xConfigFilters; + sPath = CFGPACKAGE_TD_FILTERS; + pConfig = &m_xConfigFilters; + eItemType = FilterCache::E_FILTER; + bStartListening = sal_True; + sRtlLog = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_FILTERS)"); + } + break; + + case E_PROVIDER_OTHERS : + { + if (m_xConfigOthers.is()) + return m_xConfigOthers; + sPath = CFGPACKAGE_TD_OTHERS; + pConfig = &m_xConfigOthers; + eItemType = FilterCache::E_TYPE; + sRtlLog = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_OTHERS)"); + } + break; + + case E_PROVIDER_OLD : + { + // This special provider is used to work with + // the old configuration format only. Its not cached! + sPath = CFGPACKAGE_TD_OLD; + pConfig = &xOld; + sRtlLog = ::rtl::OString("framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_OLD)"); + } + break; + + default : throw css::uno::Exception(::rtl::OUString::createFromAscii("These configuration node isnt supported here for open!"), 0); + } + + { + RTL_LOGFILE_CONTEXT(aLog, sRtlLog.getStr()); + *pConfig = impl_createConfigAccess(sPath , + sal_False, // bReadOnly + sal_True ); // bLocalesMode + } + + // Start listening for changes on that configuration access. + // We must not control the lifetime of this listener. Itself + // checks, when ist time to die :-) + if (bStartListening) + { + CacheUpdateListener* pListener = new CacheUpdateListener(m_xSMGR, *pConfig, eItemType); + pListener->startListening(); + } + + return *pConfig; + // <- SAFE +} + +/*----------------------------------------------- + 17.07.2003 10:10 +-----------------------------------------------*/ +css::uno::Any FilterCache::impl_getDirectCFGValue(const ::rtl::OUString& sDirectKey) +{ + ::rtl::OUString sRoot; + ::rtl::OUString sKey ; + + if ( + (!::utl::splitLastFromConfigurationPath(sDirectKey, sRoot, sKey)) || + (!sRoot.getLength() ) || + (!sKey.getLength() ) + ) + return css::uno::Any(); + + css::uno::Reference< css::uno::XInterface > xCfg = impl_createConfigAccess(sRoot , + sal_True , // bReadOnly + sal_False); // bLocalesMode + if (!xCfg.is()) + return css::uno::Any(); + + css::uno::Reference< css::container::XNameAccess > xAccess(xCfg, css::uno::UNO_QUERY); + if (!xAccess.is()) + return css::uno::Any(); + + css::uno::Any aValue; + try + { + aValue = xAccess->getByName(sKey); + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + #if OSL_DEBUG_LEVEL>0 + catch(const css::uno::Exception& ex) + #else + catch(const css::uno::Exception&) + #endif + { + #if OSL_DEBUG_LEVEL > 0 + OSL_ENSURE(sal_False, ::rtl::OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr()); + #endif + aValue.clear(); + } + + return aValue; +} + +/*----------------------------------------------- + 17.07.2003 09:49 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > FilterCache::impl_createConfigAccess(const ::rtl::OUString& sRoot , + sal_Bool bReadOnly , + sal_Bool bLocalesMode) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + css::uno::Reference< css::uno::XInterface > xCfg; + + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider( + m_xSMGR->createInstance(SERVICE_CONFIGURATIONPROVIDER), css::uno::UNO_QUERY); + + if (!xConfigProvider.is()) + return css::uno::Reference< css::uno::XInterface >(); + + ::comphelper::SequenceAsVector< css::uno::Any > lParams; + css::beans::PropertyValue aParam ; + + // set root path + aParam.Name = _FILTER_CONFIG_FROM_ASCII_("nodepath"); + aParam.Value <<= sRoot; + lParams.push_back(css::uno::makeAny(aParam)); + + // enable "all locales mode" ... if required + if (bLocalesMode) + { + aParam.Name = _FILTER_CONFIG_FROM_ASCII_("locale"); + aParam.Value <<= _FILTER_CONFIG_FROM_ASCII_("*" ); + lParams.push_back(css::uno::makeAny(aParam)); + } + + // open it + if (bReadOnly) + xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONACCESS, lParams.getAsConstList()); + else + xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONUPDATEACCESS, lParams.getAsConstList()); + + // If configuration could not be opened ... but factory method does not throwed an exception + // trigger throwing of our own CorruptedFilterConfigurationException. + // Let message empty. The normal exception text show enough informations to the user. + if (! xCfg.is()) + throw css::uno::Exception( + _FILTER_CONFIG_FROM_ASCII_("Got NULL reference on opening configuration file ... but no exception."), + css::uno::Reference< css::uno::XInterface >()); + } + catch(const css::uno::Exception& ex) + { + throw css::document::CorruptedFilterConfigurationException( + MESSAGE_CORRUPTED_FILTERCONFIG, + css::uno::Reference< css::uno::XInterface >(), + ex.Message); + } + + return xCfg; + // <- SAFE +} + +/*----------------------------------------------- + 24.10.2003 10:03 +-----------------------------------------------*/ +void FilterCache::impl_validateAndOptimize() + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::impl_validateAndOptimize"); + + // First check if any filter or type could be readed + // from the underlying configuration! + sal_Bool bSomeTypesShouldExist = ((m_eFillState & E_CONTAINS_STANDARD ) == E_CONTAINS_STANDARD ); + sal_Bool bAllFiltersShouldExist = ((m_eFillState & E_CONTAINS_FILTERS ) == E_CONTAINS_FILTERS ); + +#if OSL_DEBUG_LEVEL > 0 + + sal_Int32 nWarnings = 0; + +// sal_Bool bAllTypesShouldExist = ((m_eFillState & E_CONTAINS_TYPES ) == E_CONTAINS_TYPES ); + sal_Bool bAllLoadersShouldExist = ((m_eFillState & E_CONTAINS_FRAMELOADERS ) == E_CONTAINS_FRAMELOADERS ); + sal_Bool bAllHandlersShouldExist = ((m_eFillState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS); +#endif + + if ( + ( + (bSomeTypesShouldExist) && + (m_lTypes.size() < 1 ) + ) || + ( + (bAllFiltersShouldExist) && + (m_lFilters.size() < 1 ) + ) + ) + { + throw css::document::CorruptedFilterConfigurationException( + MESSAGE_CORRUPTED_FILTERCONFIG, + css::uno::Reference< css::uno::XInterface >(), + ::rtl::OUString::createFromAscii("The list of types or filters is empty.")); + } + + // Create a log for all detected problems, which + // occure in the next feew lines. + // If there are some real errors throw a RuntimException! + // If there are some warnings only, show an assertion. + sal_Int32 nErrors = 0; + ::rtl::OUStringBuffer sLog(256); + + CacheItemList::iterator pIt; + + for (pIt = m_lTypes.begin(); pIt != m_lTypes.end(); ++pIt) + { + ::rtl::OUString sType = pIt->first; + CacheItem aType = pIt->second; + + // create list of all known detect services / frame loader / content handler on demand + // Because these informations are available as type properties! + ::rtl::OUString sDetectService; + aType[PROPNAME_DETECTSERVICE ] >>= sDetectService; + if (sDetectService.getLength()) + impl_resolveItem4TypeRegistration(&m_lDetectServices, sDetectService, sType); + + // get its registration for file Extensions AND(!) URLPattern ... + // It doesnt matter if these items exists or if our + // used index access create some default ones ... + // only in case there is no filled set of Extensions AND + // no filled set of URLPattern -> we must try to remove this invalid item + // from this cache! + css::uno::Sequence< ::rtl::OUString > lExtensions; + css::uno::Sequence< ::rtl::OUString > lURLPattern; + aType[PROPNAME_EXTENSIONS] >>= lExtensions; + aType[PROPNAME_URLPATTERN] >>= lURLPattern; + sal_Int32 ce = lExtensions.getLength(); + sal_Int32 cu = lURLPattern.getLength(); + +#if OSL_DEBUG_LEVEL > 0 + + ::rtl::OUString sInternalTypeNameCheck; + aType[PROPNAME_NAME] >>= sInternalTypeNameCheck; + if (!sInternalTypeNameCheck.equals(sType)) + { + sLog.appendAscii("Warning\t:\t"); + sLog.appendAscii("The type \"" ); + sLog.append (sType ); + sLog.appendAscii("\" does support the property \"Name\" correctly.\n"); + ++nWarnings; + } + + if (!ce && !cu) + { + sLog.appendAscii("Warning\t:\t"); + sLog.appendAscii("The type \"" ); + sLog.append (sType ); + sLog.appendAscii("\" does not contain any URL pattern nor any extensions.\n"); + ++nWarnings; + } +#endif + + // create an optimized registration for this type to + // its set list of extensions/url pattern. If its a "normal" type + // set it at the end of this optimized list. But if its + // a "Preferred" one - set it to the front of this list. + // Of course multiple "Preferred" registrations can occure + // (they shouldnt - but they can!) ... Ignore it. The last + // preferred type is useable in the same manner then every + // other type! + sal_Bool bPreferred = sal_False; + aType[PROPNAME_PREFERRED] >>= bPreferred; + + const ::rtl::OUString* pExtensions = lExtensions.getConstArray(); + for (sal_Int32 e=0; e<ce; ++e) + { + // Note: We must be shure that adress the right hash entry + // does not depend from any upper/lower case problems ... + ::rtl::OUString sNormalizedExtension = pExtensions[e].toAsciiLowerCase(); + + OUStringList& lTypesForExtension = m_lExtensions2Types[sNormalizedExtension]; + if (::std::find(lTypesForExtension.begin(), lTypesForExtension.end(), sType) != lTypesForExtension.end()) + continue; + + if (bPreferred) + lTypesForExtension.insert(lTypesForExtension.begin(), sType); + else + lTypesForExtension.push_back(sType); + } + + const ::rtl::OUString* pURLPattern = lURLPattern.getConstArray(); + for (sal_Int32 u=0; u<cu; ++u) + { + OUStringList& lTypesForURLPattern = m_lURLPattern2Types[pURLPattern[u]]; + if (::std::find(lTypesForURLPattern.begin(), lTypesForURLPattern.end(), sType) != lTypesForURLPattern.end()) + continue; + + if (bPreferred) + lTypesForURLPattern.insert(lTypesForURLPattern.begin(), sType); + else + lTypesForURLPattern.push_back(sType); + } + +#if OSL_DEBUG_LEVEL > 0 + + // Dont check cross references between types and filters, if + // not all filters read from disk! + // OK - this cache can read single filters on demand too ... + // but then the fill state of this cache shouldnt be set to E_CONTAINS_FILTERS! + if (!bAllFiltersShouldExist) + continue; + + ::rtl::OUString sPrefFilter; + aType[PROPNAME_PREFERREDFILTER] >>= sPrefFilter; + if (!sPrefFilter.getLength()) + { + // OK - there is no filter for this type. But thats not an error. + // May be it can be handled by a ContentHandler ... + // But at this time its not guaranteed that there is any ContentHandler + // or FrameLoader inside this cache ... but on disk ... + sal_Bool bReferencedByLoader = sal_True; + sal_Bool bReferencedByHandler = sal_True; + if (bAllLoadersShouldExist) + bReferencedByLoader = (impl_searchFrameLoaderForType(sType).getLength()!=0); + + if (bAllHandlersShouldExist) + bReferencedByHandler = (impl_searchContentHandlerForType(sType).getLength()!=0); + + if ( + (!bReferencedByLoader ) && + (!bReferencedByHandler) + ) + { + sLog.appendAscii("Warning\t:\t" ); + sLog.appendAscii("The type \"" ); + sLog.append (sType ); + sLog.appendAscii("\" isnt used by any filter, loader or content handler.\n"); + ++nWarnings; + } + } + + if (sPrefFilter.getLength()) + { + CacheItemList::const_iterator pIt2 = m_lFilters.find(sPrefFilter); + if (pIt2 == m_lFilters.end()) + { + if (bAllFiltersShouldExist) + { + ++nWarnings; // preferred filters can point to a non-installed office module ! no error ... it's a warning only .-( + sLog.appendAscii("error\t:\t"); + } + else + { + ++nWarnings; + sLog.appendAscii("warning\t:\t"); + } + + sLog.appendAscii("The type \"" ); + sLog.append (sType ); + sLog.appendAscii("\" points to an invalid filter \""); + sLog.append (sPrefFilter ); + sLog.appendAscii("\".\n" ); + + continue; + } + + CacheItem aPrefFilter = pIt2->second; + ::rtl::OUString sFilterTypeReg; + aPrefFilter[PROPNAME_TYPE] >>= sFilterTypeReg; + if (sFilterTypeReg != sType) + { + sLog.appendAscii("error\t:\t" ); + sLog.appendAscii("The preferred filter \"" ); + sLog.append (sPrefFilter ); + sLog.appendAscii("\" of type \"" ); + sLog.append (sType ); + sLog.appendAscii("is registered for another type \""); + sLog.append (sFilterTypeReg ); + sLog.appendAscii("\".\n" ); + ++nErrors; + } + + sal_Int32 nFlags = 0; + aPrefFilter[PROPNAME_FLAGS] >>= nFlags; + if ((nFlags & FLAGVAL_IMPORT) != FLAGVAL_IMPORT) + { + sLog.appendAscii("error\t:\t" ); + sLog.appendAscii("The preferred filter \"" ); + sLog.append (sPrefFilter ); + sLog.appendAscii("\" of type \"" ); + sLog.append (sType ); + sLog.appendAscii("\" is not an IMPORT filter!\n"); + ++nErrors; + } + + ::rtl::OUString sInternalFilterNameCheck; + aPrefFilter[PROPNAME_NAME] >>= sInternalFilterNameCheck; + if (!sInternalFilterNameCheck.equals(sPrefFilter)) + { + sLog.appendAscii("Warning\t:\t" ); + sLog.appendAscii("The filter \"" ); + sLog.append (sPrefFilter ); + sLog.appendAscii("\" does support the property \"Name\" correctly.\n"); + ++nWarnings; + } + } +#endif + } + + // create dependencies between the global default frame loader + // and all types (and of course if registered filters), which + // does not registered for any other loader. + css::uno::Any aDirectValue = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER); + ::rtl::OUString sDefaultFrameLoader; + + if ( + (!(aDirectValue >>= sDefaultFrameLoader)) || + (!sDefaultFrameLoader.getLength() ) + ) + { + sLog.appendAscii("error\t:\t" ); + sLog.appendAscii("There is no valid default frame loader!?\n"); + ++nErrors; + } + + // a) get list of all well known types + // b) step over all well known frame loader services + // and remove all types from list a), which already + // referenced by a loader b) + OUStringList lTypes = getItemNames(E_TYPE); + for ( pIt = m_lFrameLoaders.begin(); + pIt != m_lFrameLoaders.end() ; + ++pIt ) + { + // Note: of course the default loader must be ignored here. + // Because we replace its registration later completly with all + // types, which are not referenced by any other loader. + // So we can avaoid our code against the complexity of a diff! + ::rtl::OUString sLoader = pIt->first; + if (sLoader.equals(sDefaultFrameLoader)) + continue; + + CacheItem& rLoader = pIt->second; + css::uno::Any& rTypesReg = rLoader[PROPNAME_TYPES]; + OUStringList lTypesReg (rTypesReg); + + for (OUStringList::const_iterator pTypesReg = lTypesReg.begin(); + pTypesReg != lTypesReg.end() ; + ++pTypesReg ) + { + OUStringList::iterator pTypeCheck = ::std::find(lTypes.begin(), lTypes.end(), *pTypesReg); + if (pTypeCheck != lTypes.end()) + lTypes.erase(pTypeCheck); + } + } + + CacheItem& rDefaultLoader = m_lFrameLoaders[sDefaultFrameLoader]; + rDefaultLoader[PROPNAME_NAME ] <<= sDefaultFrameLoader; + rDefaultLoader[PROPNAME_TYPES] <<= lTypes.getAsConstList(); + + ::rtl::OUString sLogOut = sLog.makeStringAndClear(); + OSL_ENSURE(!nErrors, ::rtl::OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr()); + if (nErrors>0) + throw css::document::CorruptedFilterConfigurationException( + MESSAGE_CORRUPTED_FILTERCONFIG, + css::uno::Reference< css::uno::XInterface >(), + sLogOut); + OSL_ENSURE(!nWarnings, ::rtl::OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr()); + + // <- SAFE +} + +/*----------------------------------------------- + 20.10.2003 08:15 +-----------------------------------------------*/ +void FilterCache::impl_addItem2FlushList( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + OUStringList* pList = 0; + switch(eType) + { + case E_TYPE : + pList = &m_lChangedTypes; + break; + + case E_FILTER : + pList = &m_lChangedFilters; + break; + + case E_FRAMELOADER : + pList = &m_lChangedFrameLoaders; + break; + + case E_CONTENTHANDLER : + pList = &m_lChangedContentHandlers; + break; + + case E_DETECTSERVICE : + pList = &m_lChangedDetectServices; + break; + + default : throw css::uno::Exception(::rtl::OUString::createFromAscii("unsupported item type"), 0); + } + + OUStringList::const_iterator pItem = ::std::find(pList->begin(), pList->end(), sItem); + if (pItem == pList->end()) + pList->push_back(sItem); +} + +/*----------------------------------------------- + 20.10.2003 08:49 +-----------------------------------------------*/ +FilterCache::EItemFlushState FilterCache::impl_specifyFlushOperation(const css::uno::Reference< css::container::XNameAccess >& xSet , + const CacheItemList& rList, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + sal_Bool bExistsInConfigLayer = xSet->hasByName(sItem); + sal_Bool bExistsInMemory = (rList.find(sItem) != rList.end()); + + EItemFlushState eState( E_ITEM_UNCHANGED ); + + // !? ... such situation can occure, if an item was added and(!) removed before it was flushed :-) + if (!bExistsInConfigLayer && !bExistsInMemory) + eState = E_ITEM_UNCHANGED; + else + if (!bExistsInConfigLayer && bExistsInMemory) + eState = E_ITEM_ADDED; + else + if (bExistsInConfigLayer && bExistsInMemory) + eState = E_ITEM_CHANGED; + else + if (bExistsInConfigLayer && !bExistsInMemory) + eState = E_ITEM_REMOVED; + + return eState; +} + +/*----------------------------------------------- + 14.10.2003 09:26 +-----------------------------------------------*/ +void FilterCache::impl_resolveItem4TypeRegistration( CacheItemList* pList, + const ::rtl::OUString& sItem, + const ::rtl::OUString& sType) + throw(css::uno::Exception) +{ + CacheItem& rItem = (*pList)[sItem]; + // In case its a new created entry (automaticly done by the hash_map index operator!) + // we must be shure, that this entry has its own name as property available. + // Its needed later at our container interface! + rItem[PROPNAME_NAME] <<= sItem; + + OUStringList lTypeRegs(rItem[PROPNAME_TYPES]); + if (::std::find(lTypeRegs.begin(), lTypeRegs.end(), sType) == lTypeRegs.end()) + { + lTypeRegs.push_back(sType); + rItem[PROPNAME_TYPES] <<= lTypeRegs.getAsConstList(); + } +} + +/*----------------------------------------------- + 28.10.2003 09:18 +-----------------------------------------------*/ +void FilterCache::impl_load(EFillState eRequiredState) + throw(css::uno::Exception) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // Attention: Detect services are part of the standard set! + // So there is no need to handle it seperatly. + + // ------------------------------------------ + // a) The standard set of config value is needed. + if ( + ((eRequiredState & E_CONTAINS_STANDARD) == E_CONTAINS_STANDARD) && + ((m_eFillState & E_CONTAINS_STANDARD) != E_CONTAINS_STANDARD) + ) + { + // Attention! If config couldnt be opened successfully + // and exception os thrown automaticly and must be forwarded + // to our calli ... + css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY); + { + RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load std"); + impl_loadSet(xTypes, E_TYPE, E_READ_STANDARD, &m_lTypes); + } + } + + // ------------------------------------------ + // b) We need all type informations ... + if ( + ((eRequiredState & E_CONTAINS_TYPES) == E_CONTAINS_TYPES) && + ((m_eFillState & E_CONTAINS_TYPES) != E_CONTAINS_TYPES) + ) + { + // Attention! If config couldnt be opened successfully + // and exception os thrown automaticly and must be forwarded + // to our calli ... + css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY); + { + RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all types"); + impl_loadSet(xTypes, E_TYPE, E_READ_UPDATE, &m_lTypes); + } + } + + // ------------------------------------------ + // c) We need all filter informations ... + if ( + ((eRequiredState & E_CONTAINS_FILTERS) == E_CONTAINS_FILTERS) && + ((m_eFillState & E_CONTAINS_FILTERS) != E_CONTAINS_FILTERS) + ) + { + // Attention! If config couldnt be opened successfully + // and exception os thrown automaticly and must be forwarded + // to our calli ... + css::uno::Reference< css::container::XNameAccess > xFilters(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY); + { + RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all filters"); + impl_loadSet(xFilters, E_FILTER, E_READ_ALL, &m_lFilters); + } + } + + // ------------------------------------------ + // c) We need all frame loader informations ... + if ( + ((eRequiredState & E_CONTAINS_FRAMELOADERS) == E_CONTAINS_FRAMELOADERS) && + ((m_eFillState & E_CONTAINS_FRAMELOADERS) != E_CONTAINS_FRAMELOADERS) + ) + { + // Attention! If config couldnt be opened successfully + // and exception os thrown automaticly and must be forwarded + // to our calli ... + css::uno::Reference< css::container::XNameAccess > xLoaders(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY); + { + RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all frame loader"); + impl_loadSet(xLoaders, E_FRAMELOADER, E_READ_ALL, &m_lFrameLoaders); + } + } + + // ------------------------------------------ + // d) We need all content handler informations ... + if ( + ((eRequiredState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS) && + ((m_eFillState & E_CONTAINS_CONTENTHANDLERS) != E_CONTAINS_CONTENTHANDLERS) + ) + { + // Attention! If config couldnt be opened successfully + // and exception os thrown automaticly and must be forwarded + // to our calli ... + css::uno::Reference< css::container::XNameAccess > xHandlers(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY); + { + RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all content handler"); + impl_loadSet(xHandlers, E_CONTENTHANDLER, E_READ_ALL, &m_lContentHandlers); + } + } + + // update fill state. Note: its a bit field, which combines different parts. + m_eFillState = (EFillState) ((sal_Int32)m_eFillState | (sal_Int32)eRequiredState); + + // any data readed? + // yes! => validate it and update optimized structures. + impl_validateAndOptimize(); + + // <- SAFE +} + +/*----------------------------------------------- + 22.09.2003 14:27 +-----------------------------------------------*/ +void FilterCache::impl_loadSet(const css::uno::Reference< css::container::XNameAccess >& xConfig, + EItemType eType , + EReadOption eOption, + CacheItemList* pCache ) + throw(css::uno::Exception) +{ + // get access to the right configuration set + ::rtl::OUString sSetName; + switch(eType) + { + case E_TYPE : + sSetName = CFGSET_TYPES; + break; + + case E_FILTER : + sSetName = CFGSET_FILTERS; + break; + + case E_FRAMELOADER : + sSetName = CFGSET_FRAMELOADERS; + break; + + case E_CONTENTHANDLER : + sSetName = CFGSET_CONTENTHANDLERS; + break; + default: break; + } + + css::uno::Reference< css::container::XNameAccess > xSet; + css::uno::Sequence< ::rtl::OUString > lItems; + + try + { + css::uno::Any aVal = xConfig->getByName(sSetName); + if (!(aVal >>= xSet) || !xSet.is()) + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("Could not open configuration set \""); + sMsg.append (sSetName ); + sMsg.appendAscii("\"." ); + throw css::uno::Exception( + sMsg.makeStringAndClear(), + css::uno::Reference< css::uno::XInterface >()); + } + lItems = xSet->getElementNames(); + } + catch(const css::uno::Exception& ex) + { + throw css::document::CorruptedFilterConfigurationException( + MESSAGE_CORRUPTED_FILTERCONFIG, + css::uno::Reference< css::uno::XInterface >(), + ex.Message); + } + + // get names of all existing sub items of this set + // step over it and fill internal cache structures. + + // But dont update optimized structures like e.g. hash + // for mapping extensions to its types! + + const ::rtl::OUString* pItems = lItems.getConstArray(); + sal_Int32 c = lItems.getLength(); + for (sal_Int32 i=0; i<c; ++i) + { + CacheItemList::iterator pItem = pCache->find(pItems[i]); + switch(eOption) + { + // a) read a standard set of properties only or read all + case E_READ_STANDARD : + case E_READ_ALL : + { + try + { + (*pCache)[pItems[i]] = impl_loadItem(xSet, eType, pItems[i], eOption); + } + catch(const css::uno::Exception& ex) + { + throw css::document::CorruptedFilterConfigurationException( + MESSAGE_CORRUPTED_FILTERCONFIG, + css::uno::Reference< css::uno::XInterface >(), + ex.Message); + } + } + break; + + // b) read optional properties only! + // All items must already exist inside our cache. + // But they must be updated. + case E_READ_UPDATE : + { + if (pItem == pCache->end()) + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("item \"" ); + sMsg.append (pItems[i] ); + sMsg.appendAscii("\" not found for update!"); + throw css::uno::Exception(sMsg.makeStringAndClear() , + css::uno::Reference< css::uno::XInterface >()); + } + try + { + CacheItem aItem = impl_loadItem(xSet, eType, pItems[i], eOption); + pItem->second.update(aItem); + } + catch(const css::uno::Exception& ex) + { + throw css::document::CorruptedFilterConfigurationException( + MESSAGE_CORRUPTED_FILTERCONFIG, + css::uno::Reference< css::uno::XInterface >(), + ex.Message); + } + } + break; + default: break; + } + } +} + +/*----------------------------------------------- + 26.11.2003 12:49 +-----------------------------------------------*/ +void FilterCache::impl_readPatchUINames(const css::uno::Reference< css::container::XNameAccess >& xNode, + CacheItem& rItem) + throw(css::uno::Exception) +{ + static ::rtl::OUString FORMATNAME_VAR = ::rtl::OUString::createFromAscii("%productname%" ); + static ::rtl::OUString FORMATVERSION_VAR = ::rtl::OUString::createFromAscii("%formatversion%"); + + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + ::rtl::OUString sFormatName = m_sFormatName ; + ::rtl::OUString sFormatVersion = m_sFormatVersion; + ::rtl::OUString sActLocale = m_sActLocale ; + aLock.clear(); + // <- SAFE ---------------------------------- + + css::uno::Any aVal = xNode->getByName(PROPNAME_UINAME); + css::uno::Reference< css::container::XNameAccess > xUIName; + if (!(aVal >>= xUIName) && !xUIName.is()) + return; + + const ::comphelper::SequenceAsVector< ::rtl::OUString > lLocales(xUIName->getElementNames()); + ::comphelper::SequenceAsVector< ::rtl::OUString >::const_iterator pLocale ; + ::comphelper::SequenceAsHashMap lUINames; + + // patch %PRODUCTNAME and %FORMATNAME + for ( pLocale = lLocales.begin(); + pLocale != lLocales.end() ; + ++pLocale ) + { + const ::rtl::OUString& sLocale = *pLocale; + + ::rtl::OUString sValue; + xUIName->getByName(sLocale) >>= sValue; + + // replace %productname% + sal_Int32 nIndex = sValue.indexOf(FORMATNAME_VAR); + while(nIndex != -1) + { + sValue = sValue.replaceAt(nIndex, FORMATNAME_VAR.getLength(), sFormatName); + nIndex = sValue.indexOf(FORMATNAME_VAR, nIndex); + } + // replace %formatversion% + nIndex = sValue.indexOf(FORMATVERSION_VAR); + while(nIndex != -1) + { + sValue = sValue.replaceAt(nIndex, FORMATVERSION_VAR.getLength(), sFormatVersion); + nIndex = sValue.indexOf(FORMATVERSION_VAR, nIndex); + } + + lUINames[sLocale] <<= sValue; + } + + aVal <<= lUINames.getAsConstPropertyValueList(); + rItem[PROPNAME_UINAMES] = aVal; + + // find right UIName for current office locale + // Use fallbacks too! + pLocale = ::comphelper::Locale::getFallback(lLocales, sActLocale); + if (pLocale == lLocales.end()) + { + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OUString sName = rItem.getUnpackedValueOrDefault(PROPNAME_NAME, ::rtl::OUString()); + + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("Fallback scenario for filter or type '" ); + sMsg.append (sName ); + sMsg.appendAscii("' and locale '" ); + sMsg.append (sActLocale ); + sMsg.appendAscii("' failed. Please check your filter configuration."); + + OSL_ENSURE(sal_False, _FILTER_CONFIG_TO_ASCII_(sMsg.makeStringAndClear())); + #endif + return; + } + + const ::rtl::OUString& sLocale = *pLocale; + ::comphelper::SequenceAsHashMap::const_iterator pUIName = lUINames.find(sLocale); + if (pUIName != lUINames.end()) + rItem[PROPNAME_UINAME] = pUIName->second; +} + +/*----------------------------------------------- + 26.11.2003 12:56 +-----------------------------------------------*/ +void FilterCache::impl_savePatchUINames(const css::uno::Reference< css::container::XNameReplace >& xNode, + const CacheItem& rItem) + throw(css::uno::Exception) +{ + css::uno::Reference< css::container::XNameContainer > xAdd (xNode, css::uno::UNO_QUERY); + css::uno::Reference< css::container::XNameAccess > xCheck(xNode, css::uno::UNO_QUERY); + + css::uno::Sequence< css::beans::PropertyValue > lUINames = rItem.getUnpackedValueOrDefault(PROPNAME_UINAMES, css::uno::Sequence< css::beans::PropertyValue >()); + sal_Int32 c = lUINames.getLength(); + const css::beans::PropertyValue* pUINames = lUINames.getConstArray(); + + for (sal_Int32 i=0; i<c; ++i) + { + if (xCheck->hasByName(pUINames[i].Name)) + xNode->replaceByName(pUINames[i].Name, pUINames[i].Value); + else + xAdd->insertByName(pUINames[i].Name, pUINames[i].Value); + } +} + +/*----------------------------------------------- + 29.10.2003 13:17 + TODO + clarify, how the real problem behind the + wrong constructed CacheItem instance (which + will force a crash during destruction) + can be solved ... +-----------------------------------------------*/ +CacheItem FilterCache::impl_loadItem(const css::uno::Reference< css::container::XNameAccess >& xSet , + EItemType eType , + const ::rtl::OUString& sItem , + EReadOption eOption) + throw(css::uno::Exception) +{ + // try to get an API object, which points directly to the + // requested item. If it fail an exception should occure and + // break this operation. Of course returned API object must be + // checked too. + css::uno::Reference< css::container::XNameAccess > xItem; + #ifdef WORKAROUND_EXCEPTION_PROBLEM + try + { + #endif + css::uno::Any aVal = xSet->getByName(sItem); + if (!(aVal >>= xItem) || !xItem.is()) + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("found corrupted item \""); + sMsg.append (sItem ); + sMsg.appendAscii("\"." ); + throw css::uno::Exception(sMsg.makeStringAndClear() , + css::uno::Reference< css::uno::XInterface >()); + } + #ifdef WORKAROUND_EXCEPTION_PROBLEM + } + catch(const css::container::NoSuchElementException&) + { + throw; + } + #endif + + // The internal name of an item must(!) be part of the property + // set too. Of course its already used as key into the e.g. outside + // used hash map ... but some of our API methods provide + // this property set as result only. But the user of this CacheItem + // should know, which value the key names has :-) ITS IMPORTANT! + CacheItem aItem; + aItem[PROPNAME_NAME] = css::uno::makeAny(sItem); + switch(eType) + { + //--------------------------------------- + case E_TYPE : + { + // read standard properties of a type + if ( + (eOption == E_READ_STANDARD) || + (eOption == E_READ_ALL ) + ) + { + aItem[PROPNAME_PREFERREDFILTER] = xItem->getByName(PROPNAME_PREFERREDFILTER); + aItem[PROPNAME_DETECTSERVICE ] = xItem->getByName(PROPNAME_DETECTSERVICE ); + aItem[PROPNAME_URLPATTERN ] = xItem->getByName(PROPNAME_URLPATTERN ); + aItem[PROPNAME_EXTENSIONS ] = xItem->getByName(PROPNAME_EXTENSIONS ); + aItem[PROPNAME_PREFERRED ] = xItem->getByName(PROPNAME_PREFERRED ); + aItem[PROPNAME_CLIPBOARDFORMAT] = xItem->getByName(PROPNAME_CLIPBOARDFORMAT); + } + // read optional properties of a type + // no else here! Is an additional switch ... + if ( + (eOption == E_READ_UPDATE) || + (eOption == E_READ_ALL ) + ) + { + aItem[PROPNAME_MEDIATYPE ] = xItem->getByName(PROPNAME_MEDIATYPE ); + impl_readPatchUINames(xItem, aItem); + } + } + break; + + //--------------------------------------- + case E_FILTER : + { + // read standard properties of a filter + if ( + (eOption == E_READ_STANDARD) || + (eOption == E_READ_ALL ) + ) + { + aItem[PROPNAME_TYPE ] = xItem->getByName(PROPNAME_TYPE ); + aItem[PROPNAME_FILEFORMATVERSION] = xItem->getByName(PROPNAME_FILEFORMATVERSION); + aItem[PROPNAME_UICOMPONENT ] = xItem->getByName(PROPNAME_UICOMPONENT ); + aItem[PROPNAME_FILTERSERVICE ] = xItem->getByName(PROPNAME_FILTERSERVICE ); + aItem[PROPNAME_DOCUMENTSERVICE ] = xItem->getByName(PROPNAME_DOCUMENTSERVICE ); + + // special handling for flags! Convert it from a list of names to its + // int representation ... + css::uno::Sequence< ::rtl::OUString > lFlagNames; + if (xItem->getByName(PROPNAME_FLAGS) >>= lFlagNames) + aItem[PROPNAME_FLAGS] <<= FilterCache::impl_convertFlagNames2FlagField(lFlagNames); + } + // read optional properties of a filter + // no else here! Is an additional switch ... + if ( + (eOption == E_READ_UPDATE) || + (eOption == E_READ_ALL ) + ) + { + aItem[PROPNAME_USERDATA ] = xItem->getByName(PROPNAME_USERDATA ); + aItem[PROPNAME_TEMPLATENAME] = xItem->getByName(PROPNAME_TEMPLATENAME); +//TODO remove it if moving of filter uinames to type uinames +// will be finished realy +#ifdef AS_ENABLE_FILTER_UINAMES + impl_readPatchUINames(xItem, aItem); +#endif // AS_ENABLE_FILTER_UINAMES + } + } + break; + + //--------------------------------------- + case E_FRAMELOADER : + case E_CONTENTHANDLER : + { + aItem[PROPNAME_TYPES] = xItem->getByName(PROPNAME_TYPES); + } + break; + default: break; + } + + return aItem; +} + +/*----------------------------------------------- + 27.10.2003 08:47 +-----------------------------------------------*/ +CacheItemList::iterator FilterCache::impl_loadItemOnDemand( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + CacheItemList* pList = 0; + css::uno::Reference< css::uno::XInterface > xConfig ; + ::rtl::OUString sSet ; + + switch(eType) + { + case E_TYPE : + { + pList = &m_lTypes; + xConfig = impl_openConfig(E_PROVIDER_TYPES); + sSet = CFGSET_TYPES; + } + break; + + case E_FILTER : + { + pList = &m_lFilters; + xConfig = impl_openConfig(E_PROVIDER_FILTERS); + sSet = CFGSET_FILTERS; + } + break; + + case E_FRAMELOADER : + { + pList = &m_lFrameLoaders; + xConfig = impl_openConfig(E_PROVIDER_OTHERS); + sSet = CFGSET_FRAMELOADERS; + } + break; + + case E_CONTENTHANDLER : + { + pList = &m_lContentHandlers; + xConfig = impl_openConfig(E_PROVIDER_OTHERS); + sSet = CFGSET_CONTENTHANDLERS; + } + break; + + case E_DETECTSERVICE : + { + OSL_ENSURE(sal_False, "Cant load detect services on demand. Who use this unsupported feature?"); + } + break; + } + + css::uno::Reference< css::container::XNameAccess > xRoot(xConfig, css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::container::XNameAccess > xSet ; + xRoot->getByName(sSet) >>= xSet; + + CacheItemList::iterator pItemInCache = pList->find(sItem); + sal_Bool bItemInConfig = xSet->hasByName(sItem); + + if (bItemInConfig) + { + CacheItem aItem; + CacheItem::iterator pDbgTest = aItem.find(PROPNAME_NAME); + aItem = impl_loadItem(xSet, eType, sItem, E_READ_ALL); + (*pList)[sItem] = aItem; + _FILTER_CONFIG_LOG_2_("impl_loadItemOnDemand(%d, \"%s\") ... OK", (int)eType, _FILTER_CONFIG_TO_ASCII_(sItem).getStr()) + } + else + { + if (pItemInCache != pList->end()) + pList->erase(pItemInCache); + // OK - this item does not exists inside configuration. + // And we already updated our internal cache. + // But the outside code needs this NoSuchElementException + // to know, that this item does notexists. + // Nobody checks the iterator! + throw css::container::NoSuchElementException(); + } + + return pList->find(sItem); +} + +/*----------------------------------------------- + 20.10.2003 09:38 +-----------------------------------------------*/ +void FilterCache::impl_saveItem(const css::uno::Reference< css::container::XNameReplace >& xItem, + EItemType eType, + const CacheItem& aItem) + throw(css::uno::Exception) +{ + CacheItem::const_iterator pIt; + switch(eType) + { + //--------------------------------------- + case E_TYPE : + { + pIt = aItem.find(PROPNAME_PREFERREDFILTER); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_PREFERREDFILTER, pIt->second); + pIt = aItem.find(PROPNAME_DETECTSERVICE); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_DETECTSERVICE, pIt->second); + pIt = aItem.find(PROPNAME_URLPATTERN); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_URLPATTERN, pIt->second); + pIt = aItem.find(PROPNAME_EXTENSIONS); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_EXTENSIONS, pIt->second); + pIt = aItem.find(PROPNAME_PREFERRED); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_PREFERRED, pIt->second); + pIt = aItem.find(PROPNAME_MEDIATYPE); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_MEDIATYPE, pIt->second); + pIt = aItem.find(PROPNAME_CLIPBOARDFORMAT); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_CLIPBOARDFORMAT, pIt->second); + + css::uno::Reference< css::container::XNameReplace > xUIName; + xItem->getByName(PROPNAME_UINAME) >>= xUIName; + impl_savePatchUINames(xUIName, aItem); + } + break; + + //--------------------------------------- + case E_FILTER : + { + pIt = aItem.find(PROPNAME_TYPE); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_TYPE, pIt->second); + pIt = aItem.find(PROPNAME_FILEFORMATVERSION); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_FILEFORMATVERSION, pIt->second); + pIt = aItem.find(PROPNAME_UICOMPONENT); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_UICOMPONENT, pIt->second); + pIt = aItem.find(PROPNAME_FILTERSERVICE); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_FILTERSERVICE, pIt->second); + pIt = aItem.find(PROPNAME_DOCUMENTSERVICE); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_DOCUMENTSERVICE, pIt->second); + pIt = aItem.find(PROPNAME_USERDATA); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_USERDATA, pIt->second); + pIt = aItem.find(PROPNAME_TEMPLATENAME); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_TEMPLATENAME, pIt->second); + + // special handling for flags! Convert it from an integer flag field back + // to a list of names ... + // But note: because we work directly on a reference to the cache item, + // its not allowd to change the value here. We must work on a copy! + sal_Int32 nFlags = 0; + pIt = aItem.find(PROPNAME_FLAGS); + if (pIt != aItem.end()) + { + pIt->second >>= nFlags; + css::uno::Any aFlagNameList; + aFlagNameList <<= FilterCache::impl_convertFlagField2FlagNames(nFlags); + xItem->replaceByName(PROPNAME_FLAGS, aFlagNameList); + } + +//TODO remove it if moving of filter uinames to type uinames +// will be finished realy +#ifdef AS_ENABLE_FILTER_UINAMES + css::uno::Reference< css::container::XNameReplace > xUIName; + xItem->getByName(PROPNAME_UINAME) >>= xUIName; + impl_savePatchUINames(xUIName, aItem); +#endif // AS_ENABLE_FILTER_UINAMES + } + break; + + //--------------------------------------- + case E_FRAMELOADER : + case E_CONTENTHANDLER : + { + pIt = aItem.find(PROPNAME_TYPES); + if (pIt != aItem.end()) + xItem->replaceByName(PROPNAME_TYPES, pIt->second); + } + break; + default: break; + } +} + +/*----------------------------------------------- + 20.10.2003 09:45 + static! => no locks neccessary +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > FilterCache::impl_convertFlagField2FlagNames(sal_Int32 nFlags) +{ + OUStringList lFlagNames; + + if ((nFlags & FLAGVAL_3RDPARTYFILTER ) == FLAGVAL_3RDPARTYFILTER ) lFlagNames.push_back(FLAGNAME_3RDPARTYFILTER ); + if ((nFlags & FLAGVAL_ALIEN ) == FLAGVAL_ALIEN ) lFlagNames.push_back(FLAGNAME_ALIEN ); + if ((nFlags & FLAGVAL_ASYNCHRON ) == FLAGVAL_ASYNCHRON ) lFlagNames.push_back(FLAGNAME_ASYNCHRON ); + if ((nFlags & FLAGVAL_BROWSERPREFERRED ) == FLAGVAL_BROWSERPREFERRED ) lFlagNames.push_back(FLAGNAME_BROWSERPREFERRED ); + if ((nFlags & FLAGVAL_CONSULTSERVICE ) == FLAGVAL_CONSULTSERVICE ) lFlagNames.push_back(FLAGNAME_CONSULTSERVICE ); + if ((nFlags & FLAGVAL_DEFAULT ) == FLAGVAL_DEFAULT ) lFlagNames.push_back(FLAGNAME_DEFAULT ); + if ((nFlags & FLAGVAL_ENCRYPTION ) == FLAGVAL_ENCRYPTION ) lFlagNames.push_back(FLAGNAME_ENCRYPTION ); + if ((nFlags & FLAGVAL_EXPORT ) == FLAGVAL_EXPORT ) lFlagNames.push_back(FLAGNAME_EXPORT ); + if ((nFlags & FLAGVAL_IMPORT ) == FLAGVAL_IMPORT ) lFlagNames.push_back(FLAGNAME_IMPORT ); + if ((nFlags & FLAGVAL_INTERNAL ) == FLAGVAL_INTERNAL ) lFlagNames.push_back(FLAGNAME_INTERNAL ); + if ((nFlags & FLAGVAL_NOTINCHOOSER ) == FLAGVAL_NOTINCHOOSER ) lFlagNames.push_back(FLAGNAME_NOTINCHOOSER ); + if ((nFlags & FLAGVAL_NOTINFILEDIALOG ) == FLAGVAL_NOTINFILEDIALOG ) lFlagNames.push_back(FLAGNAME_NOTINFILEDIALOG ); + if ((nFlags & FLAGVAL_NOTINSTALLED ) == FLAGVAL_NOTINSTALLED ) lFlagNames.push_back(FLAGNAME_NOTINSTALLED ); + if ((nFlags & FLAGVAL_OWN ) == FLAGVAL_OWN ) lFlagNames.push_back(FLAGNAME_OWN ); + if ((nFlags & FLAGVAL_PACKED ) == FLAGVAL_PACKED ) lFlagNames.push_back(FLAGNAME_PACKED ); + if ((nFlags & FLAGVAL_PASSWORDTOMODIFY ) == FLAGVAL_PASSWORDTOMODIFY ) lFlagNames.push_back(FLAGNAME_PASSWORDTOMODIFY ); + if ((nFlags & FLAGVAL_PREFERRED ) == FLAGVAL_PREFERRED ) lFlagNames.push_back(FLAGNAME_PREFERRED ); + if ((nFlags & FLAGVAL_READONLY ) == FLAGVAL_READONLY ) lFlagNames.push_back(FLAGNAME_READONLY ); + if ((nFlags & FLAGVAL_SILENTEXPORT ) == FLAGVAL_SILENTEXPORT ) lFlagNames.push_back(FLAGNAME_SILENTEXPORT ); + if ((nFlags & FLAGVAL_SUPPORTSSELECTION) == FLAGVAL_SUPPORTSSELECTION) lFlagNames.push_back(FLAGNAME_SUPPORTSSELECTION); + if ((nFlags & FLAGVAL_TEMPLATE ) == FLAGVAL_TEMPLATE ) lFlagNames.push_back(FLAGNAME_TEMPLATE ); + if ((nFlags & FLAGVAL_TEMPLATEPATH ) == FLAGVAL_TEMPLATEPATH ) lFlagNames.push_back(FLAGNAME_TEMPLATEPATH ); + if ((nFlags & FLAGVAL_USESOPTIONS ) == FLAGVAL_USESOPTIONS ) lFlagNames.push_back(FLAGNAME_USESOPTIONS ); + if ((nFlags & FLAGVAL_COMBINED ) == FLAGVAL_COMBINED ) lFlagNames.push_back(FLAGNAME_COMBINED ); + + return lFlagNames.getAsConstList(); +} + +/*----------------------------------------------- + 27.06.2003 09:26 + static! => no locks neccessary +-----------------------------------------------*/ +sal_Int32 FilterCache::impl_convertFlagNames2FlagField(const css::uno::Sequence< ::rtl::OUString >& lNames) +{ + sal_Int32 nField = 0; + + const ::rtl::OUString* pNames = lNames.getConstArray(); + sal_Int32 c = lNames.getLength(); + for (sal_Int32 i=0; i<c; ++i) + { + if (pNames[i].equals(FLAGNAME_3RDPARTYFILTER)) + { + nField |= FLAGVAL_3RDPARTYFILTER; + continue; + } + if (pNames[i].equals(FLAGNAME_ALIEN)) + { + nField |= FLAGVAL_ALIEN; + continue; + } + if (pNames[i].equals(FLAGNAME_ASYNCHRON)) + { + nField |= FLAGVAL_ASYNCHRON; + continue; + } + if (pNames[i].equals(FLAGNAME_BROWSERPREFERRED)) + { + nField |= FLAGVAL_BROWSERPREFERRED; + continue; + } + if (pNames[i].equals(FLAGNAME_CONSULTSERVICE)) + { + nField |= FLAGVAL_CONSULTSERVICE; + continue; + } + if (pNames[i].equals(FLAGNAME_DEFAULT)) + { + nField |= FLAGVAL_DEFAULT; + continue; + } + if (pNames[i].equals(FLAGNAME_ENCRYPTION)) + { + nField |= FLAGVAL_ENCRYPTION; + continue; + } + if (pNames[i].equals(FLAGNAME_EXPORT)) + { + nField |= FLAGVAL_EXPORT; + continue; + } + if (pNames[i].equals(FLAGNAME_IMPORT)) + { + nField |= FLAGVAL_IMPORT; + continue; + } + if (pNames[i].equals(FLAGNAME_INTERNAL)) + { + nField |= FLAGVAL_INTERNAL; + continue; + } + if (pNames[i].equals(FLAGNAME_NOTINCHOOSER)) + { + nField |= FLAGVAL_NOTINCHOOSER; + continue; + } + if (pNames[i].equals(FLAGNAME_NOTINFILEDIALOG)) + { + nField |= FLAGVAL_NOTINFILEDIALOG; + continue; + } + if (pNames[i].equals(FLAGNAME_NOTINSTALLED)) + { + nField |= FLAGVAL_NOTINSTALLED; + continue; + } + if (pNames[i].equals(FLAGNAME_OWN)) + { + nField |= FLAGVAL_OWN; + continue; + } + if (pNames[i].equals(FLAGNAME_PACKED)) + { + nField |= FLAGVAL_PACKED; + continue; + } + if (pNames[i].equals(FLAGNAME_PASSWORDTOMODIFY)) + { + nField |= FLAGVAL_PASSWORDTOMODIFY; + continue; + } + if (pNames[i].equals(FLAGNAME_PREFERRED)) + { + nField |= FLAGVAL_PREFERRED; + continue; + } + if (pNames[i].equals(FLAGNAME_READONLY)) + { + nField |= FLAGVAL_READONLY; + continue; + } + if (pNames[i].equals(FLAGNAME_SILENTEXPORT)) + { + nField |= FLAGVAL_SILENTEXPORT; + continue; + } + if (pNames[i].equals(FLAGNAME_SUPPORTSSELECTION)) + { + nField |= FLAGVAL_SUPPORTSSELECTION; + continue; + } + if (pNames[i].equals(FLAGNAME_TEMPLATE)) + { + nField |= FLAGVAL_TEMPLATE; + continue; + } + if (pNames[i].equals(FLAGNAME_TEMPLATEPATH)) + { + nField |= FLAGVAL_TEMPLATEPATH; + continue; + } + if (pNames[i].equals(FLAGNAME_USESOPTIONS)) + { + nField |= FLAGVAL_USESOPTIONS; + continue; + } + if (pNames[i].equals(FLAGNAME_COMBINED)) + { + nField |= FLAGVAL_COMBINED; + continue; + } + } + + return nField; +} + +/*----------------------------------------------- + 12.02.2004 08:40 +-----------------------------------------------*/ +void FilterCache::impl_interpretDataVal4Type(const ::rtl::OUString& sValue, + sal_Int32 nProp , + CacheItem& rItem ) +{ + switch(nProp) + { + // Preferred + case 0: { + if (sValue.toInt32() == 1) + rItem[PROPNAME_PREFERRED] = css::uno::makeAny(sal_True); + else + rItem[PROPNAME_PREFERRED] = css::uno::makeAny(sal_False); + } + break; + // MediaType + case 1: rItem[PROPNAME_MEDIATYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + break; + // ClipboardFormat + case 2: rItem[PROPNAME_CLIPBOARDFORMAT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + break; + // URLPattern + case 3: rItem[PROPNAME_URLPATTERN] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList(); + break; + // Extensions + case 4: rItem[PROPNAME_EXTENSIONS] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList(); + break; + } +} + +/*----------------------------------------------- + 12.02.2004 08:50 +-----------------------------------------------*/ +void FilterCache::impl_interpretDataVal4Filter(const ::rtl::OUString& sValue, + sal_Int32 nProp , + CacheItem& rItem ) +{ + switch(nProp) + { + // Order + case 0: { + sal_Int32 nOrder = sValue.toInt32(); + if (nOrder > 0) + { + OSL_ENSURE(sal_False, "FilterCache::impl_interpretDataVal4Filter()\nCant move Order value from filter to type on demand!\n"); + _FILTER_CONFIG_LOG_2_("impl_interpretDataVal4Filter(%d, \"%s\") ... OK", (int)eType, _FILTER_CONFIG_TO_ASCII_(rItem).getStr()) + } + } + break; + // Type + case 1: rItem[PROPNAME_TYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + break; + // DocumentService + case 2: rItem[PROPNAME_DOCUMENTSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + break; + // FilterService + case 3: rItem[PROPNAME_FILTERSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + break; + // Flags + case 4: rItem[PROPNAME_FLAGS] <<= sValue.toInt32(); + break; + // UserData + case 5: rItem[PROPNAME_USERDATA] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList(); + break; + // FileFormatVersion + case 6: rItem[PROPNAME_FILEFORMATVERSION] <<= sValue.toInt32(); + break; + // TemplateName + case 7: rItem[PROPNAME_TEMPLATENAME] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + break; + // [optional!] UIComponent + case 8: rItem[PROPNAME_UICOMPONENT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + break; + } +} + +/*----------------------------------------------- + 12.02.2004 08:30 + TODO work on a cache copy first, which can be flushed afterwards + That would be usefully to gurantee a consistent cache. +-----------------------------------------------*/ +void FilterCache::impl_readOldFormat() + throw(css::uno::Exception) +{ + static ::rtl::OUString TYPES_SET = ::rtl::OUString::createFromAscii("Types" ); + static ::rtl::OUString FILTER_SET = ::rtl::OUString::createFromAscii("Filters"); + + // Attention: Opening/Reading of this old configuration format has to be handled gracefully. + // Its optional and shouldnt disturb our normal work! + // E.g. we must check, if the package exists ... + + css::uno::Reference< css::container::XNameAccess > xCfg; + try + { + css::uno::Reference< css::uno::XInterface > xInt = impl_openConfig(E_PROVIDER_OLD); + xCfg = css::uno::Reference< css::container::XNameAccess >(xInt, css::uno::UNO_QUERY_THROW); + } + /* corrupt filter addon ? because it's external (optional) code .. we can ignore it. Addon wont work then ... + but that seams to be acceptable. + see #139088# for further informations + */ + catch(const css::uno::Exception&) + { return; } + + // May be there is no type set ... + if (xCfg->hasByName(TYPES_SET)) + { + css::uno::Reference< css::container::XNameAccess > xSet; + xCfg->getByName(TYPES_SET) >>= xSet; + const css::uno::Sequence< ::rtl::OUString > lItems = xSet->getElementNames(); + const ::rtl::OUString* pItems = lItems.getConstArray(); + for (sal_Int32 i=0; i<lItems.getLength(); ++i) + m_lTypes[pItems[i]] = impl_readOldItem(xSet, E_TYPE, pItems[i]); + } + + // May be there is no filter set ... + if (xCfg->hasByName(FILTER_SET)) + { + css::uno::Reference< css::container::XNameAccess > xSet; + xCfg->getByName(FILTER_SET) >>= xSet; + const css::uno::Sequence< ::rtl::OUString > lItems = xSet->getElementNames(); + const ::rtl::OUString* pItems = lItems.getConstArray(); + for (sal_Int32 i=0; i<lItems.getLength(); ++i) + m_lFilters[pItems[i]] = impl_readOldItem(xSet, E_FILTER, pItems[i]); + } +} + +/*----------------------------------------------- + 12.02.2004 08:30 +-----------------------------------------------*/ +CacheItem FilterCache::impl_readOldItem(const css::uno::Reference< css::container::XNameAccess >& xSet , + EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception) +{ + css::uno::Reference< css::container::XNameAccess > xItem; + xSet->getByName(sItem) >>= xItem; + if (!xItem.is()) + throw css::uno::Exception( + ::rtl::OUString::createFromAscii("Cant read old item."), + css::uno::Reference< css::uno::XInterface >()); + + CacheItem aItem; + aItem[PROPNAME_NAME] <<= sItem; + + // Installed flag ... + // Isnt used any longer! + + // UIName + impl_readPatchUINames(xItem, aItem); + + // Data + ::rtl::OUString sData; + OUStringList lData; + xItem->getByName(::rtl::OUString::createFromAscii("Data")) >>= sData; + lData = impl_tokenizeString(sData, (sal_Unicode)','); + if ( + (!sData.getLength()) || + (lData.size()<1 ) + ) + { + throw css::uno::Exception( + ::rtl::OUString::createFromAscii("Cant read old item property DATA."), + css::uno::Reference< css::uno::XInterface >()); + } + + sal_Int32 nProp = 0; + for (OUStringList::const_iterator pProp = lData.begin(); + pProp != lData.end() ; + ++pProp ) + { + const ::rtl::OUString& sProp = *pProp; + switch(eType) + { + case E_TYPE : + impl_interpretDataVal4Type(sProp, nProp, aItem); + break; + + case E_FILTER : + impl_interpretDataVal4Filter(sProp, nProp, aItem); + break; + default: break; + } + ++nProp; + } + + return aItem; +} + +/*----------------------------------------------- + 12.02.2004 08:15 +-----------------------------------------------*/ +OUStringList FilterCache::impl_tokenizeString(const ::rtl::OUString& sData , + sal_Unicode cSeperator) +{ + OUStringList lData ; + sal_Int32 nToken = 0; + do + { + ::rtl::OUString sToken = sData.getToken(0, cSeperator, nToken); + lData.push_back(sToken); + } + while(nToken >= 0); + return lData; +} + +#if OSL_DEBUG_LEVEL > 0 +/*-----------------------------------------------*/ +::rtl::OUString FilterCache::impl_searchFrameLoaderForType(const ::rtl::OUString& sType) const +{ + CacheItemList::const_iterator pIt; + for ( pIt = m_lFrameLoaders.begin(); + pIt != m_lFrameLoaders.end() ; + ++pIt ) + { + const ::rtl::OUString& sItem = pIt->first; + ::comphelper::SequenceAsHashMap lProps(pIt->second); + OUStringList lTypes(lProps[PROPNAME_TYPES]); + + if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end()) + return sItem; + } + + return ::rtl::OUString(); +} + +/*-----------------------------------------------*/ +::rtl::OUString FilterCache::impl_searchContentHandlerForType(const ::rtl::OUString& sType) const +{ + CacheItemList::const_iterator pIt; + for ( pIt = m_lContentHandlers.begin(); + pIt != m_lContentHandlers.end() ; + ++pIt ) + { + const ::rtl::OUString& sItem = pIt->first; + ::comphelper::SequenceAsHashMap lProps(pIt->second); + OUStringList lTypes(lProps[PROPNAME_TYPES]); + + if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end()) + return sItem; + } + + return ::rtl::OUString(); +} +#endif + +/*-----------------------------------------------*/ +sal_Bool FilterCache::impl_isModuleInstalled(const ::rtl::OUString& sModule) +{ + css::uno::Reference< css::container::XNameAccess > xCfg; + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + if (! m_xModuleCfg.is()) + { + m_xModuleCfg = css::uno::Reference< css::container::XNameAccess >( + ::comphelper::ConfigurationHelper::openConfig( + m_xSMGR, + ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office/Factories"), + ::comphelper::ConfigurationHelper::E_READONLY), + css::uno::UNO_QUERY_THROW); + } + + xCfg = m_xModuleCfg; + aLock.clear(); + // <- SAFE + + if (xCfg.is()) + return xCfg->hasByName(sModule); + + return sal_False; +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/filtercache.hxx b/filter/source/config/cache/filtercache.hxx new file mode 100644 index 000000000000..0c0e34b2783b --- /dev/null +++ b/filter/source/config/cache/filtercache.hxx @@ -0,0 +1,1066 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __FILTER_CONFIG_FILTERCACHE_HXX_ +#define __FILTER_CONFIG_FILTERCACHE_HXX_ + +//_______________________________________________ +// includes + +#include "cacheitem.hxx" +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/util/ChangesEvent.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Any.h> +#include <rtl/ustring.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements a cache, which contains all + elements of our filter and type detection + configuration. + + @descr The cache itself is threadsafe implemented. + Because it should be used as a singleton only. + To do so please use reference mechanism as wrapper + around this FilterCache class. + + @attention Because we use a trick to get a full initialized + mutex lock during initialization time (means during + the constructor runs), the base class FilterCacheLock + must be the first of all declared one! + Further we make it public. So any user of this class + can lock us from outside too. + */ +class FilterCache : public BaseLock +{ + //------------------------------------------- + // public types + + public: + + //--------------------------------------- + + /** @short identify the type of a container item. + + @descr Because the cache interface is a generic one + every group of container items must be specified. + */ + enum EItemType + { + E_TYPE , + E_FILTER , + E_FRAMELOADER , + E_CONTENTHANDLER, + E_DETECTSERVICE + }; + + //--------------------------------------- + + /** @short indicates, which items already exists inside this cache + and which not. + + @descr This cache supports a 2-step load mechanism. + First only types (and only some special properties of every type!) + but no filters/frame loaders/content handlers will be readed. + That should be enough to work with this cache e.g. for loading + the first document. After this first document was loaded successfully, + a special "load-on-demand-thread" will be started to fill this cache + with ALL other informations, which was not readed before. + Thats the second step. All operations on top of this cache will be + blocked then. + */ + enum EFillState + { + E_CONTAINS_NOTHING = 0, + E_CONTAINS_STANDARD = 1, + E_CONTAINS_TYPES = 2, + E_CONTAINS_FILTERS = 4, + E_CONTAINS_DETECTSERVICES = 8, + E_CONTAINS_FRAMELOADERS = 16, + E_CONTAINS_CONTENTHANDLERS = 32, + E_CONTAINS_ALL = 63 // must be a combination of all excepting E_CONTAINS_NOTHING! Please update if items will be added or removed ... + }; + + //------------------------------------------- + // private types + + private: + + //--------------------------------------- + /** @short regulate, which properties of a configured item + will be readed. + + @descr To perform reading of all configuration items, + only standard properties will be handled. At a second + step all optional properties will be read and added to + our internal structures. Of course the combination of + both options can be used too, to get all properties + at the same time. + */ + enum EReadOption + { + E_READ_NOTHING = 0, + E_READ_STANDARD = 1, + E_READ_UPDATE = 2, + E_READ_ALL = 3 + }; + + //--------------------------------------- + /** @short indicates the state of a configuration set item. + + @descr Inside method flush we check: + <ul> + <li>if the item exists inside config layer but not inside our cache => REMOVED</li> + <li>if the item exists inside config layer and inside our cache => CHANGED</li> + <li>if the item does not exists inside config layer but inside our cache => ADDED.</li> + </ul> + */ + enum EItemFlushState + { + /// indicates an unchanged item (can occure e.g. if an item was added and(!) removed before it was flushed ... + E_ITEM_UNCHANGED = 0, + /// indicates an item, which exists inside config layer but not inside our own cache + E_ITEM_REMOVED = 1, + /// indicates an item, which exists inside config layer and inside our own cache + E_ITEM_CHANGED = 2, + /// indicates an item, which does not exists inside config layer but inside our own cache + E_ITEM_ADDED = 3 + }; + + //--------------------------------------- + /** TODO document me */ + enum EConfigProvider + { + E_PROVIDER_TYPES = 0, + E_PROVIDER_FILTERS = 1, + E_PROVIDER_OTHERS = 2, + E_PROVIDER_OLD = 3 + }; + + //------------------------------------------- + // member + + private: + + //--------------------------------------- + /** @short reference to an uno service manager, which can be used + to create own needed services. */ + mutable css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR; + + //--------------------------------------- + /** @short holds the used configuration provider alive, which + provides access to the list of types. */ + mutable css::uno::Reference< css::uno::XInterface > m_xConfigTypes; + + //--------------------------------------- + /** @short holds the used configuration provider alive, which + provides access to the list of filters. */ + mutable css::uno::Reference< css::uno::XInterface > m_xConfigFilters; + + //--------------------------------------- + /** @short holds the used configuration provider alive, which + provides access to the list of other values needed + by our type detection framework. */ + mutable css::uno::Reference< css::uno::XInterface > m_xConfigOthers; + + //--------------------------------------- + /** @short contains all loaded types with its properties. */ + mutable CacheItemList m_lTypes; + + //--------------------------------------- + /** @short contains all well known detect service with its properties. */ + mutable CacheItemList m_lDetectServices; + + //--------------------------------------- + /** @short contains all loaded filters with its properties. */ + mutable CacheItemList m_lFilters; + + //--------------------------------------- + /** @short contains all loaded frame loader with its properties. */ + mutable CacheItemList m_lFrameLoaders; + + //--------------------------------------- + /** @short contains all loaded content handler with its properties. */ + mutable CacheItemList m_lContentHandlers; + + //--------------------------------------- + /** @short optimize mapping of URL extensions to a type representation, + by using extensions as key and a list of internal + type names as value. */ + mutable CacheItemRegistration m_lExtensions2Types; + + //--------------------------------------- + /** @short optimize mapping of URL pattern to a type representation, + by using patterns as key and a list of internal + type names as value. */ + mutable CacheItemRegistration m_lURLPattern2Types; + + //--------------------------------------- + /** @short contains the current locale of the office and will be + used to work with localized configuration values. */ + ::rtl::OUString m_sActLocale; + + //--------------------------------------- + /** TODO */ + ::rtl::OUString m_sFormatName; + + //--------------------------------------- + /** TODO */ + ::rtl::OUString m_sFormatVersion; + + //--------------------------------------- + /** @short contains status, which cache items/properties + was already loaded from the underlying configuration. + + @descr This information can be used to detect missing + informations and load it on demand. + + @see EFillState + @see load() + */ + EFillState m_eFillState; + + //--------------------------------------- + /** TODO document me ... */ + OUStringList m_lChangedTypes; + OUStringList m_lChangedFilters; + OUStringList m_lChangedDetectServices; + OUStringList m_lChangedFrameLoaders; + OUStringList m_lChangedContentHandlers; + + //--------------------------------------- + /// readonly acccess to the module configuration of OOo + css::uno::Reference< css::container::XNameAccess > m_xModuleCfg; + + //------------------------------------------- + // interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short standard ctor + + @descr Its not allowed to do anything here ... + especialy is forbidden to start operations, + which needs a FilterCache instance too! + Why? Because thie FilterCache instance will be + used as a singleton! And if during this ctor any + action related to this FilterCache singleton is + started ... a race will be the result. + + The first method after construction of a new + singleton reference should be "load()". There + a special fill state of this cache can be forced. + */ + FilterCache(); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~FilterCache(); + + //--------------------------------------- + + /** @short creates a copy of this container. + + @descr Such copy can be used then to modify items (add/change/remove) + without the risk to damage the original container. + After its changed data was flushed to the configuration it can be + removed. + + The original container will get these new data automaticly + because it listen for changes on the internal used configuration layer. + If the new data are needed immediatly inside the original container, + the method takeOver() can be used to copy all changes back. + The may be following notifications of the configuration will be superflous then. + But they cant be stopped ... + + All internal structures will be copied here. But the internal used + configuration (update) access wont be copied. The cloned instance contains + a different one. + + @note The cloned instance is created on the heap. The user of this instance + has to remove it later. + */ + virtual FilterCache* clone() const; + + //--------------------------------------- + + /** @short copy the cache content or rClone back to this instance. + */ + virtual void takeOver(const FilterCache& rClone); + + //--------------------------------------- + + /** @short force special fill state of this cache. + + @descr This method check if all requested items/properties already + exists. Only missing informations will be readed. + Otherwhise this method does nothing! + + This method must be called from every user of this cache + everytimes it need a filled cache. Normaly we load + only standard informations into this cache on startup. + After a few seconds we start a special thread, which + may fill this cache completely. But if somehwere outside + need a filled cache before ... it can run into trouble, + if this "load-on-demand" thread does not finished its work before. + This method "load(xxx)" synchronize such load-on-demand requests. + + Of course it would be possible to supress this special load thread + in general and start it manualy inside this load() request. + The outside code decide then, if and when this cache will be filled + with all available informations ... + + @param bByThread + indicates using of this method by our global "load-on-demand-thread". + Its an implementation detail! We use it to check, if this "load()" + request was forced e.g. by one of our derived service container (which need + it to full fill its own operations) or if it was forced by our own + "load-on-demand-thread", which tries to optimize our startup performance + and start this load() only in case the office startup was already finished! + + @throw An exception if the cache could not be filled realy + or seems to be invalid afterwards. But there is no reaction + at all if this method does nothing inside, because the cache + is already full filled! + */ + virtual void load(EFillState eRequired , + sal_Bool bByThread = sal_False) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short return the current fill state of this cache. + + @descr This information can be used e.g. to start + a search on top of this cache with a minimum on + informations ... and do it again, if some other + cache items seems to be available after calling of "loadAll()" + on this cache and first search does not had any valid results. + + @return TRUE if the required fill state exists for this cache; FALSE + otherwise. + */ + virtual sal_Bool isFillState(EFillState eRequired) const + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short return a list of key names for items, which match + the specified criteria. + + @descr The returned key names can be used at another method "getItem()" + of this cache to get further informations about this item. + + @attention Please note: because this cache can be used inside multithreaded + environments, such returned key name can point to an already removed + item! Please be aware of some "NoSuchElementExceptions" if you try to + call any other method of this cache in relation to this key name. + + @param eType + specify the sub container of this cache, which should be used for + searching. see also EItemType. + + @param lIProps + specify the property set, which must exist at the searched items + as minimum. + + @param lEProps + specify the property set, which must not(!) exist at the searched items + as minimum. + + @return [OUStringList] + a list of key names, which identify items of the queried sub container. + May be an empty list. + + @throw [css::uno::Exception] + if some input parameter are wrong or the cache itself is not valid + any longer, because any operation before damage it. + */ + virtual OUStringList getMatchingItemsByProps( EItemType eType , + const CacheItem& lIProps , + const CacheItem& lEProps = CacheItem()) const + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short indicates if the requested sub container + contains some items. + + @descr We dont provide any information about the count + of such items. Because we dont implement any index + based interface! The information "we have items or not" + must be enough for the outside code ... till somewhere + give us a good reason. :-) + + @param eType + specify the sub container of this cache, which should be used. + see also EItemType. + + @return [sal_Bool] + True, if the requested sub container contains some items; + False otherwhise. + + @throw [css::uno::Exception] + if some input parameter are wrong or the cache itself is not valid + any longer, because any operation before damage it. + */ + virtual sal_Bool hasItems(EItemType eType) const + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short return a list of all key names, which represent + an item inside the specified sub container. + + @attention Please note: because this cache can be used inside multithreaded + environments, such returned key names can point to some already removed + items! Please be aware of some "NoSuchElementExceptions" if you try to + call any other method of this cache in relation to this key names. + + @param eType + specify the sub container of this cache, which should be used for + searching. see also EItemType. + + @return [OUStringList] + a list of key names, which can be used to access the item properties + using some other methods of this cache. + + @throw [css::uno::Exception] + if some input parameter are wrong or the cache itself is not valid + any longer, because any operation before damage it. + */ + virtual OUStringList getItemNames(EItemType eType) const + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short check if the required item exist inside this container. + + @attention This method exists to supports some UNO container interfaces + only. (e.g. XNameAccess.hasByName()). But inside multithreaded + environments there is no guarantee, that this item still exists, if + its realy requested e.g. by calling getItem()! + Be aware of some NoSuchElementExistExceptions ... + + @param eType + specify the sub container of this cache, which should be used. + see also EItemType. + + @param sItem + the key name of the requested item inside the pecified sub container. + + @throw [css::uno::Exception] + if some input parameter are wrong or the cache itself is not valid + any longer, because any operation before damage it. + */ + virtual sal_Bool hasItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short return an item, which match the specified type and name. + + @descr Because this cache can be used inside multithreaded environments + the caller must be aware of some exceptions - especialy a "NoSuchElementExcepotion". + May another thread already removed the required item before ... + + @param eType + specify the sub container of this cache, which should be used for + searching. see also EItemType. + + @param sItem + specify the requested item by its key name. + + @return [CacheItem] + the required item if it could be located ... + But we throw an exception if the required item does not exist! + + @throw [css::container::NoSuchElementException] + if the required item does not still exist. + + @throw [css::uno::Exception] + if some input parameter are wrong or the cache itself is not valid + any longer, because any operation before damage it. + */ + virtual CacheItem getItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO document me ... + */ + virtual void removeItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO document me ... + */ + virtual void setItem( EItemType eType , + const ::rtl::OUString& sItem , + const CacheItem& aValue) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO document me ... + */ + virtual void refreshItem( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short add some implicit properties to the given + cache item reference. + + @descr Such properties can e.g. finalized or mandatory. + They are not persistent and not realy part of e.g. a + filter not. But they are attributes of a configuration + entry and can influence our container interface. + + @attention These properties are not part of the normal CacheItem + returned by the method getItem(). Because getItem() is + used internaly too but these specialized properties + are needed at our container services only. So these + function sets are different to allow different handling. + + @param eType + specify the sub container of this cache, which should be used for + searching. see also EItemType. + + @param sItem + specify the requested item by its key name. + + @param rItem + contains already the normal properties of this item, + and will be used as out parameter to add the implicit + attributes there. + + @throw [css::uno::Exception] + if an internal error occured. + Note: If the item is missing inside the underlying configuration + no exception will be thrown. In such case the item is marked as + finalized/mandatory automaticly + Reason: May be the item cames from the old configuration package and + was not migrated to the new one. So we cant provide write access + to such items ... + */ + virtual void addStatePropsToItem( EItemType eType, + const ::rtl::OUString& sItem, + CacheItem& rItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO document me + */ + virtual void removeStatePropsFromItem(CacheItem& aValue) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short force writing of all changes (which was made after + last flush was called) back to the configuration. + + @descr TODO + + @throw [css::uno::Exception] + if the cache itself is not valid + any longer, because any operation before damage it. + */ + virtual void flush() + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short supports a flat type detection for given URL. + + @descr Because such detection works on our optimized internal + structures (e.g. mapping from extensions/pattern to type names), + it should be made inside this cache. + + @param aURL + URL of the content, which type should be detected. + Its already parsed and splitted into its differnt parts, + like e.g.: main, jump marks etcpp. + + @param rFlatTypes + used as [out] parameter to add all types, which match to the given + URL. Further an information is added for every type. It indicates, how + this type is related to the specified URL (means e.g. if it matches + by extension or URLPattern ...). + + @attention Please note: because this cache can be used inside multithreaded + environments, such returned key names can point to some already removed + items! Please be aware of some "NoSuchElementExceptions" if you try to + call any other method of this cache in relation to this key names. + + @throw [css::uno::Exception] + if the cache itself is not valid + any longer, because any operation before damage it. + */ + virtual void detectFlatForURL(const css::util::URL& aURL , + FlatDetection& rFlatTypes) const + throw(css::uno::Exception); + + //------------------------------------------- + // private helper + + private: + + //--------------------------------------- + + /** @short return a reference to one of our internal + sub container, which contains items of the + requested type. + + @param eType + specify, which sub container is needed outside. + + @return [CacheItemList&] + a reference(!) to the right sub container member. + + @throw [css::uno::Exception] + if the required list does not exist. + */ + CacheItemList& impl_getItemList(EItemType eType) const + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short return a valid configuration update access + to the underlying configuration package, which + is fix for this cache. + + @descr It checks first, if the internal member m_xConfig already + points to an open update access. If not - it opens a new one. + Doing so this method can be called everytimes a configuration + access is needed. + + @param eProvider + specify the needed configuration provider. + see EConfigProvider for further informations ... + + @attention If a configuration access was opened successfully + all neccessary listener connections will be established + too. So this cache will be informed about outside updates. + */ + css::uno::Reference< css::uno::XInterface > impl_openConfig(EConfigProvider eProvide) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short tries to open the requested configuration root + using the specified modi. + + @param sRoot + specify the configuration root, which should be opened. + + @param bReadOnly + enable/disable write access on the returned configuration + object. + + @param bLocalesMode + enable/disable special handling of localized configuratiom + items by the returned configuration object. + + @return A valid reference, if the configuration access could be opened + and initialized within the requested modes successfully; + a NULL reference otherwhise. + */ + css::uno::Reference< css::uno::XInterface > impl_createConfigAccess(const ::rtl::OUString& sRoot , + sal_Bool bReadOnly , + sal_Bool bLocalesMode); + + //--------------------------------------- + + /** @short reads the specified configuration key + and return its value. + + @descr The specified key must be an absolute configuration path, + which can be splitted into its package and relative path tokens. + + @attention Because this function might opens a new configuration + read access for reading one key value only, it should + be used in rare cases only. Its an easy way ... but an + expensive one. + + @param sDirectKey + the absolute configuration path, which should be readed. + + @return [css::uno::Any] + the value of the requested key. + Can be empty if an internal error occured or if the requested + key does not exists! + */ + css::uno::Any impl_getDirectCFGValue(const ::rtl::OUString& sDirectKey); + + //--------------------------------------- + + /** @short load the underlying configuration into this cache. + + @descr Which items should be readed can be regulate by the + parameter eRequiredState. That provides the possibility + to load standard values on startup only and update this + cache later on demand with all available informations. + + @param eRequiredState + indicates, which fill state this cache should have afterwards. + */ + void impl_load(EFillState eRequiredState) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short validate the whole cache and create + structures for optimized items access. + + @descr Wrong cache items will be removed automaticly. + Wrong dependencies will be corrected automaticly. + If something could not be repaired - an exception + is thrown. + Further some optmized structures will be created. + E.g.: a hash to map extensions to her types. + + @attention There is no exception, if the cache could be repaired + but contained wrong elements before! + + @throw [css::uno::Exception] + if cache is invalid and could not be repaired. + */ + void impl_validateAndOptimize() + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short register the specified item for the given type. + + @descr Because detect services, frame loader or content handler + are not listed inside the xml configuration as seperated + items (they are properties of any type entry!), this method update + the internal lists of such items. Thats neccessary to have + it accessible for our container interfaces of detect, frame loader + and content handler services. + + @param pList + points to a CacheItemList of this filter cache, where + this item registration should be updated or added. + + @param sItem + specify the detect service, frame loader or content handler, + which should be registered for the given type. + + @param sType + contains the internal type name, where the item should be registered for. + + @throw [css::uno::Exception] + If registration failed by any reason. + That does not include double registrations! + */ + void impl_resolveItem4TypeRegistration( CacheItemList* pList, + const ::rtl::OUString& sItem, + const ::rtl::OUString& sType) + throw(css::uno::Exception); + + //------------------------------------------- + // static helper + + private: + + //--------------------------------------- + + /** @short read the specified config set into the cache. + + @descr This method provides the following mechanism for reading: + a) read only standard properties of set items + b) read anything + c) read only optional properties and update already existing + items of the specified cache + + @param xConfig + API which provides access to the required configuration set. + + @param eType + specify the type of config item, which must be interpreted. + Of course this information can be used to locate the right set + at the given xConfig API object. + + @param eOption + regulate reading of standard/optional or all properties. + + @param pCache + points to the cache member, which should be filled or updated. + + @throw [css::uno::Exception] + if an unrecoverable error occure inside this operation. + */ + void impl_loadSet(const css::uno::Reference< css::container::XNameAccess >& xConfig, + EItemType eType , + EReadOption eOption, + CacheItemList* pCache ) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short read the specified container item from the given configuration set. + + @descr Its not added to any internal structures here. That must be done + outside this method. + + @param xSet + provides access to the configuration set, which includes all items. + + @param eType + specify, which container item type must be readed. + + @param sItem + means the internal name, which can be used to adress the item + properties relativ to the given configuration set. + + @param eOption + regulate, which properties of the requested item should be read. + See defintion of EReadOption for further informations. + + @throw [css::uno::Exception] + if an unrecoverable error occure inside this operation. + */ + CacheItem impl_loadItem(const css::uno::Reference< css::container::XNameAccess >& xSet , + EItemType eType , + const ::rtl::OUString& sItem , + EReadOption eOption) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short try to load the requested item on demand from the underlying configuration + layer. + + @descr The outside code has to be shure, that the item does not already exists + inside this cachse. Otherwise it will be loaded twice. This method + doesnt check such constellations! + + @param eType + specify the type of config item, which must be interpreted. + Of course this information can be used to locate the right set + at the given xConfig API object. + + @param sItem + the set node name of the requested item. + + @return An iterator, which points directly to the new cached item. + Is a valid iterator if no exception occured here! + But to improve robustness - it should be checked :-) + + @throw [css::container::NoSuchElementException] + if the item does not exists inside the configuration layer too! + + @throw [css::uno::Exception] + if an unrecoverable error occure inside this operation. + */ + CacheItemList::iterator impl_loadItemOnDemand( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO */ + void impl_saveItem(const css::uno::Reference< css::container::XNameReplace >& xSet , + EItemType eType , + const CacheItem& aValue) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO */ + void impl_addItem2FlushList( EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + + //--------------------------------------- + + /** TODO */ + void impl_flushByList(const css::uno::Reference< css::container::XNameAccess >& xSet , + EItemType eType , + const CacheItemList& rCache, + const OUStringList& lItems) + throw(css::uno::Exception); + + //--------------------------------------- + + /** @short specify, which save operation is neccessary for the specified item. + + @desrc If an item of this cache will be added/removed or modified it will + be changed inside memory only first. But we save its name inside a special + list of changed items. If at least the method flush() is called, we use + this list to check if the item was changed/added or removed. This method + checks the exist state of the requested item inside our own cache + and inside the underlying configuration layer to find out, if the item + must be removed/added or modified inside the configuratuion layer. + + @param xSet + points directly to the configuration set, where the item should resist + (if it exists!). + + @param rList + points to our internal cache list, where the item should resist + (if it exists!). + + @param sItem + the internal name of the item, which should be checked. + + @return An enum value of type EItemFlushState, which indicates the needed + API operation for updating the underlying configuration layer. + + @throws An exception if anything failed inside this operation. + e.g. the given configuration set was not open. + */ + EItemFlushState impl_specifyFlushOperation(const css::uno::Reference< css::container::XNameAccess >& xSet , + const CacheItemList& rList, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO */ + void impl_readPatchUINames(const css::uno::Reference< css::container::XNameAccess >& xNode, + CacheItem& rItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO */ + void impl_savePatchUINames(const css::uno::Reference< css::container::XNameReplace >& xNode, + const CacheItem& rItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO */ + void impl_readOldFormat() + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO */ + CacheItem impl_readOldItem(const css::uno::Reference< css::container::XNameAccess >& xSet , + EItemType eType, + const ::rtl::OUString& sItem) + throw(css::uno::Exception); + + //--------------------------------------- + + /** TODO */ + void impl_interpretDataVal4Type(const ::rtl::OUString& sValue, + sal_Int32 nProp , + CacheItem& rItem ); + + //--------------------------------------- + + /** TODO */ + void impl_interpretDataVal4Filter(const ::rtl::OUString& sValue, + sal_Int32 nProp , + CacheItem& rItem ); + + //--------------------------------------- + + /** TODO */ + OUStringList impl_tokenizeString(const ::rtl::OUString& sData , + sal_Unicode cSeperator); + + //--------------------------------------- + +#if OSL_DEBUG_LEVEL > 0 + /** TODO */ + ::rtl::OUString impl_searchFrameLoaderForType(const ::rtl::OUString& sType) const; + ::rtl::OUString impl_searchContentHandlerForType(const ::rtl::OUString& sType) const; +#endif + + //--------------------------------------- + /** @short check if the specified OOo module is installed. + + @param sModule + the long name of the module (e.g. "com.sun.star.text.TextDocument"). + + @return TRUE if the requested module is installed; FALSE otherwise. + */ + sal_Bool impl_isModuleInstalled(const ::rtl::OUString& sModule); + + //--------------------------------------- + + /** @short convert a list of flag names to its int representation. + + @param lNames + the list of flag names. + + @return [sal_Int32] + the converted flag field. + */ + static sal_Int32 impl_convertFlagNames2FlagField(const css::uno::Sequence< ::rtl::OUString >& lNames); + + //--------------------------------------- + + /** @short convert a flag field value to its list representation of flag names. + + @param nFlags + the flag field value + + @return [seq< string >] + the converted flag name list. + */ + static css::uno::Sequence< ::rtl::OUString > impl_convertFlagField2FlagNames(sal_Int32 nFlags); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_FILTERCACHE_HXX_ diff --git a/filter/source/config/cache/filterconfig1.component b/filter/source/config/cache/filterconfig1.component new file mode 100644 index 000000000000..9d3c7c90fb31 --- /dev/null +++ b/filter/source/config/cache/filterconfig1.component @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.filter.config.ConfigFlush"> + <service name="com.sun.star.document.FilterConfigRefresh"/> + </implementation> + <implementation name="com.sun.star.comp.filter.config.ContentHandlerFactory"> + <service name="com.sun.star.frame.ContentHandlerFactory"/> + </implementation> + <implementation name="com.sun.star.comp.filter.config.FilterFactory"> + <service name="com.sun.star.document.FilterFactory"/> + </implementation> + <implementation name="com.sun.star.comp.filter.config.FrameLoaderFactory"> + <service name="com.sun.star.frame.FrameLoaderFactory"/> + </implementation> + <implementation name="com.sun.star.comp.filter.config.TypeDetection"> + <service name="com.sun.star.document.TypeDetection"/> + </implementation> +</component> diff --git a/filter/source/config/cache/filterfactory.cxx b/filter/source/config/cache/filterfactory.cxx new file mode 100644 index 000000000000..dc7869be27ca --- /dev/null +++ b/filter/source/config/cache/filterfactory.cxx @@ -0,0 +1,724 @@ +/************************************************************************* + * + * 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 "filterfactory.hxx" +#include "macros.hxx" +#include "constant.hxx" +#include "versions.hxx" + +//_______________________________________________ +// includes +#include <com/sun/star/lang/XInitialization.hpp> +#include <comphelper/enumhelper.hxx> +#include <comphelper/configurationhelper.hxx> +#include <rtl/ustrbuf.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/** @short can be used to query for filters related to its application module. + */ +#define BASE_QUERY_ALL "_query_all" +#define BASE_QUERY_WRITER "_query_Writer" +#define BASE_QUERY_WEB "_query_web" +#define BASE_QUERY_GLOBAL "_query_global" +#define BASE_QUERY_CHART "_query_chart" +#define BASE_QUERY_CALC "_query_calc" +#define BASE_QUERY_IMPRESS "_query_impress" +#define BASE_QUERY_DRAW "_query_draw" +#define BASE_QUERY_MATH "_query_math" + +//_______________________________________________ + +/** @short define all possible parts of a filter query. + + @descr syntax: "<query>[:<param>[=<value>]]" + e.g.: "_query_writer:default_first:use_order:sort_prop=uiname" + + argument description default + ----------------------------------------------------------------------------------------------- + iflags=<mask> include filters by given mask 0 + eflags=<mask> exclude filters by given mask 0 + sort_prop=<[name,uiname]> sort by internal name or uiname name + descending sort descending false + use_order use order flag of filters for sorting false + default_first set default filter on top of return list false + case_sensitive compare "sort_prop" case sensitive false + */ +#define SEPERATOR_QUERYPARAM ((sal_Unicode)':') +#define SEPERATOR_QUERYPARAMVALUE ((sal_Unicode)'=') + +#define QUERYPARAM_IFLAGS ::rtl::OUString::createFromAscii("iflags") +#define QUERYPARAM_EFLAGS ::rtl::OUString::createFromAscii("eflags") +#define QUERYPARAM_SORT_PROP ::rtl::OUString::createFromAscii("sort_prop") + +#define QUERYPARAM_DESCENDING ::rtl::OUString::createFromAscii("descending") +#define QUERYPARAM_USE_ORDER ::rtl::OUString::createFromAscii("use_order") +#define QUERYPARAM_DEFAULT_FIRST ::rtl::OUString::createFromAscii("default_first") +#define QUERYPARAM_CASE_SENSITIVE ::rtl::OUString::createFromAscii("case_sensitive") + +#define QUERYPARAMVALUE_SORT_PROP_NAME ::rtl::OUString::createFromAscii("name") +#define QUERYPARAMVALUE_SORT_PROP_UINAME ::rtl::OUString::createFromAscii("uiname") + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +FilterFactory::FilterFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + BaseContainer::init(xSMGR , + FilterFactory::impl_getImplementationName() , + FilterFactory::impl_getSupportedServiceNames(), + FilterCache::E_FILTER ); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +FilterFactory::~FilterFactory() +{ +} + +/*----------------------------------------------- + 16.07.2003 13:43 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::createInstance(const ::rtl::OUString& sFilter) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + return createInstanceWithArguments(sFilter, css::uno::Sequence< css::uno::Any >()); +} + +/*----------------------------------------------- + 17.07.2003 08:56 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::createInstanceWithArguments(const ::rtl::OUString& sFilter , + const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + ::rtl::OUString sRealFilter = sFilter; + + #ifdef _FILTER_CONFIG_MIGRATION_Q_ + + /* -> TODO - HACK + check if the given filter name realy exist ... + Because our old implementation worked with an internal + type name instead of a filter name. For a small migration time + we must simulate this old feature :-( */ + + if (!m_rCache->hasItem(FilterCache::E_FILTER, sFilter) && m_rCache->hasItem(FilterCache::E_TYPE, sFilter)) + { + OSL_ENSURE(sal_False, "Who use this deprecated functionality?"); + _FILTER_CONFIG_LOG_("FilterFactory::createInstanceWithArguments() ... simulate old type search functionality!\n"); + + css::uno::Sequence< css::beans::NamedValue > lQuery(1); + lQuery[0].Name = PROPNAME_TYPE; + lQuery[0].Value <<= sFilter; + + css::uno::Reference< css::container::XEnumeration > xSet = createSubSetEnumerationByProperties(lQuery); + while(xSet->hasMoreElements()) + { + ::comphelper::SequenceAsHashMap lHandlerProps(xSet->nextElement()); + if (!(lHandlerProps[PROPNAME_NAME] >>= sRealFilter)) + continue; + } + + // prevent outside code against NoSuchElementException! + // But dont implement such defensive strategy for our new create handling :-) + if (!m_rCache->hasItem(FilterCache::E_FILTER, sRealFilter)) + return css::uno::Reference< css::uno::XInterface>(); + } + + /* <- HACK */ + + #endif // _FILTER_CONFIG_MIGRATION_Q_ + + // search filter on cache + CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sRealFilter); + ::rtl::OUString sFilterService; + aFilter[PROPNAME_FILTERSERVICE] >>= sFilterService; + + // create service instance + css::uno::Reference< css::uno::XInterface > xFilter; + if (sFilterService.getLength()) + xFilter = m_xSMGR->createInstance(sFilterService); + + // initialize filter + css::uno::Reference< css::lang::XInitialization > xInit(xFilter, css::uno::UNO_QUERY); + if (xInit.is()) + { + // format: lInitData[0] = seq<PropertyValue>, which contains all configuration properties of this filter + // lInitData[1] = lArguments[0] + // ... + // lInitData[n] = lArguments[n-1] + css::uno::Sequence< css::beans::PropertyValue > lConfig; + aFilter >> lConfig; + + ::comphelper::SequenceAsVector< css::uno::Any > stlArguments(lArguments); + stlArguments.insert(stlArguments.begin(), css::uno::makeAny(lConfig)); + + css::uno::Sequence< css::uno::Any > lInitData; + stlArguments >> lInitData; + + xInit->initialize(lInitData); + } + + return xFilter; + // <- SAFE +} + +/*----------------------------------------------- + 18.02.2004 14:21 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > SAL_CALL FilterFactory::getAvailableServiceNames() + throw(css::uno::RuntimeException) +{ + /* Attention: Instead of getElementNames() this method have to return only filter names, + which can be created as UNO Services realy. Thats why we search for filters, + which dont have a valid value for the property "FilterService". + Of course we cant check for corrupted service names here. We can check + for empty strings only ... + */ + CacheItem lIProps; + CacheItem lEProps; + lEProps[PROPNAME_FILTERSERVICE] <<= ::rtl::OUString(); + + OUStringList lUNOFilters; + try + { + lUNOFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps, lEProps); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { lUNOFilters.clear(); } + + return lUNOFilters.getAsConstList(); +} + +/*----------------------------------------------- + 11.03.2004 08:37 +-----------------------------------------------*/ +css::uno::Reference< css::container::XEnumeration > SAL_CALL FilterFactory::createSubSetEnumerationByQuery(const ::rtl::OUString& sQuery) + throw (css::uno::RuntimeException) +{ + // reject old deprecated queries ... + if (sQuery.matchAsciiL("_filterquery_",13,0)) + throw css::uno::RuntimeException( + _FILTER_CONFIG_FROM_ASCII_("Use of deprecated and now unsupported query!"), + static_cast< css::container::XContainerQuery* >(this)); + + // convert "_query_xxx:..." to "getByDocService=xxx:..." + ::rtl::OUString sNewQuery(sQuery); + sal_Int32 pos = sNewQuery.indexOf(::rtl::OUString::createFromAscii("_query_"),0); + if (pos != -1) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use new query format: 'matchByDocumentService=...'"); + ::rtl::OUStringBuffer sPatchedQuery(256); + sPatchedQuery.appendAscii("matchByDocumentService="); + sPatchedQuery.append (sNewQuery.copy(7) ); + sNewQuery = sPatchedQuery.makeStringAndClear(); + } + + // analyze query and split it into its tokens + QueryTokenizer lTokens(sNewQuery); + QueryTokenizer::const_iterator pIt; + OUStringList lEnumSet; + + // start query + // (see attention comment below!) + if (lTokens.valid()) + { + // SAFE -> ---------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + // May be not all filters was loaded ... + // But we need it now! + impl_loadOnDemand(); + aLock.clear(); + // <- SAFE ---------------------- + + if (lTokens.find(QUERY_IDENTIFIER_GETPREFERREDFILTERFORTYPE) != lTokens.end()) + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use prop search at the TypeDetection container!"); +// lEnumSet = impl_queryGetPreferredFilterForType(lTokens); + else + if (lTokens.find(QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE) != lTokens.end()) + lEnumSet = impl_queryMatchByDocumentService(lTokens); + else + if (lTokens.find(QUERY_IDENTIFIER_GET_SORTED_FILTERLIST) != lTokens.end()) + lEnumSet = impl_getSortedFilterList(lTokens); + } + + // pack list of item names as an enum list + // Attention: Do not return empty reference for empty list! + // The outside check "hasMoreElements()" should be enough, to detect this state :-) +// size_t c = lEnumSet.size(); + css::uno::Sequence< ::rtl::OUString > lSet = lEnumSet.getAsConstList(); + ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, lSet); + return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY); +} +/* + if (lEnumSet.empty()) + { + //------------------------------------------- + // 1) getDefaultFilterForType=<internal_typename> + + pIt = lTokens.find(::rtl::OUString::createFromAscii("getDefaultFilterForType")); + if (pIt != lTokens.end()) + { + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // might not all types was loaded till now! + impl_loadOnDemand(); + + ::rtl::OUString sType = pIt->second; + FilterCache* pCache = impl_getWorkingCache(); + if (pCache->hasItem(FilterCache::E_TYPE, sType)) + { + CacheItem aType = pCache->getItem(FilterCache::E_TYPE, sType); + ::rtl::OUString sPreferredFilter; + aType[PROPNAME_PREFERREDFILTER] >>= sPreferredFilter; + + if ( + (sPreferredFilter.getLength() ) && + (pCache->hasItem(FilterCache::E_FILTER, sPreferredFilter)) + ) + { + lEnumSet.push_back(sPreferredFilter); + } + } + + aLock.clear(); + // <- SAFE + } + } +*/ + +/*----------------------------------------------- + 11.03.2004 08:33 +-----------------------------------------------*/ +OUStringList FilterFactory::impl_queryMatchByDocumentService(const QueryTokenizer& lTokens) const +{ + // analyze query + QueryTokenizer::const_iterator pIt; + + ::rtl::OUString sDocumentService; + sal_Int32 nIFlags = 0; + sal_Int32 nEFlags = 0; + + pIt = lTokens.find(QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE); + if (pIt != lTokens.end()) + sDocumentService = pIt->second; + +#define COMP_HACK +#ifdef COMP_HACK + if (sDocumentService.equalsAscii("writer")) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!"); + sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.text.TextDocument"); + } + else + if (sDocumentService.equalsAscii("web")) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!"); + sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.text.WebDocument"); + } + else + if (sDocumentService.equalsAscii("global")) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!"); + sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.text.GlobalDocument"); + } + else + if (sDocumentService.equalsAscii("calc")) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!"); + sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.sheet.SpreadsheetDocument"); + } + else + if (sDocumentService.equalsAscii("draw")) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!"); + sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.drawing.DrawingDocument"); + } + else + if (sDocumentService.equalsAscii("impress")) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!"); + sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.presentation.PresentationDocument"); + } + else + if (sDocumentService.equalsAscii("math")) + { + OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!"); + sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.formula.FormulaProperties"); + } +#endif + + pIt = lTokens.find(QUERY_PARAM_IFLAGS); + if (pIt != lTokens.end()) + nIFlags = ::rtl::OUString(pIt->second).toInt32(); + + pIt = lTokens.find(QUERY_PARAM_EFLAGS); + if (pIt != lTokens.end()) + nEFlags = ::rtl::OUString(pIt->second).toInt32(); + + // SAFE -> ---------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + // search suitable filters + FilterCache* pCache = impl_getWorkingCache(); + OUStringList lFilterNames = pCache->getItemNames(FilterCache::E_FILTER); + OUStringList lResult ; + + for (OUStringList::const_iterator pName = lFilterNames.begin(); + pName != lFilterNames.end() ; + ++pName ) + { + try + { + const ::rtl::OUString& sName = *pName; + const CacheItem aFilter = pCache->getItem(FilterCache::E_FILTER, sName); + CacheItem::const_iterator pProp ; + + // "matchByDocumentService=" => any filter will be adressed here + // "matchByDocumentService=all" => any filter will be adressed here + // "matchByDocumentService=com.sun.star..." => only filter matching this document service will be adressed + ::rtl::OUString sCheckValue = aFilter.getUnpackedValueOrDefault(PROPNAME_DOCUMENTSERVICE, ::rtl::OUString()); + if ( + ( sDocumentService.getLength() ) && + (!sDocumentService.equals(QUERY_CONSTVALUE_ALL)) && + (!sCheckValue.equals(sDocumentService) ) + ) + { + continue; // ignore filter -> try next one! + } + + // "iflags=" => not allowed + // "iflags=-1" => not allowed + // "iflags=0" => not usefull + // "iflags=283648" => only filter, which has set these flag field will be adressed + sal_Int32 nCheckValue = aFilter.getUnpackedValueOrDefault(PROPNAME_FLAGS, (sal_Int32)0); + if ( + (nIFlags > 0 ) && + ((nCheckValue & nIFlags) != nIFlags) + ) + { + continue; // ignore filter -> try next one! + } + + // "eflags=" => not allowed + // "eflags=-1" => not allowed + // "eflags=0" => not usefull + // "eflags=283648" => only filter, which has not set these flag field will be adressed + if ( + (nEFlags > 0 ) && + ((nCheckValue & nEFlags) == nEFlags) + ) + { + continue; // ignore filter -> try next one! + } + + // OK - this filter passed all checks. + // It match the query ... + lResult.push_back(sName); + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + { continue; } + } + + aLock.clear(); + // <- SAFE ---------------------- + + return lResult; +} + +/*----------------------------------------------- + 21.01.2005 13:39 +-----------------------------------------------*/ +class stlcomp_removeIfMatchFlags +{ + private: + FilterCache* m_pCache ; + sal_Int32 m_nFlags ; + sal_Bool m_bIFlags; + + public: + stlcomp_removeIfMatchFlags(FilterCache* pCache , + sal_Int32 nFlags , + sal_Bool bIFlags) + : m_pCache (pCache ) + , m_nFlags (nFlags ) + , m_bIFlags(bIFlags) + {} + + bool operator() (const ::rtl::OUString& sFilter) const + { + try + { + const CacheItem aFilter = m_pCache->getItem(FilterCache::E_FILTER, sFilter); + sal_Int32 nFlags = aFilter.getUnpackedValueOrDefault(PROPNAME_FLAGS, ((sal_Int32)0)); + + bool bMatch = false; + if (m_bIFlags) + // IFlags are interpeted as ALL_FLAGS_MUST_MATCH ! + bMatch = ((nFlags & m_nFlags) == m_nFlags); + else + // EFlags are interpreted as ATE_LEAST_ONE_FLAG_MUST_MATCH ! + bMatch = !(nFlags & m_nFlags); + // We are asked for bRemove ! And bMatch = !bRemove => so bRemove = !bMatch .-) + return !bMatch; + } + catch(css::container::NoSuchElementException) + { + return true; + } + } +}; + +/*----------------------------------------------- + 21.01.2005 13:39 +-----------------------------------------------*/ +OUStringList FilterFactory::impl_getSortedFilterList(const QueryTokenizer& lTokens) const +{ + // analyze the given query parameter + QueryTokenizer::const_iterator pIt1; + + ::rtl::OUString sModule; + sal_Int32 nIFlags = -1; + sal_Int32 nEFlags = -1; + + pIt1 = lTokens.find(QUERY_PARAM_MODULE); + if (pIt1 != lTokens.end()) + sModule = pIt1->second; + pIt1 = lTokens.find(QUERY_PARAM_IFLAGS); + if (pIt1 != lTokens.end()) + nIFlags = ::rtl::OUString(pIt1->second).toInt32(); + pIt1 = lTokens.find(QUERY_PARAM_EFLAGS); + if (pIt1 != lTokens.end()) + nEFlags = ::rtl::OUString(pIt1->second).toInt32(); + + // simple search for filters of one specific module. + OUStringList lFilterList; + if (sModule.getLength()) + lFilterList = impl_getSortedFilterListForModule(sModule, nIFlags, nEFlags); + else + { + // more complex search for all filters + // We check first, which office modules are installed ... + OUStringList lModules = impl_getListOfInstalledModules(); + OUStringList::const_iterator pIt2; + for ( pIt2 = lModules.begin(); + pIt2 != lModules.end() ; + ++pIt2 ) + { + sModule = *pIt2; + OUStringList lFilters4Module = impl_getSortedFilterListForModule(sModule, nIFlags, nEFlags); + OUStringList::const_iterator pIt3; + for ( pIt3 = lFilters4Module.begin(); + pIt3 != lFilters4Module.end() ; + ++pIt3 ) + { + const ::rtl::OUString& sFilter = *pIt3; + lFilterList.push_back(sFilter); + } + } + } + + return lFilterList; +} + +/*----------------------------------------------- + 21.01.2005 10:19 +-----------------------------------------------*/ +OUStringList FilterFactory::impl_getListOfInstalledModules() const +{ + // SAFE -> ---------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aLock.clear(); + // <- SAFE ---------------------- + + try + { + css::uno::Reference< css::container::XNameAccess > xModuleConfig( + ::comphelper::ConfigurationHelper::openConfig(xSMGR, + CFGPACKAGE_OOO_MODULES, + ::comphelper::ConfigurationHelper::E_READONLY), + css::uno::UNO_QUERY_THROW); + OUStringList lModules(xModuleConfig->getElementNames()); + return lModules; + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} + + return OUStringList(); +} + +/*----------------------------------------------- + 21.01.2005 10:19 +-----------------------------------------------*/ +OUStringList FilterFactory::impl_getSortedFilterListForModule(const ::rtl::OUString& sModule, + sal_Int32 nIFlags, + sal_Int32 nEFlags) const +{ + OUStringList lSortedFilters = impl_readSortedFilterListFromConfig(sModule); + + // get all filters for the requested module + CacheItem lIProps; + lIProps[PROPNAME_DOCUMENTSERVICE] <<= sModule; + + // SAFE -> ---------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + FilterCache* pCache = impl_getWorkingCache(); + OUStringList lOtherFilters = pCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps); + aLock.clear(); + // <- SAFE ---------------------- + + // bring "other" filters in an alphabeticly order + // It's needed below. + ::std::sort(lOtherFilters.begin(), lOtherFilters.end()); + + // merge both lists together + OUStringList lMergedFilters = lSortedFilters; + OUStringList::iterator pIt2; + OUStringList::iterator pIt3; + for ( pIt2 = lOtherFilters.begin(); + pIt2 != lOtherFilters.end() ; + ++pIt2 ) + { + const ::rtl::OUString& rFilter = *pIt2; + pIt3 = ::std::find(lSortedFilters.begin(), lSortedFilters.end(), rFilter); + if (pIt3 == lSortedFilters.end()) + lMergedFilters.push_back(rFilter); + } + + // remove all filters from this merged list, which does not fit the flag specification + if (nIFlags != -1) + { + pIt2 = ::std::remove_if(lMergedFilters.begin(), lMergedFilters.end(), stlcomp_removeIfMatchFlags(pCache, nIFlags, sal_True)); + lMergedFilters.erase(pIt2, lMergedFilters.end()); + } + if (nEFlags != -1) + { + pIt2 = ::std::remove_if(lMergedFilters.begin(), lMergedFilters.end(), stlcomp_removeIfMatchFlags(pCache, nEFlags, sal_False)); + lMergedFilters.erase(pIt2, lMergedFilters.end()); + } + + // sort the default filter to the front of this list + // TODO + + return lMergedFilters; +} + +/*----------------------------------------------- + 21.01.2005 10:19 +-----------------------------------------------*/ +OUStringList FilterFactory::impl_readSortedFilterListFromConfig(const ::rtl::OUString& sModule) const +{ + // SAFE -> ---------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aLock.clear(); + // <- SAFE ---------------------- + + try + { + css::uno::Reference< css::container::XNameAccess > xUISortConfig( + ::comphelper::ConfigurationHelper::openConfig(xSMGR, + CFGPACKAGE_TD_UISORT, + ::comphelper::ConfigurationHelper::E_READONLY), + css::uno::UNO_QUERY_THROW); + + // dont ccheck the module name here. If it does not exists, an exception is thrown and catched below. + // We return an empty list as result then. + css::uno::Reference< css::container::XNameAccess > xModule; + xUISortConfig->getByName(sModule) >>= xModule; + if (xModule.is()) // only to be on the safe side of life if the exception was not thrown .-) + { + // Note: convertion of the returned Any to OUStringList throws + // an IllegalArgumentException if the type does not match ... + // but it resets the OUStringList to a length of 0 if the Any is empty! + OUStringList lSortedFilters(xModule->getByName(PROPNAME_SORTEDFILTERLIST)); + return lSortedFilters; + } + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} + + return OUStringList(); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +::rtl::OUString FilterFactory::impl_getImplementationName() +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.FilterFactory"); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > FilterFactory::impl_getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > lServiceNames(1); + lServiceNames[0] = ::rtl::OUString::createFromAscii("com.sun.star.document.FilterFactory"); + return lServiceNames; +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + FilterFactory* pNew = new FilterFactory(xSMGR); + return css::uno::Reference< css::uno::XInterface >(static_cast< css::lang::XMultiServiceFactory* >(pNew), css::uno::UNO_QUERY); +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/filterfactory.hxx b/filter/source/config/cache/filterfactory.hxx new file mode 100644 index 000000000000..2f0ba31f942b --- /dev/null +++ b/filter/source/config/cache/filterfactory.hxx @@ -0,0 +1,212 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __FILTER_CONFIG_FILTERFACTORY_HXX_ +#define __FILTER_CONFIG_FILTERFACTORY_HXX_ + +//_______________________________________________ +// includes + +#include "basecontainer.hxx" +#include "querytokenizer.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <cppuhelper/implbase1.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements the service <type scope="com.sun.star.document">FilterFactory</type>. + */ +class FilterFactory : public ::cppu::ImplInheritanceHelper1< BaseContainer , + css::lang::XMultiServiceFactory > +{ + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short standard ctor to connect this interface wrapper to + the global filter cache instance ... + + @param xSMGR + reference to the uno service manager, which created this service instance. + */ + FilterFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~FilterFactory(); + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // XMultiServiceFactory + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const ::rtl::OUString& sFilter) + throw(css::uno::Exception , + css::uno::RuntimeException); + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const ::rtl::OUString& sFilter , + const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames() + throw(css::uno::RuntimeException); + + //--------------------------------------- + // XContainerQuery + + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery(const ::rtl::OUString& sQuery) + throw (css::uno::RuntimeException); + + //------------------------------------------- + // internal helper! + + private: + + //--------------------------------------- + + /** @short implement the container string query: "matchByDocumentService=:iflags=:eflags=:..." + + @param lTokens + the list of query tokens and its values. + + @return A string list of internal filter names, including + all filters, which match this query. + */ + OUStringList impl_queryMatchByDocumentService(const QueryTokenizer& lTokens) const; + + //--------------------------------------- + + /** TODO document me + */ + OUStringList impl_getListOfInstalledModules() const; + + //--------------------------------------- + + /** @short implement the container string query: + "getSortedFilterList()[:module=<xxx>]:[iflags=<xxx>][:eflags=<xxx>]" + + @param lTokens + the list of query tokens and its values. + + @return A string list of internal filter names, including + all filters, which match this query. + */ + OUStringList impl_getSortedFilterList(const QueryTokenizer& lTokens) const; + + //--------------------------------------- + + /** TODO document me + */ + OUStringList impl_getSortedFilterListForModule(const ::rtl::OUString& sModule, + sal_Int32 nIFlags, + sal_Int32 nEFlags) const; + + //--------------------------------------- + + /** @short read a specialized and sorted list of filter names from + the configuration (matching the specified module) + + @param sModule + the module for which the sorted list should be retrieved for. + + @return A string list of internal filter names. + Can be empty. + */ + OUStringList impl_readSortedFilterListFromConfig(const ::rtl::OUString& sModule) const; + + //------------------------------------------- + // static uno helper! + + public: + + //--------------------------------------- + + /** @short return the uno implementation name of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix uno implementation name of this class. + */ + static ::rtl::OUString impl_getImplementationName(); + + //--------------------------------------- + + /** @short return the list of supported uno services of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix list of uno services supported by this class. + */ + static css::uno::Sequence< ::rtl::OUString > impl_getSupportedServiceNames(); + + //--------------------------------------- + + /** @short return a new intsnace of this class. + + @descr This method is used by the uno service manager, to create + a new instance of this service if needed. + + @param xSMGR + reference to the uno service manager, which require + this new instance. It should be passed to the new object + so it can be used internaly to create own needed uno resources. + + @return The new instance of this service as an uno reference. + */ + static css::uno::Reference< css::uno::XInterface > impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_FILTERFACTORY_HXX_ diff --git a/filter/source/config/cache/frameloaderfactory.cxx b/filter/source/config/cache/frameloaderfactory.cxx new file mode 100644 index 000000000000..3c9163899a97 --- /dev/null +++ b/filter/source/config/cache/frameloaderfactory.cxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * 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 "frameloaderfactory.hxx" +#include "macros.hxx" +#include "constant.hxx" +#include "versions.hxx" + +//_______________________________________________ +// includes +#include <com/sun/star/lang/XInitialization.hpp> +#include <comphelper/enumhelper.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +FrameLoaderFactory::FrameLoaderFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + BaseContainer::init(xSMGR , + FrameLoaderFactory::impl_getImplementationName() , + FrameLoaderFactory::impl_getSupportedServiceNames(), + FilterCache::E_FRAMELOADER ); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +FrameLoaderFactory::~FrameLoaderFactory() +{ +} + +/*----------------------------------------------- + 16.07.2003 13:37 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL FrameLoaderFactory::createInstance(const ::rtl::OUString& sLoader) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + return createInstanceWithArguments(sLoader, css::uno::Sequence< css::uno::Any >()); +} + +/*----------------------------------------------- + 17.07.2003 09:00 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL FrameLoaderFactory::createInstanceWithArguments(const ::rtl::OUString& sLoader , + const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + ::rtl::OUString sRealLoader = sLoader; + + #ifdef _FILTER_CONFIG_MIGRATION_Q_ + + /* -> TODO - HACK + check if the given loader name realy exist ... + Because our old implementation worked with an internal + type name instead of a loader name. For a small migration time + we must simulate this old feature :-( */ + + if (!m_rCache->hasItem(FilterCache::E_FRAMELOADER, sLoader) && m_rCache->hasItem(FilterCache::E_TYPE, sLoader)) + { + _FILTER_CONFIG_LOG_("FrameLoaderFactory::createInstanceWithArguments() ... simulate old type search functionality!\n"); + + css::uno::Sequence< ::rtl::OUString > lTypes(1); + lTypes[0] = sLoader; + + css::uno::Sequence< css::beans::NamedValue > lQuery(1); + lQuery[0].Name = PROPNAME_TYPES; + lQuery[0].Value <<= lTypes; + + css::uno::Reference< css::container::XEnumeration > xSet = createSubSetEnumerationByProperties(lQuery); + while(xSet->hasMoreElements()) + { + ::comphelper::SequenceAsHashMap lLoaderProps(xSet->nextElement()); + if (!(lLoaderProps[PROPNAME_NAME] >>= sRealLoader)) + continue; + } + + // prevent outside code against NoSuchElementException! + // But dont implement such defensive strategy for our new create handling :-) + if (!m_rCache->hasItem(FilterCache::E_FRAMELOADER, sRealLoader)) + return css::uno::Reference< css::uno::XInterface>(); + } + + /* <- HACK */ + + #endif // _FILTER_CONFIG_MIGRATION_Q_ + + // search loader on cache + CacheItem aLoader = m_rCache->getItem(m_eType, sRealLoader); + + // create service instance + css::uno::Reference< css::uno::XInterface > xLoader = m_xSMGR->createInstance(sRealLoader); + + // initialize filter + css::uno::Reference< css::lang::XInitialization > xInit(xLoader, css::uno::UNO_QUERY); + if (xInit.is()) + { + // format: lInitData[0] = seq<PropertyValue>, which contains all configuration properties of this loader + // lInitData[1] = lArguments[0] + // ... + // lInitData[n] = lArguments[n-1] + css::uno::Sequence< css::beans::PropertyValue > lConfig; + aLoader >> lConfig; + + ::comphelper::SequenceAsVector< css::uno::Any > stlArguments(lArguments); + stlArguments.insert(stlArguments.begin(), css::uno::makeAny(lConfig)); + + css::uno::Sequence< css::uno::Any > lInitData; + stlArguments >> lInitData; + + xInit->initialize(lInitData); + } + + return xLoader; + // <- SAFE +} + +/*----------------------------------------------- + 09.07.2003 07:46 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > SAL_CALL FrameLoaderFactory::getAvailableServiceNames() + throw(css::uno::RuntimeException) +{ + // must be the same list as ((XNameAccess*)this)->getElementNames() return! + return getElementNames(); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +::rtl::OUString FrameLoaderFactory::impl_getImplementationName() +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.FrameLoaderFactory"); +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > FrameLoaderFactory::impl_getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > lServiceNames(1); + lServiceNames[0] = ::rtl::OUString::createFromAscii("com.sun.star.frame.FrameLoaderFactory"); + return lServiceNames; +} + +/*----------------------------------------------- + 09.07.2003 07:43 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL FrameLoaderFactory::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + FrameLoaderFactory* pNew = new FrameLoaderFactory(xSMGR); + return css::uno::Reference< css::uno::XInterface >(static_cast< css::lang::XMultiServiceFactory* >(pNew), css::uno::UNO_QUERY); +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/frameloaderfactory.hxx b/filter/source/config/cache/frameloaderfactory.hxx new file mode 100644 index 000000000000..7741f0011f38 --- /dev/null +++ b/filter/source/config/cache/frameloaderfactory.hxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __FILTER_CONFIG_FRAMELOADERFACTORY_HXX_ +#define __FILTER_CONFIG_FRAMELOADERFACTORY_HXX_ + +//_______________________________________________ +// includes + +#include "basecontainer.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <cppuhelper/implbase1.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements the service <type scope="com.sun.star.document">FrameLoaderFactory</type>. + */ +class FrameLoaderFactory : public ::cppu::ImplInheritanceHelper1< BaseContainer , + css::lang::XMultiServiceFactory > +{ + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short standard ctor to connect this interface wrapper to + the global filter cache instance ... + + @param xSMGR + reference to the uno service manager, which created this service instance. + */ + FrameLoaderFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~FrameLoaderFactory(); + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // XMultiServiceFactory + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const ::rtl::OUString& sLoader) + throw(css::uno::Exception , + css::uno::RuntimeException); + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const ::rtl::OUString& sLoader , + const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames() + throw(css::uno::RuntimeException); + + //------------------------------------------- + // static uno helper! + + public: + + //--------------------------------------- + + /** @short return the uno implementation name of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix uno implementation name of this class. + */ + static ::rtl::OUString impl_getImplementationName(); + + //--------------------------------------- + + /** @short return the list of supported uno services of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix list of uno services supported by this class. + */ + static css::uno::Sequence< ::rtl::OUString > impl_getSupportedServiceNames(); + + //--------------------------------------- + + /** @short return a new intsnace of this class. + + @descr This method is used by the uno service manager, to create + a new instance of this service if needed. + + @param xSMGR + reference to the uno service manager, which require + this new instance. It should be passed to the new object + so it can be used internaly to create own needed uno resources. + + @return The new instance of this service as an uno reference. + */ + static css::uno::Reference< css::uno::XInterface > impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_FRAMELOADERFACTORY_HXX_ diff --git a/filter/source/config/cache/lateinitlistener.cxx b/filter/source/config/cache/lateinitlistener.cxx new file mode 100644 index 000000000000..b9b090025227 --- /dev/null +++ b/filter/source/config/cache/lateinitlistener.cxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * 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 "lateinitlistener.hxx" +#include "lateinitthread.hxx" + +//_______________________________________________ +// includes +#include <rtl/ustring.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 14.08.2003 07:35 +-----------------------------------------------*/ +LateInitListener::LateInitListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) + : BaseLock( ) + , m_xSMGR (xSMGR) +{ + // important to do so ... + // Otherwhise the temp. reference to ourselves + // will kill us at realeasing time! + osl_incrementInterlockedCount( &m_refCount ); + + m_xBroadcaster = css::uno::Reference< css::document::XEventBroadcaster >( + m_xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.GlobalEventBroadcaster")), + css::uno::UNO_QUERY); + + m_xBroadcaster->addEventListener(static_cast< css::document::XEventListener* >(this)); + + osl_decrementInterlockedCount( &m_refCount ); +} + +/*----------------------------------------------- + 14.08.2003 07:25 +-----------------------------------------------*/ +LateInitListener::~LateInitListener() +{ +} + +/*----------------------------------------------- + 14.08.2003 08:45 +-----------------------------------------------*/ +void SAL_CALL LateInitListener::notifyEvent(const css::document::EventObject& aEvent) + throw(css::uno::RuntimeException) +{ + // wait for events, which indicates finished open of the first document + if ( + (aEvent.EventName.equalsAscii("OnNew") ) || + (aEvent.EventName.equalsAscii("OnLoad")) + ) + { + // this thread must be started one times only ... + // cancel listener connection before! + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + if ( !m_xBroadcaster.is() ) + // the beauty of multi-threading ... OnLoad can be notified synchronously or asynchronously. In particular, + // SFX-based documents notify it synchronously, database documents do it asynchronously. + // Now if multiple documents are opened "at the same time", it is well possible that we get two events from + // different threads, where upon the first event, we already remove ourself from m_xBroadcaster, and start + // the thread, nonetheless there's also a second notification "in the queue", which will arrive short + // thereafter. + // In such a case, simply ignore this second event. + return; + + m_xBroadcaster->removeEventListener(static_cast< css::document::XEventListener* >(this)); + m_xBroadcaster.clear(); + + aLock.clear(); + // <- SAFE + + LateInitThread* pThread = new LateInitThread(); + pThread->create(); + } +} + +/*----------------------------------------------- + 14.08.2003 07:48 +-----------------------------------------------*/ +void SAL_CALL LateInitListener::disposing(const css::lang::EventObject& /* aEvent */ ) + throw(css::uno::RuntimeException) +{ + // ??? + // Normaly it should never be called. Because we cancel our listener connection + // if we got the event about finished open of the first office document. + // But if this method was reached, it indicates an office, which was started + // (might as remote script container for an external API client) but not realy used. + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + m_xBroadcaster.clear(); + aLock.clear(); + // <- SAFE +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/lateinitlistener.hxx b/filter/source/config/cache/lateinitlistener.hxx new file mode 100644 index 000000000000..0ed1abf1e679 --- /dev/null +++ b/filter/source/config/cache/lateinitlistener.hxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __FILTER_CONFIG_LATEINITLISTENER_HXX_ +#define __FILTER_CONFIG_LATEINITLISTENER_HXX_ + +//_______________________________________________ +// includes + +#include "cacheitem.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <cppuhelper/implbase1.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements a listener, which will update the + global filter cache of an office, after zje office + startup was finished. + + @descr To perform startup of an office, the filter cache starts + with a minimum set of properties only. After the first document + was loaded successfully a thread will be started to fill the + cache with all other proeprties, so it can work with the whole + filter configuration. + */ +class LateInitListener : public BaseLock // must be the first one to guarantee right initialized mutex member! + , public ::cppu::WeakImplHelper1< css::document::XEventListener > +{ + //------------------------------------------- + // member + + private: + + /** @short reference to an uno service manager, which can be used + to create own needed services. */ + css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR; + + /** @short reference to the global event broadcaster, which is usde to find + out, when the first office document was opened successfully. */ + css::uno::Reference< css::document::XEventBroadcaster > m_xBroadcaster; + + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short initialize new instance of this class. + + @descr It set a reference to the global filter cache singleton, + which should be updated here. Further it starts listening + on the global event broadcaster to get the information, when + loading of the first document was finished. + + @param xSMGR + reference to a service manager, which can be used to create + own needed uno services. + */ + LateInitListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~LateInitListener(); + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // document.XEventListener + + virtual void SAL_CALL notifyEvent(const css::document::EventObject& aEvent) + throw(css::uno::RuntimeException); + + //--------------------------------------- + // lang.XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) + throw(css::uno::RuntimeException); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_LATEINITLISTENER_HXX_ diff --git a/filter/source/config/cache/lateinitthread.cxx b/filter/source/config/cache/lateinitthread.cxx new file mode 100644 index 000000000000..13432c30ad0f --- /dev/null +++ b/filter/source/config/cache/lateinitthread.cxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * 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 "lateinitthread.hxx" + +//_______________________________________________ +// includes + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 14.08.2003 09:31 +-----------------------------------------------*/ +LateInitThread::LateInitThread() +{ +} + +/*----------------------------------------------- + 14.08.2003 08:42 +-----------------------------------------------*/ +LateInitThread::~LateInitThread() +{ +} + +/*----------------------------------------------- + 28.10.2003 09:30 +-----------------------------------------------*/ +void SAL_CALL LateInitThread::run() +{ + // sal_True => It indicates using of this method by this thread + // The filter cache use this information to show an assertion + // for "optimization failure" in case the first calli of loadAll() + // was not this thread ... + + // Further please dont catch any exception here. + // May be they show the problem of a corrupted filter + // configuration, which is handled inside our event loop or desktop.main()! + + ::salhelper::SingletonRef< FilterCache > rCache; + rCache->load(FilterCache::E_CONTAINS_ALL, sal_True); +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/lateinitthread.hxx b/filter/source/config/cache/lateinitthread.hxx new file mode 100644 index 000000000000..c330394d434d --- /dev/null +++ b/filter/source/config/cache/lateinitthread.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __FILTER_CONFIG_LATEINITTHREAD_HXX_ +#define __FILTER_CONFIG_LATEINITTHREAD_HXX_ + +//_______________________________________________ +// includes + +#include "filtercache.hxx" +#include <salhelper/singletonref.hxx> +#include <osl/thread.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements a thread, which will update the + global filter cache of an office, after its + startup was finished. + + @descr Its started by a LateInitListener instance ... + + @see LateInitListener + + @attention The filter cache will be blocked during this thrad runs! + */ +class LateInitThread : public ::osl::Thread +{ + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short initialize new instance of this class. + */ + LateInitThread(); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~LateInitThread(); + + //--------------------------------------- + + /** @short thread function. + */ + virtual void SAL_CALL run(); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_LATEINITTHREAD_HXX_ diff --git a/filter/source/config/cache/macros.hxx b/filter/source/config/cache/macros.hxx new file mode 100644 index 000000000000..485029ead5a8 --- /dev/null +++ b/filter/source/config/cache/macros.hxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _FILTER_CONFIG_MACROS_HXX_ +#define _FILTER_CONFIG_MACROS_HXX_ + +//_______________________________________________ + +#include <rtl/ustring.hxx> + +#ifdef _FILTER_CONFIG_FROM_ASCII_ + #error "who already defined such macro :-(" +#endif + +#ifdef _FILTER_CONFIG_TO_ASCII_ + #error "who already defined such macro :-(" +#endif + +/* +//#define _FILTER_CONFIG_FROM_ASCII_(ASCII_STRING) \ +// ::rtl::OUString::createFromAscii(ASCII_STRING) +*/ + +#define _FILTER_CONFIG_FROM_ASCII_(ASCII_STRING) \ + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ASCII_STRING)) + +#define _FILTER_CONFIG_TO_ASCII_(UNICODE_STRING) \ + ::rtl::OUStringToOString(UNICODE_STRING, RTL_TEXTENCODING_UTF8).getStr() + +#define _FILTER_CONFIG_LOG_(TEXT) +#define _FILTER_CONFIG_LOG_1_(FORMAT, ARG1) +#define _FILTER_CONFIG_LOG_2_(FORMAT, ARG1, ARG2) +#define _FILTER_CONFIG_LOG_3_(FORMAT, ARG1, ARG2, ARG3) + +/* +#include <rtl/ustrbuf.hxx> + +#include <stdio.h> + +//_______________________________________________ + + #ifdef _FILTER_CONFIG_LOG_ + #error "who already defined such macro :-(" + #endif + + #ifdef _FILTER_CONFIG_LOG_1_ + #error "who already defined such macro :-(" + #endif + + #ifdef _FILTER_CONFIG_LOG_2_ + #error "who already defined such macro :-(" + #endif + + #ifdef _FILTER_CONFIG_LOG_3_ + #error "who already defined such macro :-(" + #endif + + //------------------------------------------- + // @short append given text to the log file + // + // @param TEXT [const char*] + // contains the text, which should be logged + // + #define _FILTER_CONFIG_LOG_(TEXT) \ + { \ + FILE* pFile = fopen("filtercache.log", "a");\ + fprintf(pFile, "%s", TEXT); \ + fclose(pFile); \ + } + + //------------------------------------------- + // @short append given text to the log file + // and supports using one optional argument. + // + // @descr The syntax of FORMAT and ARG1 follows the + // mechanism of e.g. sprintf(); + // + // @param FORMAT [const char*] + // specify the format of the log message + // + // @param ARGn + // points to any argument(s), which will be used + // inside the FORMAT string to replace place holder(s). + // + #define _FILTER_CONFIG_LOG_1_(FORMAT, ARG1) \ + { \ + FILE* pFile = fopen("filtercache.log", "a");\ + fprintf(pFile, FORMAT, ARG1); \ + fclose(pFile); \ + } + + #define _FILTER_CONFIG_LOG_2_(FORMAT, ARG1, ARG2) \ + { \ + FILE* pFile = fopen("filtercache.log", "a");\ + fprintf(pFile, FORMAT, ARG1, ARG2); \ + fclose(pFile); \ + } + + #define _FILTER_CONFIG_LOG_3_(FORMAT, ARG1, ARG2, ARG3) \ + { \ + FILE* pFile = fopen("filtercache.log", "a");\ + fprintf(pFile, FORMAT, ARG1, ARG2, ARG3); \ + fclose(pFile); \ + } + +#endif // OSL_DEBUG_LEVEL < 2 +*/ +#endif // _FILTER_CONFIG_MACROS_HXX_ diff --git a/filter/source/config/cache/makefile.mk b/filter/source/config/cache/makefile.mk new file mode 100644 index 000000000000..d94c81e35010 --- /dev/null +++ b/filter/source/config/cache/makefile.mk @@ -0,0 +1,87 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ = ..$/..$/.. + +PRJNAME = filter +TARGET = filterconfig +ENABLE_EXCEPTIONS = TRUE +VERSION = 1 +USE_DEFFILE = TRUE +LIBTARGET = NO + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Library ----------------------------------- + +SHL1TARGET= $(TARGET)$(VERSION) + +SLOFILES= \ + $(SLO)$/configflush.obj \ + $(SLO)$/basecontainer.obj \ + $(SLO)$/cacheitem.obj \ + $(SLO)$/contenthandlerfactory.obj \ + $(SLO)$/filtercache.obj \ + $(SLO)$/filterfactory.obj \ + $(SLO)$/frameloaderfactory.obj \ + $(SLO)$/lateinitlistener.obj \ + $(SLO)$/lateinitthread.obj \ + $(SLO)$/querytokenizer.obj \ + $(SLO)$/registration.obj \ + $(SLO)$/typedetection.obj \ + $(SLO)$/cacheupdatelistener.obj + +SHL1OBJS= $(SLOFILES) + +SHL1STDLIBS= \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(TOOLSLIB) \ + $(UNOTOOLSLIB) \ + $(FWELIB) + +DEF1NAME= $(SHL1TARGET) +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1DEPN= +SHL1IMPLIB= i$(SHL1TARGET) +SHL1VERSIONMAP= $(SOLARENV)/src/component.map + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/filterconfig1.component + +$(MISC)/filterconfig1.component .ERRREMOVE : \ + $(SOLARENV)/bin/createcomponent.xslt filterconfig1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt filterconfig1.component diff --git a/filter/source/config/cache/querytokenizer.cxx b/filter/source/config/cache/querytokenizer.cxx new file mode 100644 index 000000000000..a07a95e37d23 --- /dev/null +++ b/filter/source/config/cache/querytokenizer.cxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * 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 "querytokenizer.hxx" + +//_______________________________________________ +// includes + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 01.08.2003 10:42 +-----------------------------------------------*/ +QueryTokenizer::QueryTokenizer(const ::rtl::OUString& sQuery) + : m_bValid(sal_True) +{ + sal_Int32 token = 0; + while(token != -1) + { + ::rtl::OUString sToken = sQuery.getToken(0, ':', token); + if (sToken.getLength()) + { + sal_Int32 equal = sToken.indexOf('='); + + if (equal == 0) + m_bValid = sal_False; + OSL_ENSURE(m_bValid, "QueryTokenizer::QueryTokenizer()\nFound non boolean query parameter ... but its key is empty. Will be ignored!\n"); + + ::rtl::OUString sKey; + ::rtl::OUString sVal; + + sKey = sToken; + if (equal > 0) + { + sKey = sToken.copy(0 , equal ); + sVal = sToken.copy(equal+1, sToken.getLength()-(equal+1)); + } + + if (find(sKey) != end()) + m_bValid = sal_False; + OSL_ENSURE(m_bValid, "QueryTokenizer::QueryTokenizer()\nQuery contains same param more then once. Last one wins :-)\n"); + + (*this)[sKey] = sVal; + } + } +} + +/*----------------------------------------------- + 01.08.2003 10:28 +-----------------------------------------------*/ +QueryTokenizer::~QueryTokenizer() +{ + /*TODO*/ +} + +/*----------------------------------------------- + 01.08.2003 10:53 +-----------------------------------------------*/ +sal_Bool QueryTokenizer::valid() const +{ + return m_bValid; +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/querytokenizer.hxx b/filter/source/config/cache/querytokenizer.hxx new file mode 100644 index 000000000000..0823e49f5616 --- /dev/null +++ b/filter/source/config/cache/querytokenizer.hxx @@ -0,0 +1,115 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _FILTER_CONFIG_QUERYTOKENIZER_HXX_ +#define _FILTER_CONFIG_QUERYTOKENIZER_HXX_ + +//_______________________________________________ +// includes + +#include <hash_map> +#include <rtl/ustring.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +//_______________________________________________ +// definitions + +/** @short It can be used to split any query string (which can be used at the + related interface <type scope="com::sun::star::container">XContainerQuery</type>) + into its different tokens using a fix schema. + + @descr All queries implemented of the services + <ul> + <li><type scope="com::sun::star::document">TypeDetection</type></li> + <li><type scope="com::sun::star::document">FilterFactory</type></li> + <li><type scope="com::sun::star::document">ExtendedTypeDetectionFactory</type></li> + <li><type scope="com::sun::star::frame">FrameLoaderFactory</type></li> + <li><type scope="com::sun::star::frame">ContentHandlerFactory</type></li> + </ul> + uses this schema. + + @attention This class is not threadsafe implemented. Because its not neccessary. + But you have to make shure, that ist not used as such :-) + */ +class QueryTokenizer : public ::std::hash_map< ::rtl::OUString , + ::rtl::OUString , + ::rtl::OUStringHash , + ::std::equal_to< ::rtl::OUString > > +{ + //------------------------------------------- + // member + + private: + + /** @short Because the given query can contain errors, + it should be checked outside. + + TODO May its a good idea to describe the real problem + more detailed ... + */ + sal_Bool m_bValid; + + //------------------------------------------- + // interface + + public: + + /** @short create a new tokenizer instance with a + a new query. + + @descr The given query is immidiatly analyzed + and seperated into its token, which can + be access by some specialized method later. + + @param sQuery + the query string. + */ + QueryTokenizer(const ::rtl::OUString& sQuery); + + //--------------------------------------- + + /** @short destruct an instance of this class. + */ + virtual ~QueryTokenizer(); + + //--------------------------------------- + + /** @short can be used to check if analyzing of given query + was successfully or not. + */ + virtual sal_Bool valid() const; +}; + + } // namespace config +} // namespace filter + +#endif // _FILTER_CONFIG_QUERYTOKENIZER_HXX_ diff --git a/filter/source/config/cache/registration.cxx b/filter/source/config/cache/registration.cxx new file mode 100644 index 000000000000..2be110871ee1 --- /dev/null +++ b/filter/source/config/cache/registration.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * 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 "registration.hxx" + +//_______________________________________________ +// includes + +#ifdef _FILTER_CONFIG_CONSTANT_HXX_ +# error "Already included constant.hxx" +#else +# define PROPNAME_IMPL_DECL +# include "constant.hxx" +#endif +#include <stdio.h> +#include "typedetection.hxx" +#include "filterfactory.hxx" +#include "contenthandlerfactory.hxx" +#include "frameloaderfactory.hxx" +#include "configflush.hxx" + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +rtl::OUString pFilterStrings[19]; +static bool bInitialized = false; + +static void InitConstants() +{ + if (!bInitialized) + { + ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex()); + if (!bInitialized) + { + PROPNAME_NAME; + PROPNAME_UINAME; + PROPNAME_UINAMES; + PROPNAME_PREFERRED; + PROPNAME_PREFERREDFILTER; + PROPNAME_DETECTSERVICE; + PROPNAME_MEDIATYPE; + PROPNAME_CLIPBOARDFORMAT; + PROPNAME_URLPATTERN; + PROPNAME_EXTENSIONS; + PROPNAME_TYPE; + PROPNAME_DOCUMENTSERVICE; + PROPNAME_FILTERSERVICE; + PROPNAME_UICOMPONENT; + PROPNAME_FLAGS; + PROPNAME_USERDATA; + PROPNAME_TEMPLATENAME; + PROPNAME_FILEFORMATVERSION; + PROPNAME_TYPES; + bInitialized = true; + } + } +} + +// extern "C" component_getImplementationEnvironment() +_COMPHELPER_COMPONENT_GETIMPLEMENTATIONENVIRONMENT + +// extern "C" component_getFactory() +_COMPHELPER_COMPONENT_GETFACTORY +( + { InitConstants(); }, + _COMPHELPER_MULTIINSTANCEFACTORY( TypeDetection::impl_getImplementationName() , + TypeDetection::impl_getSupportedServiceNames(), + TypeDetection::impl_createInstance ) + + _COMPHELPER_MULTIINSTANCEFACTORY( FilterFactory::impl_getImplementationName() , + FilterFactory::impl_getSupportedServiceNames(), + FilterFactory::impl_createInstance ) + + _COMPHELPER_MULTIINSTANCEFACTORY( ContentHandlerFactory::impl_getImplementationName() , + ContentHandlerFactory::impl_getSupportedServiceNames(), + ContentHandlerFactory::impl_createInstance ) + + _COMPHELPER_MULTIINSTANCEFACTORY( FrameLoaderFactory::impl_getImplementationName() , + FrameLoaderFactory::impl_getSupportedServiceNames(), + FrameLoaderFactory::impl_createInstance ) + + _COMPHELPER_ONEINSTANCEFACTORY( ConfigFlush::impl_getImplementationName() , + ConfigFlush::impl_getSupportedServiceNames(), + ConfigFlush::impl_createInstance ) +) + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/registration.hxx b/filter/source/config/cache/registration.hxx new file mode 100644 index 000000000000..d664cc365abb --- /dev/null +++ b/filter/source/config/cache/registration.hxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef __COMPHELPER_REGISTRATION_HXX_ +#define __COMPHELPER_REGISTRATION_HXX_ + +//_______________________________________________ +// includes + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/factory.hxx> + +//_______________________________________________ +// namespace + +namespace comphelper{ + +//_______________________________________________ +// declaration + +//_______________________________________________ + +/** TODO doc + */ +#define _COMPHELPER_COMPONENT_GETIMPLEMENTATIONENVIRONMENT \ + extern "C" void SAL_CALL component_getImplementationEnvironment(const sal_Char** ppEnvironmentTypeName, \ + uno_Environment** /* ppEnvironment */ ) \ + { \ + *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; \ + } + +//_______________________________________________ + +/** TODO doc + */ +#define _COMPHELPER_MULTIINSTANCEFACTORY(IMPLEMENTATIONNAME, SERVICENAMES, FACTORYMETHOD) \ + if (IMPLEMENTATIONNAME == sImplName) \ + xFactory = ::cppu::createSingleFactory(xSMGR , \ + IMPLEMENTATIONNAME, \ + FACTORYMETHOD , \ + SERVICENAMES ); + +//_______________________________________________ + +/** TODO doc + */ +#define _COMPHELPER_ONEINSTANCEFACTORY(IMPLEMENTATIONNAME, SERVICENAMES, FACTORYMETHOD) \ + if (IMPLEMENTATIONNAME == sImplName) \ + xFactory = ::cppu::createOneInstanceFactory(xSMGR , \ + IMPLEMENTATIONNAME, \ + FACTORYMETHOD , \ + SERVICENAMES ); + +//_______________________________________________ + +/** TODO doc + */ +#define _COMPHELPER_COMPONENT_GETFACTORY(STATIC_INIT,FACTORYLIST) \ + extern "C" void* SAL_CALL component_getFactory(const sal_Char* pImplementationName, \ + void* pServiceManager , \ + void* /* pRegistryKey */ ) \ + { \ + if ( \ + (!pImplementationName) || \ + (!pServiceManager ) \ + ) \ + return NULL; \ + \ + STATIC_INIT \ + \ + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = reinterpret_cast< css::lang::XMultiServiceFactory* >(pServiceManager); \ + css::uno::Reference< css::lang::XSingleServiceFactory > xFactory ; \ + rtl::OUString sImplName = ::rtl::OUString::createFromAscii(pImplementationName); \ + \ + /* This parameter will expand to: */ \ + /* _COMPHELPER_xxxFACTORY(1) */ \ + /* else */ \ + /* ... */ \ + /* else */ \ + /* _COMPHELPER_xxxFACTORY(n) */ \ + FACTORYLIST \ + \ + /* And if one of these checks was successfully => xFactory was set! */ \ + if (xFactory.is()) \ + { \ + xFactory->acquire(); \ + return xFactory.get(); \ + } \ + \ + return NULL; \ + } + +} // namespace comphelper + +#endif // #ifndef __COMPHELPER_REGISTRATION_HXX_ diff --git a/filter/source/config/cache/typedetection.cxx b/filter/source/config/cache/typedetection.cxx new file mode 100644 index 000000000000..4fe9a1df64e6 --- /dev/null +++ b/filter/source/config/cache/typedetection.cxx @@ -0,0 +1,1257 @@ +/************************************************************************* + * + * 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 "typedetection.hxx" +#include "constant.hxx" + +//_______________________________________________ +// includes +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> + +#ifndef _COM_SUN_STAR_IO_XINPUSTREAM_HPP_ +#include <com/sun/star/io/XInputStream.hpp> +#endif +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <tools/wldcrd.hxx> +#include <rtl/ustrbuf.hxx> +#include <framework/interaction.hxx> +#include <tools/urlobj.hxx> +#include <unotools/localfilehelper.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +// Use this switch to change the behaviour of preselection DocumentService ... (see using for further informations) +#define IGNORE_NON_URLMATCHING_TYPES_FOR_PRESELECTION_DOCUMENTSERVICE + +// enable/disable special handling for CSV/TXT problem +#define WORKAROUND_CSV_TXT_BUG_i60158 + +/*----------------------------------------------- + 03.07.2003 11:25 +-----------------------------------------------*/ +TypeDetection::TypeDetection(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + BaseContainer::init(xSMGR , + TypeDetection::impl_getImplementationName() , + TypeDetection::impl_getSupportedServiceNames(), + FilterCache::E_TYPE ); +} + +/*----------------------------------------------- + 03.07.2003 10:36 +-----------------------------------------------*/ +TypeDetection::~TypeDetection() +{ +} + +/*----------------------------------------------- + 03.11.2003 08:43 +-----------------------------------------------*/ +::rtl::OUString SAL_CALL TypeDetection::queryTypeByURL(const ::rtl::OUString& sURL) + throw (css::uno::RuntimeException) +{ + ::rtl::OUString sType; + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + css::util::URL aURL; + aURL.Complete = sURL; + css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICE_URLTRANSFORMER), css::uno::UNO_QUERY); + xParser->parseStrict(aURL); + + // set std types as minimum requirement first! + // Only in case no type was found for given URL, + // use optional types too ... + FlatDetection lFlatTypes; + m_rCache->detectFlatForURL(aURL, lFlatTypes); + + if ( + (lFlatTypes.size() < 1 ) && + (!m_rCache->isFillState(FilterCache::E_CONTAINS_TYPES)) + ) + { + m_rCache->load(FilterCache::E_CONTAINS_TYPES); + m_rCache->detectFlatForURL(aURL, lFlatTypes); + } + + // first item is guaranteed as "preferred" one! + if (lFlatTypes.size() > 0) + { + const FlatDetectionInfo& aMatch = *(lFlatTypes.begin()); + sType = aMatch.sType; + } + + return sType; + // <- SAFE +} + +/*----------------------------------------------- + 31.10.2003 09:36 +-----------------------------------------------*/ +::rtl::OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor, + sal_Bool bAllowDeep ) + throw (css::uno::RuntimeException) +{ + // make the descriptor more useable :-) + ::comphelper::MediaDescriptor stlDescriptor(lDescriptor); + + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + //******************************************* + // parse given URL to split it into e.g. main and jump marks ... + ::rtl::OUString sURL = stlDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString()); + +#if OSL_DEBUG_LEVEL > 0 + if (stlDescriptor.find(::rtl::OUString::createFromAscii("FileName")) != stlDescriptor.end()) + OSL_ENSURE(sal_False, "Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!"); +#endif + + css::util::URL aURL; + aURL.Complete = sURL; + css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICE_URLTRANSFORMER), css::uno::UNO_QUERY); + xParser->parseStrict(aURL); + + //******************************************* + // preselected filter, type or document service? + // use it as first "flat" detected type later! + FlatDetection lFlatTypes; + impl_getPreselection(aURL, stlDescriptor, lFlatTypes); + + //******************************************* + // get all types, which match to the given descriptor + // That can be true by: extensions/url pattern/mime type etcpp. + m_rCache->detectFlatForURL(aURL, lFlatTypes); + + aLock.clear(); + // <- SAFE ---------------------------------- + + ::rtl::OUString sType ; + ::rtl::OUString sLastChance; + + try + { + //******************************************* + // verify every flat detected (or preselected!) type + // by calling its registered deep detection service. + // But break this loop if a type match to the given descriptor + // by an URL pattern(!) or if deep detection isnt allowed from + // outside (bAllowDeep=FALSE) or break the whole detection by + // throwing an exception if creation of the might needed input + // stream failed by e.g. an IO exception ... + OUStringList lUsedDetectors; + if (lFlatTypes.size()>0) + sType = impl_detectTypeFlatAndDeep(stlDescriptor, lFlatTypes, bAllowDeep, lUsedDetectors, sLastChance); + + //******************************************* + // if no flat detected (nor preselected!) type could be + // verified and no error occured during creation of + // the might needed input stream, start detection + // which uses all registered deep detection services. + if ( + (!sType.getLength()) && + (bAllowDeep ) + ) + { + sType = impl_detectTypeDeepOnly(stlDescriptor, lUsedDetectors); + } + + //******************************************* + // flat detection failed + // pure deep detection failed + // => ask might existing InteractionHandler + // means: ask user for it's decision + if (!sType.getLength()) + sType = impl_askUserForTypeAndFilterIfAllowed(stlDescriptor); + + //******************************************* + // no real detected type - but a might valid one. + // update descriptor and set last chance for return. + if (!sType.getLength() && sLastChance.getLength()) + { + OSL_ENSURE(sal_False, "set first flat detected type without a registered deep detection service as \"last chance\" ... nevertheless some other deep detections said \"NO\". I TRY IT!"); + sType = sLastChance; + } + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { sType = ::rtl::OUString(); } + + //******************************************* + // adapt media descriptor, so it contains the right values + // for type/filter name/document service/ etcpp. + impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!! + impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType); + + stlDescriptor >> lDescriptor; + return sType; +} + +/*----------------------------------------------- + 03.07.2003 10:36 +-----------------------------------------------*/ +void TypeDetection::impl_checkResultsAndAddBestFilter(::comphelper::MediaDescriptor& rDescriptor, + ::rtl::OUString& sType ) +{ + // a) + // Dont overwrite a might preselected filter! + ::rtl::OUString sFilter = rDescriptor.getUnpackedValueOrDefault( + ::comphelper::MediaDescriptor::PROP_FILTERNAME(), + ::rtl::OUString()); + if (sFilter.getLength()) + return; + + // b) + // check a preselected document service too. + // Then we have to search a suitable filter witin this module. + ::rtl::OUString sDocumentService = rDescriptor.getUnpackedValueOrDefault( + ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), + ::rtl::OUString()); + if (sDocumentService.getLength()) + { + try + { + ::rtl::OUString sRealType = sType; + + #ifdef WORKAROUND_CSV_TXT_BUG_i60158 + // Workaround for #i60158# + // We do not have right filter for Text_Ascii in calc nor a suitable filter for CSV in writer. + // So we must overrule our detection and make the right things. Normaly we should have + // one type TextAscii and two filters registered for these one type. + // But then we loose automatic opening of CSV files in calc instead of opening these files + // inside writer. + if ( + (sDocumentService.equalsAscii("com.sun.star.sheet.SpreadsheetDocument")) && + ( + (sRealType.equalsAscii("writer_Text" )) || + (sRealType.equalsAscii("writer_Text_encoded")) + ) + ) + { + sRealType = ::rtl::OUString::createFromAscii("calc_Text_txt_csv_StarCalc"); + } + else + if ( + (sDocumentService.equalsAscii("com.sun.star.text.TextDocument")) && + (sRealType.equalsAscii("calc_Text_txt_csv_StarCalc" )) + ) + { + sRealType = ::rtl::OUString::createFromAscii("writer_Text"); + } + #endif // WORKAROUND_CSV_TXT_BUG_i60158 + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // Attention: For executing next lines of code, We must be shure that + // all filters already loaded :-( + // That can disturb our "load on demand feature". But we have no other chance! + m_rCache->load(FilterCache::E_CONTAINS_FILTERS); + + CacheItem lIProps; + lIProps[PROPNAME_DOCUMENTSERVICE] <<= sDocumentService; + lIProps[PROPNAME_TYPE ] <<= sRealType; + OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps); + + aLock.clear(); + // <- SAFE + + for ( OUStringList::const_iterator pIt = lFilters.begin(); + pIt != lFilters.end() && sFilter.getLength() == 0 ; + ++pIt ) + { + // SAFE -> + aLock.reset(); + try + { + CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, *pIt); + sal_Int32 nFlags = 0; + aFilter[PROPNAME_FLAGS] >>= nFlags; + + if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT) + sFilter = *pIt; + } + catch(const css::uno::Exception&) {} + aLock.clear(); + // <- SAFE + } + + if (sFilter.getLength() > 0) + { + rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sRealType; + rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; + sType = sRealType; + return; + } + } + catch(const css::uno::Exception&) + {} + } + + // c) + // We can use the preferred filter for the specified type. + // Such preferred filter points: + // - to the default filter of the preferred application + // - or to any other filter if no preferred filter was set. + // Note: It's an optimization only! + // It's not guaranteed, that such preferred filter exists. + sFilter = ::rtl::OUString(); + try + { + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType); + aType[PROPNAME_PREFERREDFILTER] >>= sFilter; + CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); + + aLock.clear(); + // <- SAFE + + // no exception => found valid type and filter => set it on the given descriptor + rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sType ; + rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; + return; + } + catch(const css::uno::Exception&) + {} + + // d) + // Search for any import(!) filter, which is registered for this type. + sFilter = ::rtl::OUString(); + try + { + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + // Attention: For executing next lines of code, We must be shure that + // all filters already loaded :-( + // That can disturb our "load on demand feature". But we have no other chance! + m_rCache->load(FilterCache::E_CONTAINS_FILTERS); + + CacheItem lIProps; + lIProps[PROPNAME_TYPE] <<= sType; + OUStringList lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps); + + aLock.clear(); + // <- SAFE + + OUStringList::const_iterator pIt; + for ( pIt = lFilters.begin(); + pIt != lFilters.end() ; + ++pIt ) + { + sFilter = *pIt; + + // SAFE -> + aLock.reset(); + try + { + CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); + sal_Int32 nFlags = 0; + aFilter[PROPNAME_FLAGS] >>= nFlags; + + if ((nFlags & FLAGVAL_IMPORT) == FLAGVAL_IMPORT) + break; + } + catch(const css::uno::Exception&) + { continue; } + aLock.clear(); + // <- SAFE + + sFilter = ::rtl::OUString(); + } + + if (sFilter.getLength()) + { + rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sType ; + rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; + return; + } + } + catch(const css::uno::Exception&) + {} +} + +/*----------------------------------------------- + 14.11.2003 12:06 +-----------------------------------------------*/ +sal_Bool TypeDetection::impl_getPreselectionForType(const ::rtl::OUString& sPreSelType, + const css::util::URL& aParsedURL , + FlatDetection& rFlatTypes ) +{ + // Can be used to supress execution of some parts of this method + // if its already clear that detected type is valid or not. + // Its neccessary to use shared code at the end, which update + // all return parameters constistency! + sal_Bool bBreakDetection = sal_False; + + // Further we must know if it matches by pattern + // Every flat detected type by pattern wont be detected deep! + sal_Bool bMatchByPattern = sal_False; + + // And we must know if a preselection must be preferred, because + // it matches by it's extension too. + sal_Bool bMatchByExtension = sal_False; + + // If we e.g. collect all filters of a factory (be a forced factory preselection) + // we should preferr all filters of this factory, where the type match the given URL. + // All other types (which sorrespond to filters of the same factory - but dont match + // the URL) should be "used later" for detection and sorted at the end of our return vector + // rFlatTypes! + // => bPreferredPreselection = (matchByExtension || matchByURLPattern) + sal_Bool bPreferredPreselection = sal_False; + + // validate type + ::rtl::OUString sType(sPreSelType); + CacheItem aType; + try + { + // SAFE -> -------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + aType = m_rCache->getItem(FilterCache::E_TYPE, sType); + aLock.clear(); + // <- SAFE -------------------------- + } + catch(const css::container::NoSuchElementException&) + { + sType = ::rtl::OUString(); + bBreakDetection = sal_True; + } + + if (!bBreakDetection) + { + // We cant check a preselected type for a given stream! + // So we must believe, that it can work ... + if (aParsedURL.Complete.equalsAsciiL("private:stream", 14)) + bBreakDetection = sal_True; + } + + if (!bBreakDetection) + { + // extract extension from URL .. to check it case-insensitive ! + INetURLObject aParser (aParsedURL.Main); + ::rtl::OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT , + sal_True , + INetURLObject::DECODE_WITH_CHARSET); + sExtension = sExtension.toAsciiLowerCase(); + + // otherwhise we must know, if it matches to the given URL realy. + // especialy if it matches by its extension or pattern registration. + OUStringList lExtensions(aType[PROPNAME_EXTENSIONS]); + OUStringList lURLPattern(aType[PROPNAME_URLPATTERN]); + + for (OUStringList::const_iterator pIt = lExtensions.begin(); + pIt != lExtensions.end() ; + ++pIt ) + { + ::rtl::OUString sCheckExtension(pIt->toAsciiLowerCase()); + if (sCheckExtension.equals(sExtension)) + { + bBreakDetection = sal_True; + bMatchByExtension = sal_True; + bPreferredPreselection = sal_True; + break; + } + } + + if (!bBreakDetection) + { + for (OUStringList::const_iterator pIt = lURLPattern.begin(); + pIt != lURLPattern.end() ; + ++pIt ) + { + WildCard aCheck(*pIt); + if (aCheck.Matches(aParsedURL.Main)) + { + bBreakDetection = sal_True; + bMatchByPattern = sal_True; + bPreferredPreselection = sal_True; + break; + } + } + } + + /* + Comment ... why the following line of code should be comened out .-) + + This type does not seem to fit the requirements + But its an existing and well known type. + At least - [because may be the extension was missing :-( ] + we should try to detect this type deep ... + So we accept it here :-) + + if (!bBreakDetection) + sType = ::rtl::OUString(); + */ + } + + // if its a valid type - set it on all return values! + if (sType.getLength()) + { + FlatDetectionInfo aInfo; + aInfo.sType = sType; + aInfo.bMatchByExtension = bMatchByExtension; + aInfo.bMatchByPattern = bMatchByPattern; + aInfo.bPreselectedAsType = sal_True; + + if (bPreferredPreselection) + rFlatTypes.push_front(aInfo); + else + rFlatTypes.push_back(aInfo); + + return sal_True; + } + + // not valid! + return sal_False; +} + +/*----------------------------------------------- + 14.11.2003 12:09 +-----------------------------------------------*/ +sal_Bool TypeDetection::impl_getPreselectionForFilter(const ::rtl::OUString& sPreSelFilter, + const css::util::URL& aParsedURL , + FlatDetection& rFlatTypes ) +{ + // Can be used to supress execution of some parts of this method + // if its already clear that detected filter is valid or not. + // Its neccessary to use shared code at the end, which update + // all return parameters constistency! + sal_Bool bBreakDetection = sal_False; + + // validate filter + ::rtl::OUString sFilter(sPreSelFilter); + CacheItem aFilter; + try + { + // SAFE -> -------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); + aLock.clear(); + // <- SAFE -------------------------- + } + catch(const css::container::NoSuchElementException&) + { + sFilter = ::rtl::OUString(); + bBreakDetection = sal_True; + } + + if (!bBreakDetection) + { + // get its type and check if it matches the given URL + ::rtl::OUString sType; + aFilter[PROPNAME_TYPE] >>= sType; + + bBreakDetection = impl_getPreselectionForType(sType, aParsedURL, rFlatTypes); + + // not a valid type? -> not a valid filter! + if (!bBreakDetection) + sFilter = ::rtl::OUString(); + } + + // We have to mark all retrieved preselection items as "preselected by filter"! + FlatDetection::iterator pIt; + for ( pIt = rFlatTypes.begin(); + pIt != rFlatTypes.end() ; + ++pIt ) + { + FlatDetectionInfo& rInfo = *pIt; + rInfo.bPreselectedAsType = sal_False; + rInfo.bPreselectedByFilter = sal_True; + } + + if (sFilter.getLength()) + return sal_True; + else + return sal_False; +} + +/*----------------------------------------------- + 14.11.2003 12:11 +-----------------------------------------------*/ +sal_Bool TypeDetection::impl_getPreselectionForDocumentService(const ::rtl::OUString& sPreSelDocumentService, + const css::util::URL& aParsedURL , + FlatDetection& rFlatTypes ) +{ + // get all filters, which match to this doc service + OUStringList lFilters; + try + { + // SAFE -> -------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + + // Attention: For executing next lines of code, We must be shure that + // all filters already loaded :-( + // That can disturb our "load on demand feature". But we have no other chance! + m_rCache->load(FilterCache::E_CONTAINS_FILTERS); + + CacheItem lIProps; + lIProps[PROPNAME_DOCUMENTSERVICE] <<= sPreSelDocumentService; + lFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps); + + aLock.clear(); + // <- SAFE -------------------------- + } + catch(const css::container::NoSuchElementException&) + { + lFilters.clear(); + } + + // step over all filters, and check if its registered type + // match the given URL. + // But use temp. list of "preselected types" instead of incoming rFlatTypes list! + // The reason behind: we must filter the getted results. And copying of stl entries + // is an easier job then removing it .-) + FlatDetection lPreselections; + for (OUStringList::const_iterator pFilter = lFilters.begin(); + pFilter != lFilters.end() ; + ++pFilter ) + { + const ::rtl::OUString sFilter = *pFilter; + impl_getPreselectionForFilter(sFilter, aParsedURL, lPreselections); + } + + // We have to mark all retrieved preselection items as "preselected by document service". + // Further we must ignore all preselected items, which does not match the URL! + FlatDetection::iterator pIt; + for ( pIt = lPreselections.begin(); + pIt != lPreselections.end() ; + ++pIt ) + { + FlatDetectionInfo& rInfo = *pIt; + + /* + #i60158# + Preselection by DocumentService ... + How many filters (and corresponding types) must be checked ? + All or only the list of filters/types, which match to the given URL too ? + There is no final decision about this currently. So we make it "configurable" .-) + */ + #ifdef IGNORE_NON_URLMATCHING_TYPES_FOR_PRESELECTION_DOCUMENTSERVICE + if ( + (!rInfo.bMatchByExtension) && + (!rInfo.bMatchByPattern ) + ) + continue; + #endif + + rInfo.bPreselectedAsType = sal_False; + rInfo.bPreselectedByFilter = sal_False; + rInfo.bPreselectedByDocumentService = sal_True ; + rFlatTypes.push_back(rInfo); + } + + return sal_True; +} + +/*----------------------------------------------- + 14.11.2003 12:21 +-----------------------------------------------*/ +void TypeDetection::impl_getPreselection(const css::util::URL& aParsedURL , + ::comphelper::MediaDescriptor& rDescriptor, + FlatDetection& rFlatTypes ) +{ + // done to be shure, that only valid results leave this function! + rFlatTypes.clear(); + + /* #i55122# + Sometimes we must detect files without or with real unknown extensions. + If it does not work /which can happen of course .-)/, the user tried to preselect + the right format. But some special dialogs (e.g. "Insert->Sheet From File") + add it's own preselection too. + So we have a combination of preselected values ... + + The we should preferr the most important one - set by the user. + And the user normaly preselects a filter or type. The preslected + document service cames from the dialog. + + Further it doesnt matter if the user preselected a filter or a document service. + A filter selection is always more explicit then a document service selection. + So it must be pereferred. An order between type and filter selection cant be discussed .-) + */ + + ::rtl::OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_TYPENAME(), ::rtl::OUString()); + if (sSelectedType.getLength()) + impl_getPreselectionForType(sSelectedType, aParsedURL, rFlatTypes); + + ::rtl::OUString sSelectedFilter = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_FILTERNAME(), ::rtl::OUString()); + if (sSelectedFilter.getLength()) + impl_getPreselectionForFilter(sSelectedFilter, aParsedURL, rFlatTypes); + + ::rtl::OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), ::rtl::OUString()); + if (sSelectedDoc.getLength()) + impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes); +} + +/*----------------------------------------------- + 03.11.2003 09:17 +-----------------------------------------------*/ +::rtl::OUString TypeDetection::impl_detectTypeFlatAndDeep( ::comphelper::MediaDescriptor& rDescriptor , + const FlatDetection& lFlatTypes , + sal_Bool bAllowDeep , + OUStringList& rUsedDetectors, + ::rtl::OUString& rLastChance ) +{ + // reset it everytimes, so the outside code can distinguish between + // a set and a not set value. + rLastChance = ::rtl::OUString(); + rUsedDetectors.clear(); + + // step over all possible types for this URL. + // solutions: + // a) no types => no detection + // b) deep detection not allowed => return first valid type of list (because its the preferred or the first valid one) + // or(!) match by URLPattern => in such case a deep detection will be supressed! + // c) type has no detect service => safe the first occured type without a detect service + // as "last chance"(!). It will be used outside of this method + // if no further type could be detected. + // It must be the first one, because it can be a preferred type. + // Our types list was sorted by such criteria! + // d) detect service return a valid result => return its decision + // e) detect service return an invalid result + // or any needed information could not be + // getted from the cache => ignore it, and continue with search + + for (FlatDetection::const_iterator pFlatIt = lFlatTypes.begin(); + pFlatIt != lFlatTypes.end() ; + ++pFlatIt ) + { + const FlatDetectionInfo& aFlatTypeInfo = *pFlatIt; + ::rtl::OUString sFlatType = aFlatTypeInfo.sType; + + if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType)) + continue; + + // b) + if ( + (!bAllowDeep ) || + (aFlatTypeInfo.bMatchByPattern) + ) + { + return sFlatType; + } + + try + { + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sFlatType); + aLock.clear(); + + ::rtl::OUString sDetectService; + aType[PROPNAME_DETECTSERVICE] >>= sDetectService; + + // c) + if (!sDetectService.getLength()) + { + // accept or not accept flat types without deep detection: that's the question :-) + // May be there exists some states, where we have to use our LastChance feature instead + // of using the flat type directly. + // Here the list of task ID's, which wasrelated to these lines of code: + // #i47159#, #i43404#, #i46494# + + // a flat detected type without the chance for a deep detection ... but preselected by the user + // explicitly (means preselected as type or filter ... not as documentservice!) + // should be accepted. So the user can overrule our detection. + if ( + (aFlatTypeInfo.bPreselectedAsType ) || + (aFlatTypeInfo.bPreselectedByFilter) + ) + return sFlatType; + + // flat detected types without any registered deep detection service and not + // preselected by the user can be used as LAST CHANCE in case no other type could + // be detected. Of course only the first type without deep detector can be used. + // Further ones has to be ignored. + if (rLastChance.getLength() < 1) + rLastChance = sFlatType; + + continue; + } + + // dont forget to add every real asked deep detection service here. + // Such detectors will be ignored if may be "impl_detectTypeDeepOnly()" + // must be called later! + rUsedDetectors.push_back(sDetectService); + ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); + + // d) + if (sDeepType.getLength()) + return sDeepType; + } + catch(const css::container::NoSuchElementException&) + {} + // e) + } + + return ::rtl::OUString(); + // <- SAFE ---------------------------------- +} + +/*----------------------------------------------- + 03.11.2003 09:19 +-----------------------------------------------*/ +::rtl::OUString TypeDetection::impl_detectTypeDeepOnly( ::comphelper::MediaDescriptor& rDescriptor , + const OUStringList& lOutsideUsedDetectors) +{ + // We must know if a detect service was already used: + // i) in a combined flat/deep detection scenario outside or + // ii) in this method for a deep detection only. + // Reason: Such deep detection services work differently in these two modes! + OUStringList lInsideUsedDetectors; + OUStringList::const_iterator pIt; + + // a) + // The list of "already used detect services" correspond to the list + // of preselected or flat detected types. But these detect services was called + // to check these types explicitly and return black/white ... yes/no only. + // Now they are called to return any possible result. But we should preferr + // these already used detect services against all other ones! + for ( pIt = lOutsideUsedDetectors.begin(); + pIt != lOutsideUsedDetectors.end() ; + ++pIt ) + { + const ::rtl::OUString& sDetectService = *pIt; + ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); + if (sDeepType.getLength()) + return sDeepType; + lInsideUsedDetectors.push_back(sDetectService); + } + + // SAFE -> ---------------------------------- + ::osl::ResettableMutexGuard aLock(m_aLock); + OUStringList lDetectors = m_rCache->getItemNames(FilterCache::E_DETECTSERVICE); + aLock.clear(); + // <- SAFE ---------------------------------- + + // b) + // Sometimes it would be nice to ask a special set of detect services before + // any other detect service is asked. E.g. by using a preselection of a DocumentService. + // That's needed to prevent us from asking the "wrong application module" and + // opening the files into the "wrong application". + ::rtl::OUString sPreselDocumentService = rDescriptor.getUnpackedValueOrDefault( + ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(), + ::rtl::OUString()); + if (sPreselDocumentService.getLength()) + { + for ( pIt = lDetectors.begin(); + pIt != lDetectors.end() ; + ++pIt ) + { + const ::rtl::OUString& sDetectService = *pIt; + + OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService); + if (pAlreadyUsed != lInsideUsedDetectors.end()) + continue; + + // SAFE -> -------------------------------------------------------- + aLock.reset(); + + CacheItem lIProps; + lIProps[PROPNAME_DETECTSERVICE] <<= sDetectService; + OUStringList lTypes = m_rCache->getMatchingItemsByProps(FilterCache::E_TYPE, lIProps); + + aLock.clear(); + // <- SAFE -------------------------------------------------------- + + sal_Bool bMatchDetectorToDocumentService = sal_False; + OUStringList::const_iterator pIt2; + for ( pIt2 = lTypes.begin(); + pIt2 != lTypes.end() ; + ++pIt2 ) + { + const ::rtl::OUString& sType = *pIt2; + + try + { + // SAFE -> ---------------------------------------------------- + aLock.reset(); + + CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType); + ::rtl::OUString sFilter; + aType[PROPNAME_PREFERREDFILTER] >>= sFilter; + CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); + ::rtl::OUString sCheckDocumentService; + aFilter[PROPNAME_DOCUMENTSERVICE] >>= sCheckDocumentService; + + aLock.clear(); + // <- SAFE + + if (sCheckDocumentService.equals(sPreselDocumentService)) + { + bMatchDetectorToDocumentService = sal_True; + break; + } + } + catch(const css::uno::Exception&) + { continue; } + } + + if (bMatchDetectorToDocumentService) + { + ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); + if (sDeepType.getLength()) + return sDeepType; + lInsideUsedDetectors.push_back(sDetectService); + } + } + } + + // c) + // Last chance. No "used detectors", no "preselected detectors" ... ask any existing detect services + // for this till know unknown format. + for ( pIt = lDetectors.begin(); + pIt != lDetectors.end() ; + ++pIt ) + { + const ::rtl::OUString& sDetectService = *pIt; + + OUStringList::const_iterator pAlreadyUsed = ::std::find(lInsideUsedDetectors.begin(), lInsideUsedDetectors.end(), sDetectService); + if (pAlreadyUsed != lInsideUsedDetectors.end()) + continue; + + ::rtl::OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor); + if (sDeepType.getLength()) + return sDeepType; + } + + return ::rtl::OUString(); +} + +/*----------------------------------------------- + 07.03.2005 11:13 +-----------------------------------------------*/ +void TypeDetection::impl_seekStreamToZero(comphelper::MediaDescriptor& rDescriptor) +{ + // try to seek to 0 ... + // But because XSeekable is an optional interface ... try it only .-) + css::uno::Reference< css::io::XInputStream > xStream = rDescriptor.getUnpackedValueOrDefault( + ::comphelper::MediaDescriptor::PROP_INPUTSTREAM(), + css::uno::Reference< css::io::XInputStream >()); + css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY); + if (xSeek.is()) + { + try + { + xSeek->seek(0); + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} + } +} + +/*----------------------------------------------- + 30.10.2003 15:12 +-----------------------------------------------*/ +::rtl::OUString TypeDetection::impl_askDetectService(const ::rtl::OUString& sDetectService, + ::comphelper::MediaDescriptor& rDescriptor ) +{ + // Open the stream and add it to the media descriptor if this method is called for the first time. + // All following requests to this method will detect, that there already exists a stream .-) + // Attention: This method throws an exception if the stream could not be opened. + // It's important to break any further detection in such case. + // Catch it on the highest detection level only !!! + impl_openStream(rDescriptor); + + // seek to 0 is an optional feature to be more robust against + // "simple implemented detect services" .-) + impl_seekStreamToZero(rDescriptor); + + css::uno::Reference< css::document::XExtendedFilterDetection > xDetector; + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR; + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + xSMGR = m_xSMGR; + aLock.clear(); + // <- SAFE + + // Attention! If e.g. an office module was not installed sometimes we find a + // registered detect service, which is referred inside the configuration ... but not realy + // installed. On the other side we use third party components here, which can make trouble anyway. + // So we should handle errors during creation of such services more gracefully .-) + xDetector = css::uno::Reference< css::document::XExtendedFilterDetection >( + xSMGR->createInstance(sDetectService), + css::uno::UNO_QUERY); + + if ( ! xDetector.is()) + return ::rtl::OUString(); + + ::rtl::OUString sDeepType; + try + { + // start deep detection + // Dont forget to convert stl descriptor to its uno representation. + + /* Attention! + You have to use an explicit instance of this uno sequence ... + Because its used as an in out parameter. And in case of a temp. used object + we will run into memory corruptions! + */ + css::uno::Sequence< css::beans::PropertyValue > lDescriptor; + rDescriptor >> lDescriptor; + sDeepType = xDetector->detect(lDescriptor); + rDescriptor << lDescriptor; + } + catch(const css::uno::Exception&) + { + // We should ignore errors here. + // Thrown exceptions mostly will end in crash recovery ... + // But might be we find another deep detection service which can detect the same + // document without a problem .-) + sDeepType = ::rtl::OUString(); + } + + // seek to 0 is an optional feature to be more robust against + // "simple implemented detect services" .-) + impl_seekStreamToZero(rDescriptor); + + // analyze the results + // a) detect service returns "" => return "" too and remove TYPE/FILTER prop from descriptor + // b) returned type is unknown => return "" too and remove TYPE/FILTER prop from descriptor + // c) returned type is valid => check TYPE/FILTER props inside descriptor and return the type + + // this special helper checks for a valid type + // and set right values on the descriptor! + sal_Bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType); + if (bValidType) + return sDeepType; + + return ::rtl::OUString(); +} + +/*----------------------------------------------- + 17.12.2004 13:47 +-----------------------------------------------*/ +::rtl::OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(::comphelper::MediaDescriptor& rDescriptor) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aLock.clear(); + // <- SAFE + + css::uno::Reference< css::task::XInteractionHandler > xInteraction = + rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER(), + css::uno::Reference< css::task::XInteractionHandler >()); + + if (!xInteraction.is()) + return ::rtl::OUString(); + + ::rtl::OUString sURL = + rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(), + ::rtl::OUString()); + + css::uno::Reference< css::io::XInputStream > xStream = + rDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INPUTSTREAM(), + css::uno::Reference< css::io::XInputStream >()); + + // Dont distrub the user for "non existing files - means empty URLs" or + // if we was forced to detect a stream. + // Reason behind: We must be shure to ask user for "unknown contents" only ... + // and not for "missing files". Especialy if detection is done by a stream only + // we cant check if the stream points to an "existing content"! + if ( + (!sURL.getLength() ) || // "non existing file" ? + (!xStream.is() ) || // non existing file ! + (sURL.equalsIgnoreAsciiCaseAsciiL("private:stream", 14)) // not a good idea .-) + ) + return ::rtl::OUString(); + + try + { + // create a new request to ask user for it's decision about the usable filter + ::framework::RequestFilterSelect* pRequest = new ::framework::RequestFilterSelect(sURL); + css::uno::Reference< css::task::XInteractionRequest > xRequest(static_cast< css::task::XInteractionRequest* >(pRequest), css::uno::UNO_QUERY_THROW); + xInteraction->handle(xRequest); + + // "Cancel" pressed? => return with error + if (pRequest->isAbort()) + return ::rtl::OUString(); + + // "OK" pressed => verify the selected filter, get it's coressponding + // type and return it. (BTW: We must update the media descriptor here ...) + // The user selected explicitly a filter ... but normaly we are interested on + // a type here only. But we must be shure, that the selected filter is used + // too and no ambigous filter registration disturb us .-) + + ::rtl::OUString sFilter = pRequest->getFilter(); + if (!impl_validateAndSetFilterOnDescriptor(rDescriptor, sFilter)) + return ::rtl::OUString(); + + ::rtl::OUString sType; + rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] >>= sType; + return sType; + } + catch(const css::uno::Exception&) + {} + + return ::rtl::OUString(); +} + +/*----------------------------------------------- + 10.03.2004 10:30 +-----------------------------------------------*/ +void TypeDetection::impl_openStream(::comphelper::MediaDescriptor& rDescriptor) + throw (css::uno::Exception) +{ + sal_Bool bSuccess = sal_False; + ::rtl::OUString sURL = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_URL(), ::rtl::OUString() ); + sal_Bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( ::comphelper::MediaDescriptor::PROP_READONLY(), sal_False ); + if ( sURL.getLength() && ::utl::LocalFileHelper::IsLocalFile( INetURLObject( sURL ).GetMainURL( INetURLObject::NO_DECODE ) ) ) + { + // OOo uses own file locking mechanics in case of local file + bSuccess = rDescriptor.addInputStreamOwnLock(); + } + else + bSuccess = rDescriptor.addInputStream(); + + if ( !bSuccess ) + throw css::uno::Exception(_FILTER_CONFIG_FROM_ASCII_("Could not open stream."), static_cast< css::document::XTypeDetection* >(this)); + + if ( !bRequestedReadOnly ) + { + // The MediaDescriptor implementation adds ReadOnly argument if the file can not be opened for writing + // this argument should be either removed or an additional argument should be added so that application + // can separate the case when the user explicitly requests readonly document. + // The current solution is to remove it here. + rDescriptor.erase( ::comphelper::MediaDescriptor::PROP_READONLY() ); + } +} + +/*----------------------------------------------- + 04.07.2003 13:47 +-----------------------------------------------*/ +void TypeDetection::impl_removeTypeFilterFromDescriptor(::comphelper::MediaDescriptor& rDescriptor) +{ + ::comphelper::MediaDescriptor::iterator pItType = rDescriptor.find(::comphelper::MediaDescriptor::PROP_TYPENAME() ); + ::comphelper::MediaDescriptor::iterator pItFilter = rDescriptor.find(::comphelper::MediaDescriptor::PROP_FILTERNAME()); + if (pItType != rDescriptor.end()) + rDescriptor.erase(pItType); + if (pItFilter != rDescriptor.end()) + rDescriptor.erase(pItFilter); +} + +/*----------------------------------------------- + 14.10.2003 11:15 +-----------------------------------------------*/ +sal_Bool TypeDetection::impl_validateAndSetTypeOnDescriptor( ::comphelper::MediaDescriptor& rDescriptor, + const ::rtl::OUString& sType ) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + if (m_rCache->hasItem(FilterCache::E_TYPE, sType)) + { + rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sType; + return sal_True; + } + aLock.clear(); + // <- SAFE + + // remove all related informations from the descriptor + impl_removeTypeFilterFromDescriptor(rDescriptor); + return sal_False; +} + +/*----------------------------------------------- + 04.07.2003 14:01 +-----------------------------------------------*/ +sal_Bool TypeDetection::impl_validateAndSetFilterOnDescriptor( ::comphelper::MediaDescriptor& rDescriptor, + const ::rtl::OUString& sFilter ) +{ + try + { + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + + CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sFilter); + ::rtl::OUString sType; + aFilter[PROPNAME_TYPE] >>= sType; + CacheItem aType = m_rCache->getItem(FilterCache::E_TYPE, sType); + + aLock.clear(); + // <- SAFE + + // found valid type and filter => set it on the given descriptor + rDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= sType ; + rDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= sFilter; + return sal_True; + } + catch(const css::container::NoSuchElementException&){} + + // remove all related informations from the descriptor + impl_removeTypeFilterFromDescriptor(rDescriptor); + return sal_False; +} + +/*----------------------------------------------- + 03.07.2003 10:36 +-----------------------------------------------*/ +::rtl::OUString TypeDetection::impl_getImplementationName() +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.TypeDetection"); +} + +/*----------------------------------------------- + 03.07.2003 11:27 +-----------------------------------------------*/ +css::uno::Sequence< ::rtl::OUString > TypeDetection::impl_getSupportedServiceNames() +{ + css::uno::Sequence< ::rtl::OUString > lServiceNames(1); + lServiceNames[0] = ::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection"); + return lServiceNames; +} + +/*----------------------------------------------- + 09.07.2003 08:02 +-----------------------------------------------*/ +css::uno::Reference< css::uno::XInterface > SAL_CALL TypeDetection::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) +{ + TypeDetection* pNew = new TypeDetection(xSMGR); + return css::uno::Reference< css::uno::XInterface >(static_cast< css::document::XTypeDetection* >(pNew), css::uno::UNO_QUERY); +} + + } // namespace config +} // namespace filter diff --git a/filter/source/config/cache/typedetection.hxx b/filter/source/config/cache/typedetection.hxx new file mode 100644 index 000000000000..4dbf6f07d33e --- /dev/null +++ b/filter/source/config/cache/typedetection.hxx @@ -0,0 +1,459 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef __FILTER_CONFIG_TYPEDETECTION_HXX_ +#define __FILTER_CONFIG_TYPEDETECTION_HXX_ + +//_______________________________________________ +// includes + +#include "basecontainer.hxx" +#include <com/sun/star/document/XTypeDetection.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <comphelper/mediadescriptor.hxx> +#include <cppuhelper/implbase1.hxx> + +//_______________________________________________ +// namespace + +namespace filter{ + namespace config{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +//_______________________________________________ + +/** @short implements the service <type scope="com.sun.star.document">TypeDetection</type>. + */ +class TypeDetection : public ::cppu::ImplInheritanceHelper1< BaseContainer , + css::document::XTypeDetection > +{ + //------------------------------------------- + // native interface + + public: + + //--------------------------------------- + // ctor/dtor + + /** @short standard ctor to connect this interface wrapper to + the global filter cache instance ... + + @param xSMGR + reference to the uno service manager, which created this service instance. + */ + TypeDetection(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); + + //--------------------------------------- + + /** @short standard dtor. + */ + virtual ~TypeDetection(); + + //------------------------------------------- + // private helper + + private: + + //--------------------------------------- + /** TODO document me */ + sal_Bool impl_getPreselectionForType(const ::rtl::OUString& sPreSelType, + const css::util::URL& aParsedURL , + FlatDetection& rFlatTypes ); + + //--------------------------------------- + /** TODO document me */ + sal_Bool impl_getPreselectionForFilter(const ::rtl::OUString& sPreSelFilter, + const css::util::URL& aParsedURL , + FlatDetection& rFlatTypes ); + + //--------------------------------------- + /** TODO document me */ + sal_Bool impl_getPreselectionForDocumentService(const ::rtl::OUString& sPreSelDocumentService, + const css::util::URL& aParsedURL , + FlatDetection& rFlatTypes ); + + //--------------------------------------- + + /** @short check if a filter or a type was preselected inside the given + MediaDescriptor and validate this information. + + @descr Only in case the preselected filter exists and its type registration + seems to be usefully, it would be used realy as valid type detection + result. This method doesnt make any deep detection here. It checks only + if the preselection match to the URL by an URLPattern. + This information has to be added to the given rFlatTypes list too. + The outside code can use it to supress a deep detection then in general. + Because pattern are defined as non detectable at all! + + @param pDescriptor + provides any easy-to-use stl interface to the MediaDescriptor. + Note : Its content will be adapted to returned result of this method. + Means: The type/filter entries of it will be actualized or removed. + + @param rFlatTypes + the preselected type (or the registered type of a preselected filter) + will be added here as first(!) element. Further we have to provide the + information, if this type match to the given URL by its URLPattern + registration. + */ + void impl_getPreselection(const css::util::URL& aParsedURL , + ::comphelper::MediaDescriptor& rDescriptor, + FlatDetection& rFlatTypes ); + + //--------------------------------------- + + /** @short make a combined flat/deep type detection + + @descr It steps over all flat detected types (given by the parameter lFlatTypes), + try it and search for most suitable one. + The specified MediaDescriptor will be patched, so it contain + the right values everytime. Using of any deep detection service + can be enabled/disabled. And last but not least: If the results + wont be realy clear (because a flat detected type has no deep + detection service), a "sugested" type name will be returned as "rLastChance". + It can be used after e.g. all well known deep detection services + was used without getting any result. Then this "last-chance-type" + should be returned. Of course using of it can fail too ... but its a try :-) + + As an optimization - this method collects the names of all used deep + detection services. This information can be usefull inside the may be + afterwards called method "impl_detectTypeDeepOnly()"! + + @param rDescriptor + provides any easy-to-use stl interface to the MediaDescriptor. + Note : Its content will be adapted to returned result of this method. + Means: The type/filter entries of it will be actualized or removed from it. + + @param lFlatTypes + a list of all flat detected types, which should be checked here. + No other types are allowed here! + + @param rLastChance + the internal name of a "suggested type" ... (see before) + Note: it will be reseted to an empty string everytimes. So + a set value of "rLastChance" can be detected outside very easy. + + @param rUsedDetectors + used as [out] parameter. It contains a list of names of all deep + detection services, which was used inside this method. + Such detectors can be ignored later if "impl_detectTypeDeepOnly()" + is called. + + @param bAllowDeep + enable/disable using of a might existing deep detection service. + + @return The internal name of a detected type. + An empty value if detection failed. .... but see rLastChance + for additional returns! + */ + ::rtl::OUString impl_detectTypeFlatAndDeep( ::comphelper::MediaDescriptor& rDescriptor , + const FlatDetection& lFlatTypes , + sal_Bool bAllowDeep , + OUStringList& rUsedDetectors, + ::rtl::OUString& rLastChance ); + + //--------------------------------------- + + /** @short make a deep type detection only + + @descr It steps over all well known deep detection services + and check her results. The first positive result will be + used for return. Its more a "try and error" algorithm then + a real type detection and will be used if a flat detection + cant work realy ... e.g. if the extension of an URL is + missing or wrong. + + @param rDescriptor + provides any easy-to-use stl interface to the MediaDescriptor. + Note : Its content will be adapted to returned result of this method. + Means: The type/filter entries of it will be actualized or removed from it. + + @param rUsedDetectors + It contains a list of names of all deep detection services, + which was already used inside the method "impl_detectTypeFlatAndDeep()"! + Such detectors must be ignored here! + + @return The internal name of a detected type. + An empty value if detection failed. + */ + ::rtl::OUString impl_detectTypeDeepOnly( ::comphelper::MediaDescriptor& rDescriptor , + const OUStringList& rUsedDetectors); + + //--------------------------------------- + + /** @short seek a might existing stream to position 0. + + @descr This is an optinal action to be more robust + in case any detect service doesnt make this seek ... + Normaly it's part of any called detect service or filter ... + but sometimes it's not done there. + + @param rDescriptor + a stl representation of the MediaDescriptor as in/out parameter. + */ + void impl_seekStreamToZero(comphelper::MediaDescriptor& rDescriptor); + + //--------------------------------------- + + /** @short make deep type detection for a specified + detect service (threadsafe!). + + @descr It creates the right uno service, prepare the + needed MediaDescriptor, call ths right interfaces, + and return the results. + + @attention The results (means type and corresponding filter) + are already part of the in/out parameter pDescriptor. + (in case they was valid). + + @param sDetectService + uno service name of the detect service. + + @param rDescriptor + a stl representation of the MediaDescriptor as in/out parameter. + */ + ::rtl::OUString impl_askDetectService(const ::rtl::OUString& sDetectService, + ::comphelper::MediaDescriptor& rDescriptor ); + + //--------------------------------------- + + /** @short try to find an interaction handler and + ask him to select a possible filter for + this unknown format. + + @descr If the user select a filter, it will be used as return value + without further checking against the given file content! + + @param rDescriptor + a stl representation of the MediaDescriptor as in/out parameter. + + @return [string] + a valid type name or an empty string if user canceled interaction. + */ + ::rtl::OUString impl_askUserForTypeAndFilterIfAllowed(::comphelper::MediaDescriptor& rDescriptor); + + //--------------------------------------- + + /** @short check if an input stream is already part of the + given MediaDesciptor and creates a new one if neccessary. + + @attention This method does further something special! + <ul> + <li> + If the given URL seem to be a streamable content, but creation of the stream + failed (might by an IOException), this method throws an exception. + (May be an existing interaction handler must be called here too ...) + The whole detection must be interrupted then and the interface method queryTypeByDescriptor() + must return an empty type name value. + + That prevent us against multiple handling of the same error more then ones + (e.g. if we ask all detect services as fallback ...). + </li> + <li> + In case the stream already exists inside the descriptor this method does nothing. + </li> + <li> + In case the stream does not exists but can be created successfully, the stream will + be added to the descriptor. + </li> + </ul> + + @param rDescriptor + provides any easy-to-use stl interface to the MediaDescriptor. + Note : Its content will be adapted to returned result of this method. + Means: The stream will be added to it. + + @throw Any suitable exception if stream should be opened but operation was not sucessfull. + Note: If an interactionHandler is part of the given descriptor too, it was already used. + Means: let the exception pass trough the top most interface method! + */ + void impl_openStream(::comphelper::MediaDescriptor& rDescriptor) + throw (css::uno::Exception); + + //--------------------------------------- + + /** @short validate the specified type and its relation ships + and set all needed informations related to this type + in the specified descriptor. + + @descr Related informations are: - corresponding filter + - media type + - ... + + @param rDescriptor + provides access to the outside MediaDescriptor. + + @param sType + the name of the type, which should be set on the descriptor. + Can be empty to remove any related value from the descriptor! + + @return TRUE the specified type and its registrations was valid(!) and + could be set on the descriptor. + */ + sal_Bool impl_validateAndSetTypeOnDescriptor( ::comphelper::MediaDescriptor& rDescriptor, + const ::rtl::OUString& sType ); + + //--------------------------------------- + + /** @short validate the specified filter and its relation ships + and set all needed informations related to this filter + in the specified descriptor. + + @descr Related informations are: - corresponding type + - ... + + @param rDescriptor + provides access to the outside MediaDescriptor. + + @param sFilter + the name of the filter, which should be set on the descriptor. + Can be empty to remove any related value from the descriptor! + + @return TRUE the specified type and its registrations was valid(!) and + could be set on the descriptor. + */ + sal_Bool impl_validateAndSetFilterOnDescriptor( ::comphelper::MediaDescriptor& rDescriptor, + const ::rtl::OUString& sFilter ); + + //--------------------------------------- + + /** @short remove anythimng related to a TYPE/FILTER entry from the + specified MediaDescriptor. + + @descr This method works together with impl_validateAndSetTypeOnDescriptor()/ + impl_validateAndSetFilterOnDescriptor(). All informations, which can be + set by these two operations must be "removeable" by this method. + + @param rDescriptor + reference to the MediaDescriptor (represented by an easy-to-use + stl interface!), which should be patched. + */ + void impl_removeTypeFilterFromDescriptor(::comphelper::MediaDescriptor& rDescriptor); + + //--------------------------------------- + + /** @short search the best suitable filter for the given type + and add it into the media descriptor. + + @descr Normaly this is a type detection only ... + but for some special features we must overwrite our detection + because a file must be loaded into a special (means preselected) + application. + + E.g. CSV/TXT format are sometimes ugly to handle .-) + + Note: If the descriptor already include a filter + (may be selected by a FilterSelect interaction or preselected + by the user itself) ... we dont change that here ! + + @param rDescriptor + reference to the MediaDescriptor (represented by an easy-to-use + stl interface!), which should be patched. + + @param sType + the internal type name, where we search a filter for. + Used as IN/OUT parameter so we can overrule the detection result for + types too ! + + @note #i60158# + sometimes our text ascii and our csv filter cant work together. + Then we overwrite our detection hardly. + sType param is used as out parameter then too ... and + rDescriptor will be changed by selecting another filter. + (see code) + */ + void impl_checkResultsAndAddBestFilter(::comphelper::MediaDescriptor& rDescriptor, + ::rtl::OUString& sType ); + + //------------------------------------------- + // uno interface + + public: + + //--------------------------------------- + // XTypeDetection + + virtual ::rtl::OUString SAL_CALL queryTypeByURL(const ::rtl::OUString& sURL) + throw (css::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor, + sal_Bool bAllowDeep ) + throw (css::uno::RuntimeException); + + //------------------------------------------- + // static uno helper! + + public: + + //--------------------------------------- + + /** @short return the uno implementation name of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix uno implementation name of this class. + */ + static ::rtl::OUString impl_getImplementationName(); + + //--------------------------------------- + + /** @short return the list of supported uno services of this class. + + @descr Because this information is used at several places + (and mostly an object instance of this class is not possible) + its implemented as a static function! + + @return The fix list of uno services supported by this class. + */ + static css::uno::Sequence< ::rtl::OUString > impl_getSupportedServiceNames(); + + //--------------------------------------- + + /** @short return a new intsnace of this class. + + @descr This method is used by the uno service manager, to create + a new instance of this service if needed. + + @param xSMGR + reference to the uno service manager, which require + this new instance. It should be passed to the new object + so it can be used internaly to create own needed uno resources. + + @return The new instance of this service as an uno reference. + */ + static css::uno::Reference< css::uno::XInterface > impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR); +}; + + } // namespace config +} // namespace filter + +#endif // __FILTER_CONFIG_TYPEDETECTION_HXX_ diff --git a/filter/source/config/cache/versions.hxx b/filter/source/config/cache/versions.hxx new file mode 100644 index 000000000000..fbd92604170f --- /dev/null +++ b/filter/source/config/cache/versions.hxx @@ -0,0 +1,36 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _FILTER_CONFIG_VERSIONS_HXX_ +#define _FILTER_CONFIG_VERSIONS_HXX_ + +//_______________________________________________ + +//#define _FILTER_CONFIG_Q_ // final Q code base +#define _FILTER_CONFIG_MIGRATION_Q_ // usefull for migration time, to support some old functionality temp. :-) + +#endif // _FILTER_CONFIG_VERSIONS_HXX_ |