blob: da42ee84c451bcf572aeab29b719c8332bc25fae [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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_sProductName = m_sProductName;
pClone->m_sOOoXMLFormatName = m_sOOoXMLFormatName;
pClone->m_sOOoXMLFormatVersion = m_sOOoXMLFormatVersion;
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_sProductName = rClone.m_sProductName;
m_sOOoXMLFormatName = rClone.m_sOOoXMLFormatName;
m_sOOoXMLFormatVersion = rClone.m_sOOoXMLFormatVersion;
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_PRODUCTNAME) >>= m_sProductName;
impl_getDirectCFGValue(CFGDIRECTKEY_FORMATNAME) >>= m_sOOoXMLFormatName;
if (!m_sOOoXMLFormatName.getLength())
{
_FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format name => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATNAME));
m_sOOoXMLFormatName = DEFAULT_FORMATNAME;
}
impl_getDirectCFGValue(CFGDIRECTKEY_FORMATVERSION) >>= m_sOOoXMLFormatVersion;
if (!m_sOOoXMLFormatVersion.getLength())
{
_FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format version => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATVERSION));
m_sOOoXMLFormatVersion = 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 PRODUCTNAME_VAR = ::rtl::OUString::createFromAscii("%productname%");
static ::rtl::OUString FORMATNAME_VAR = ::rtl::OUString::createFromAscii("%oooxmlformatname%" );
static ::rtl::OUString FORMATVERSION_VAR = ::rtl::OUString::createFromAscii("%oooxmlformatversion%");
// SAFE -> ----------------------------------
::osl::ResettableMutexGuard aLock(m_aLock);
::rtl::OUString sProductName = m_sProductName;
::rtl::OUString sFormatName = m_sOOoXMLFormatName;
::rtl::OUString sFormatVersion = m_sOOoXMLFormatVersion;
::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%, %oooxmlformatname% and %oooxmlformatversion%
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(PRODUCTNAME_VAR);
while(nIndex != -1)
{
sValue = sValue.replaceAt(nIndex, PRODUCTNAME_VAR.getLength(), sProductName);
nIndex = sValue.indexOf(PRODUCTNAME_VAR, nIndex);
}
// replace %oooxmlformatname%
nIndex = sValue.indexOf(FORMATNAME_VAR);
while(nIndex != -1)
{
sValue = sValue.replaceAt(nIndex, FORMATNAME_VAR.getLength(), sFormatName);
nIndex = sValue.indexOf(FORMATNAME_VAR, nIndex);
}
// replace %oooxmlformatversion%
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_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_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