bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / config / cache / basecontainer.cxx
blobebbb7f2b38d8a0692daba813468f8794384a7468
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 "basecontainer.hxx"
22 #include "constant.hxx"
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 <osl/diagnose.h>
29 #include <rtl/instance.hxx>
32 #define LOAD_IMPLICIT
34 namespace filter{
35 namespace config{
38 namespace
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>
50 BaseContainer::BaseContainer()
51 : BaseLock ( )
52 , m_rCache ( )
53 , m_pFlushCache(NULL )
54 , m_eType()
55 , m_lListener (m_aLock)
57 m_rCache->load(FilterCache::E_CONTAINS_STANDARD);
58 thePerformanceOptimizer::get();
63 BaseContainer::~BaseContainer()
69 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 )
74 // SAFE ->
75 ::osl::ResettableMutexGuard aLock(m_aLock);
77 m_sImplementationName = sImplementationName;
78 m_lServiceNames = lServiceNames ;
79 m_eType = eType ;
80 m_xRefreshBroadcaster = css::document::FilterConfigRefresh::create(rxContext);
81 // <- SAFE
86 void BaseContainer::impl_loadOnDemand()
88 #ifdef LOAD_IMPLICIT
89 // SAFE ->
90 ::osl::ResettableMutexGuard aLock(m_aLock);
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 realy filled.
94 // Note: dont load all sets supported by the cache here!
96 FilterCache::EFillState eRequiredState = FilterCache::E_CONTAINS_NOTHING;
97 switch(m_eType)
99 case FilterCache::E_TYPE :
100 eRequiredState = FilterCache::E_CONTAINS_TYPES;
101 break;
103 case FilterCache::E_FILTER :
104 eRequiredState = FilterCache::E_CONTAINS_FILTERS;
105 break;
107 case FilterCache::E_DETECTSERVICE :
108 eRequiredState = FilterCache::E_CONTAINS_DETECTSERVICES;
109 break;
111 case FilterCache::E_FRAMELOADER :
112 eRequiredState = FilterCache::E_CONTAINS_FRAMELOADERS;
113 break;
115 case FilterCache::E_CONTENTHANDLER :
116 eRequiredState = FilterCache::E_CONTAINS_CONTENTHANDLERS;
117 break;
120 m_rCache->load(eRequiredState);
121 // <- SAFE
122 #endif
127 void BaseContainer::impl_initFlushMode()
128 throw (css::uno::RuntimeException)
130 // SAFE ->
131 ::osl::ResettableMutexGuard aLock(m_aLock);
132 if (!m_pFlushCache)
133 m_pFlushCache = m_rCache->clone();
134 if (!m_pFlushCache)
135 throw css::uno::RuntimeException( "Cant create write copy of internal used cache on demand.",
136 dynamic_cast< css::container::XNameAccess* >(this));
137 // <- SAFE
142 FilterCache* BaseContainer::impl_getWorkingCache() const
144 // SAFE ->
145 ::osl::ResettableMutexGuard aLock(m_aLock);
146 if (m_pFlushCache)
147 return m_pFlushCache;
148 else
149 return &(*m_rCache);
150 // <- SAFE
155 OUString SAL_CALL BaseContainer::getImplementationName()
156 throw (css::uno::RuntimeException)
158 // SAFE ->
159 ::osl::ResettableMutexGuard aLock(m_aLock);
160 return m_sImplementationName;
161 // <- SAFE
166 sal_Bool SAL_CALL BaseContainer::supportsService(const OUString& sServiceName)
167 throw (css::uno::RuntimeException)
169 // SAFE ->
170 ::osl::ResettableMutexGuard aLock(m_aLock);
172 sal_Int32 c = m_lServiceNames.getLength();
173 const OUString* pNames = m_lServiceNames.getConstArray();
174 for (sal_Int32 i=0; i<c; ++i)
176 if (pNames[i].equals(sServiceName))
177 return sal_True;
179 return sal_False;
180 // <- SAFE
185 css::uno::Sequence< OUString > SAL_CALL BaseContainer::getSupportedServiceNames()
186 throw (css::uno::RuntimeException)
188 // SAFE ->
189 ::osl::ResettableMutexGuard aLock(m_aLock);
190 return m_lServiceNames;
191 // <- SAFE
196 void SAL_CALL BaseContainer::insertByName(const OUString& sItem ,
197 const css::uno::Any& aValue)
198 throw (css::lang::IllegalArgumentException ,
199 css::container::ElementExistException,
200 css::lang::WrappedTargetException ,
201 css::uno::RuntimeException )
203 if (sItem.isEmpty())
204 throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
205 static_cast< css::container::XNameContainer* >(this),
208 CacheItem aItem;
211 aItem << aValue;
213 catch(const css::uno::Exception& ex)
215 throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
218 impl_loadOnDemand();
220 // SAFE -> ----------------------------------
221 ::osl::ResettableMutexGuard aLock(m_aLock);
223 // create write copy of used cache on demand ...
224 impl_initFlushMode();
226 FilterCache* pCache = impl_getWorkingCache();
227 if (pCache->hasItem(m_eType, sItem))
228 throw css::container::ElementExistException(OUString(), static_cast< css::container::XNameContainer* >(this));
229 pCache->setItem(m_eType, sItem, aItem);
231 aLock.clear();
232 // <- SAFE ----------------------------------
237 void SAL_CALL BaseContainer::removeByName(const OUString& sItem)
238 throw (css::container::NoSuchElementException,
239 css::lang::WrappedTargetException ,
240 css::uno::RuntimeException )
242 impl_loadOnDemand();
244 // SAFE -> ----------------------------------
245 ::osl::ResettableMutexGuard aLock(m_aLock);
247 // create write copy of used cache on demand ...
248 impl_initFlushMode();
250 FilterCache* pCache = impl_getWorkingCache();
251 pCache->removeItem(m_eType, sItem); // throw exceptions automaticly
253 aLock.clear();
254 // <- SAFE ----------------------------------
259 void SAL_CALL BaseContainer::replaceByName(const OUString& sItem ,
260 const css::uno::Any& aValue)
261 throw (css::lang::IllegalArgumentException ,
262 css::container::NoSuchElementException,
263 css::lang::WrappedTargetException ,
264 css::uno::RuntimeException )
266 if (sItem.isEmpty())
267 throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
268 static_cast< css::container::XNameContainer* >(this),
271 CacheItem aItem;
274 aItem << aValue;
276 catch(const css::uno::Exception& ex)
278 throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
281 impl_loadOnDemand();
283 // SAFE -> ----------------------------------
284 ::osl::ResettableMutexGuard aLock(m_aLock);
286 // create write copy of used cache on demand ...
287 impl_initFlushMode();
289 FilterCache* pCache = impl_getWorkingCache();
290 if (!pCache->hasItem(m_eType, sItem))
291 throw css::container::NoSuchElementException(OUString(), static_cast< css::container::XNameContainer* >(this));
292 pCache->setItem(m_eType, sItem, aItem);
294 aLock.clear();
295 // <- SAFE ----------------------------------
300 css::uno::Any SAL_CALL BaseContainer::getByName(const OUString& sItem)
301 throw (css::container::NoSuchElementException,
302 css::lang::WrappedTargetException ,
303 css::uno::RuntimeException )
305 if (sItem.isEmpty())
306 throw css::container::NoSuchElementException( "An empty item cant be part of this cache!",
307 css::uno::Reference< css::uno::XInterface >(static_cast< css::container::XNameAccess* >(this), css::uno::UNO_QUERY));
309 css::uno::Any aValue;
311 impl_loadOnDemand();
313 // SAFE ->
314 ::osl::ResettableMutexGuard aLock(m_aLock);
316 CacheItem aItem;
319 FilterCache* pCache = impl_getWorkingCache();
320 aItem = pCache->getItem(m_eType, sItem);
321 pCache->addStatePropsToItem(m_eType, sItem, aItem); // add implicit props "Finalized"/"Mandatory"
323 catch(const css::container::NoSuchElementException&)
325 throw;
327 catch(const css::uno::Exception&)
329 // TODO invalid cache!? How should it be handled right?
330 aItem.clear();
333 aValue <<= aItem.getAsPackedPropertyValueList();
334 // <- SAFE
336 return aValue;
341 css::uno::Sequence< OUString > SAL_CALL BaseContainer::getElementNames()
342 throw (css::uno::RuntimeException)
344 css::uno::Sequence< OUString > lNames;
346 impl_loadOnDemand();
348 // SAFE ->
349 ::osl::ResettableMutexGuard aLock(m_aLock);
353 FilterCache* pCache = impl_getWorkingCache();
354 OUStringList lKeys = pCache->getItemNames(m_eType);
355 lKeys >> lNames;
357 catch(const css::uno::Exception&)
359 // invalid cache!?
360 lNames.realloc(0);
363 // <- SAFE
365 return lNames;
370 sal_Bool SAL_CALL BaseContainer::hasByName(const OUString& sItem)
371 throw (css::uno::RuntimeException)
373 sal_Bool bHasOne = sal_False;
375 impl_loadOnDemand();
377 // SAFE ->
378 ::osl::ResettableMutexGuard aLock(m_aLock);
382 FilterCache* pCache = impl_getWorkingCache();
383 bHasOne = pCache->hasItem(m_eType, sItem);
385 catch(const css::uno::Exception&)
387 // invalid cache!?
388 bHasOne = sal_False;
391 // <- SAFE
393 return bHasOne;
398 css::uno::Type SAL_CALL BaseContainer::getElementType()
399 throw (css::uno::RuntimeException)
401 // no lock necessary - because the type of our items
402 // is fix! no internal call or member needed ...
403 return ::getCppuType(static_cast< css::uno::Sequence< css::beans::PropertyValue >* >(NULL));
408 sal_Bool SAL_CALL BaseContainer::hasElements()
409 throw (css::uno::RuntimeException)
411 sal_Bool bHasSome = sal_False;
413 impl_loadOnDemand();
415 // SAFE ->
416 ::osl::ResettableMutexGuard aLock(m_aLock);
420 FilterCache* pCache = impl_getWorkingCache();
421 bHasSome = pCache->hasItems(m_eType);
423 catch(const css::uno::Exception&)
425 // invalid cache?!
426 bHasSome = sal_False;
429 // <- SAFE
431 return bHasSome;
436 css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const OUString& /* sQuery */ )
437 throw (css::uno::RuntimeException)
439 OSL_FAIL("not pure virtual ... but not realy implemented .-)");
441 ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, css::uno::Sequence< OUString >());
442 return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
447 css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
448 throw (css::uno::RuntimeException)
450 css::uno::Reference< css::container::XEnumeration > xEnum;
451 OUStringList lKeys;
453 impl_loadOnDemand();
455 // SAFE ->
456 ::osl::ResettableMutexGuard aLock(m_aLock);
460 // convert the given properties first to our internal representation
461 CacheItem lProps;
462 lProps << lProperties;
464 // search the key names of all items, where its properties match
465 // the given ones in its minimum
466 FilterCache* pCache = impl_getWorkingCache();
467 lKeys = pCache->getMatchingItemsByProps(m_eType, lProps);
469 catch(const css::uno::Exception&)
471 // invalid cache, internal failure, wrong conversion ...!?
472 // doesnt matter
473 lKeys.clear();
476 // <- SAFE
478 // create a specialized enumeration helper, which
479 // provides the collected information outside.
480 // It hold a reference to us ... and call our container interface directly.
481 // be aware of some direct callbacks if it will be created :-)
483 /* Note: Its not allowed to return NULL. Because an empty enumeration
484 transport the same information but make no trouble outside.
485 Further its easiear to work directly with the return value
486 instaed of checking of NULL returns! */
488 css::uno::Sequence< OUString > lSubSet;
489 lKeys >> lSubSet;
490 ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, lSubSet);
491 return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
496 void SAL_CALL BaseContainer::flush()
497 throw (css::uno::RuntimeException)
499 // SAFE ->
500 ::osl::ResettableMutexGuard aLock(m_aLock);
502 if (!m_pFlushCache)
503 throw css::lang::WrappedTargetRuntimeException(
504 "Cant guarantee cache consistency. Special flush container does not exists!",
505 dynamic_cast< css::container::XNameAccess* >(this),
506 css::uno::Any());
510 m_pFlushCache->flush();
511 // Take over all changes into the global cache and
512 // forget the clone.
513 /* TODO
514 -think about me
515 If the global cache gets this information via listener,
516 we should remove this method!
518 m_rCache->takeOver(*m_pFlushCache);
520 catch(const css::uno::Exception& ex)
522 // Dont remove the clone. May be the outside
523 // user whish to repair it now and calls flush()
524 // later again ...
526 throw css::lang::WrappedTargetRuntimeException( "Flush rejected by internal container.",
527 dynamic_cast< css::container::XNameAccess* >(this),
528 css::uno::makeAny(ex));
531 delete m_pFlushCache;
532 m_pFlushCache = NULL;
534 css::uno::Reference< css::util::XRefreshable > xRefreshBroadcaster = m_xRefreshBroadcaster;
536 aLock.clear();
537 // <- SAFE
539 if (xRefreshBroadcaster.is())
540 xRefreshBroadcaster->refresh();
542 // notify listener outside the lock!
543 // The used listener helper lives if we live
544 // and is threadsafe by itself.
545 // Further its not a good idea to hold the own lock
546 // if an outside object is called :-)
547 css::lang::EventObject aSource (static_cast< css::util::XFlushable* >(this));
548 ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)));
549 if (pContainer)
551 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
552 while (pIterator.hasMoreElements())
556 // ... this pointer can be interesting to find out, where will be called as listener
557 // Dont optimize it to a direct iterator cast :-)
558 css::util::XFlushListener* pListener = (css::util::XFlushListener*)pIterator.next();
559 pListener->flushed(aSource);
561 catch(const css::uno::Exception&)
563 // ignore any "damaged" flush listener!
564 // May its remote reference is broken ...
565 pIterator.remove();
573 void SAL_CALL BaseContainer::addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
574 throw (css::uno::RuntimeException)
576 // no locks necessary
577 // used helper lives if we live and is threadsafe by itself ...
578 m_lListener.addInterface(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)),
579 xListener );
584 void SAL_CALL BaseContainer::removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
585 throw (css::uno::RuntimeException)
587 // no locks necessary
588 // used helper lives if we live and is threadsafe by itself ...
589 m_lListener.removeInterface(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)),
590 xListener );
593 } // namespace config
594 } // namespace filter
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */