LCOV - code coverage report
Current view: top level - filter/source/config/cache - basecontainer.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 145 183 79.2 %
Date: 2015-06-13 12:38:46 Functions: 19 23 82.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : #include "basecontainer.hxx"
      22             : #include "constant.hxx"
      23             : 
      24             : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
      25             : #include <com/sun/star/document/FilterConfigRefresh.hpp>
      26             : #include <com/sun/star/uno/Type.h>
      27             : #include <comphelper/enumhelper.hxx>
      28             : #include <comphelper/sequence.hxx>
      29             : #include <cppuhelper/supportsservice.hxx>
      30             : #include <osl/diagnose.h>
      31             : #include <rtl/instance.hxx>
      32             : 
      33             : #define LOAD_IMPLICIT
      34             : 
      35             : namespace filter{
      36             :     namespace config{
      37             : 
      38             : 
      39             : namespace
      40             : {
      41             :     typedef ::salhelper::SingletonRef< FilterCache > FilterCacheRefHold;
      42             :     /** @short  hold at least one filter cache instance alive and
      43             :                 prevent the office from unloading this cache if no filter
      44             :                 is currently used.*/
      45             :     struct thePerformanceOptimizer :
      46             :         public rtl::Static<FilterCacheRefHold, thePerformanceOptimizer>
      47             :     {
      48             :     };
      49             : }
      50             : 
      51      123045 : BaseContainer::BaseContainer()
      52             :     : BaseLock     (       )
      53             :     , m_rCache     (       )
      54             :     , m_pFlushCache(NULL   )
      55             :     , m_eType()
      56      123045 :     , m_lListener  (m_aLock)
      57             : {
      58      123045 :     m_rCache->load(FilterCache::E_CONTAINS_STANDARD);
      59      123045 :     thePerformanceOptimizer::get();
      60      123045 : }
      61             : 
      62             : 
      63             : 
      64      123045 : BaseContainer::~BaseContainer()
      65             : {
      66      123045 : }
      67             : 
      68             : 
      69             : 
      70      123045 : void BaseContainer::init(const css::uno::Reference< css::uno::XComponentContext >&     rxContext              ,
      71             :                          const OUString&                                        sImplementationName,
      72             :                          const css::uno::Sequence< OUString >&                  lServiceNames      ,
      73             :                                FilterCache::EItemType                                  eType              )
      74             : {
      75             :     // SAFE ->
      76      123045 :     ::osl::ResettableMutexGuard aLock(m_aLock);
      77             : 
      78      123045 :     m_sImplementationName = sImplementationName;
      79      123045 :     m_lServiceNames       = lServiceNames      ;
      80      123045 :     m_eType               = eType              ;
      81      123045 :     m_xRefreshBroadcaster = css::document::FilterConfigRefresh::create(rxContext);
      82             :     // <- SAFE
      83      123045 : }
      84             : 
      85             : 
      86             : 
      87       77944 : void BaseContainer::impl_loadOnDemand()
      88             : {
      89             : #ifdef LOAD_IMPLICIT
      90             :     // SAFE ->
      91       77944 :     ::osl::ResettableMutexGuard aLock(m_aLock);
      92             : 
      93             :     // A generic container needs all items of a set of our cache!
      94             :     // Of course it can block for a while, till the cache is really filled.
      95             :     // Note: dont load all sets supported by the cache here!
      96             : 
      97       77944 :     FilterCache::EFillState eRequiredState = FilterCache::E_CONTAINS_NOTHING;
      98       77944 :     switch(m_eType)
      99             :     {
     100             :         case FilterCache::E_TYPE :
     101        7989 :             eRequiredState = FilterCache::E_CONTAINS_TYPES;
     102        7989 :             break;
     103             : 
     104             :         case FilterCache::E_FILTER :
     105       19051 :             eRequiredState = FilterCache::E_CONTAINS_FILTERS;
     106       19051 :             break;
     107             : 
     108             :         case FilterCache::E_FRAMELOADER :
     109       29581 :             eRequiredState = FilterCache::E_CONTAINS_FRAMELOADERS;
     110       29581 :             break;
     111             : 
     112             :         case FilterCache::E_CONTENTHANDLER :
     113       21323 :             eRequiredState = FilterCache::E_CONTAINS_CONTENTHANDLERS;
     114       21323 :             break;
     115             :     }
     116             : 
     117       77944 :     m_rCache->load(eRequiredState);
     118             :     // <- SAFE
     119             : #endif
     120       77944 : }
     121             : 
     122             : 
     123             : 
     124           4 : void BaseContainer::impl_initFlushMode()
     125             :     throw (css::uno::RuntimeException)
     126             : {
     127             :     // SAFE ->
     128           4 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     129           4 :     if (!m_pFlushCache)
     130           1 :         m_pFlushCache = m_rCache->clone();
     131           4 :     if (!m_pFlushCache)
     132             :         throw css::uno::RuntimeException( "Can not create write copy of internal used cache on demand.",
     133           0 :                 static_cast< OWeakObject* >(this));
     134             :     // <- SAFE
     135           4 : }
     136             : 
     137             : 
     138             : 
     139       77944 : FilterCache* BaseContainer::impl_getWorkingCache() const
     140             : {
     141             :     // SAFE ->
     142       77944 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     143       77944 :     if (m_pFlushCache)
     144           8 :         return m_pFlushCache;
     145             :     else
     146       77936 :         return &(*m_rCache);
     147             :     // <- SAFE
     148             : }
     149             : 
     150             : 
     151             : 
     152           7 : OUString SAL_CALL BaseContainer::getImplementationName()
     153             :     throw (css::uno::RuntimeException, std::exception)
     154             : {
     155             :     // SAFE ->
     156           7 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     157           7 :     return m_sImplementationName;
     158             :     // <- SAFE
     159             : }
     160             : 
     161             : 
     162             : 
     163           0 : sal_Bool SAL_CALL BaseContainer::supportsService(const OUString& sServiceName)
     164             :     throw (css::uno::RuntimeException, std::exception)
     165             : {
     166           0 :     return cppu::supportsService(this, sServiceName);
     167             : }
     168             : 
     169           4 : css::uno::Sequence< OUString > SAL_CALL BaseContainer::getSupportedServiceNames()
     170             :     throw (css::uno::RuntimeException, std::exception)
     171             : {
     172             :     // SAFE ->
     173           4 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     174           4 :     return m_lServiceNames;
     175             :     // <- SAFE
     176             : }
     177             : 
     178             : 
     179             : 
     180           3 : void SAL_CALL BaseContainer::insertByName(const OUString& sItem ,
     181             :                                           const css::uno::Any&   aValue)
     182             :     throw (css::lang::IllegalArgumentException  ,
     183             :            css::container::ElementExistException,
     184             :            css::lang::WrappedTargetException    ,
     185             :            css::uno::RuntimeException, std::exception           )
     186             : {
     187           3 :     if (sItem.isEmpty())
     188             :         throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
     189             :             static_cast< css::container::XNameContainer* >(this),
     190           0 :             1);
     191             : 
     192           3 :     CacheItem aItem;
     193             :     try
     194             :     {
     195           3 :         aItem << aValue;
     196             :     }
     197           1 :     catch(const css::uno::Exception& ex)
     198             :     {
     199           1 :         throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
     200             :     }
     201             : 
     202           2 :     impl_loadOnDemand();
     203             : 
     204             :     // SAFE -> ----------------------------------
     205           4 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     206             : 
     207             :     // create write copy of used cache on demand ...
     208           2 :     impl_initFlushMode();
     209             : 
     210           2 :     FilterCache* pCache = impl_getWorkingCache();
     211           2 :     if (pCache->hasItem(m_eType, sItem))
     212           1 :         throw css::container::ElementExistException(OUString(), static_cast< css::container::XNameContainer* >(this));
     213           1 :     pCache->setItem(m_eType, sItem, aItem);
     214             : 
     215           4 :     aLock.clear();
     216             :     // <- SAFE ----------------------------------
     217           1 : }
     218             : 
     219             : 
     220             : 
     221           2 : void SAL_CALL BaseContainer::removeByName(const OUString& sItem)
     222             :     throw (css::container::NoSuchElementException,
     223             :            css::lang::WrappedTargetException     ,
     224             :            css::uno::RuntimeException, std::exception            )
     225             : {
     226           2 :     impl_loadOnDemand();
     227             : 
     228             :     // SAFE -> ----------------------------------
     229           2 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     230             : 
     231             :     // create write copy of used cache on demand ...
     232           2 :     impl_initFlushMode();
     233             : 
     234           2 :     FilterCache* pCache = impl_getWorkingCache();
     235           2 :     pCache->removeItem(m_eType, sItem); // throw exceptions automatically
     236             : 
     237           2 :     aLock.clear();
     238             :     // <- SAFE ----------------------------------
     239           1 : }
     240             : 
     241             : 
     242             : 
     243           0 : void SAL_CALL BaseContainer::replaceByName(const OUString& sItem ,
     244             :                                            const css::uno::Any&   aValue)
     245             :     throw (css::lang::IllegalArgumentException   ,
     246             :            css::container::NoSuchElementException,
     247             :            css::lang::WrappedTargetException     ,
     248             :            css::uno::RuntimeException, std::exception            )
     249             : {
     250           0 :     if (sItem.isEmpty())
     251             :         throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
     252             :             static_cast< css::container::XNameContainer* >(this),
     253           0 :             1);
     254             : 
     255           0 :     CacheItem aItem;
     256             :     try
     257             :     {
     258           0 :         aItem << aValue;
     259             :     }
     260           0 :     catch(const css::uno::Exception& ex)
     261             :     {
     262           0 :         throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
     263             :     }
     264             : 
     265           0 :     impl_loadOnDemand();
     266             : 
     267             :     // SAFE -> ----------------------------------
     268           0 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     269             : 
     270             :     // create write copy of used cache on demand ...
     271           0 :     impl_initFlushMode();
     272             : 
     273           0 :     FilterCache* pCache = impl_getWorkingCache();
     274           0 :     if (!pCache->hasItem(m_eType, sItem))
     275           0 :         throw css::container::NoSuchElementException(OUString(), static_cast< css::container::XNameContainer* >(this));
     276           0 :     pCache->setItem(m_eType, sItem, aItem);
     277             : 
     278           0 :     aLock.clear();
     279             :     // <- SAFE ----------------------------------
     280           0 : }
     281             : 
     282             : 
     283             : 
     284       25639 : css::uno::Any SAL_CALL BaseContainer::getByName(const OUString& sItem)
     285             :     throw (css::container::NoSuchElementException,
     286             :            css::lang::WrappedTargetException     ,
     287             :            css::uno::RuntimeException, std::exception            )
     288             : {
     289       25639 :     if (sItem.isEmpty())
     290             :         throw css::container::NoSuchElementException( "An empty item can't be part of this cache!",
     291        1708 :                 static_cast< css::container::XNameAccess* >(this));
     292             : 
     293       23931 :     css::uno::Any aValue;
     294             : 
     295       23931 :     impl_loadOnDemand();
     296             : 
     297             :     // SAFE ->
     298       47862 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     299             : 
     300       47862 :     CacheItem aItem;
     301             :     try
     302             :     {
     303       23931 :         FilterCache* pCache = impl_getWorkingCache();
     304       23931 :         aItem = pCache->getItem(m_eType, sItem);
     305       23916 :         pCache->addStatePropsToItem(m_eType, sItem, aItem); // add implicit props "Finalized"/"Mandatory"
     306             :     }
     307          15 :     catch(const css::container::NoSuchElementException&)
     308             :     {
     309          15 :         throw;
     310             :     }
     311           0 :     catch(const css::uno::Exception&)
     312             :     {
     313             :         // TODO invalid cache!? How should it be handled right?
     314           0 :         aItem.clear();
     315             :     }
     316             : 
     317       23916 :     aValue <<= aItem.getAsPackedPropertyValueList();
     318             :     // <- SAFE
     319             : 
     320       47832 :     return aValue;
     321             : }
     322             : 
     323             : 
     324             : 
     325          26 : css::uno::Sequence< OUString > SAL_CALL BaseContainer::getElementNames()
     326             :     throw (css::uno::RuntimeException, std::exception)
     327             : {
     328          26 :     css::uno::Sequence< OUString > lNames;
     329             : 
     330          26 :     impl_loadOnDemand();
     331             : 
     332             :     // SAFE ->
     333          52 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     334             : 
     335             :     try
     336             :     {
     337          26 :         FilterCache* pCache = impl_getWorkingCache();
     338          26 :         OUStringList lKeys  = pCache->getItemNames(m_eType);
     339          26 :         lNames = comphelper::containerToSequence(lKeys);
     340             :     }
     341           0 :     catch(const css::uno::Exception&)
     342             :     {
     343             :         // invalid cache!?
     344           0 :         lNames.realloc(0);
     345             :     }
     346             : 
     347             :     // <- SAFE
     348             : 
     349          52 :     return lNames;
     350             : }
     351             : 
     352             : 
     353             : 
     354        2858 : sal_Bool SAL_CALL BaseContainer::hasByName(const OUString& sItem)
     355             :     throw (css::uno::RuntimeException, std::exception)
     356             : {
     357        2858 :     bool bHasOne = false;
     358             : 
     359        2858 :     impl_loadOnDemand();
     360             : 
     361             :     // SAFE ->
     362        2858 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     363             : 
     364             :     try
     365             :     {
     366        2858 :         FilterCache* pCache = impl_getWorkingCache();
     367        2858 :         bHasOne = pCache->hasItem(m_eType, sItem);
     368             :     }
     369           0 :     catch(const css::uno::Exception&)
     370             :     {
     371             :         // invalid cache!?
     372           0 :         bHasOne = false;
     373             :     }
     374             : 
     375             :     // <- SAFE
     376             : 
     377        2858 :     return bHasOne;
     378             : }
     379             : 
     380             : 
     381             : 
     382           3 : css::uno::Type SAL_CALL BaseContainer::getElementType()
     383             :     throw (css::uno::RuntimeException, std::exception)
     384             : {
     385             :     // no lock necessary - because the type of our items
     386             :     // is fix! no internal call or member needed ...
     387           3 :     return cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get();
     388             : }
     389             : 
     390             : 
     391             : 
     392           3 : sal_Bool SAL_CALL BaseContainer::hasElements()
     393             :     throw (css::uno::RuntimeException, std::exception)
     394             : {
     395           3 :     bool bHasSome = false;
     396             : 
     397           3 :     impl_loadOnDemand();
     398             : 
     399             :     // SAFE ->
     400           3 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     401             : 
     402             :     try
     403             :     {
     404           3 :         FilterCache* pCache = impl_getWorkingCache();
     405           3 :         bHasSome = pCache->hasItems(m_eType);
     406             :     }
     407           0 :     catch(const css::uno::Exception&)
     408             :     {
     409             :         // invalid cache?!
     410           0 :         bHasSome = false;
     411             :     }
     412             : 
     413             :     // <- SAFE
     414             : 
     415           3 :     return bHasSome;
     416             : }
     417             : 
     418             : 
     419             : 
     420           0 : css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const OUString& /* sQuery */ )
     421             :     throw (css::uno::RuntimeException, std::exception)
     422             : {
     423             :     OSL_FAIL("not pure virtual ... but not really implemented .-)");
     424             : 
     425           0 :     ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, css::uno::Sequence< OUString >());
     426           0 :     return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
     427             : }
     428             : 
     429             : 
     430             : 
     431       51122 : css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
     432             :     throw (css::uno::RuntimeException, std::exception)
     433             : {
     434       51122 :     css::uno::Reference< css::container::XEnumeration > xEnum;
     435      102244 :     OUStringList                                        lKeys;
     436             : 
     437       51122 :     impl_loadOnDemand();
     438             : 
     439             :     // SAFE ->
     440      102244 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     441             : 
     442             :     try
     443             :     {
     444             :         // convert the given properties first to our internal representation
     445       51122 :         CacheItem lProps;
     446       51122 :         lProps << lProperties;
     447             : 
     448             :         // search the key names of all items, where its properties match
     449             :         // the given ones in its minimum
     450       51122 :         FilterCache* pCache = impl_getWorkingCache();
     451       51122 :         lKeys = pCache->getMatchingItemsByProps(m_eType, lProps);
     452             :     }
     453           0 :     catch(const css::uno::Exception&)
     454             :     {
     455             :         // invalid cache, internal failure, wrong conversion ...!?
     456             :         // doesn't matter
     457           0 :         lKeys.clear();
     458             :     }
     459             : 
     460             :     // <- SAFE
     461             : 
     462             :     // create a specialized enumeration helper, which
     463             :     // provides the collected information outside.
     464             :     // It hold a reference to us ... and call our container interface directly.
     465             :     // be aware of some direct callbacks if it will be created :-)
     466             : 
     467             :     /* Note: Its not allowed to return NULL. Because an empty enumeration
     468             :              transport the same information but make no trouble outside.
     469             :              Further its easier to work directly with the return value
     470             :              instaed of checking of NULL returns! */
     471             : 
     472      102244 :     css::uno::Sequence< OUString > lSubSet = comphelper::containerToSequence(lKeys);
     473       51122 :     ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, lSubSet);
     474      102244 :     return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
     475             : }
     476             : 
     477             : 
     478             : 
     479           1 : void SAL_CALL BaseContainer::flush()
     480             :     throw (css::uno::RuntimeException, std::exception)
     481             : {
     482             :     // SAFE ->
     483           1 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     484             : 
     485           1 :     if (!m_pFlushCache)
     486             :         throw css::lang::WrappedTargetRuntimeException(
     487             :                 "Can not guarantee cache consistency. Special flush container does not exists!",
     488             :                 static_cast< OWeakObject* >(this),
     489           0 :                 css::uno::Any());
     490             : 
     491             :     try
     492             :     {
     493           1 :         m_pFlushCache->flush();
     494             :         // Take over all changes into the global cache and
     495             :         // forget the clone.
     496             :         /* TODO
     497             :             -think about me
     498             :                 If the global cache gets this information via listener,
     499             :                 we should remove this method!
     500             :         */
     501           1 :         m_rCache->takeOver(*m_pFlushCache);
     502             :     }
     503           0 :     catch(const css::uno::Exception& ex)
     504             :     {
     505             :         // Dont remove the clone. May be the outside
     506             :         // user wish to repair it now and calls flush()
     507             :         // later again ...
     508             : 
     509             :         throw css::lang::WrappedTargetRuntimeException( "Flush rejected by internal container.",
     510             :                 static_cast< OWeakObject* >(this),
     511           0 :                 css::uno::makeAny(ex));
     512             :     }
     513             : 
     514           1 :     delete m_pFlushCache;
     515           1 :     m_pFlushCache = NULL;
     516             : 
     517           2 :     css::uno::Reference< css::util::XRefreshable > xRefreshBroadcaster = m_xRefreshBroadcaster;
     518             : 
     519           1 :     aLock.clear();
     520             :     // <- SAFE
     521             : 
     522           1 :     if (xRefreshBroadcaster.is())
     523           1 :         xRefreshBroadcaster->refresh();
     524             : 
     525             :     // notify listener outside the lock!
     526             :     // The used listener helper lives if we live
     527             :     // and is threadsafe by itself.
     528             :     // Further its not a good idea to hold the own lock
     529             :     // if an outside object is called :-)
     530           2 :     css::lang::EventObject             aSource    (static_cast< css::util::XFlushable* >(this));
     531           1 :     ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(cppu::UnoType<css::util::XFlushListener>::get());
     532           1 :     if (pContainer)
     533             :     {
     534           1 :         ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
     535           3 :         while (pIterator.hasMoreElements())
     536             :         {
     537             :             try
     538             :             {
     539             :                 // ... this pointer can be interesting to find out, where will be called as listener
     540             :                 // Dont optimize it to a direct iterator cast :-)
     541           1 :                 css::util::XFlushListener* pListener = static_cast<css::util::XFlushListener*>(pIterator.next());
     542           1 :                 pListener->flushed(aSource);
     543             :             }
     544           0 :             catch(const css::uno::Exception&)
     545             :             {
     546             :                 // ignore any "damaged" flush listener!
     547             :                 // May its remote reference is broken ...
     548           0 :                 pIterator.remove();
     549             :             }
     550           1 :         }
     551           1 :     }
     552           1 : }
     553             : 
     554             : 
     555             : 
     556           2 : void SAL_CALL BaseContainer::addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
     557             :     throw (css::uno::RuntimeException, std::exception)
     558             : {
     559             :     // no locks necessary
     560             :     // used helper lives if we live and is threadsafe by itself ...
     561           2 :     m_lListener.addInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener);
     562           2 : }
     563             : 
     564             : 
     565             : 
     566           1 : void SAL_CALL BaseContainer::removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
     567             :     throw (css::uno::RuntimeException, std::exception)
     568             : {
     569             :     // no locks necessary
     570             :     // used helper lives if we live and is threadsafe by itself ...
     571           1 :     m_lListener.removeInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener);
     572           1 : }
     573             : 
     574             :     } // namespace config
     575             : } // namespace filter
     576             : 
     577             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11