1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26
27 #include "basecontainer.hxx"
28 #include "constant.hxx"
29
30 //_______________________________________________
31 // includes
32 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
33 #include <com/sun/star/uno/Type.h>
34 #include <comphelper/enumhelper.hxx>
35 #include <osl/diagnose.h>
36
37 //_______________________________________________
38 // namespace
39
40 #define LOAD_IMPLICIT
41
42 namespace css = ::com::sun::star;
43
44 namespace filter{
45 namespace config{
46
47 //_______________________________________________
48 // definitions
49
50 ::salhelper::SingletonRef< FilterCache >* BaseContainer::m_pPerformanceOptimizer = 0;
51
52 /*-----------------------------------------------
53 03.03.2004 11:37
54 -----------------------------------------------*/
BaseContainer()55 BaseContainer::BaseContainer()
56 : BaseLock ( )
57 , m_rCache ( )
58 , m_pFlushCache(NULL )
59 , m_lListener (m_aLock)
60 {
61 m_rCache->load(FilterCache::E_CONTAINS_STANDARD);
62
63 // GLOBAL SAFE (!) -> -----------------------
64 // TODO use rtl pattern to create it really threadsafe!
65 ::osl::ResettableMutexGuard aGlobalLock(::osl::Mutex::getGlobalMutex());
66 if (!m_pPerformanceOptimizer)
67 m_pPerformanceOptimizer = new ::salhelper::SingletonRef< FilterCache >();
68 aGlobalLock.clear();
69 // <- GLOBAL SAFE (!) -----------------------
70 }
71
72 /*-----------------------------------------------
73 02.07.2003 10:16
74 -----------------------------------------------*/
~BaseContainer()75 BaseContainer::~BaseContainer()
76 {
77 }
78
79 /*-----------------------------------------------
80 03.07.2003 11:16
81 -----------------------------------------------*/
init(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,const::rtl::OUString & sImplementationName,const css::uno::Sequence<::rtl::OUString> & lServiceNames,FilterCache::EItemType eType)82 void BaseContainer::init(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
83 const ::rtl::OUString& sImplementationName,
84 const css::uno::Sequence< ::rtl::OUString >& lServiceNames ,
85 FilterCache::EItemType eType )
86 {
87 // SAFE ->
88 ::osl::ResettableMutexGuard aLock(m_aLock);
89
90 m_sImplementationName = sImplementationName;
91 m_lServiceNames = lServiceNames ;
92 m_xSMGR = xSMGR ;
93 m_eType = eType ;
94 m_xRefreshBroadcaster = css::uno::Reference< css::util::XRefreshable >(
95 xSMGR->createInstance(SERVICE_FILTERCONFIGREFRESH),
96 css::uno::UNO_QUERY);
97 // <- SAFE
98 }
99
100 /*-----------------------------------------------
101 28.10.2003 09:04
102 -----------------------------------------------*/
impl_loadOnDemand()103 void BaseContainer::impl_loadOnDemand()
104 {
105 #ifdef LOAD_IMPLICIT
106 // SAFE ->
107 ::osl::ResettableMutexGuard aLock(m_aLock);
108
109 // A generic container needs all items of a set of our cache!
110 // Of course it can block for a while, till the cache is really filled.
111 // Note: don't load all sets supported by the cache here!
112
113 FilterCache::EFillState eRequiredState = FilterCache::E_CONTAINS_NOTHING;
114 switch(m_eType)
115 {
116 case FilterCache::E_TYPE :
117 eRequiredState = FilterCache::E_CONTAINS_TYPES;
118 break;
119
120 case FilterCache::E_FILTER :
121 eRequiredState = FilterCache::E_CONTAINS_FILTERS;
122 break;
123
124 case FilterCache::E_DETECTSERVICE :
125 eRequiredState = FilterCache::E_CONTAINS_DETECTSERVICES;
126 break;
127
128 case FilterCache::E_FRAMELOADER :
129 eRequiredState = FilterCache::E_CONTAINS_FRAMELOADERS;
130 break;
131
132 case FilterCache::E_CONTENTHANDLER :
133 eRequiredState = FilterCache::E_CONTAINS_CONTENTHANDLERS;
134 break;
135 }
136
137 m_rCache->load(eRequiredState);
138 // <- SAFE
139 #endif
140 }
141
142 /*-----------------------------------------------
143 03.03.2004 12:18
144 -----------------------------------------------*/
impl_initFlushMode()145 void BaseContainer::impl_initFlushMode()
146 throw (css::uno::RuntimeException)
147 {
148 // SAFE ->
149 ::osl::ResettableMutexGuard aLock(m_aLock);
150 if (!m_pFlushCache)
151 m_pFlushCache = m_rCache->clone();
152 if (!m_pFlushCache)
153 throw css::uno::RuntimeException(
154 ::rtl::OUString::createFromAscii("Can't create write copy of internal used cache on demand."),
155 dynamic_cast< css::container::XNameAccess* >(this));
156 // <- SAFE
157 }
158
159 /*-----------------------------------------------
160 03.03.2004 12:11
161 -----------------------------------------------*/
impl_getWorkingCache() const162 FilterCache* BaseContainer::impl_getWorkingCache() const
163 {
164 // SAFE ->
165 ::osl::ResettableMutexGuard aLock(m_aLock);
166 if (m_pFlushCache)
167 return m_pFlushCache;
168 else
169 return &(*m_rCache);
170 // <- SAFE
171 }
172
173 /*-----------------------------------------------
174 03.07.2003 11:12
175 -----------------------------------------------*/
getImplementationName()176 ::rtl::OUString SAL_CALL BaseContainer::getImplementationName()
177 throw (css::uno::RuntimeException)
178 {
179 // SAFE ->
180 ::osl::ResettableMutexGuard aLock(m_aLock);
181 return m_sImplementationName;
182 // <- SAFE
183 }
184
185 /*-----------------------------------------------
186 03.07.2003 11:14
187 -----------------------------------------------*/
supportsService(const::rtl::OUString & sServiceName)188 sal_Bool SAL_CALL BaseContainer::supportsService(const ::rtl::OUString& sServiceName)
189 throw (css::uno::RuntimeException)
190 {
191 // SAFE ->
192 ::osl::ResettableMutexGuard aLock(m_aLock);
193
194 sal_Int32 c = m_lServiceNames.getLength();
195 const ::rtl::OUString* pNames = m_lServiceNames.getConstArray();
196 for (sal_Int32 i=0; i<c; ++i)
197 {
198 if (pNames[i].equals(sServiceName))
199 return sal_True;
200 }
201 return sal_False;
202 // <- SAFE
203 }
204
205 /*-----------------------------------------------
206 03.07.2003 11:12
207 -----------------------------------------------*/
getSupportedServiceNames()208 css::uno::Sequence< ::rtl::OUString > SAL_CALL BaseContainer::getSupportedServiceNames()
209 throw (css::uno::RuntimeException)
210 {
211 // SAFE ->
212 ::osl::ResettableMutexGuard aLock(m_aLock);
213 return m_lServiceNames;
214 // <- SAFE
215 }
216
217 /*-----------------------------------------------
218 20.10.2003 11:39
219 -----------------------------------------------*/
insertByName(const::rtl::OUString & sItem,const css::uno::Any & aValue)220 void SAL_CALL BaseContainer::insertByName(const ::rtl::OUString& sItem ,
221 const css::uno::Any& aValue)
222 throw (css::lang::IllegalArgumentException ,
223 css::container::ElementExistException,
224 css::lang::WrappedTargetException ,
225 css::uno::RuntimeException )
226 {
227 if (!sItem.getLength())
228 throw css::lang::IllegalArgumentException(
229 ::rtl::OUString::createFromAscii("empty value not allowed as item name."),
230 static_cast< css::container::XNameContainer* >(this),
231 1);
232
233 CacheItem aItem;
234 try
235 {
236 aItem << aValue;
237 }
238 catch(const css::uno::Exception& ex)
239 {
240 throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
241 }
242
243 impl_loadOnDemand();
244
245 // SAFE -> ----------------------------------
246 ::osl::ResettableMutexGuard aLock(m_aLock);
247
248 // create write copy of used cache on demand ...
249 impl_initFlushMode();
250
251 FilterCache* pCache = impl_getWorkingCache();
252 if (pCache->hasItem(m_eType, sItem))
253 throw css::container::ElementExistException(::rtl::OUString(), static_cast< css::container::XNameContainer* >(this));
254 pCache->setItem(m_eType, sItem, aItem);
255
256 aLock.clear();
257 // <- SAFE ----------------------------------
258 }
259
260 /*-----------------------------------------------
261 03.03.2004 11:40
262 -----------------------------------------------*/
removeByName(const::rtl::OUString & sItem)263 void SAL_CALL BaseContainer::removeByName(const ::rtl::OUString& sItem)
264 throw (css::container::NoSuchElementException,
265 css::lang::WrappedTargetException ,
266 css::uno::RuntimeException )
267 {
268 impl_loadOnDemand();
269
270 // SAFE -> ----------------------------------
271 ::osl::ResettableMutexGuard aLock(m_aLock);
272
273 // create write copy of used cache on demand ...
274 impl_initFlushMode();
275
276 FilterCache* pCache = impl_getWorkingCache();
277 pCache->removeItem(m_eType, sItem); // throw exceptions automatically
278
279 aLock.clear();
280 // <- SAFE ----------------------------------
281 }
282
283 /*-----------------------------------------------
284 03.03.2004 11:41
285 -----------------------------------------------*/
replaceByName(const::rtl::OUString & sItem,const css::uno::Any & aValue)286 void SAL_CALL BaseContainer::replaceByName(const ::rtl::OUString& sItem ,
287 const css::uno::Any& aValue)
288 throw (css::lang::IllegalArgumentException ,
289 css::container::NoSuchElementException,
290 css::lang::WrappedTargetException ,
291 css::uno::RuntimeException )
292 {
293 if (!sItem.getLength())
294 throw css::lang::IllegalArgumentException(
295 ::rtl::OUString::createFromAscii("empty value not allowed as item name."),
296 static_cast< css::container::XNameContainer* >(this),
297 1);
298
299 CacheItem aItem;
300 try
301 {
302 aItem << aValue;
303 }
304 catch(const css::uno::Exception& ex)
305 {
306 throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
307 }
308
309 impl_loadOnDemand();
310
311 // SAFE -> ----------------------------------
312 ::osl::ResettableMutexGuard aLock(m_aLock);
313
314 // create write copy of used cache on demand ...
315 impl_initFlushMode();
316
317 FilterCache* pCache = impl_getWorkingCache();
318 if (!pCache->hasItem(m_eType, sItem))
319 throw css::container::NoSuchElementException(::rtl::OUString(), static_cast< css::container::XNameContainer* >(this));
320 pCache->setItem(m_eType, sItem, aItem);
321
322 aLock.clear();
323 // <- SAFE ----------------------------------
324 }
325
326 /*-----------------------------------------------
327 03.03.2004 11:44
328 -----------------------------------------------*/
getByName(const::rtl::OUString & sItem)329 css::uno::Any SAL_CALL BaseContainer::getByName(const ::rtl::OUString& sItem)
330 throw (css::container::NoSuchElementException,
331 css::lang::WrappedTargetException ,
332 css::uno::RuntimeException )
333 {
334 if (!sItem.getLength())
335 throw css::container::NoSuchElementException(
336 ::rtl::OUString::createFromAscii("An empty item can't be part of this cache!"),
337 css::uno::Reference< css::uno::XInterface >(static_cast< css::container::XNameAccess* >(this), css::uno::UNO_QUERY));
338
339 css::uno::Any aValue;
340
341 impl_loadOnDemand();
342
343 // SAFE ->
344 ::osl::ResettableMutexGuard aLock(m_aLock);
345
346 CacheItem aItem;
347 try
348 {
349 FilterCache* pCache = impl_getWorkingCache();
350 aItem = pCache->getItem(m_eType, sItem);
351 pCache->addStatePropsToItem(m_eType, sItem, aItem); // add implicit props "Finalized"/"Mandatory"
352 }
353 catch(const css::container::NoSuchElementException& exNotExist)
354 {
355 throw exNotExist;
356 }
357 catch(const css::uno::Exception&)
358 {
359 // TODO invalid cache!? How should it be handled right?
360 aItem.clear();
361 }
362
363 aValue <<= aItem.getAsPackedPropertyValueList();
364 // <- SAFE
365
366 return aValue;
367 }
368
369 /*-----------------------------------------------
370 03.03.2004 11:46
371 -----------------------------------------------*/
getElementNames()372 css::uno::Sequence< ::rtl::OUString > SAL_CALL BaseContainer::getElementNames()
373 throw (css::uno::RuntimeException)
374 {
375 css::uno::Sequence< ::rtl::OUString > lNames;
376
377 impl_loadOnDemand();
378
379 // SAFE ->
380 ::osl::ResettableMutexGuard aLock(m_aLock);
381
382 try
383 {
384 FilterCache* pCache = impl_getWorkingCache();
385 OUStringList lKeys = pCache->getItemNames(m_eType);
386 lKeys >> lNames;
387 }
388 catch(const css::uno::Exception&)
389 {
390 // invalid cache!?
391 lNames.realloc(0);
392 }
393
394 // <- SAFE
395
396 return lNames;
397 }
398
399 /*-----------------------------------------------
400 03.03.2004 11:47
401 -----------------------------------------------*/
hasByName(const::rtl::OUString & sItem)402 sal_Bool SAL_CALL BaseContainer::hasByName(const ::rtl::OUString& sItem)
403 throw (css::uno::RuntimeException)
404 {
405 sal_Bool bHasOne = sal_False;
406
407 impl_loadOnDemand();
408
409 // SAFE ->
410 ::osl::ResettableMutexGuard aLock(m_aLock);
411
412 try
413 {
414 FilterCache* pCache = impl_getWorkingCache();
415 bHasOne = pCache->hasItem(m_eType, sItem);
416 }
417 catch(const css::uno::Exception&)
418 {
419 // invalid cache!?
420 bHasOne = sal_False;
421 }
422
423 // <- SAFE
424
425 return bHasOne;
426 }
427
428 /*-----------------------------------------------
429 02.07.2003 10:18
430 -----------------------------------------------*/
getElementType()431 css::uno::Type SAL_CALL BaseContainer::getElementType()
432 throw (css::uno::RuntimeException)
433 {
434 // no lock necessary - because the type of our items
435 // is fix! no internal call or member needed ...
436 return ::getCppuType(static_cast< css::uno::Sequence< css::beans::PropertyValue >* >(NULL));
437 }
438
439 /*-----------------------------------------------
440 03.03.2004 11:48
441 -----------------------------------------------*/
hasElements()442 sal_Bool SAL_CALL BaseContainer::hasElements()
443 throw (css::uno::RuntimeException)
444 {
445 sal_Bool bHasSome = sal_False;
446
447 impl_loadOnDemand();
448
449 // SAFE ->
450 ::osl::ResettableMutexGuard aLock(m_aLock);
451
452 try
453 {
454 FilterCache* pCache = impl_getWorkingCache();
455 bHasSome = pCache->hasItems(m_eType);
456 }
457 catch(const css::uno::Exception&)
458 {
459 // invalid cache?!
460 bHasSome = sal_False;
461 }
462
463 // <- SAFE
464
465 return bHasSome;
466 }
467
468 /*-----------------------------------------------
469 15.07.2003 09:21
470 -----------------------------------------------*/
createSubSetEnumerationByQuery(const::rtl::OUString &)471 css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const ::rtl::OUString& /* sQuery */ )
472 throw (css::uno::RuntimeException)
473 {
474 OSL_ENSURE(sal_False, "not pure virtual ... but not really implemented .-)");
475
476 ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, css::uno::Sequence< ::rtl::OUString >());
477 return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
478 }
479
480 /*-----------------------------------------------
481 15.07.2003 10:15
482 -----------------------------------------------*/
createSubSetEnumerationByProperties(const css::uno::Sequence<css::beans::NamedValue> & lProperties)483 css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
484 throw (css::uno::RuntimeException)
485 {
486 css::uno::Reference< css::container::XEnumeration > xEnum;
487 OUStringList lKeys;
488
489 impl_loadOnDemand();
490
491 // SAFE ->
492 ::osl::ResettableMutexGuard aLock(m_aLock);
493
494 try
495 {
496 // convert the given properties first to our internal representation
497 CacheItem lProps;
498 lProps << lProperties;
499
500 // search the key names of all items, where its properties match
501 // the given ones in its minimum
502 FilterCache* pCache = impl_getWorkingCache();
503 lKeys = pCache->getMatchingItemsByProps(m_eType, lProps);
504 }
505 catch(const css::uno::Exception&)
506 {
507 // invalid cache, internal failure, wrong conversion ...!?
508 // doesn't matter
509 lKeys.clear();
510 }
511
512 // <- SAFE
513
514 // create a specialized enumeration helper, which
515 // provides the collected informations outside.
516 // It hold a reference to us ... and call our container interface directly.
517 // be aware of some direct callbacks if it will be created :-)
518
519 /* Note: Its not allowed to return NULL. Because an empty enumeration
520 transport the same information but make no trouble outside.
521 Further its easiear to work directly with the return value
522 instaed of checking of NULL returns! */
523
524 css::uno::Sequence< ::rtl::OUString > lSubSet;
525 lKeys >> lSubSet;
526 ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, lSubSet);
527 return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
528 }
529
530 /*-----------------------------------------------
531 07.03.2004 10:48
532 -----------------------------------------------*/
flush()533 void SAL_CALL BaseContainer::flush()
534 throw (css::uno::RuntimeException)
535 {
536 // SAFE ->
537 ::osl::ResettableMutexGuard aLock(m_aLock);
538
539 if (!m_pFlushCache)
540 throw css::lang::WrappedTargetRuntimeException(
541 ::rtl::OUString::createFromAscii("Can't guarantee cache consistency. Special flush container does not exists!"),
542 dynamic_cast< css::container::XNameAccess* >(this),
543 css::uno::Any());
544
545 try
546 {
547 m_pFlushCache->flush();
548 // Take over all changes into the global cache and
549 // forget the clone.
550 /* TODO
551 -think about me
552 If the global cache gets this information via listener,
553 we should remove this method!
554 */
555 m_rCache->takeOver(*m_pFlushCache);
556 }
557 catch(const css::uno::Exception& ex)
558 {
559 // Dont remove the clone. May be the outside
560 // user whish to repair it now and calls flush()
561 // later again ...
562
563 throw css::lang::WrappedTargetRuntimeException(
564 ::rtl::OUString::createFromAscii("Flush rejected by internal container."),
565 dynamic_cast< css::container::XNameAccess* >(this),
566 css::uno::makeAny(ex));
567 }
568
569 delete m_pFlushCache;
570 m_pFlushCache = NULL;
571
572 css::uno::Reference< css::util::XRefreshable > xRefreshBroadcaster = m_xRefreshBroadcaster;
573
574 aLock.clear();
575 // <- SAFE
576
577 if (xRefreshBroadcaster.is())
578 xRefreshBroadcaster->refresh();
579
580 // notify listener outside the lock!
581 // The used listener helper lives if we live
582 // and is threadsafe by itself.
583 // Further its not a good idea to hold the own lock
584 // if an outside object is called :-)
585 css::lang::EventObject aSource (static_cast< css::util::XFlushable* >(this));
586 ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)));
587 if (pContainer)
588 {
589 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
590 while (pIterator.hasMoreElements())
591 {
592 try
593 {
594 // ... this pointer can be interesting to find out, where will be called as listener
595 // Dont optimize it to a direct iterator cast :-)
596 css::util::XFlushListener* pListener = (css::util::XFlushListener*)pIterator.next();
597 pListener->flushed(aSource);
598 }
599 catch(const css::uno::Exception&)
600 {
601 // ignore any "damaged" flush listener!
602 // May its remote reference is broken ...
603 pIterator.remove();
604 }
605 }
606 }
607 }
608
609 /*-----------------------------------------------
610 02.07.2003 12:16
611 -----------------------------------------------*/
addFlushListener(const css::uno::Reference<css::util::XFlushListener> & xListener)612 void SAL_CALL BaseContainer::addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
613 throw (css::uno::RuntimeException)
614 {
615 // no locks necessary
616 // used helper lives if we live and is threadsafe by itself ...
617 m_lListener.addInterface(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)),
618 xListener );
619 }
620
621 /*-----------------------------------------------
622 02.07.2003 12:18
623 -----------------------------------------------*/
removeFlushListener(const css::uno::Reference<css::util::XFlushListener> & xListener)624 void SAL_CALL BaseContainer::removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
625 throw (css::uno::RuntimeException)
626 {
627 // no locks necessary
628 // used helper lives if we live and is threadsafe by itself ...
629 m_lListener.removeInterface(::getCppuType(static_cast< css::uno::Reference< css::util::XFlushListener >* >(NULL)),
630 xListener );
631 }
632
633 } // namespace config
634 } // namespace filter
635