1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
44 struct thePerformanceOptimizer
:
45 public rtl::Static
<FilterCacheRefHold
, thePerformanceOptimizer
>
50 BaseContainer::BaseContainer()
53 , m_pFlushCache(NULL
)
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
)
75 ::osl::ResettableMutexGuard
aLock(m_aLock
);
77 m_sImplementationName
= sImplementationName
;
78 m_lServiceNames
= lServiceNames
;
80 m_xRefreshBroadcaster
= css::document::FilterConfigRefresh::create(rxContext
);
86 void BaseContainer::impl_loadOnDemand()
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
;
99 case FilterCache::E_TYPE
:
100 eRequiredState
= FilterCache::E_CONTAINS_TYPES
;
103 case FilterCache::E_FILTER
:
104 eRequiredState
= FilterCache::E_CONTAINS_FILTERS
;
107 case FilterCache::E_DETECTSERVICE
:
108 eRequiredState
= FilterCache::E_CONTAINS_DETECTSERVICES
;
111 case FilterCache::E_FRAMELOADER
:
112 eRequiredState
= FilterCache::E_CONTAINS_FRAMELOADERS
;
115 case FilterCache::E_CONTENTHANDLER
:
116 eRequiredState
= FilterCache::E_CONTAINS_CONTENTHANDLERS
;
120 m_rCache
->load(eRequiredState
);
127 void BaseContainer::impl_initFlushMode()
128 throw (css::uno::RuntimeException
)
131 ::osl::ResettableMutexGuard
aLock(m_aLock
);
133 m_pFlushCache
= m_rCache
->clone();
135 throw css::uno::RuntimeException( "Cant create write copy of internal used cache on demand.",
136 dynamic_cast< css::container::XNameAccess
* >(this));
142 FilterCache
* BaseContainer::impl_getWorkingCache() const
145 ::osl::ResettableMutexGuard
aLock(m_aLock
);
147 return m_pFlushCache
;
155 OUString SAL_CALL
BaseContainer::getImplementationName()
156 throw (css::uno::RuntimeException
)
159 ::osl::ResettableMutexGuard
aLock(m_aLock
);
160 return m_sImplementationName
;
166 sal_Bool SAL_CALL
BaseContainer::supportsService(const OUString
& sServiceName
)
167 throw (css::uno::RuntimeException
)
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
))
185 css::uno::Sequence
< OUString
> SAL_CALL
BaseContainer::getSupportedServiceNames()
186 throw (css::uno::RuntimeException
)
189 ::osl::ResettableMutexGuard
aLock(m_aLock
);
190 return m_lServiceNames
;
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
)
204 throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
205 static_cast< css::container::XNameContainer
* >(this),
213 catch(const css::uno::Exception
& ex
)
215 throw css::lang::IllegalArgumentException(ex
.Message
, static_cast< css::container::XNameContainer
* >(this), 2);
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
);
232 // <- SAFE ----------------------------------
237 void SAL_CALL
BaseContainer::removeByName(const OUString
& sItem
)
238 throw (css::container::NoSuchElementException
,
239 css::lang::WrappedTargetException
,
240 css::uno::RuntimeException
)
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
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
)
267 throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
268 static_cast< css::container::XNameContainer
* >(this),
276 catch(const css::uno::Exception
& ex
)
278 throw css::lang::IllegalArgumentException(ex
.Message
, static_cast< css::container::XNameContainer
* >(this), 2);
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
);
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
)
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
;
314 ::osl::ResettableMutexGuard
aLock(m_aLock
);
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
&)
327 catch(const css::uno::Exception
&)
329 // TODO invalid cache!? How should it be handled right?
333 aValue
<<= aItem
.getAsPackedPropertyValueList();
341 css::uno::Sequence
< OUString
> SAL_CALL
BaseContainer::getElementNames()
342 throw (css::uno::RuntimeException
)
344 css::uno::Sequence
< OUString
> lNames
;
349 ::osl::ResettableMutexGuard
aLock(m_aLock
);
353 FilterCache
* pCache
= impl_getWorkingCache();
354 OUStringList lKeys
= pCache
->getItemNames(m_eType
);
357 catch(const css::uno::Exception
&)
370 sal_Bool SAL_CALL
BaseContainer::hasByName(const OUString
& sItem
)
371 throw (css::uno::RuntimeException
)
373 sal_Bool bHasOne
= sal_False
;
378 ::osl::ResettableMutexGuard
aLock(m_aLock
);
382 FilterCache
* pCache
= impl_getWorkingCache();
383 bHasOne
= pCache
->hasItem(m_eType
, sItem
);
385 catch(const css::uno::Exception
&)
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
;
416 ::osl::ResettableMutexGuard
aLock(m_aLock
);
420 FilterCache
* pCache
= impl_getWorkingCache();
421 bHasSome
= pCache
->hasItems(m_eType
);
423 catch(const css::uno::Exception
&)
426 bHasSome
= sal_False
;
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
;
456 ::osl::ResettableMutexGuard
aLock(m_aLock
);
460 // convert the given properties first to our internal representation
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 ...!?
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
;
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
)
500 ::osl::ResettableMutexGuard
aLock(m_aLock
);
503 throw css::lang::WrappedTargetRuntimeException(
504 "Cant guarantee cache consistency. Special flush container does not exists!",
505 dynamic_cast< css::container::XNameAccess
* >(this),
510 m_pFlushCache
->flush();
511 // Take over all changes into the global cache and
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()
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
;
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
)));
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 ...
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
)),
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
)),
593 } // namespace config
594 } // namespace filter
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */