blob: fe0dca98410730ae916a7379104859407ebfdcee [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: Don't tell user something about "setup -repair"!
// It's 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();
// Don't 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)
// Don't 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!
// Otherwise 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 can't be sure, 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_TRACE("Who disturbs 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 really needed here!");
}
#endif
// Otherwise load the missing items.
// ------------------------------------------
// a) load some const values from configuration.
// 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 time 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: It's 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 if "eType" is unknown.
// => rList will be valid every time the 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 if "eType" is unknown.
// => rList will be valid every time the 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 if "eType" is unknown.
// => rList will be valid every time the 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 if "eType" is unknown.
// => rList will be valid every time the 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 every time the 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 automatically 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 suppress 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 shouldn't; because the corresponding AOO 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 if "eType" is unknown.
// => rList will be valid every time the 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 if "eType" is unknown.
// => rList will be valid every time the next line is reached.
CacheItemList& rList = impl_getItemList(eType);
// name must be part of the property set too ... otherwise our
// container query can't work correctly
CacheItem aItem = aValue;
aItem[PROPNAME_NAME] <<= sItem;
aItem.validateUINames(m_sActLocale);
// remove implicit properties as e.g. FINALIZED or MANDATORY
// They can't be saved here and must be read 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 don't have to 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 can't be located inside the normal set of frame loaders.
It's an atomic property inside the misc cfg package. So we can't retrieve the information
about FINALIZED and MANDATORY very easy ... :-(
=> set it to readonly/required every time :-)
*/
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.
Maybe 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 don't migrate such items
automatically 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 automatically created new one ...
=> mark item as FINALIZED / MANDATORY, we don't 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 couldn't be flushed.
if (!xItem.is())
throw css::uno::Exception(::rtl::OUString::createFromAscii("Can't 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 couldn't be flushed.
if (!xItem.is())
throw css::uno::Exception(::rtl::OUString::createFromAscii("Can't change item. It's 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 suppressed!
// 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 matching type without changing its order!
// Because preferred type 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. It's 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 isn't 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 it's 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 throw 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 read
// 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
// occur in the next few 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 doesn't 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 it's a "normal" type
// set it at the end of this optimized list. But if it's
// a "Preferred" one - set it to the front of this list.
// Of course multiple "Preferred" registrations can occur
// (they shouldn't - but they can!) ... Ignore it. The last
// preferred type is usable 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 sure that address 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
// Don't 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 shouldn't 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.
// Maybe it can be handled by a ContentHandler ...
// But at this time it's 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("\" isn't 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 completely with all
// types, which are not referenced by any other loader.
// So we can avoid 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 a situation can occur, 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 it's a new created entry (automatically done by the hash_map index operator!)
// we must be sure, that this entry has its own name as property available.
// It's 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 separately.
// ------------------------------------------
// 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 couldn't be opened successfully
// and exception os thrown automatically 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 couldn't be opened successfully
// and exception os thrown automatically 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 couldn't be opened successfully
// and exception os thrown automatically 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 couldn't be opened successfully
// and exception os thrown automatically 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 couldn't be opened successfully
// and exception os thrown automatically 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: it's a bit field, which combines different parts.
m_eFillState = (EFillState) ((sal_Int32)m_eFillState | (sal_Int32)eRequiredState);
// any data read?
// 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 don't 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 occur 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 it's 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 :-) IT'S 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! It's 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 really
#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, "Can't load detect services on demand. Who uses 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 exist inside configuration.
// And we already updated our internal cache.
// But the outside code needs this NoSuchElementException
// to know, that this item does not exist.
// 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,
// it's not allowed 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 really
#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 necessary
-----------------------------------------------*/
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 necessary
-----------------------------------------------*/
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 guarantee 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.
// It's optional and shouldn't 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 seems to be acceptable.
see #139088# for further informations
*/
catch(const css::uno::Exception&)
{ return; }
// Maybe 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]);
}
// Maybe 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("Can't read old item."),
css::uno::Reference< css::uno::XInterface >());
CacheItem aItem;
aItem[PROPNAME_NAME] <<= sItem;
// Installed flag ...
// Isn't 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("Can't 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