LCOV - code coverage report
Current view: top level - filter/source/config/cache - basecontainer.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 143 184 77.7 %
Date: 2014-11-03 Functions: 18 23 78.3 %
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 <cppuhelper/supportsservice.hxx>
      29             : #include <osl/diagnose.h>
      30             : #include <rtl/instance.hxx>
      31             : 
      32             : #define LOAD_IMPLICIT
      33             : 
      34             : namespace filter{
      35             :     namespace config{
      36             : 
      37             : 
      38             : namespace
      39             : {
      40             :     typedef ::salhelper::SingletonRef< FilterCache > FilterCacheRefHold;
      41             :     /** @short  hold at least one filter cache instance alive and
      42             :                 prevent the office from unloading this cache if no filter
      43             :                 is currently used.*/
      44             :     struct thePerformanceOptimizer :
      45             :         public rtl::Static<FilterCacheRefHold, thePerformanceOptimizer>
      46             :     {
      47             :     };
      48             : }
      49             : 
      50      219894 : BaseContainer::BaseContainer()
      51             :     : BaseLock     (       )
      52             :     , m_rCache     (       )
      53             :     , m_pFlushCache(NULL   )
      54             :     , m_eType()
      55      219894 :     , m_lListener  (m_aLock)
      56             : {
      57      219894 :     m_rCache->load(FilterCache::E_CONTAINS_STANDARD);
      58      219894 :     thePerformanceOptimizer::get();
      59      219894 : }
      60             : 
      61             : 
      62             : 
      63      219894 : BaseContainer::~BaseContainer()
      64             : {
      65      219894 : }
      66             : 
      67             : 
      68             : 
      69      219894 : void BaseContainer::init(const css::uno::Reference< css::uno::XComponentContext >&     rxContext              ,
      70             :                          const OUString&                                        sImplementationName,
      71             :                          const css::uno::Sequence< OUString >&                  lServiceNames      ,
      72             :                                FilterCache::EItemType                                  eType              )
      73             : {
      74             :     // SAFE ->
      75      219894 :     ::osl::ResettableMutexGuard aLock(m_aLock);
      76             : 
      77      219894 :     m_sImplementationName = sImplementationName;
      78      219894 :     m_lServiceNames       = lServiceNames      ;
      79      219894 :     m_eType               = eType              ;
      80      219894 :     m_xRefreshBroadcaster = css::document::FilterConfigRefresh::create(rxContext);
      81             :     // <- SAFE
      82      219894 : }
      83             : 
      84             : 
      85             : 
      86      137466 : void BaseContainer::impl_loadOnDemand()
      87             : {
      88             : #ifdef LOAD_IMPLICIT
      89             :     // SAFE ->
      90      137466 :     ::osl::ResettableMutexGuard aLock(m_aLock);
      91             : 
      92             :     // A generic container needs all items of a set of our cache!
      93             :     // Of course it can block for a while, till the cache is really filled.
      94             :     // Note: dont load all sets supported by the cache here!
      95             : 
      96      137466 :     FilterCache::EFillState eRequiredState = FilterCache::E_CONTAINS_NOTHING;
      97      137466 :     switch(m_eType)
      98             :     {
      99             :         case FilterCache::E_TYPE :
     100       11240 :             eRequiredState = FilterCache::E_CONTAINS_TYPES;
     101       11240 :             break;
     102             : 
     103             :         case FilterCache::E_FILTER :
     104       33532 :             eRequiredState = FilterCache::E_CONTAINS_FILTERS;
     105       33532 :             break;
     106             : 
     107             :         case FilterCache::E_FRAMELOADER :
     108       53380 :             eRequiredState = FilterCache::E_CONTAINS_FRAMELOADERS;
     109       53380 :             break;
     110             : 
     111             :         case FilterCache::E_CONTENTHANDLER :
     112       39314 :             eRequiredState = FilterCache::E_CONTAINS_CONTENTHANDLERS;
     113       39314 :             break;
     114             :     }
     115             : 
     116      137466 :     m_rCache->load(eRequiredState);
     117             :     // <- SAFE
     118             : #endif
     119      137466 : }
     120             : 
     121             : 
     122             : 
     123           8 : void BaseContainer::impl_initFlushMode()
     124             :     throw (css::uno::RuntimeException)
     125             : {
     126             :     // SAFE ->
     127           8 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     128           8 :     if (!m_pFlushCache)
     129           2 :         m_pFlushCache = m_rCache->clone();
     130           8 :     if (!m_pFlushCache)
     131             :         throw css::uno::RuntimeException( "Cant create write copy of internal used cache on demand.",
     132           0 :                 static_cast< OWeakObject* >(this));
     133             :     // <- SAFE
     134           8 : }
     135             : 
     136             : 
     137             : 
     138      137466 : FilterCache* BaseContainer::impl_getWorkingCache() const
     139             : {
     140             :     // SAFE ->
     141      137466 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     142      137466 :     if (m_pFlushCache)
     143          16 :         return m_pFlushCache;
     144             :     else
     145      137450 :         return &(*m_rCache);
     146             :     // <- SAFE
     147             : }
     148             : 
     149             : 
     150             : 
     151           6 : OUString SAL_CALL BaseContainer::getImplementationName()
     152             :     throw (css::uno::RuntimeException, std::exception)
     153             : {
     154             :     // SAFE ->
     155           6 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     156           6 :     return m_sImplementationName;
     157             :     // <- SAFE
     158             : }
     159             : 
     160             : 
     161             : 
     162           0 : sal_Bool SAL_CALL BaseContainer::supportsService(const OUString& sServiceName)
     163             :     throw (css::uno::RuntimeException, std::exception)
     164             : {
     165           0 :     return cppu::supportsService(this, sServiceName);
     166             : }
     167             : 
     168           0 : css::uno::Sequence< OUString > SAL_CALL BaseContainer::getSupportedServiceNames()
     169             :     throw (css::uno::RuntimeException, std::exception)
     170             : {
     171             :     // SAFE ->
     172           0 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     173           0 :     return m_lServiceNames;
     174             :     // <- SAFE
     175             : }
     176             : 
     177             : 
     178             : 
     179           6 : void SAL_CALL BaseContainer::insertByName(const OUString& sItem ,
     180             :                                           const css::uno::Any&   aValue)
     181             :     throw (css::lang::IllegalArgumentException  ,
     182             :            css::container::ElementExistException,
     183             :            css::lang::WrappedTargetException    ,
     184             :            css::uno::RuntimeException, std::exception           )
     185             : {
     186           6 :     if (sItem.isEmpty())
     187             :         throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
     188             :             static_cast< css::container::XNameContainer* >(this),
     189           0 :             1);
     190             : 
     191           6 :     CacheItem aItem;
     192             :     try
     193             :     {
     194           6 :         aItem << aValue;
     195             :     }
     196           2 :     catch(const css::uno::Exception& ex)
     197             :     {
     198           2 :         throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
     199             :     }
     200             : 
     201           4 :     impl_loadOnDemand();
     202             : 
     203             :     // SAFE -> ----------------------------------
     204           8 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     205             : 
     206             :     // create write copy of used cache on demand ...
     207           4 :     impl_initFlushMode();
     208             : 
     209           4 :     FilterCache* pCache = impl_getWorkingCache();
     210           4 :     if (pCache->hasItem(m_eType, sItem))
     211           2 :         throw css::container::ElementExistException(OUString(), static_cast< css::container::XNameContainer* >(this));
     212           2 :     pCache->setItem(m_eType, sItem, aItem);
     213             : 
     214           8 :     aLock.clear();
     215             :     // <- SAFE ----------------------------------
     216           2 : }
     217             : 
     218             : 
     219             : 
     220           4 : void SAL_CALL BaseContainer::removeByName(const OUString& sItem)
     221             :     throw (css::container::NoSuchElementException,
     222             :            css::lang::WrappedTargetException     ,
     223             :            css::uno::RuntimeException, std::exception            )
     224             : {
     225           4 :     impl_loadOnDemand();
     226             : 
     227             :     // SAFE -> ----------------------------------
     228           4 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     229             : 
     230             :     // create write copy of used cache on demand ...
     231           4 :     impl_initFlushMode();
     232             : 
     233           4 :     FilterCache* pCache = impl_getWorkingCache();
     234           4 :     pCache->removeItem(m_eType, sItem); // throw exceptions automatically
     235             : 
     236           4 :     aLock.clear();
     237             :     // <- SAFE ----------------------------------
     238           2 : }
     239             : 
     240             : 
     241             : 
     242           0 : void SAL_CALL BaseContainer::replaceByName(const OUString& sItem ,
     243             :                                            const css::uno::Any&   aValue)
     244             :     throw (css::lang::IllegalArgumentException   ,
     245             :            css::container::NoSuchElementException,
     246             :            css::lang::WrappedTargetException     ,
     247             :            css::uno::RuntimeException, std::exception            )
     248             : {
     249           0 :     if (sItem.isEmpty())
     250             :         throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
     251             :             static_cast< css::container::XNameContainer* >(this),
     252           0 :             1);
     253             : 
     254           0 :     CacheItem aItem;
     255             :     try
     256             :     {
     257           0 :         aItem << aValue;
     258             :     }
     259           0 :     catch(const css::uno::Exception& ex)
     260             :     {
     261           0 :         throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
     262             :     }
     263             : 
     264           0 :     impl_loadOnDemand();
     265             : 
     266             :     // SAFE -> ----------------------------------
     267           0 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     268             : 
     269             :     // create write copy of used cache on demand ...
     270           0 :     impl_initFlushMode();
     271             : 
     272           0 :     FilterCache* pCache = impl_getWorkingCache();
     273           0 :     if (!pCache->hasItem(m_eType, sItem))
     274           0 :         throw css::container::NoSuchElementException(OUString(), static_cast< css::container::XNameContainer* >(this));
     275           0 :     pCache->setItem(m_eType, sItem, aItem);
     276             : 
     277           0 :     aLock.clear();
     278             :     // <- SAFE ----------------------------------
     279           0 : }
     280             : 
     281             : 
     282             : 
     283       41956 : css::uno::Any SAL_CALL BaseContainer::getByName(const OUString& sItem)
     284             :     throw (css::container::NoSuchElementException,
     285             :            css::lang::WrappedTargetException     ,
     286             :            css::uno::RuntimeException, std::exception            )
     287             : {
     288       41956 :     if (sItem.isEmpty())
     289             :         throw css::container::NoSuchElementException( "An empty item can't be part of this cache!",
     290        3220 :                 static_cast< css::container::XNameAccess* >(this));
     291             : 
     292       38736 :     css::uno::Any aValue;
     293             : 
     294       38736 :     impl_loadOnDemand();
     295             : 
     296             :     // SAFE ->
     297       77472 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     298             : 
     299       77472 :     CacheItem aItem;
     300             :     try
     301             :     {
     302       38736 :         FilterCache* pCache = impl_getWorkingCache();
     303       38736 :         aItem = pCache->getItem(m_eType, sItem);
     304       38704 :         pCache->addStatePropsToItem(m_eType, sItem, aItem); // add implicit props "Finalized"/"Mandatory"
     305             :     }
     306          64 :     catch(const css::container::NoSuchElementException&)
     307             :     {
     308          32 :         throw;
     309             :     }
     310           0 :     catch(const css::uno::Exception&)
     311             :     {
     312             :         // TODO invalid cache!? How should it be handled right?
     313           0 :         aItem.clear();
     314             :     }
     315             : 
     316       38704 :     aValue <<= aItem.getAsPackedPropertyValueList();
     317             :     // <- SAFE
     318             : 
     319       77408 :     return aValue;
     320             : }
     321             : 
     322             : 
     323             : 
     324          30 : css::uno::Sequence< OUString > SAL_CALL BaseContainer::getElementNames()
     325             :     throw (css::uno::RuntimeException, std::exception)
     326             : {
     327          30 :     css::uno::Sequence< OUString > lNames;
     328             : 
     329          30 :     impl_loadOnDemand();
     330             : 
     331             :     // SAFE ->
     332          60 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     333             : 
     334             :     try
     335             :     {
     336          30 :         FilterCache* pCache = impl_getWorkingCache();
     337          30 :         OUStringList lKeys  = pCache->getItemNames(m_eType);
     338          30 :         lKeys >> lNames;
     339             :     }
     340           0 :     catch(const css::uno::Exception&)
     341             :     {
     342             :         // invalid cache!?
     343           0 :         lNames.realloc(0);
     344             :     }
     345             : 
     346             :     // <- SAFE
     347             : 
     348          60 :     return lNames;
     349             : }
     350             : 
     351             : 
     352             : 
     353        4758 : sal_Bool SAL_CALL BaseContainer::hasByName(const OUString& sItem)
     354             :     throw (css::uno::RuntimeException, std::exception)
     355             : {
     356        4758 :     bool bHasOne = false;
     357             : 
     358        4758 :     impl_loadOnDemand();
     359             : 
     360             :     // SAFE ->
     361        4758 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     362             : 
     363             :     try
     364             :     {
     365        4758 :         FilterCache* pCache = impl_getWorkingCache();
     366        4758 :         bHasOne = pCache->hasItem(m_eType, sItem);
     367             :     }
     368           0 :     catch(const css::uno::Exception&)
     369             :     {
     370             :         // invalid cache!?
     371           0 :         bHasOne = false;
     372             :     }
     373             : 
     374             :     // <- SAFE
     375             : 
     376        4758 :     return bHasOne;
     377             : }
     378             : 
     379             : 
     380             : 
     381           6 : css::uno::Type SAL_CALL BaseContainer::getElementType()
     382             :     throw (css::uno::RuntimeException, std::exception)
     383             : {
     384             :     // no lock necessary - because the type of our items
     385             :     // is fix! no internal call or member needed ...
     386           6 :     return ::getCppuType(static_cast< css::uno::Sequence< css::beans::PropertyValue >* >(NULL));
     387             : }
     388             : 
     389             : 
     390             : 
     391           6 : sal_Bool SAL_CALL BaseContainer::hasElements()
     392             :     throw (css::uno::RuntimeException, std::exception)
     393             : {
     394           6 :     bool bHasSome = false;
     395             : 
     396           6 :     impl_loadOnDemand();
     397             : 
     398             :     // SAFE ->
     399           6 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     400             : 
     401             :     try
     402             :     {
     403           6 :         FilterCache* pCache = impl_getWorkingCache();
     404           6 :         bHasSome = pCache->hasItems(m_eType);
     405             :     }
     406           0 :     catch(const css::uno::Exception&)
     407             :     {
     408             :         // invalid cache?!
     409           0 :         bHasSome = false;
     410             :     }
     411             : 
     412             :     // <- SAFE
     413             : 
     414           6 :     return bHasSome;
     415             : }
     416             : 
     417             : 
     418             : 
     419           0 : css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const OUString& /* sQuery */ )
     420             :     throw (css::uno::RuntimeException, std::exception)
     421             : {
     422             :     OSL_FAIL("not pure virtual ... but not really implemented .-)");
     423             : 
     424           0 :     ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, css::uno::Sequence< OUString >());
     425           0 :     return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
     426             : }
     427             : 
     428             : 
     429             : 
     430       93928 : css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
     431             :     throw (css::uno::RuntimeException, std::exception)
     432             : {
     433       93928 :     css::uno::Reference< css::container::XEnumeration > xEnum;
     434      187856 :     OUStringList                                        lKeys;
     435             : 
     436       93928 :     impl_loadOnDemand();
     437             : 
     438             :     // SAFE ->
     439      187856 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     440             : 
     441             :     try
     442             :     {
     443             :         // convert the given properties first to our internal representation
     444       93928 :         CacheItem lProps;
     445       93928 :         lProps << lProperties;
     446             : 
     447             :         // search the key names of all items, where its properties match
     448             :         // the given ones in its minimum
     449       93928 :         FilterCache* pCache = impl_getWorkingCache();
     450       93928 :         lKeys = pCache->getMatchingItemsByProps(m_eType, lProps);
     451             :     }
     452           0 :     catch(const css::uno::Exception&)
     453             :     {
     454             :         // invalid cache, internal failure, wrong conversion ...!?
     455             :         // doesn't matter
     456           0 :         lKeys.clear();
     457             :     }
     458             : 
     459             :     // <- SAFE
     460             : 
     461             :     // create a specialized enumeration helper, which
     462             :     // provides the collected information outside.
     463             :     // It hold a reference to us ... and call our container interface directly.
     464             :     // be aware of some direct callbacks if it will be created :-)
     465             : 
     466             :     /* Note: Its not allowed to return NULL. Because an empty enumeration
     467             :              transport the same information but make no trouble outside.
     468             :              Further its easier to work directly with the return value
     469             :              instaed of checking of NULL returns! */
     470             : 
     471      187856 :     css::uno::Sequence< OUString > lSubSet;
     472       93928 :     lKeys >> lSubSet;
     473       93928 :     ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, lSubSet);
     474      187856 :     return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
     475             : }
     476             : 
     477             : 
     478             : 
     479           2 : void SAL_CALL BaseContainer::flush()
     480             :     throw (css::uno::RuntimeException, std::exception)
     481             : {
     482             :     // SAFE ->
     483           2 :     ::osl::ResettableMutexGuard aLock(m_aLock);
     484             : 
     485           2 :     if (!m_pFlushCache)
     486             :         throw css::lang::WrappedTargetRuntimeException(
     487             :                 "Cant guarantee cache consistency. Special flush container does not exists!",
     488             :                 static_cast< OWeakObject* >(this),
     489           0 :                 css::uno::Any());
     490             : 
     491             :     try
     492             :     {
     493           2 :         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           2 :         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           2 :     delete m_pFlushCache;
     515           2 :     m_pFlushCache = NULL;
     516             : 
     517           4 :     css::uno::Reference< css::util::XRefreshable > xRefreshBroadcaster = m_xRefreshBroadcaster;
     518             : 
     519           2 :     aLock.clear();
     520             :     // <- SAFE
     521             : 
     522           2 :     if (xRefreshBroadcaster.is())
     523           2 :         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           4 :     css::lang::EventObject             aSource    (static_cast< css::util::XFlushable* >(this));
     531           2 :     ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(cppu::UnoType<css::util::XFlushListener>::get());
     532           2 :     if (pContainer)
     533             :     {
     534           2 :         ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
     535           6 :         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           2 :                 css::util::XFlushListener* pListener = static_cast<css::util::XFlushListener*>(pIterator.next());
     542           2 :                 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           2 :         }
     551           2 :     }
     552           2 : }
     553             : 
     554             : 
     555             : 
     556           4 : 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           4 :     m_lListener.addInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener);
     562           4 : }
     563             : 
     564             : 
     565             : 
     566           2 : 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           2 :     m_lListener.removeInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener);
     572           2 : }
     573             : 
     574             :     } // namespace config
     575             : } // namespace filter
     576             : 
     577             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10