bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / config / cache / filtercache.cxx
blobf4251c3c1c1c18c08a76120f76322cebea6f8de0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "filtercache.hxx"
22 #include "lateinitlistener.hxx"
23 #include "macros.hxx"
24 #include "constant.hxx"
25 #include "cacheupdatelistener.hxx"
27 /*TODO see using below ... */
28 #define AS_ENABLE_FILTER_UINAMES
29 #define WORKAROUND_EXCEPTION_PROBLEM
31 #include <com/sun/star/configuration/theDefaultProvider.hpp>
32 #include <com/sun/star/util/XChangesBatch.hpp>
33 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
34 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35 #include <com/sun/star/beans/NamedValue.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/beans/XProperty.hpp>
38 #include <com/sun/star/beans/PropertyValue.hpp>
39 #include <com/sun/star/beans/Property.hpp>
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
41 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
42 #include <comphelper/sequenceasvector.hxx>
43 #include <comphelper/processfactory.hxx>
45 #include <unotools/configpaths.hxx>
46 #include <rtl/ustrbuf.hxx>
47 #include <rtl/logfile.hxx>
48 #include <rtl/uri.hxx>
49 #include <tools/urlobj.hxx>
50 #include <tools/wldcrd.hxx>
51 #include <i18nlangtag/languagetag.hxx>
53 #include <comphelper/configurationhelper.hxx>
56 namespace filter{
57 namespace config{
59 FilterCache::FilterCache()
60 : BaseLock ( )
61 , m_eFillState(E_CONTAINS_NOTHING )
63 RTL_LOGFILE_TRACE("{ (as96863) FilterCache lifetime");
68 FilterCache::~FilterCache()
70 RTL_LOGFILE_TRACE("} (as96863) FilterCache lifetime");
71 if (m_xTypesChglisteners.is())
72 m_xTypesChglisteners->stopListening();
73 if (m_xFiltersChgListener.is())
74 m_xFiltersChgListener->stopListening();
79 FilterCache* FilterCache::clone() const
81 // SAFE -> ----------------------------------
82 ::osl::ResettableMutexGuard aLock(m_aLock);
84 FilterCache* pClone = new FilterCache();
86 // Dont copy the configuration access points here.
87 // They will be created on demand inside the cloned instance,
88 // if they are needed.
90 pClone->m_lTypes = m_lTypes;
91 pClone->m_lDetectServices = m_lDetectServices;
92 pClone->m_lFilters = m_lFilters;
93 pClone->m_lFrameLoaders = m_lFrameLoaders;
94 pClone->m_lContentHandlers = m_lContentHandlers;
95 pClone->m_lExtensions2Types = m_lExtensions2Types;
96 pClone->m_lURLPattern2Types = m_lURLPattern2Types;
98 pClone->m_sActLocale = m_sActLocale;
99 pClone->m_sFormatName = m_sFormatName;
100 pClone->m_sFormatVersion = m_sFormatVersion;
102 pClone->m_eFillState = m_eFillState;
104 pClone->m_lChangedTypes = m_lChangedTypes;
105 pClone->m_lChangedFilters = m_lChangedFilters;
106 pClone->m_lChangedDetectServices = m_lChangedDetectServices;
107 pClone->m_lChangedFrameLoaders = m_lChangedFrameLoaders;
108 pClone->m_lChangedContentHandlers = m_lChangedContentHandlers;
110 return pClone;
111 // <- SAFE ----------------------------------
116 void FilterCache::takeOver(const FilterCache& rClone)
118 // SAFE -> ----------------------------------
119 ::osl::ResettableMutexGuard aLock(m_aLock);
121 // a)
122 // Dont copy the configuration access points here!
123 // We must use our own ones ...
125 // b)
126 // Further we can ignore the uno service manager.
127 // We should already have a valid instance.
129 // c)
130 // Take over only changed items!
131 // Otherwise we risk the following scenario:
132 // c1) clone_1 contains changed filters
133 // c2) clone_2 container changed types
134 // c3) clone_1 take over changed filters and unchanged types
135 // c4) clone_2 take over unchanged filters(!) and changed types(!)
136 // c5) c4 overwrites c3!
138 if (rClone.m_lChangedTypes.size()>0)
139 m_lTypes = rClone.m_lTypes;
140 if (rClone.m_lChangedDetectServices.size()>0)
141 m_lDetectServices = rClone.m_lDetectServices;
142 if (rClone.m_lChangedFilters.size()>0)
143 m_lFilters = rClone.m_lFilters;
144 if (rClone.m_lChangedFrameLoaders.size()>0)
145 m_lFrameLoaders = rClone.m_lFrameLoaders;
146 if (rClone.m_lChangedContentHandlers.size()>0)
147 m_lContentHandlers = rClone.m_lContentHandlers;
149 m_lChangedTypes.clear();
150 m_lChangedDetectServices.clear();
151 m_lChangedFilters.clear();
152 m_lChangedFrameLoaders.clear();
153 m_lChangedContentHandlers.clear();
155 m_sActLocale = rClone.m_sActLocale;
156 m_sFormatName = rClone.m_sFormatName;
157 m_sFormatVersion = rClone.m_sFormatVersion;
159 m_eFillState = rClone.m_eFillState;
161 // renew all dependencies and optimizations
162 // Because we cant be shure, that changed filters on one clone
163 // and changed types of another clone work together.
164 // But here we can check against the lates changes ...
165 impl_validateAndOptimize();
166 // <- SAFE ----------------------------------
171 void FilterCache::load(EFillState eRequired,
172 #if OSL_DEBUG_LEVEL > 1
173 sal_Bool bByThread
174 #else
175 sal_Bool
176 #endif
178 throw(css::uno::Exception)
180 // SAFE -> ----------------------------------
181 ::osl::ResettableMutexGuard aLock(m_aLock);
183 // check if required fill state is already reached ...
184 // There is nothing to do then.
185 if ((m_eFillState & eRequired) == eRequired)
186 return;
188 #if OSL_DEBUG_LEVEL > 1
189 if (!bByThread && ((eRequired & E_CONTAINS_ALL) == E_CONTAINS_ALL))
191 OSL_FAIL("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!");
193 #endif
195 // Otherwise load the missing items.
197 // ------------------------------------------
198 // a) load some const values from configration.
199 // These values are needed there for loading
200 // config items ...
201 // Further we load some std items from the
202 // configuration so we can try to load the first
203 // office document with a minimal set of values.
204 if (m_eFillState == E_CONTAINS_NOTHING)
206 impl_getDirectCFGValue(CFGDIRECTKEY_OFFICELOCALE) >>= m_sActLocale;
207 if (m_sActLocale.isEmpty())
209 _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify office locale => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_OFFICELOCALE));
210 m_sActLocale = DEFAULT_OFFICELOCALE;
213 impl_getDirectCFGValue(CFGDIRECTKEY_FORMATNAME) >>= m_sFormatName;
214 if (m_sFormatName.isEmpty())
215 impl_getDirectCFGValue(CFGDIRECTKEY_PRODUCTNAME) >>= m_sFormatName;
217 if (m_sFormatName.isEmpty())
219 _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format name => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATNAME));
220 m_sFormatName = DEFAULT_FORMATNAME;
223 impl_getDirectCFGValue(CFGDIRECTKEY_FORMATVERSION) >>= m_sFormatVersion;
224 if (m_sFormatVersion.isEmpty())
226 _FILTER_CONFIG_LOG_1_("FilterCache::ctor() ... could not specify format version => use default \"%s\"\n", _FILTER_CONFIG_TO_ASCII_(DEFAULT_FORMATVERSION));
227 m_sFormatVersion = DEFAULT_FORMATVERSION;
230 // Support the old configuration support. Read it only one times during office runtime!
231 impl_readOldFormat();
233 // enable "loadOnDemand" feature ...
234 // Create uno listener, which waits for finishing the office startup
235 // and starts a thread, which calls loadAll() at this filter cache.
236 // Note: Its not a leak to create this listener with new here.
237 // It kills itself after working!
238 /* LateInitListener* pLateInit = */ new LateInitListener(comphelper::getProcessComponentContext());
241 // ------------------------------------------
242 // b) If the required fill state was not reached
243 // but std values was already loaded ...
244 // we must load some further missing items.
245 impl_load(eRequired);
246 // <- SAFE
251 sal_Bool FilterCache::isFillState(FilterCache::EFillState eState) const
252 throw(css::uno::Exception)
254 // SAFE ->
255 ::osl::ResettableMutexGuard aLock(m_aLock);
256 return ((m_eFillState & eState) == eState);
257 // <- SAFE
262 OUStringList FilterCache::getMatchingItemsByProps( EItemType eType ,
263 const CacheItem& lIProps,
264 const CacheItem& lEProps) const
265 throw(css::uno::Exception)
267 // SAFE ->
268 ::osl::ResettableMutexGuard aLock(m_aLock);
270 // search for right list
271 // An exception is thrown - "eType" is unknown.
272 // => rList will be valid everytimes next line is reached.
273 const CacheItemList& rList = impl_getItemList(eType);
275 OUStringList lKeys;
277 // search items, which provides all needed properties of set "lIProps"
278 // but not of set "lEProps"!
279 for (CacheItemList::const_iterator pIt = rList.begin();
280 pIt != rList.end() ;
281 ++pIt )
283 _FILTER_CONFIG_LOG_1_("getMatchingProps for \"%s\" ...\n",
284 _FILTER_CONFIG_TO_ASCII_(pIt->first))
285 if (
286 (pIt->second.haveProps(lIProps) ) &&
287 (pIt->second.dontHaveProps(lEProps))
290 lKeys.push_back(pIt->first);
294 return lKeys;
295 // <- SAFE
300 sal_Bool FilterCache::hasItems(EItemType eType) const
301 throw(css::uno::Exception)
303 // SAFE ->
304 ::osl::ResettableMutexGuard aLock(m_aLock);
306 // search for right list
307 // An exception is thrown - "eType" is unknown.
308 // => rList will be valid everytimes next line is reached.
309 const CacheItemList& rList = impl_getItemList(eType);
311 return !rList.empty();
312 // <- SAFE
317 OUStringList FilterCache::getItemNames(EItemType eType) const
318 throw(css::uno::Exception)
320 // SAFE ->
321 ::osl::ResettableMutexGuard aLock(m_aLock);
323 // search for right list
324 // An exception is thrown - "eType" is unknown.
325 // => rList will be valid everytimes next line is reached.
326 const CacheItemList& rList = impl_getItemList(eType);
328 OUStringList lKeys;
329 for (CacheItemList::const_iterator pIt = rList.begin();
330 pIt != rList.end() ;
331 ++pIt )
333 lKeys.push_back(pIt->first);
335 return lKeys;
336 // <- SAFE
341 sal_Bool FilterCache::hasItem( EItemType eType,
342 const OUString& sItem)
343 throw(css::uno::Exception)
345 // SAFE ->
346 ::osl::ResettableMutexGuard aLock(m_aLock);
348 // search for right list
349 // An exception is thrown - "eType" is unknown.
350 // => rList will be valid everytimes next line is reached.
351 const CacheItemList& rList = impl_getItemList(eType);
353 // if item could not be found - check if it can be loaded
354 // from the underlying configuration layer. Might it was not already
355 // loaded into this FilterCache object before.
356 CacheItemList::const_iterator pIt = rList.find(sItem);
357 if (pIt != rList.end())
358 return sal_True;
362 impl_loadItemOnDemand(eType, sItem);
363 // no exception => item could be loaded!
364 return sal_True;
366 catch(const css::container::NoSuchElementException&)
369 return sal_False;
370 // <- SAFE
375 CacheItem FilterCache::getItem( EItemType eType,
376 const OUString& sItem)
377 throw(css::uno::Exception)
379 // SAFE ->
380 ::osl::ResettableMutexGuard aLock(m_aLock);
382 // search for right list
383 // An exception is thrown if "eType" is unknown.
384 // => rList will be valid everytimes next line is reached.
385 CacheItemList& rList = impl_getItemList(eType);
387 // check if item exists ...
388 CacheItemList::iterator pIt = rList.find(sItem);
389 if (pIt == rList.end())
391 // ... or load it on demand from the
392 // underlying configuration layer.
393 // Note: NoSuchElementException is thrown automaticly here if
394 // item could not be loaded!
395 pIt = impl_loadItemOnDemand(eType, sItem);
398 /* Workaround for #137955#
399 Draw types and filters are installed ... but draw was disabled during setup.
400 We must supress accessing these filters. Otherwise the office can crash.
401 Solution for the next major release: do not install those filters !
403 if (eType == E_FILTER)
405 CacheItem& rFilter = pIt->second;
406 OUString sDocService;
407 rFilter[PROPNAME_DOCUMENTSERVICE] >>= sDocService;
409 // In Standalone-Impress the module WriterWeb is not installed
410 // but it is there to load help pages
411 bool bIsHelpFilter = sItem == "writer_web_HTML_help";
413 if ( !bIsHelpFilter && !impl_isModuleInstalled(sDocService) )
415 OUString sMsg("The requested filter '" + sItem +
416 "' exists ... but it shouldnt; because the corresponding LibreOffice module was not installed.");
417 throw css::container::NoSuchElementException(sMsg, css::uno::Reference< css::uno::XInterface >());
421 return pIt->second;
422 // <- SAFE
427 void FilterCache::removeItem( EItemType eType,
428 const OUString& sItem)
429 throw(css::uno::Exception)
431 // SAFE ->
432 ::osl::ResettableMutexGuard aLock(m_aLock);
434 // search for right list
435 // An exception is thrown - "eType" is unknown.
436 // => rList will be valid everytimes next line is reached.
437 CacheItemList& rList = impl_getItemList(eType);
439 CacheItemList::iterator pItem = rList.find(sItem);
440 if (pItem == rList.end())
441 pItem = impl_loadItemOnDemand(eType, sItem); // throws NoSuchELementException!
442 rList.erase(pItem);
444 impl_addItem2FlushList(eType, sItem);
449 void FilterCache::setItem( EItemType eType ,
450 const OUString& sItem ,
451 const CacheItem& aValue)
452 throw(css::uno::Exception)
454 // SAFE ->
455 ::osl::ResettableMutexGuard aLock(m_aLock);
457 // search for right list
458 // An exception is thrown - "eType" is unknown.
459 // => rList will be valid everytimes next line is reached.
460 CacheItemList& rList = impl_getItemList(eType);
462 // name must be part of the property set too ... otherwise our
463 // container query cant work correctly
464 CacheItem aItem = aValue;
465 aItem[PROPNAME_NAME] <<= sItem;
466 aItem.validateUINames(m_sActLocale);
468 // remove implicit properties as e.g. FINALIZED or MANDATORY
469 // They cant be saved here and must be readed on demand later, if they are needed.
470 removeStatePropsFromItem(aItem);
472 rList[sItem] = aItem;
474 impl_addItem2FlushList(eType, sItem);
477 //-----------------------------------------------
478 void FilterCache::refreshItem( EItemType eType,
479 const OUString& sItem)
480 throw(css::uno::Exception)
482 // SAFE ->
483 ::osl::ResettableMutexGuard aLock(m_aLock);
484 impl_loadItemOnDemand(eType, sItem);
489 void FilterCache::addStatePropsToItem( EItemType eType,
490 const OUString& sItem,
491 CacheItem& rItem)
492 throw(css::uno::Exception)
494 // SAFE ->
495 ::osl::ResettableMutexGuard aLock(m_aLock);
497 // Note: Opening of the configuration layer throws some exceptions
498 // if it failed. So we dont must check any reference here ...
499 css::uno::Reference< css::container::XNameAccess > xPackage;
500 css::uno::Reference< css::container::XNameAccess > xSet;
501 switch(eType)
503 case E_TYPE :
505 xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
506 xPackage->getByName(CFGSET_TYPES) >>= xSet;
508 break;
510 case E_FILTER :
512 xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY_THROW);
513 xPackage->getByName(CFGSET_FILTERS) >>= xSet;
515 break;
517 case E_FRAMELOADER :
519 /* TODO
520 Hack -->
521 The default frame loader cant be located inside te normal set of frame loaders.
522 Its an atomic property inside the misc cfg package. So we cant retrieve the information
523 about FINALIZED and MANDATORY very easy ... :-(
524 => set it to readonly/required everytimes :-)
526 css::uno::Any aDirectValue = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER);
527 OUString sDefaultFrameLoader;
528 if (
529 (aDirectValue >>= sDefaultFrameLoader) &&
530 (!sDefaultFrameLoader.isEmpty() ) &&
531 (sItem.equals(sDefaultFrameLoader) )
534 rItem[PROPNAME_FINALIZED] <<= sal_True;
535 rItem[PROPNAME_MANDATORY] <<= sal_True;
536 return;
538 /* <-- HACK */
540 xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
541 xPackage->getByName(CFGSET_FRAMELOADERS) >>= xSet;
543 break;
545 case E_CONTENTHANDLER :
547 xPackage = css::uno::Reference< css::container::XNameAccess >(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
548 xPackage->getByName(CFGSET_CONTENTHANDLERS) >>= xSet;
550 break;
551 default: break;
556 css::uno::Reference< css::beans::XProperty > xItem;
557 xSet->getByName(sItem) >>= xItem;
558 css::beans::Property aDescription = xItem->getAsProperty();
560 sal_Bool bFinalized = ((aDescription.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY );
561 sal_Bool bMandatory = ((aDescription.Attributes & css::beans::PropertyAttribute::REMOVABLE) != css::beans::PropertyAttribute::REMOVABLE);
563 rItem[PROPNAME_FINALIZED] <<= bFinalized;
564 rItem[PROPNAME_MANDATORY] <<= bMandatory;
566 catch(const css::container::NoSuchElementException&)
568 /* Ignore exceptions for missing elements inside configuration.
569 May by the following reason exists:
570 - The item does not exists inside the new configuration package org.openoffice.TypeDetection - but
571 we got it from the old package org.openoffice.Office/TypeDetection. We dont migrate such items
572 automaticly to the new format. Because it will disturb e.g. the deinstallation of an external filter
573 package. Because such external filter can remove the old file - but not the automaticly created new one ...
575 => mark item as FINALIZED / MANDATORY, we dont support writing to the old format
577 rItem[PROPNAME_FINALIZED] <<= sal_True;
578 rItem[PROPNAME_MANDATORY] <<= sal_True;
581 // <- SAFE
586 void FilterCache::removeStatePropsFromItem(CacheItem& rItem)
587 throw(css::uno::Exception)
589 CacheItem::iterator pIt;
590 pIt = rItem.find(PROPNAME_FINALIZED);
591 if (pIt != rItem.end())
592 rItem.erase(pIt);
593 pIt = rItem.find(PROPNAME_MANDATORY);
594 if (pIt != rItem.end())
595 rItem.erase(pIt);
600 void FilterCache::flush()
601 throw(css::uno::Exception)
603 // SAFE ->
604 ::osl::ResettableMutexGuard aLock(m_aLock);
606 // renew all dependencies and optimizations
607 impl_validateAndOptimize();
609 if (m_lChangedTypes.size() > 0)
611 css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
612 css::uno::Reference< css::container::XNameAccess > xSet ;
614 xConfig->getByName(CFGSET_TYPES) >>= xSet;
615 impl_flushByList(xSet, E_TYPE, m_lTypes, m_lChangedTypes);
617 css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY);
618 xFlush->commitChanges();
621 if (m_lChangedFilters.size() > 0)
623 css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY_THROW);
624 css::uno::Reference< css::container::XNameAccess > xSet ;
626 xConfig->getByName(CFGSET_FILTERS) >>= xSet;
627 impl_flushByList(xSet, E_FILTER, m_lFilters, m_lChangedFilters);
629 css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY);
630 xFlush->commitChanges();
633 /*TODO FrameLoader/ContentHandler must be flushed here too ... */
638 void FilterCache::impl_flushByList(const css::uno::Reference< css::container::XNameAccess >& xSet ,
639 EItemType eType ,
640 const CacheItemList& rCache,
641 const OUStringList& lItems)
642 throw(css::uno::Exception)
644 css::uno::Reference< css::container::XNameContainer > xAddRemoveSet = css::uno::Reference< css::container::XNameContainer > (xSet, css::uno::UNO_QUERY);
645 css::uno::Reference< css::container::XNameReplace > xReplaceeSet = css::uno::Reference< css::container::XNameReplace > (xSet, css::uno::UNO_QUERY);
646 css::uno::Reference< css::lang::XSingleServiceFactory > xFactory = css::uno::Reference< css::lang::XSingleServiceFactory >(xSet, css::uno::UNO_QUERY);
648 for (OUStringList::const_iterator pIt = lItems.begin();
649 pIt != lItems.end() ;
650 ++pIt )
652 const OUString& sItem = *pIt;
653 EItemFlushState eState = impl_specifyFlushOperation(xSet, rCache, sItem);
654 switch(eState)
656 case E_ITEM_REMOVED :
658 xAddRemoveSet->removeByName(sItem);
660 break;
662 case E_ITEM_ADDED :
664 css::uno::Reference< css::container::XNameReplace > xItem (xFactory->createInstance(), css::uno::UNO_QUERY);
666 // special case. no exception - but not a valid item => set must be finalized or mandatory!
667 // Reject flush operation by throwing an exception. At least one item couldnt be flushed.
668 if (!xItem.is())
669 throw css::uno::Exception("Cant add item. Set is finalized or mandatory!",
670 css::uno::Reference< css::uno::XInterface >());
672 CacheItemList::const_iterator pItem = rCache.find(sItem);
673 impl_saveItem(xItem, eType, pItem->second);
674 xAddRemoveSet->insertByName(sItem, css::uno::makeAny(xItem));
676 break;
678 case E_ITEM_CHANGED :
680 css::uno::Reference< css::container::XNameReplace > xItem;
681 xSet->getByName(sItem) >>= xItem;
683 // special case. no exception - but not a valid item => it must be finalized or mandatory!
684 // Reject flush operation by throwing an exception. At least one item couldnt be flushed.
685 if (!xItem.is())
686 throw css::uno::Exception("Cant change item. Its finalized or mandatory!",
687 css::uno::Reference< css::uno::XInterface >());
689 CacheItemList::const_iterator pItem = rCache.find(sItem);
690 impl_saveItem(xItem, eType, pItem->second);
692 break;
693 default: break;
700 void FilterCache::detectFlatForURL(const css::util::URL& aURL ,
701 FlatDetection& rFlatTypes) const
702 throw(css::uno::Exception)
704 // extract extension from URL, so it can be used directly as key into our hash map!
705 // Note further: It must be converted to lower case, because the optimize hash
706 // (which maps extensions to types) work with lower case key strings!
707 INetURLObject aParser (aURL.Main);
708 OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT ,
709 sal_True ,
710 INetURLObject::DECODE_WITH_CHARSET);
711 sExtension = sExtension.toAsciiLowerCase();
713 // SAFE -> ----------------------------------
714 ::osl::ResettableMutexGuard aLock(m_aLock);
716 //*******************************************
717 // i) Step over all well known URL pattern
718 // and add registered types to the return list too
719 // Do it as first one - because: if a type match by a
720 // pattern a following deep detection can be supressed!
721 // Further we can stop after first match ...
722 for (CacheItemRegistration::const_iterator pPattReg = m_lURLPattern2Types.begin();
723 pPattReg != m_lURLPattern2Types.end() ;
724 ++pPattReg )
726 WildCard aPatternCheck(pPattReg->first);
727 if (aPatternCheck.Matches(aURL.Main))
729 const OUStringList& rTypesForPattern = pPattReg->second;
731 FlatDetectionInfo aInfo;
732 aInfo.sType = *(rTypesForPattern.begin());
733 aInfo.bMatchByPattern = sal_True;
735 rFlatTypes.push_back(aInfo);
736 // return;
740 //*******************************************
741 // ii) search types matching to the given extension.
742 // Copy every macthing type without changing its order!
743 // Because preferred types was added as first one during
744 // loading configuration.
745 CacheItemRegistration::const_iterator pExtReg = m_lExtensions2Types.find(sExtension);
746 if (pExtReg != m_lExtensions2Types.end())
748 const OUStringList& rTypesForExtension = pExtReg->second;
749 for (OUStringList::const_iterator pIt = rTypesForExtension.begin();
750 pIt != rTypesForExtension.end() ;
751 ++pIt )
753 FlatDetectionInfo aInfo;
754 aInfo.sType = *pIt;
755 aInfo.bMatchByExtension = sal_True;
757 rFlatTypes.push_back(aInfo);
761 aLock.clear();
762 // <- SAFE ----------------------------------
765 const CacheItemList& FilterCache::impl_getItemList(EItemType eType) const
767 // SAFE -> ----------------------------------
768 ::osl::ResettableMutexGuard aLock(m_aLock);
770 switch(eType)
772 case E_TYPE : return m_lTypes ;
773 case E_FILTER : return m_lFilters ;
774 case E_FRAMELOADER : return m_lFrameLoaders ;
775 case E_CONTENTHANDLER : return m_lContentHandlers;
776 case E_DETECTSERVICE : return m_lDetectServices ;
780 throw css::uno::Exception("unknown sub container requested.",
781 css::uno::Reference< css::uno::XInterface >());
782 // <- SAFE ----------------------------------
785 CacheItemList& FilterCache::impl_getItemList(EItemType eType)
787 // SAFE -> ----------------------------------
788 ::osl::ResettableMutexGuard aLock(m_aLock);
790 switch(eType)
792 case E_TYPE : return m_lTypes ;
793 case E_FILTER : return m_lFilters ;
794 case E_FRAMELOADER : return m_lFrameLoaders ;
795 case E_CONTENTHANDLER : return m_lContentHandlers;
796 case E_DETECTSERVICE : return m_lDetectServices ;
800 throw css::uno::Exception("unknown sub container requested.",
801 css::uno::Reference< css::uno::XInterface >());
802 // <- SAFE ----------------------------------
805 css::uno::Reference< css::uno::XInterface > FilterCache::impl_openConfig(EConfigProvider eProvider)
806 throw(css::uno::Exception)
808 ::osl::ResettableMutexGuard aLock(m_aLock);
810 OUString sPath ;
811 css::uno::Reference< css::uno::XInterface >* pConfig = 0;
812 css::uno::Reference< css::uno::XInterface > xOld ;
813 OString sRtlLog ;
815 switch(eProvider)
817 case E_PROVIDER_TYPES :
819 if (m_xConfigTypes.is())
820 return m_xConfigTypes;
821 sPath = CFGPACKAGE_TD_TYPES;
822 pConfig = &m_xConfigTypes;
823 sRtlLog = "framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_TYPES)";
825 break;
827 case E_PROVIDER_FILTERS :
829 if (m_xConfigFilters.is())
830 return m_xConfigFilters;
831 sPath = CFGPACKAGE_TD_FILTERS;
832 pConfig = &m_xConfigFilters;
833 sRtlLog = "framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_FILTERS)";
835 break;
837 case E_PROVIDER_OTHERS :
839 if (m_xConfigOthers.is())
840 return m_xConfigOthers;
841 sPath = CFGPACKAGE_TD_OTHERS;
842 pConfig = &m_xConfigOthers;
843 sRtlLog = "framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_OTHERS)";
845 break;
847 case E_PROVIDER_OLD :
849 // This special provider is used to work with
850 // the old configuration format only. Its not cached!
851 sPath = CFGPACKAGE_TD_OLD;
852 pConfig = &xOld;
853 sRtlLog = "framework (as96863) ::FilterCache::impl_openconfig(E_PROVIDER_OLD)";
855 break;
857 default : throw css::uno::Exception("These configuration node isnt supported here for open!", 0);
861 RTL_LOGFILE_CONTEXT(aLog, sRtlLog.getStr());
862 *pConfig = impl_createConfigAccess(sPath ,
863 sal_False, // bReadOnly
864 sal_True ); // bLocalesMode
868 // Start listening for changes on that configuration access.
869 switch(eProvider)
871 case E_PROVIDER_TYPES:
873 m_xTypesChglisteners.set(new CacheUpdateListener(*this, *pConfig, FilterCache::E_TYPE));
874 m_xTypesChglisteners->startListening();
876 break;
877 case E_PROVIDER_FILTERS:
879 m_xFiltersChgListener.set(new CacheUpdateListener(*this, *pConfig, FilterCache::E_FILTER));
880 m_xFiltersChgListener->startListening();
882 break;
883 default:
884 break;
887 return *pConfig;
892 css::uno::Any FilterCache::impl_getDirectCFGValue(const OUString& sDirectKey)
894 OUString sRoot;
895 OUString sKey ;
897 if (
898 (!::utl::splitLastFromConfigurationPath(sDirectKey, sRoot, sKey)) ||
899 (sRoot.isEmpty() ) ||
900 (sKey.isEmpty() )
902 return css::uno::Any();
904 css::uno::Reference< css::uno::XInterface > xCfg = impl_createConfigAccess(sRoot ,
905 sal_True , // bReadOnly
906 sal_False); // bLocalesMode
907 if (!xCfg.is())
908 return css::uno::Any();
910 css::uno::Reference< css::container::XNameAccess > xAccess(xCfg, css::uno::UNO_QUERY);
911 if (!xAccess.is())
912 return css::uno::Any();
914 css::uno::Any aValue;
917 aValue = xAccess->getByName(sKey);
919 catch(const css::uno::RuntimeException&)
920 { throw; }
921 #if OSL_DEBUG_LEVEL > 0
922 catch(const css::uno::Exception& ex)
923 #else
924 catch(const css::uno::Exception&)
925 #endif
927 #if OSL_DEBUG_LEVEL > 0
928 OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr());
929 #endif
930 aValue.clear();
933 return aValue;
938 css::uno::Reference< css::uno::XInterface > FilterCache::impl_createConfigAccess(const OUString& sRoot ,
939 sal_Bool bReadOnly ,
940 sal_Bool bLocalesMode)
942 // SAFE ->
943 ::osl::ResettableMutexGuard aLock(m_aLock);
945 css::uno::Reference< css::uno::XInterface > xCfg;
949 css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider(
950 css::configuration::theDefaultProvider::get( comphelper::getProcessComponentContext() ) );
952 ::comphelper::SequenceAsVector< css::uno::Any > lParams;
953 css::beans::NamedValue aParam;
955 // set root path
956 aParam.Name = _FILTER_CONFIG_FROM_ASCII_("nodepath");
957 aParam.Value <<= sRoot;
958 lParams.push_back(css::uno::makeAny(aParam));
960 // enable "all locales mode" ... if required
961 if (bLocalesMode)
963 aParam.Name = _FILTER_CONFIG_FROM_ASCII_("locale");
964 aParam.Value <<= _FILTER_CONFIG_FROM_ASCII_("*" );
965 lParams.push_back(css::uno::makeAny(aParam));
968 // open it
969 if (bReadOnly)
970 xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONACCESS, lParams.getAsConstList());
971 else
972 xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONUPDATEACCESS, lParams.getAsConstList());
974 // If configuration could not be opened ... but factory method does not throwed an exception
975 // trigger throwing of our own CorruptedFilterConfigurationException.
976 // Let message empty. The normal exception text show enough information to the user.
977 if (! xCfg.is())
978 throw css::uno::Exception(
979 _FILTER_CONFIG_FROM_ASCII_("Got NULL reference on opening configuration file ... but no exception."),
980 css::uno::Reference< css::uno::XInterface >());
982 catch(const css::uno::Exception& ex)
984 throw css::document::CorruptedFilterConfigurationException(
985 "filter configuration, caught: " + ex.Message,
986 css::uno::Reference< css::uno::XInterface >(),
987 ex.Message);
990 return xCfg;
991 // <- SAFE
996 void FilterCache::impl_validateAndOptimize()
997 throw(css::uno::Exception)
999 // SAFE ->
1000 ::osl::ResettableMutexGuard aLock(m_aLock);
1002 RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::impl_validateAndOptimize");
1004 // First check if any filter or type could be readed
1005 // from the underlying configuration!
1006 sal_Bool bSomeTypesShouldExist = ((m_eFillState & E_CONTAINS_STANDARD ) == E_CONTAINS_STANDARD );
1007 sal_Bool bAllFiltersShouldExist = ((m_eFillState & E_CONTAINS_FILTERS ) == E_CONTAINS_FILTERS );
1009 #if OSL_DEBUG_LEVEL > 0
1011 sal_Int32 nWarnings = 0;
1013 // sal_Bool bAllTypesShouldExist = ((m_eFillState & E_CONTAINS_TYPES ) == E_CONTAINS_TYPES );
1014 sal_Bool bAllLoadersShouldExist = ((m_eFillState & E_CONTAINS_FRAMELOADERS ) == E_CONTAINS_FRAMELOADERS );
1015 sal_Bool bAllHandlersShouldExist = ((m_eFillState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS);
1016 #endif
1018 if (
1020 (bSomeTypesShouldExist) &&
1021 (m_lTypes.size() < 1 )
1022 ) ||
1024 (bAllFiltersShouldExist) &&
1025 (m_lFilters.size() < 1 )
1029 throw css::document::CorruptedFilterConfigurationException(
1030 "filter configuration: the list of types or filters is empty",
1031 css::uno::Reference< css::uno::XInterface >(),
1032 "The list of types or filters is empty." );
1035 // Create a log for all detected problems, which
1036 // occur in the next few lines.
1037 // If there are some real errors throw a RuntimException!
1038 // If there are some warnings only, show an assertion.
1039 sal_Int32 nErrors = 0;
1040 OUStringBuffer sLog(256);
1042 CacheItemList::iterator pIt;
1044 for (pIt = m_lTypes.begin(); pIt != m_lTypes.end(); ++pIt)
1046 OUString sType = pIt->first;
1047 CacheItem aType = pIt->second;
1049 // create list of all known detect services / frame loader / content handler on demand
1050 // Because these information are available as type properties!
1051 OUString sDetectService;
1052 aType[PROPNAME_DETECTSERVICE ] >>= sDetectService;
1053 if (!sDetectService.isEmpty())
1054 impl_resolveItem4TypeRegistration(&m_lDetectServices, sDetectService, sType);
1056 // get its registration for file Extensions AND(!) URLPattern ...
1057 // It doesnt matter if these items exists or if our
1058 // used index access create some default ones ...
1059 // only in case there is no filled set of Extensions AND
1060 // no filled set of URLPattern -> we must try to remove this invalid item
1061 // from this cache!
1062 css::uno::Sequence< OUString > lExtensions;
1063 css::uno::Sequence< OUString > lURLPattern;
1064 aType[PROPNAME_EXTENSIONS] >>= lExtensions;
1065 aType[PROPNAME_URLPATTERN] >>= lURLPattern;
1066 sal_Int32 ce = lExtensions.getLength();
1067 sal_Int32 cu = lURLPattern.getLength();
1069 #if OSL_DEBUG_LEVEL > 0
1071 OUString sInternalTypeNameCheck;
1072 aType[PROPNAME_NAME] >>= sInternalTypeNameCheck;
1073 if (!sInternalTypeNameCheck.equals(sType))
1075 sLog.append("Warning\t:\t" "The type \"" + sType + "\" does support the property \"Name\" correctly.\n");
1076 ++nWarnings;
1079 if (!ce && !cu)
1081 sLog.append("Warning\t:\t" "The type \"" + sType + "\" does not contain any URL pattern nor any extensions.\n");
1082 ++nWarnings;
1084 #endif
1086 // create an optimized registration for this type to
1087 // its set list of extensions/url pattern. If its a "normal" type
1088 // set it at the end of this optimized list. But if its
1089 // a "Preferred" one - set it to the front of this list.
1090 // Of course multiple "Preferred" registrations can occur
1091 // (they shouldn't - but they can!) ... Ignore it. The last
1092 // preferred type is useable in the same manner then every
1093 // other type!
1094 sal_Bool bPreferred = sal_False;
1095 aType[PROPNAME_PREFERRED] >>= bPreferred;
1097 const OUString* pExtensions = lExtensions.getConstArray();
1098 for (sal_Int32 e=0; e<ce; ++e)
1100 // Note: We must be sure that address the right hash entry
1101 // does not depend from any upper/lower case problems ...
1102 OUString sNormalizedExtension = pExtensions[e].toAsciiLowerCase();
1104 OUStringList& lTypesForExtension = m_lExtensions2Types[sNormalizedExtension];
1105 if (::std::find(lTypesForExtension.begin(), lTypesForExtension.end(), sType) != lTypesForExtension.end())
1106 continue;
1108 if (bPreferred)
1109 lTypesForExtension.insert(lTypesForExtension.begin(), sType);
1110 else
1111 lTypesForExtension.push_back(sType);
1114 const OUString* pURLPattern = lURLPattern.getConstArray();
1115 for (sal_Int32 u=0; u<cu; ++u)
1117 OUStringList& lTypesForURLPattern = m_lURLPattern2Types[pURLPattern[u]];
1118 if (::std::find(lTypesForURLPattern.begin(), lTypesForURLPattern.end(), sType) != lTypesForURLPattern.end())
1119 continue;
1121 if (bPreferred)
1122 lTypesForURLPattern.insert(lTypesForURLPattern.begin(), sType);
1123 else
1124 lTypesForURLPattern.push_back(sType);
1127 #if OSL_DEBUG_LEVEL > 0
1129 // Dont check cross references between types and filters, if
1130 // not all filters read from disk!
1131 // OK - this cache can read single filters on demand too ...
1132 // but then the fill state of this cache shouldnt be set to E_CONTAINS_FILTERS!
1133 if (!bAllFiltersShouldExist)
1134 continue;
1136 OUString sPrefFilter;
1137 aType[PROPNAME_PREFERREDFILTER] >>= sPrefFilter;
1138 if (sPrefFilter.isEmpty())
1140 // OK - there is no filter for this type. But thats not an error.
1141 // May be it can be handled by a ContentHandler ...
1142 // But at this time its not guaranteed that there is any ContentHandler
1143 // or FrameLoader inside this cache ... but on disk ...
1144 sal_Bool bReferencedByLoader = sal_True;
1145 sal_Bool bReferencedByHandler = sal_True;
1146 if (bAllLoadersShouldExist)
1147 bReferencedByLoader = !impl_searchFrameLoaderForType(sType).isEmpty();
1149 if (bAllHandlersShouldExist)
1150 bReferencedByHandler = !impl_searchContentHandlerForType(sType).isEmpty();
1152 if (
1153 (!bReferencedByLoader ) &&
1154 (!bReferencedByHandler)
1157 sLog.append("Warning\t:\t" "The type \"" + sType + "\" isnt used by any filter, loader or content handler.\n");
1158 ++nWarnings;
1162 if (!sPrefFilter.isEmpty())
1164 CacheItemList::const_iterator pIt2 = m_lFilters.find(sPrefFilter);
1165 if (pIt2 == m_lFilters.end())
1167 if (bAllFiltersShouldExist)
1169 ++nWarnings; // preferred filters can point to a non-installed office module ! no error ... it's a warning only .-(
1170 sLog.append("error\t:\t");
1172 else
1174 ++nWarnings;
1175 sLog.append("warning\t:\t");
1178 sLog.append("The type \"" + sType + "\" points to an invalid filter \"" + sPrefFilter + "\".\n");
1179 continue;
1182 CacheItem aPrefFilter = pIt2->second;
1183 OUString sFilterTypeReg;
1184 aPrefFilter[PROPNAME_TYPE] >>= sFilterTypeReg;
1185 if (sFilterTypeReg != sType)
1187 sLog.append("error\t:\t" "The preferred filter \"" + sPrefFilter + "\" of type \"" + sType +
1188 "is registered for another type \"" + sFilterTypeReg + "\".\n");
1189 ++nErrors;
1192 sal_Int32 nFlags = 0;
1193 aPrefFilter[PROPNAME_FLAGS] >>= nFlags;
1194 if ((nFlags & FLAGVAL_IMPORT) != FLAGVAL_IMPORT)
1196 sLog.append("error\t:\t" "The preferred filter \"" + sPrefFilter + "\" of type \"" +
1197 sType + "\" is not an IMPORT filter!\n");
1198 ++nErrors;
1201 OUString sInternalFilterNameCheck;
1202 aPrefFilter[PROPNAME_NAME] >>= sInternalFilterNameCheck;
1203 if (!sInternalFilterNameCheck.equals(sPrefFilter))
1205 sLog.append("Warning\t:\t" "The filter \"" + sPrefFilter +
1206 "\" does support the property \"Name\" correctly.\n");
1207 ++nWarnings;
1210 #endif
1213 // create dependencies between the global default frame loader
1214 // and all types (and of course if registered filters), which
1215 // does not registered for any other loader.
1216 css::uno::Any aDirectValue = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER);
1217 OUString sDefaultFrameLoader;
1219 if (
1220 (!(aDirectValue >>= sDefaultFrameLoader)) ||
1221 (sDefaultFrameLoader.isEmpty() )
1224 sLog.append("error\t:\t" "There is no valid default frame loader!?\n");
1225 ++nErrors;
1228 // a) get list of all well known types
1229 // b) step over all well known frame loader services
1230 // and remove all types from list a), which already
1231 // referenced by a loader b)
1232 OUStringList lTypes = getItemNames(E_TYPE);
1233 for ( pIt = m_lFrameLoaders.begin();
1234 pIt != m_lFrameLoaders.end() ;
1235 ++pIt )
1237 // Note: of course the default loader must be ignored here.
1238 // Because we replace its registration later completely with all
1239 // types, which are not referenced by any other loader.
1240 // So we can avaoid our code against the complexity of a diff!
1241 OUString sLoader = pIt->first;
1242 if (sLoader.equals(sDefaultFrameLoader))
1243 continue;
1245 CacheItem& rLoader = pIt->second;
1246 css::uno::Any& rTypesReg = rLoader[PROPNAME_TYPES];
1247 OUStringList lTypesReg (rTypesReg);
1249 for (OUStringList::const_iterator pTypesReg = lTypesReg.begin();
1250 pTypesReg != lTypesReg.end() ;
1251 ++pTypesReg )
1253 OUStringList::iterator pTypeCheck = ::std::find(lTypes.begin(), lTypes.end(), *pTypesReg);
1254 if (pTypeCheck != lTypes.end())
1255 lTypes.erase(pTypeCheck);
1259 CacheItem& rDefaultLoader = m_lFrameLoaders[sDefaultFrameLoader];
1260 rDefaultLoader[PROPNAME_NAME ] <<= sDefaultFrameLoader;
1261 rDefaultLoader[PROPNAME_TYPES] <<= lTypes.getAsConstList();
1263 OUString sLogOut = sLog.makeStringAndClear();
1264 OSL_ENSURE(!nErrors, OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr());
1265 if (nErrors>0)
1266 throw css::document::CorruptedFilterConfigurationException(
1267 "filter configuration: " + sLogOut,
1268 css::uno::Reference< css::uno::XInterface >(),
1269 sLogOut);
1270 OSL_ENSURE(!nWarnings, OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr());
1272 // <- SAFE
1277 void FilterCache::impl_addItem2FlushList( EItemType eType,
1278 const OUString& sItem)
1279 throw(css::uno::Exception)
1281 OUStringList* pList = 0;
1282 switch(eType)
1284 case E_TYPE :
1285 pList = &m_lChangedTypes;
1286 break;
1288 case E_FILTER :
1289 pList = &m_lChangedFilters;
1290 break;
1292 case E_FRAMELOADER :
1293 pList = &m_lChangedFrameLoaders;
1294 break;
1296 case E_CONTENTHANDLER :
1297 pList = &m_lChangedContentHandlers;
1298 break;
1300 case E_DETECTSERVICE :
1301 pList = &m_lChangedDetectServices;
1302 break;
1304 default : throw css::uno::Exception("unsupported item type", 0);
1307 OUStringList::const_iterator pItem = ::std::find(pList->begin(), pList->end(), sItem);
1308 if (pItem == pList->end())
1309 pList->push_back(sItem);
1314 FilterCache::EItemFlushState FilterCache::impl_specifyFlushOperation(const css::uno::Reference< css::container::XNameAccess >& xSet ,
1315 const CacheItemList& rList,
1316 const OUString& sItem)
1317 throw(css::uno::Exception)
1319 sal_Bool bExistsInConfigLayer = xSet->hasByName(sItem);
1320 sal_Bool bExistsInMemory = (rList.find(sItem) != rList.end());
1322 EItemFlushState eState( E_ITEM_UNCHANGED );
1324 // !? ... such situation can occur, if an item was added and(!) removed before it was flushed :-)
1325 if (!bExistsInConfigLayer && !bExistsInMemory)
1326 eState = E_ITEM_UNCHANGED;
1327 else if (!bExistsInConfigLayer && bExistsInMemory)
1328 eState = E_ITEM_ADDED;
1329 else if (bExistsInConfigLayer && bExistsInMemory)
1330 eState = E_ITEM_CHANGED;
1331 else if (bExistsInConfigLayer && !bExistsInMemory)
1332 eState = E_ITEM_REMOVED;
1334 return eState;
1339 void FilterCache::impl_resolveItem4TypeRegistration( CacheItemList* pList,
1340 const OUString& sItem,
1341 const OUString& sType)
1342 throw(css::uno::Exception)
1344 CacheItem& rItem = (*pList)[sItem];
1345 // In case its a new created entry (automaticly done by the boost::unordered_map index operator!)
1346 // we must be shure, that this entry has its own name as property available.
1347 // Its needed later at our container interface!
1348 rItem[PROPNAME_NAME] <<= sItem;
1350 OUStringList lTypeRegs(rItem[PROPNAME_TYPES]);
1351 if (::std::find(lTypeRegs.begin(), lTypeRegs.end(), sType) == lTypeRegs.end())
1353 lTypeRegs.push_back(sType);
1354 rItem[PROPNAME_TYPES] <<= lTypeRegs.getAsConstList();
1360 void FilterCache::impl_load(EFillState eRequiredState)
1361 throw(css::uno::Exception)
1363 // SAFE ->
1364 ::osl::ResettableMutexGuard aLock(m_aLock);
1366 // Attention: Detect services are part of the standard set!
1367 // So there is no need to handle it separately.
1369 // ------------------------------------------
1370 // a) The standard set of config value is needed.
1371 if (
1372 ((eRequiredState & E_CONTAINS_STANDARD) == E_CONTAINS_STANDARD) &&
1373 ((m_eFillState & E_CONTAINS_STANDARD) != E_CONTAINS_STANDARD)
1376 // Attention! If config couldnt be opened successfully
1377 // and exception os thrown automaticly and must be forwarded
1378 // to our calli ...
1379 css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
1381 RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load std");
1382 impl_loadSet(xTypes, E_TYPE, E_READ_STANDARD, &m_lTypes);
1386 // ------------------------------------------
1387 // b) We need all type information ...
1388 if (
1389 ((eRequiredState & E_CONTAINS_TYPES) == E_CONTAINS_TYPES) &&
1390 ((m_eFillState & E_CONTAINS_TYPES) != E_CONTAINS_TYPES)
1393 // Attention! If config couldnt be opened successfully
1394 // and exception os thrown automaticly and must be forwarded
1395 // to our calli ...
1396 css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
1398 RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all types");
1399 impl_loadSet(xTypes, E_TYPE, E_READ_UPDATE, &m_lTypes);
1403 // ------------------------------------------
1404 // c) We need all filter information ...
1405 if (
1406 ((eRequiredState & E_CONTAINS_FILTERS) == E_CONTAINS_FILTERS) &&
1407 ((m_eFillState & E_CONTAINS_FILTERS) != E_CONTAINS_FILTERS)
1410 // Attention! If config couldnt be opened successfully
1411 // and exception os thrown automaticly and must be forwarded
1412 // to our calli ...
1413 css::uno::Reference< css::container::XNameAccess > xFilters(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY_THROW);
1415 RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all filters");
1416 impl_loadSet(xFilters, E_FILTER, E_READ_ALL, &m_lFilters);
1420 // ------------------------------------------
1421 // c) We need all frame loader information ...
1422 if (
1423 ((eRequiredState & E_CONTAINS_FRAMELOADERS) == E_CONTAINS_FRAMELOADERS) &&
1424 ((m_eFillState & E_CONTAINS_FRAMELOADERS) != E_CONTAINS_FRAMELOADERS)
1427 // Attention! If config couldnt be opened successfully
1428 // and exception os thrown automaticly and must be forwarded
1429 // to our calli ...
1430 css::uno::Reference< css::container::XNameAccess > xLoaders(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
1432 RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all frame loader");
1433 impl_loadSet(xLoaders, E_FRAMELOADER, E_READ_ALL, &m_lFrameLoaders);
1437 // ------------------------------------------
1438 // d) We need all content handler information ...
1439 if (
1440 ((eRequiredState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS) &&
1441 ((m_eFillState & E_CONTAINS_CONTENTHANDLERS) != E_CONTAINS_CONTENTHANDLERS)
1444 // Attention! If config couldnt be opened successfully
1445 // and exception os thrown automaticly and must be forwarded
1446 // to our calli ...
1447 css::uno::Reference< css::container::XNameAccess > xHandlers(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
1449 RTL_LOGFILE_CONTEXT( aLog, "framework (as96863) ::FilterCache::load all content handler");
1450 impl_loadSet(xHandlers, E_CONTENTHANDLER, E_READ_ALL, &m_lContentHandlers);
1454 // update fill state. Note: its a bit field, which combines different parts.
1455 m_eFillState = (EFillState) ((sal_Int32)m_eFillState | (sal_Int32)eRequiredState);
1457 // any data readed?
1458 // yes! => validate it and update optimized structures.
1459 impl_validateAndOptimize();
1461 // <- SAFE
1466 void FilterCache::impl_loadSet(const css::uno::Reference< css::container::XNameAccess >& xConfig,
1467 EItemType eType ,
1468 EReadOption eOption,
1469 CacheItemList* pCache )
1470 throw(css::uno::Exception)
1472 // get access to the right configuration set
1473 OUString sSetName;
1474 switch(eType)
1476 case E_TYPE :
1477 sSetName = CFGSET_TYPES;
1478 break;
1480 case E_FILTER :
1481 sSetName = CFGSET_FILTERS;
1482 break;
1484 case E_FRAMELOADER :
1485 sSetName = CFGSET_FRAMELOADERS;
1486 break;
1488 case E_CONTENTHANDLER :
1489 sSetName = CFGSET_CONTENTHANDLERS;
1490 break;
1491 default: break;
1494 css::uno::Reference< css::container::XNameAccess > xSet;
1495 css::uno::Sequence< OUString > lItems;
1499 css::uno::Any aVal = xConfig->getByName(sSetName);
1500 if (!(aVal >>= xSet) || !xSet.is())
1502 OUString sMsg("Could not open configuration set \"" + sSetName + "\".");
1503 throw css::uno::Exception(sMsg, css::uno::Reference< css::uno::XInterface >());
1505 lItems = xSet->getElementNames();
1507 catch(const css::uno::Exception& ex)
1509 throw css::document::CorruptedFilterConfigurationException(
1510 "filter configuration, caught: " + ex.Message,
1511 css::uno::Reference< css::uno::XInterface >(),
1512 ex.Message);
1515 // get names of all existing sub items of this set
1516 // step over it and fill internal cache structures.
1518 // But dont update optimized structures like e.g. hash
1519 // for mapping extensions to its types!
1521 const OUString* pItems = lItems.getConstArray();
1522 sal_Int32 c = lItems.getLength();
1523 for (sal_Int32 i=0; i<c; ++i)
1525 CacheItemList::iterator pItem = pCache->find(pItems[i]);
1526 switch(eOption)
1528 // a) read a standard set of properties only or read all
1529 case E_READ_STANDARD :
1530 case E_READ_ALL :
1534 (*pCache)[pItems[i]] = impl_loadItem(xSet, eType, pItems[i], eOption);
1536 catch(const css::uno::Exception& ex)
1538 throw css::document::CorruptedFilterConfigurationException(
1539 "filter configuration, caught: " + ex.Message,
1540 css::uno::Reference< css::uno::XInterface >(),
1541 ex.Message);
1544 break;
1546 // b) read optional properties only!
1547 // All items must already exist inside our cache.
1548 // But they must be updated.
1549 case E_READ_UPDATE :
1551 if (pItem == pCache->end())
1553 OUString sMsg("item \"" + pItems[i] + "\" not found for update!");
1554 throw css::uno::Exception(sMsg, css::uno::Reference< css::uno::XInterface >());
1558 CacheItem aItem = impl_loadItem(xSet, eType, pItems[i], eOption);
1559 pItem->second.update(aItem);
1561 catch(const css::uno::Exception& ex)
1563 throw css::document::CorruptedFilterConfigurationException(
1564 "filter configuration, caught: " + ex.Message,
1565 css::uno::Reference< css::uno::XInterface >(),
1566 ex.Message);
1569 break;
1570 default: break;
1577 void FilterCache::impl_readPatchUINames(const css::uno::Reference< css::container::XNameAccess >& xNode,
1578 CacheItem& rItem)
1579 throw(css::uno::Exception)
1582 // SAFE -> ----------------------------------
1583 ::osl::ResettableMutexGuard aLock(m_aLock);
1584 OUString sFormatName = m_sFormatName ;
1585 OUString sFormatVersion = m_sFormatVersion;
1586 OUString sActLocale = m_sActLocale ;
1587 aLock.clear();
1588 // <- SAFE ----------------------------------
1590 css::uno::Any aVal = xNode->getByName(PROPNAME_UINAME);
1591 css::uno::Reference< css::container::XNameAccess > xUIName;
1592 if (!(aVal >>= xUIName) && !xUIName.is())
1593 return;
1595 const ::comphelper::SequenceAsVector< OUString > lLocales(xUIName->getElementNames());
1596 ::comphelper::SequenceAsVector< OUString >::const_iterator pLocale ;
1597 ::comphelper::SequenceAsHashMap lUINames;
1599 const char FORMATNAME_VAR[] = "%productname%";
1600 const char FORMATVERSION_VAR[] = "%formatversion%";
1601 // patch %PRODUCTNAME and %FORMATNAME
1602 for ( pLocale = lLocales.begin();
1603 pLocale != lLocales.end() ;
1604 ++pLocale )
1606 const OUString& sLocale = *pLocale;
1608 OUString sValue;
1609 xUIName->getByName(sLocale) >>= sValue;
1611 // replace %productname%
1612 sal_Int32 nIndex = sValue.indexOf(FORMATNAME_VAR);
1613 while(nIndex != -1)
1615 sValue = sValue.replaceAt(nIndex, RTL_CONSTASCII_LENGTH(FORMATNAME_VAR), sFormatName);
1616 nIndex = sValue.indexOf(FORMATNAME_VAR, nIndex);
1618 // replace %formatversion%
1619 nIndex = sValue.indexOf(FORMATVERSION_VAR);
1620 while(nIndex != -1)
1622 sValue = sValue.replaceAt(nIndex, RTL_CONSTASCII_LENGTH(FORMATVERSION_VAR), sFormatVersion);
1623 nIndex = sValue.indexOf(FORMATVERSION_VAR, nIndex);
1626 lUINames[sLocale] <<= sValue;
1629 aVal <<= lUINames.getAsConstPropertyValueList();
1630 rItem[PROPNAME_UINAMES] = aVal;
1632 // find right UIName for current office locale
1633 // Use fallbacks too!
1634 pLocale = LanguageTag::getFallback(lLocales, sActLocale);
1635 if (pLocale == lLocales.end())
1637 #if OSL_DEBUG_LEVEL > 0
1638 if ( sActLocale == "en-US" )
1639 return;
1640 OUString sName = rItem.getUnpackedValueOrDefault(PROPNAME_NAME, OUString());
1642 OUString sMsg("Fallback scenario for filter or type '" + sName + "' and locale '" +
1643 sActLocale + "' failed. Please check your filter configuration.");
1645 OSL_FAIL(_FILTER_CONFIG_TO_ASCII_(sMsg));
1646 #endif
1647 return;
1650 const OUString& sLocale = *pLocale;
1651 ::comphelper::SequenceAsHashMap::const_iterator pUIName = lUINames.find(sLocale);
1652 if (pUIName != lUINames.end())
1653 rItem[PROPNAME_UINAME] = pUIName->second;
1658 void FilterCache::impl_savePatchUINames(const css::uno::Reference< css::container::XNameReplace >& xNode,
1659 const CacheItem& rItem)
1660 throw(css::uno::Exception)
1662 css::uno::Reference< css::container::XNameContainer > xAdd (xNode, css::uno::UNO_QUERY);
1663 css::uno::Reference< css::container::XNameAccess > xCheck(xNode, css::uno::UNO_QUERY);
1665 css::uno::Sequence< css::beans::PropertyValue > lUINames = rItem.getUnpackedValueOrDefault(PROPNAME_UINAMES, css::uno::Sequence< css::beans::PropertyValue >());
1666 sal_Int32 c = lUINames.getLength();
1667 const css::beans::PropertyValue* pUINames = lUINames.getConstArray();
1669 for (sal_Int32 i=0; i<c; ++i)
1671 if (xCheck->hasByName(pUINames[i].Name))
1672 xNode->replaceByName(pUINames[i].Name, pUINames[i].Value);
1673 else
1674 xAdd->insertByName(pUINames[i].Name, pUINames[i].Value);
1678 /*-----------------------------------------------
1679 TODO
1680 clarify, how the real problem behind the
1681 wrong constructed CacheItem instance (which
1682 will force a crash during destruction)
1683 can be solved ...
1684 -----------------------------------------------*/
1685 CacheItem FilterCache::impl_loadItem(const css::uno::Reference< css::container::XNameAccess >& xSet ,
1686 EItemType eType ,
1687 const OUString& sItem ,
1688 EReadOption eOption)
1689 throw(css::uno::Exception)
1691 // try to get an API object, which points directly to the
1692 // requested item. If it fail an exception should occur and
1693 // break this operation. Of course returned API object must be
1694 // checked too.
1695 css::uno::Reference< css::container::XNameAccess > xItem;
1696 #ifdef WORKAROUND_EXCEPTION_PROBLEM
1699 #endif
1700 css::uno::Any aVal = xSet->getByName(sItem);
1701 if (!(aVal >>= xItem) || !xItem.is())
1703 OUString sMsg("found corrupted item \"" + sItem + "\".");
1704 throw css::uno::Exception(sMsg, css::uno::Reference< css::uno::XInterface >());
1706 #ifdef WORKAROUND_EXCEPTION_PROBLEM
1708 catch(const css::container::NoSuchElementException&)
1710 throw;
1712 #endif
1714 // The internal name of an item must(!) be part of the property
1715 // set too. Of course its already used as key into the e.g. outside
1716 // used hash map ... but some of our API methods provide
1717 // this property set as result only. But the user of this CacheItem
1718 // should know, which value the key names has :-) ITS IMPORTANT!
1719 CacheItem aItem;
1720 aItem[PROPNAME_NAME] = css::uno::makeAny(sItem);
1721 switch(eType)
1723 //---------------------------------------
1724 case E_TYPE :
1726 // read standard properties of a type
1727 if (
1728 (eOption == E_READ_STANDARD) ||
1729 (eOption == E_READ_ALL )
1732 aItem[PROPNAME_PREFERREDFILTER] = xItem->getByName(PROPNAME_PREFERREDFILTER);
1733 aItem[PROPNAME_DETECTSERVICE ] = xItem->getByName(PROPNAME_DETECTSERVICE );
1734 aItem[PROPNAME_URLPATTERN ] = xItem->getByName(PROPNAME_URLPATTERN );
1735 aItem[PROPNAME_EXTENSIONS ] = xItem->getByName(PROPNAME_EXTENSIONS );
1736 aItem[PROPNAME_PREFERRED ] = xItem->getByName(PROPNAME_PREFERRED );
1737 aItem[PROPNAME_CLIPBOARDFORMAT] = xItem->getByName(PROPNAME_CLIPBOARDFORMAT);
1739 // read optional properties of a type
1740 // no else here! Is an additional switch ...
1741 if (
1742 (eOption == E_READ_UPDATE) ||
1743 (eOption == E_READ_ALL )
1746 aItem[PROPNAME_MEDIATYPE ] = xItem->getByName(PROPNAME_MEDIATYPE );
1747 impl_readPatchUINames(xItem, aItem);
1750 break;
1752 //---------------------------------------
1753 case E_FILTER :
1755 // read standard properties of a filter
1756 if (
1757 (eOption == E_READ_STANDARD) ||
1758 (eOption == E_READ_ALL )
1761 aItem[PROPNAME_TYPE ] = xItem->getByName(PROPNAME_TYPE );
1762 aItem[PROPNAME_FILEFORMATVERSION] = xItem->getByName(PROPNAME_FILEFORMATVERSION);
1763 aItem[PROPNAME_UICOMPONENT ] = xItem->getByName(PROPNAME_UICOMPONENT );
1764 aItem[PROPNAME_FILTERSERVICE ] = xItem->getByName(PROPNAME_FILTERSERVICE );
1765 aItem[PROPNAME_DOCUMENTSERVICE ] = xItem->getByName(PROPNAME_DOCUMENTSERVICE );
1766 aItem[PROPNAME_EXPORTEXTENSION ] = xItem->getByName(PROPNAME_EXPORTEXTENSION );
1768 // special handling for flags! Convert it from a list of names to its
1769 // int representation ...
1770 css::uno::Sequence< OUString > lFlagNames;
1771 if (xItem->getByName(PROPNAME_FLAGS) >>= lFlagNames)
1772 aItem[PROPNAME_FLAGS] <<= FilterCache::impl_convertFlagNames2FlagField(lFlagNames);
1774 // read optional properties of a filter
1775 // no else here! Is an additional switch ...
1776 if (
1777 (eOption == E_READ_UPDATE) ||
1778 (eOption == E_READ_ALL )
1781 aItem[PROPNAME_USERDATA ] = xItem->getByName(PROPNAME_USERDATA );
1782 aItem[PROPNAME_TEMPLATENAME] = xItem->getByName(PROPNAME_TEMPLATENAME);
1783 //TODO remove it if moving of filter uinames to type uinames
1784 // will be finished realy
1785 #ifdef AS_ENABLE_FILTER_UINAMES
1786 impl_readPatchUINames(xItem, aItem);
1787 #endif // AS_ENABLE_FILTER_UINAMES
1790 break;
1792 //---------------------------------------
1793 case E_FRAMELOADER :
1794 case E_CONTENTHANDLER :
1796 aItem[PROPNAME_TYPES] = xItem->getByName(PROPNAME_TYPES);
1798 break;
1799 default: break;
1802 return aItem;
1807 CacheItemList::iterator FilterCache::impl_loadItemOnDemand( EItemType eType,
1808 const OUString& sItem)
1809 throw(css::uno::Exception)
1811 CacheItemList* pList = 0;
1812 css::uno::Reference< css::uno::XInterface > xConfig ;
1813 OUString sSet ;
1815 switch(eType)
1817 case E_TYPE :
1819 pList = &m_lTypes;
1820 xConfig = impl_openConfig(E_PROVIDER_TYPES);
1821 sSet = CFGSET_TYPES;
1823 break;
1825 case E_FILTER :
1827 pList = &m_lFilters;
1828 xConfig = impl_openConfig(E_PROVIDER_FILTERS);
1829 sSet = CFGSET_FILTERS;
1831 break;
1833 case E_FRAMELOADER :
1835 pList = &m_lFrameLoaders;
1836 xConfig = impl_openConfig(E_PROVIDER_OTHERS);
1837 sSet = CFGSET_FRAMELOADERS;
1839 break;
1841 case E_CONTENTHANDLER :
1843 pList = &m_lContentHandlers;
1844 xConfig = impl_openConfig(E_PROVIDER_OTHERS);
1845 sSet = CFGSET_CONTENTHANDLERS;
1847 break;
1849 case E_DETECTSERVICE :
1851 OSL_FAIL("Cant load detect services on demand. Who use this unsupported feature?");
1853 break;
1856 css::uno::Reference< css::container::XNameAccess > xRoot(xConfig, css::uno::UNO_QUERY_THROW);
1857 css::uno::Reference< css::container::XNameAccess > xSet ;
1858 xRoot->getByName(sSet) >>= xSet;
1860 CacheItemList::iterator pItemInCache = pList->find(sItem);
1861 sal_Bool bItemInConfig = xSet->hasByName(sItem);
1863 if (bItemInConfig)
1865 (*pList)[sItem] = impl_loadItem(xSet, eType, sItem, E_READ_ALL);
1866 _FILTER_CONFIG_LOG_2_("impl_loadItemOnDemand(%d, \"%s\") ... OK", (int)eType, _FILTER_CONFIG_TO_ASCII_(sItem).getStr())
1868 else
1870 if (pItemInCache != pList->end())
1871 pList->erase(pItemInCache);
1872 // OK - this item does not exists inside configuration.
1873 // And we already updated our internal cache.
1874 // But the outside code needs this NoSuchElementException
1875 // to know, that this item does notexists.
1876 // Nobody checks the iterator!
1877 throw css::container::NoSuchElementException();
1880 return pList->find(sItem);
1885 void FilterCache::impl_saveItem(const css::uno::Reference< css::container::XNameReplace >& xItem,
1886 EItemType eType,
1887 const CacheItem& aItem)
1888 throw(css::uno::Exception)
1890 CacheItem::const_iterator pIt;
1891 switch(eType)
1893 //---------------------------------------
1894 case E_TYPE :
1896 pIt = aItem.find(PROPNAME_PREFERREDFILTER);
1897 if (pIt != aItem.end())
1898 xItem->replaceByName(PROPNAME_PREFERREDFILTER, pIt->second);
1899 pIt = aItem.find(PROPNAME_DETECTSERVICE);
1900 if (pIt != aItem.end())
1901 xItem->replaceByName(PROPNAME_DETECTSERVICE, pIt->second);
1902 pIt = aItem.find(PROPNAME_URLPATTERN);
1903 if (pIt != aItem.end())
1904 xItem->replaceByName(PROPNAME_URLPATTERN, pIt->second);
1905 pIt = aItem.find(PROPNAME_EXTENSIONS);
1906 if (pIt != aItem.end())
1907 xItem->replaceByName(PROPNAME_EXTENSIONS, pIt->second);
1908 pIt = aItem.find(PROPNAME_PREFERRED);
1909 if (pIt != aItem.end())
1910 xItem->replaceByName(PROPNAME_PREFERRED, pIt->second);
1911 pIt = aItem.find(PROPNAME_MEDIATYPE);
1912 if (pIt != aItem.end())
1913 xItem->replaceByName(PROPNAME_MEDIATYPE, pIt->second);
1914 pIt = aItem.find(PROPNAME_CLIPBOARDFORMAT);
1915 if (pIt != aItem.end())
1916 xItem->replaceByName(PROPNAME_CLIPBOARDFORMAT, pIt->second);
1918 css::uno::Reference< css::container::XNameReplace > xUIName;
1919 xItem->getByName(PROPNAME_UINAME) >>= xUIName;
1920 impl_savePatchUINames(xUIName, aItem);
1922 break;
1924 //---------------------------------------
1925 case E_FILTER :
1927 pIt = aItem.find(PROPNAME_TYPE);
1928 if (pIt != aItem.end())
1929 xItem->replaceByName(PROPNAME_TYPE, pIt->second);
1930 pIt = aItem.find(PROPNAME_FILEFORMATVERSION);
1931 if (pIt != aItem.end())
1932 xItem->replaceByName(PROPNAME_FILEFORMATVERSION, pIt->second);
1933 pIt = aItem.find(PROPNAME_UICOMPONENT);
1934 if (pIt != aItem.end())
1935 xItem->replaceByName(PROPNAME_UICOMPONENT, pIt->second);
1936 pIt = aItem.find(PROPNAME_FILTERSERVICE);
1937 if (pIt != aItem.end())
1938 xItem->replaceByName(PROPNAME_FILTERSERVICE, pIt->second);
1939 pIt = aItem.find(PROPNAME_DOCUMENTSERVICE);
1940 if (pIt != aItem.end())
1941 xItem->replaceByName(PROPNAME_DOCUMENTSERVICE, pIt->second);
1942 pIt = aItem.find(PROPNAME_USERDATA);
1943 if (pIt != aItem.end())
1944 xItem->replaceByName(PROPNAME_USERDATA, pIt->second);
1945 pIt = aItem.find(PROPNAME_TEMPLATENAME);
1946 if (pIt != aItem.end())
1947 xItem->replaceByName(PROPNAME_TEMPLATENAME, pIt->second);
1949 // special handling for flags! Convert it from an integer flag field back
1950 // to a list of names ...
1951 // But note: because we work directly on a reference to the cache item,
1952 // its not allowd to change the value here. We must work on a copy!
1953 pIt = aItem.find(PROPNAME_FLAGS);
1954 if (pIt != aItem.end())
1956 sal_Int32 nFlags = 0;
1957 pIt->second >>= nFlags;
1958 css::uno::Any aFlagNameList;
1959 aFlagNameList <<= FilterCache::impl_convertFlagField2FlagNames(nFlags);
1960 xItem->replaceByName(PROPNAME_FLAGS, aFlagNameList);
1963 //TODO remove it if moving of filter uinames to type uinames
1964 // will be finished realy
1965 #ifdef AS_ENABLE_FILTER_UINAMES
1966 css::uno::Reference< css::container::XNameReplace > xUIName;
1967 xItem->getByName(PROPNAME_UINAME) >>= xUIName;
1968 impl_savePatchUINames(xUIName, aItem);
1969 #endif // AS_ENABLE_FILTER_UINAMES
1971 break;
1973 //---------------------------------------
1974 case E_FRAMELOADER :
1975 case E_CONTENTHANDLER :
1977 pIt = aItem.find(PROPNAME_TYPES);
1978 if (pIt != aItem.end())
1979 xItem->replaceByName(PROPNAME_TYPES, pIt->second);
1981 break;
1982 default: break;
1986 /*-----------------------------------------------
1987 static! => no locks neccessary
1988 -----------------------------------------------*/
1989 css::uno::Sequence< OUString > FilterCache::impl_convertFlagField2FlagNames(sal_Int32 nFlags)
1991 OUStringList lFlagNames;
1993 if ((nFlags & FLAGVAL_3RDPARTYFILTER ) == FLAGVAL_3RDPARTYFILTER ) lFlagNames.push_back(FLAGNAME_3RDPARTYFILTER );
1994 if ((nFlags & FLAGVAL_ALIEN ) == FLAGVAL_ALIEN ) lFlagNames.push_back(FLAGNAME_ALIEN );
1995 if ((nFlags & FLAGVAL_ASYNCHRON ) == FLAGVAL_ASYNCHRON ) lFlagNames.push_back(FLAGNAME_ASYNCHRON );
1996 if ((nFlags & FLAGVAL_BROWSERPREFERRED ) == FLAGVAL_BROWSERPREFERRED ) lFlagNames.push_back(FLAGNAME_BROWSERPREFERRED );
1997 if ((nFlags & FLAGVAL_CONSULTSERVICE ) == FLAGVAL_CONSULTSERVICE ) lFlagNames.push_back(FLAGNAME_CONSULTSERVICE );
1998 if ((nFlags & FLAGVAL_DEFAULT ) == FLAGVAL_DEFAULT ) lFlagNames.push_back(FLAGNAME_DEFAULT );
1999 if ((nFlags & FLAGVAL_ENCRYPTION ) == FLAGVAL_ENCRYPTION ) lFlagNames.push_back(FLAGNAME_ENCRYPTION );
2000 if ((nFlags & FLAGVAL_EXPORT ) == FLAGVAL_EXPORT ) lFlagNames.push_back(FLAGNAME_EXPORT );
2001 if ((nFlags & FLAGVAL_IMPORT ) == FLAGVAL_IMPORT ) lFlagNames.push_back(FLAGNAME_IMPORT );
2002 if ((nFlags & FLAGVAL_INTERNAL ) == FLAGVAL_INTERNAL ) lFlagNames.push_back(FLAGNAME_INTERNAL );
2003 if ((nFlags & FLAGVAL_NOTINCHOOSER ) == FLAGVAL_NOTINCHOOSER ) lFlagNames.push_back(FLAGNAME_NOTINCHOOSER );
2004 if ((nFlags & FLAGVAL_NOTINFILEDIALOG ) == FLAGVAL_NOTINFILEDIALOG ) lFlagNames.push_back(FLAGNAME_NOTINFILEDIALOG );
2005 if ((nFlags & FLAGVAL_NOTINSTALLED ) == FLAGVAL_NOTINSTALLED ) lFlagNames.push_back(FLAGNAME_NOTINSTALLED );
2006 if ((nFlags & FLAGVAL_OWN ) == FLAGVAL_OWN ) lFlagNames.push_back(FLAGNAME_OWN );
2007 if ((nFlags & FLAGVAL_PACKED ) == FLAGVAL_PACKED ) lFlagNames.push_back(FLAGNAME_PACKED );
2008 if ((nFlags & FLAGVAL_PASSWORDTOMODIFY ) == FLAGVAL_PASSWORDTOMODIFY ) lFlagNames.push_back(FLAGNAME_PASSWORDTOMODIFY );
2009 if ((nFlags & FLAGVAL_PREFERRED ) == FLAGVAL_PREFERRED ) lFlagNames.push_back(FLAGNAME_PREFERRED );
2010 if ((nFlags & FLAGVAL_STARTPRESENTATION) == FLAGVAL_STARTPRESENTATION) lFlagNames.push_back(FLAGNAME_STARTPRESENTATION);
2011 if ((nFlags & FLAGVAL_READONLY ) == FLAGVAL_READONLY ) lFlagNames.push_back(FLAGNAME_READONLY );
2012 if ((nFlags & FLAGVAL_SUPPORTSSELECTION) == FLAGVAL_SUPPORTSSELECTION) lFlagNames.push_back(FLAGNAME_SUPPORTSSELECTION);
2013 if ((nFlags & FLAGVAL_TEMPLATE ) == FLAGVAL_TEMPLATE ) lFlagNames.push_back(FLAGNAME_TEMPLATE );
2014 if ((nFlags & FLAGVAL_TEMPLATEPATH ) == FLAGVAL_TEMPLATEPATH ) lFlagNames.push_back(FLAGNAME_TEMPLATEPATH );
2015 if ((nFlags & FLAGVAL_USESOPTIONS ) == FLAGVAL_USESOPTIONS ) lFlagNames.push_back(FLAGNAME_USESOPTIONS );
2016 if ((nFlags & FLAGVAL_COMBINED ) == FLAGVAL_COMBINED ) lFlagNames.push_back(FLAGNAME_COMBINED );
2018 return lFlagNames.getAsConstList();
2021 /*-----------------------------------------------
2022 static! => no locks neccessary
2023 -----------------------------------------------*/
2024 sal_Int32 FilterCache::impl_convertFlagNames2FlagField(const css::uno::Sequence< OUString >& lNames)
2026 sal_Int32 nField = 0;
2028 const OUString* pNames = lNames.getConstArray();
2029 sal_Int32 c = lNames.getLength();
2030 for (sal_Int32 i=0; i<c; ++i)
2032 if (pNames[i].equals(FLAGNAME_3RDPARTYFILTER))
2034 nField |= FLAGVAL_3RDPARTYFILTER;
2035 continue;
2037 if (pNames[i].equals(FLAGNAME_ALIEN))
2039 nField |= FLAGVAL_ALIEN;
2040 continue;
2042 if (pNames[i].equals(FLAGNAME_ASYNCHRON))
2044 nField |= FLAGVAL_ASYNCHRON;
2045 continue;
2047 if (pNames[i].equals(FLAGNAME_BROWSERPREFERRED))
2049 nField |= FLAGVAL_BROWSERPREFERRED;
2050 continue;
2052 if (pNames[i].equals(FLAGNAME_CONSULTSERVICE))
2054 nField |= FLAGVAL_CONSULTSERVICE;
2055 continue;
2057 if (pNames[i].equals(FLAGNAME_DEFAULT))
2059 nField |= FLAGVAL_DEFAULT;
2060 continue;
2062 if (pNames[i].equals(FLAGNAME_ENCRYPTION))
2064 nField |= FLAGVAL_ENCRYPTION;
2065 continue;
2067 if (pNames[i].equals(FLAGNAME_EXPORT))
2069 nField |= FLAGVAL_EXPORT;
2070 continue;
2072 if (pNames[i].equals(FLAGNAME_IMPORT))
2074 nField |= FLAGVAL_IMPORT;
2075 continue;
2077 if (pNames[i].equals(FLAGNAME_INTERNAL))
2079 nField |= FLAGVAL_INTERNAL;
2080 continue;
2082 if (pNames[i].equals(FLAGNAME_NOTINCHOOSER))
2084 nField |= FLAGVAL_NOTINCHOOSER;
2085 continue;
2087 if (pNames[i].equals(FLAGNAME_NOTINFILEDIALOG))
2089 nField |= FLAGVAL_NOTINFILEDIALOG;
2090 continue;
2092 if (pNames[i].equals(FLAGNAME_NOTINSTALLED))
2094 nField |= FLAGVAL_NOTINSTALLED;
2095 continue;
2097 if (pNames[i].equals(FLAGNAME_OWN))
2099 nField |= FLAGVAL_OWN;
2100 continue;
2102 if (pNames[i].equals(FLAGNAME_PACKED))
2104 nField |= FLAGVAL_PACKED;
2105 continue;
2107 if (pNames[i].equals(FLAGNAME_PASSWORDTOMODIFY))
2109 nField |= FLAGVAL_PASSWORDTOMODIFY;
2110 continue;
2112 if (pNames[i].equals(FLAGNAME_PREFERRED))
2114 nField |= FLAGVAL_PREFERRED;
2115 continue;
2117 if (pNames[i].equals(FLAGNAME_STARTPRESENTATION))
2119 nField |= FLAGVAL_STARTPRESENTATION;
2120 continue;
2122 if (pNames[i].equals(FLAGNAME_READONLY))
2124 nField |= FLAGVAL_READONLY;
2125 continue;
2127 if (pNames[i].equals(FLAGNAME_SUPPORTSSELECTION))
2129 nField |= FLAGVAL_SUPPORTSSELECTION;
2130 continue;
2132 if (pNames[i].equals(FLAGNAME_TEMPLATE))
2134 nField |= FLAGVAL_TEMPLATE;
2135 continue;
2137 if (pNames[i].equals(FLAGNAME_TEMPLATEPATH))
2139 nField |= FLAGVAL_TEMPLATEPATH;
2140 continue;
2142 if (pNames[i].equals(FLAGNAME_USESOPTIONS))
2144 nField |= FLAGVAL_USESOPTIONS;
2145 continue;
2147 if (pNames[i].equals(FLAGNAME_COMBINED))
2149 nField |= FLAGVAL_COMBINED;
2150 continue;
2154 return nField;
2159 void FilterCache::impl_interpretDataVal4Type(const OUString& sValue,
2160 sal_Int32 nProp ,
2161 CacheItem& rItem )
2163 switch(nProp)
2165 // Preferred
2166 case 0: {
2167 if (sValue.toInt32() == 1)
2168 rItem[PROPNAME_PREFERRED] = css::uno::makeAny(sal_True);
2169 else
2170 rItem[PROPNAME_PREFERRED] = css::uno::makeAny(sal_False);
2172 break;
2173 // MediaType
2174 case 1: rItem[PROPNAME_MEDIATYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2175 break;
2176 // ClipboardFormat
2177 case 2: rItem[PROPNAME_CLIPBOARDFORMAT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2178 break;
2179 // URLPattern
2180 case 3: rItem[PROPNAME_URLPATTERN] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList();
2181 break;
2182 // Extensions
2183 case 4: rItem[PROPNAME_EXTENSIONS] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList();
2184 break;
2190 void FilterCache::impl_interpretDataVal4Filter(const OUString& sValue,
2191 sal_Int32 nProp ,
2192 CacheItem& rItem )
2194 switch(nProp)
2196 // Order
2197 case 0: {
2198 sal_Int32 nOrder = sValue.toInt32();
2199 if (nOrder > 0)
2201 OSL_FAIL("FilterCache::impl_interpretDataVal4Filter()\nCant move Order value from filter to type on demand!\n");
2202 _FILTER_CONFIG_LOG_2_("impl_interpretDataVal4Filter(%d, \"%s\") ... OK", (int)eType, _FILTER_CONFIG_TO_ASCII_(rItem).getStr())
2205 break;
2206 // Type
2207 case 1: rItem[PROPNAME_TYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2208 break;
2209 // DocumentService
2210 case 2: rItem[PROPNAME_DOCUMENTSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2211 break;
2212 // FilterService
2213 case 3: rItem[PROPNAME_FILTERSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2214 break;
2215 // Flags
2216 case 4: rItem[PROPNAME_FLAGS] <<= sValue.toInt32();
2217 break;
2218 // UserData
2219 case 5: rItem[PROPNAME_USERDATA] <<= impl_tokenizeString(sValue, (sal_Unicode)';').getAsConstList();
2220 break;
2221 // FileFormatVersion
2222 case 6: rItem[PROPNAME_FILEFORMATVERSION] <<= sValue.toInt32();
2223 break;
2224 // TemplateName
2225 case 7: rItem[PROPNAME_TEMPLATENAME] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2226 break;
2227 // [optional!] UIComponent
2228 case 8: rItem[PROPNAME_UICOMPONENT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
2229 break;
2233 /*-----------------------------------------------
2234 TODO work on a cache copy first, which can be flushed afterwards
2235 That would be useful to guarantee a consistent cache.
2236 -----------------------------------------------*/
2237 void FilterCache::impl_readOldFormat()
2238 throw(css::uno::Exception)
2240 // Attention: Opening/Reading of this old configuration format has to be handled gracefully.
2241 // Its optional and shouldnt disturb our normal work!
2242 // E.g. we must check, if the package exists ...
2244 css::uno::Reference< css::container::XNameAccess > xCfg;
2247 css::uno::Reference< css::uno::XInterface > xInt = impl_openConfig(E_PROVIDER_OLD);
2248 xCfg = css::uno::Reference< css::container::XNameAccess >(xInt, css::uno::UNO_QUERY_THROW);
2250 /* corrupt filter addon ? because it's external (optional) code .. we can ignore it. Addon wont work then ...
2251 but that seams to be acceptable.
2252 see #139088# for further information
2254 catch(const css::uno::Exception&)
2255 { return; }
2257 OUString TYPES_SET("Types");
2259 // May be there is no type set ...
2260 if (xCfg->hasByName(TYPES_SET))
2262 css::uno::Reference< css::container::XNameAccess > xSet;
2263 xCfg->getByName(TYPES_SET) >>= xSet;
2264 const css::uno::Sequence< OUString > lItems = xSet->getElementNames();
2265 const OUString* pItems = lItems.getConstArray();
2266 for (sal_Int32 i=0; i<lItems.getLength(); ++i)
2267 m_lTypes[pItems[i]] = impl_readOldItem(xSet, E_TYPE, pItems[i]);
2270 OUString FILTER_SET("Filters");
2271 // May be there is no filter set ...
2272 if (xCfg->hasByName(FILTER_SET))
2274 css::uno::Reference< css::container::XNameAccess > xSet;
2275 xCfg->getByName(FILTER_SET) >>= xSet;
2276 const css::uno::Sequence< OUString > lItems = xSet->getElementNames();
2277 const OUString* pItems = lItems.getConstArray();
2278 for (sal_Int32 i=0; i<lItems.getLength(); ++i)
2279 m_lFilters[pItems[i]] = impl_readOldItem(xSet, E_FILTER, pItems[i]);
2285 CacheItem FilterCache::impl_readOldItem(const css::uno::Reference< css::container::XNameAccess >& xSet ,
2286 EItemType eType,
2287 const OUString& sItem)
2288 throw(css::uno::Exception)
2290 css::uno::Reference< css::container::XNameAccess > xItem;
2291 xSet->getByName(sItem) >>= xItem;
2292 if (!xItem.is())
2293 throw css::uno::Exception("Cant read old item.", css::uno::Reference< css::uno::XInterface >());
2295 CacheItem aItem;
2296 aItem[PROPNAME_NAME] <<= sItem;
2298 // Installed flag ...
2299 // Isnt used any longer!
2301 // UIName
2302 impl_readPatchUINames(xItem, aItem);
2304 // Data
2305 OUString sData;
2306 OUStringList lData;
2307 xItem->getByName( "Data" ) >>= sData;
2308 lData = impl_tokenizeString(sData, (sal_Unicode)',');
2309 if (
2310 (sData.isEmpty()) ||
2311 (lData.size()<1 )
2314 throw css::uno::Exception( "Cant read old item property DATA.", css::uno::Reference< css::uno::XInterface >());
2317 sal_Int32 nProp = 0;
2318 for (OUStringList::const_iterator pProp = lData.begin();
2319 pProp != lData.end() ;
2320 ++pProp )
2322 const OUString& sProp = *pProp;
2323 switch(eType)
2325 case E_TYPE :
2326 impl_interpretDataVal4Type(sProp, nProp, aItem);
2327 break;
2329 case E_FILTER :
2330 impl_interpretDataVal4Filter(sProp, nProp, aItem);
2331 break;
2332 default: break;
2334 ++nProp;
2337 return aItem;
2342 OUStringList FilterCache::impl_tokenizeString(const OUString& sData ,
2343 sal_Unicode cSeparator)
2345 OUStringList lData ;
2346 sal_Int32 nToken = 0;
2349 OUString sToken = sData.getToken(0, cSeparator, nToken);
2350 lData.push_back(sToken);
2352 while(nToken >= 0);
2353 return lData;
2356 #if OSL_DEBUG_LEVEL > 0
2359 OUString FilterCache::impl_searchFrameLoaderForType(const OUString& sType) const
2361 CacheItemList::const_iterator pIt;
2362 for ( pIt = m_lFrameLoaders.begin();
2363 pIt != m_lFrameLoaders.end() ;
2364 ++pIt )
2366 const OUString& sItem = pIt->first;
2367 ::comphelper::SequenceAsHashMap lProps(pIt->second);
2368 OUStringList lTypes(lProps[PROPNAME_TYPES]);
2370 if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end())
2371 return sItem;
2374 return OUString();
2379 OUString FilterCache::impl_searchContentHandlerForType(const OUString& sType) const
2381 CacheItemList::const_iterator pIt;
2382 for ( pIt = m_lContentHandlers.begin();
2383 pIt != m_lContentHandlers.end() ;
2384 ++pIt )
2386 const OUString& sItem = pIt->first;
2387 ::comphelper::SequenceAsHashMap lProps(pIt->second);
2388 OUStringList lTypes(lProps[PROPNAME_TYPES]);
2390 if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end())
2391 return sItem;
2394 return OUString();
2396 #endif
2400 sal_Bool FilterCache::impl_isModuleInstalled(const OUString& sModule)
2402 css::uno::Reference< css::container::XNameAccess > xCfg;
2404 // SAFE ->
2405 ::osl::ResettableMutexGuard aLock(m_aLock);
2406 if (! m_xModuleCfg.is())
2408 m_xModuleCfg = css::uno::Reference< css::container::XNameAccess >(
2409 ::comphelper::ConfigurationHelper::openConfig(
2410 comphelper::getProcessComponentContext(),
2411 "org.openoffice.Setup/Office/Factories",
2412 ::comphelper::ConfigurationHelper::E_READONLY),
2413 css::uno::UNO_QUERY_THROW);
2416 xCfg = m_xModuleCfg;
2417 aLock.clear();
2418 // <- SAFE
2420 if (xCfg.is())
2421 return xCfg->hasByName(sModule);
2423 return sal_False;
2426 } // namespace config
2427 } // namespace filter
2429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */