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 "filterfactory.hxx"
28 #include "macros.hxx"
29 #include "constant.hxx"
30 #include "versions.hxx"
31 
32 //_______________________________________________
33 // includes
34 #include <com/sun/star/lang/XInitialization.hpp>
35 #include <comphelper/enumhelper.hxx>
36 #include <comphelper/configurationhelper.hxx>
37 #include <rtl/ustrbuf.hxx>
38 
39 //_______________________________________________
40 // namespace
41 
42 namespace filter{
43     namespace config{
44 
45 namespace css = ::com::sun::star;
46 
47 //_______________________________________________
48 // definitions
49 
50 /** @short  can be used to query for filters related to its application module.
51  */
52 #define BASE_QUERY_ALL          "_query_all"
53 #define BASE_QUERY_WRITER       "_query_Writer"
54 #define BASE_QUERY_WEB          "_query_web"
55 #define BASE_QUERY_GLOBAL       "_query_global"
56 #define BASE_QUERY_CHART        "_query_chart"
57 #define BASE_QUERY_CALC         "_query_calc"
58 #define BASE_QUERY_IMPRESS      "_query_impress"
59 #define BASE_QUERY_DRAW         "_query_draw"
60 #define BASE_QUERY_MATH         "_query_math"
61 
62 //_______________________________________________
63 
64 /** @short  define all possible parts of a filter query.
65 
66     @descr  syntax: "<query>[:<param>[=<value>]]"
67             e.g.:   "_query_writer:default_first:use_order:sort_prop=uiname"
68 
69             argument                        description                                     default
70             -----------------------------------------------------------------------------------------------
71             iflags=<mask>                   include filters by given mask                   0
72             eflags=<mask>                   exclude filters by given mask                   0
73             sort_prop=<[name,uiname]>       sort by internal name or uiname                 name
74             descending                      sort descending                                 false
75             use_order                       use order flag of filters for sorting           false
76             default_first                   set default filter on top of return list        false
77             case_sensitive                  compare "sort_prop" case sensitive              false
78  */
79 #define SEPERATOR_QUERYPARAM                            ((sal_Unicode)':')
80 #define SEPERATOR_QUERYPARAMVALUE                       ((sal_Unicode)'=')
81 
82 #define QUERYPARAM_IFLAGS                               ::rtl::OUString::createFromAscii("iflags")
83 #define QUERYPARAM_EFLAGS                               ::rtl::OUString::createFromAscii("eflags")
84 #define QUERYPARAM_SORT_PROP                            ::rtl::OUString::createFromAscii("sort_prop")
85 
86 #define QUERYPARAM_DESCENDING                           ::rtl::OUString::createFromAscii("descending")
87 #define QUERYPARAM_USE_ORDER                            ::rtl::OUString::createFromAscii("use_order")
88 #define QUERYPARAM_DEFAULT_FIRST                        ::rtl::OUString::createFromAscii("default_first")
89 #define QUERYPARAM_CASE_SENSITIVE                       ::rtl::OUString::createFromAscii("case_sensitive")
90 
91 #define QUERYPARAMVALUE_SORT_PROP_NAME                  ::rtl::OUString::createFromAscii("name")
92 #define QUERYPARAMVALUE_SORT_PROP_UINAME                ::rtl::OUString::createFromAscii("uiname")
93 
94 /*-----------------------------------------------
95     09.07.2003 07:43
96 -----------------------------------------------*/
FilterFactory(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)97 FilterFactory::FilterFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
98 {
99     BaseContainer::init(xSMGR                                         ,
100                         FilterFactory::impl_getImplementationName()   ,
101                         FilterFactory::impl_getSupportedServiceNames(),
102                         FilterCache::E_FILTER                         );
103 }
104 
105 /*-----------------------------------------------
106     09.07.2003 07:43
107 -----------------------------------------------*/
~FilterFactory()108 FilterFactory::~FilterFactory()
109 {
110 }
111 
112 /*-----------------------------------------------
113     16.07.2003 13:43
114 -----------------------------------------------*/
createInstance(const::rtl::OUString & sFilter)115 css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::createInstance(const ::rtl::OUString& sFilter)
116     throw(css::uno::Exception       ,
117           css::uno::RuntimeException)
118 {
119     return createInstanceWithArguments(sFilter, css::uno::Sequence< css::uno::Any >());
120 }
121 
122 /*-----------------------------------------------
123     17.07.2003 08:56
124 -----------------------------------------------*/
createInstanceWithArguments(const::rtl::OUString & sFilter,const css::uno::Sequence<css::uno::Any> & lArguments)125 css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::createInstanceWithArguments(const ::rtl::OUString&                     sFilter   ,
126                                                                                                 const css::uno::Sequence< css::uno::Any >& lArguments)
127     throw(css::uno::Exception       ,
128           css::uno::RuntimeException)
129 {
130     // SAFE ->
131     ::osl::ResettableMutexGuard aLock(m_aLock);
132 
133     ::rtl::OUString sRealFilter = sFilter;
134 
135     #ifdef _FILTER_CONFIG_MIGRATION_Q_
136 
137         /* -> TODO - HACK
138             check if the given filter name really exists ...
139             Because our old implementation worked with an internal
140             type name instead of a filter name. For a small migration time
141             we must simulate this old feature :-( */
142 
143         if (!m_rCache->hasItem(FilterCache::E_FILTER, sFilter) && m_rCache->hasItem(FilterCache::E_TYPE, sFilter))
144         {
145             OSL_ENSURE(sal_False, "Who use this deprecated functionality?");
146             _FILTER_CONFIG_LOG_("FilterFactory::createInstanceWithArguments() ... simulate old type search functionality!\n");
147 
148             css::uno::Sequence< css::beans::NamedValue > lQuery(1);
149             lQuery[0].Name    = PROPNAME_TYPE;
150             lQuery[0].Value <<= sFilter;
151 
152             css::uno::Reference< css::container::XEnumeration > xSet = createSubSetEnumerationByProperties(lQuery);
153             while(xSet->hasMoreElements())
154             {
155                 ::comphelper::SequenceAsHashMap lHandlerProps(xSet->nextElement());
156                 if (!(lHandlerProps[PROPNAME_NAME] >>= sRealFilter))
157                     continue;
158             }
159 
160             // prevent outside code against NoSuchElementException!
161             // But don't implement such defensive strategy for our new create handling :-)
162             if (!m_rCache->hasItem(FilterCache::E_FILTER, sRealFilter))
163                 return css::uno::Reference< css::uno::XInterface>();
164         }
165 
166         /* <- HACK */
167 
168     #endif // _FILTER_CONFIG_MIGRATION_Q_
169 
170     // search filter on cache
171     CacheItem aFilter = m_rCache->getItem(FilterCache::E_FILTER, sRealFilter);
172     ::rtl::OUString sFilterService;
173     aFilter[PROPNAME_FILTERSERVICE] >>= sFilterService;
174 
175     // create service instance
176     css::uno::Reference< css::uno::XInterface > xFilter;
177     if (sFilterService.getLength())
178         xFilter = m_xSMGR->createInstance(sFilterService);
179 
180     // initialize filter
181     css::uno::Reference< css::lang::XInitialization > xInit(xFilter, css::uno::UNO_QUERY);
182     if (xInit.is())
183     {
184         // format: lInitData[0] = seq<PropertyValue>, which contains all configuration properties of this filter
185         //         lInitData[1] = lArguments[0]
186         //         ...
187         //         lInitData[n] = lArguments[n-1]
188         css::uno::Sequence< css::beans::PropertyValue > lConfig;
189         aFilter >> lConfig;
190 
191         ::comphelper::SequenceAsVector< css::uno::Any > stlArguments(lArguments);
192         stlArguments.insert(stlArguments.begin(), css::uno::makeAny(lConfig));
193 
194         css::uno::Sequence< css::uno::Any > lInitData;
195         stlArguments >> lInitData;
196 
197         xInit->initialize(lInitData);
198     }
199 
200     return xFilter;
201     // <- SAFE
202 }
203 
204 /*-----------------------------------------------
205     18.02.2004 14:21
206 -----------------------------------------------*/
getAvailableServiceNames()207 css::uno::Sequence< ::rtl::OUString > SAL_CALL FilterFactory::getAvailableServiceNames()
208     throw(css::uno::RuntimeException)
209 {
210     /* Attention: Instead of getElementNames() this method have to return only filter names,
211                   which can be created as UNO Services really. That's why we search for filters,
212                   which dont have a valid value for the property "FilterService".
213                   Of course we can't check for corrupted service names here. We can check
214                   for empty strings only ...
215     */
216     CacheItem lIProps;
217     CacheItem lEProps;
218     lEProps[PROPNAME_FILTERSERVICE] <<= ::rtl::OUString();
219 
220     OUStringList lUNOFilters;
221     try
222     {
223         lUNOFilters = m_rCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps, lEProps);
224     }
225     catch(const css::uno::RuntimeException&)
226         { throw; }
227     catch(const css::uno::Exception&)
228         { lUNOFilters.clear(); }
229 
230     return lUNOFilters.getAsConstList();
231 }
232 
233 /*-----------------------------------------------
234     11.03.2004 08:37
235 -----------------------------------------------*/
createSubSetEnumerationByQuery(const::rtl::OUString & sQuery)236 css::uno::Reference< css::container::XEnumeration > SAL_CALL FilterFactory::createSubSetEnumerationByQuery(const ::rtl::OUString& sQuery)
237     throw (css::uno::RuntimeException)
238 {
239     // reject old deprecated queries ...
240     if (sQuery.matchAsciiL("_filterquery_",13,0))
241         throw css::uno::RuntimeException(
242                     _FILTER_CONFIG_FROM_ASCII_("Use of deprecated and now unsupported query!"),
243                     static_cast< css::container::XContainerQuery* >(this));
244 
245     // convert "_query_xxx:..." to "getByDocService=xxx:..."
246     ::rtl::OUString sNewQuery(sQuery);
247     sal_Int32 pos = sNewQuery.indexOf(::rtl::OUString::createFromAscii("_query_"),0);
248     if (pos != -1)
249     {
250         OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use new query format: 'matchByDocumentService=...'");
251         ::rtl::OUStringBuffer sPatchedQuery(256);
252         sPatchedQuery.appendAscii("matchByDocumentService=");
253         sPatchedQuery.append     (sNewQuery.copy(7)        );
254         sNewQuery = sPatchedQuery.makeStringAndClear();
255     }
256 
257     // analyze query and split it into its tokens
258     QueryTokenizer                  lTokens(sNewQuery);
259     QueryTokenizer::const_iterator  pIt;
260     OUStringList                    lEnumSet;
261 
262     // start query
263     // (see attention comment below!)
264     if (lTokens.valid())
265     {
266         // SAFE -> ----------------------
267         ::osl::ResettableMutexGuard aLock(m_aLock);
268         // May be not all filters was loaded ...
269         // But we need it now!
270         impl_loadOnDemand();
271         aLock.clear();
272         // <- SAFE ----------------------
273 
274         if (lTokens.find(QUERY_IDENTIFIER_GETPREFERREDFILTERFORTYPE) != lTokens.end())
275             OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use prop search at the TypeDetection container!");
276 //            lEnumSet = impl_queryGetPreferredFilterForType(lTokens);
277         else
278         if (lTokens.find(QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE) != lTokens.end())
279             lEnumSet = impl_queryMatchByDocumentService(lTokens);
280         else
281         if (lTokens.find(QUERY_IDENTIFIER_GET_SORTED_FILTERLIST) != lTokens.end())
282             lEnumSet = impl_getSortedFilterList(lTokens);
283     }
284 
285     // pack list of item names as an enum list
286     // Attention: Do not return empty reference for empty list!
287     // The outside check "hasMoreElements()" should be enough, to detect this state :-)
288 //	size_t c = lEnumSet.size();
289 	css::uno::Sequence< ::rtl::OUString > lSet = lEnumSet.getAsConstList();
290     ::comphelper::OEnumerationByName* pEnum = new ::comphelper::OEnumerationByName(this, lSet);
291     return css::uno::Reference< css::container::XEnumeration >(static_cast< css::container::XEnumeration* >(pEnum), css::uno::UNO_QUERY);
292 }
293 /*
294         if (lEnumSet.empty())
295         {
296             //-------------------------------------------
297             // 1) getDefaultFilterForType=<internal_typename>
298 
299             pIt = lTokens.find(::rtl::OUString::createFromAscii("getDefaultFilterForType"));
300             if (pIt != lTokens.end())
301             {
302                 // SAFE ->
303                 ::osl::ResettableMutexGuard aLock(m_aLock);
304 
305                 // might not all types was loaded till now!
306                 impl_loadOnDemand();
307 
308                 ::rtl::OUString sType  = pIt->second;
309                 FilterCache*    pCache = impl_getWorkingCache();
310                 if (pCache->hasItem(FilterCache::E_TYPE, sType))
311                 {
312                     CacheItem aType = pCache->getItem(FilterCache::E_TYPE, sType);
313                     ::rtl::OUString sPreferredFilter;
314                     aType[PROPNAME_PREFERREDFILTER] >>= sPreferredFilter;
315 
316                     if (
317                         (sPreferredFilter.getLength()                              ) &&
318                         (pCache->hasItem(FilterCache::E_FILTER, sPreferredFilter))
319                        )
320                     {
321                         lEnumSet.push_back(sPreferredFilter);
322                     }
323                 }
324 
325                 aLock.clear();
326                 // <- SAFE
327             }
328         }
329 */
330 
331 /*-----------------------------------------------
332     11.03.2004 08:33
333 -----------------------------------------------*/
impl_queryMatchByDocumentService(const QueryTokenizer & lTokens) const334 OUStringList FilterFactory::impl_queryMatchByDocumentService(const QueryTokenizer& lTokens) const
335 {
336     // analyze query
337     QueryTokenizer::const_iterator pIt;
338 
339     ::rtl::OUString sDocumentService;
340     sal_Int32       nIFlags = 0;
341     sal_Int32       nEFlags = 0;
342 
343     pIt = lTokens.find(QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE);
344     if (pIt != lTokens.end())
345         sDocumentService = pIt->second;
346 
347 #define COMP_HACK
348 #ifdef COMP_HACK
349 	if (sDocumentService.equalsAscii("writer"))
350 	{
351 		OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!");
352 		sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.text.TextDocument");
353 	}
354 	else
355 	if (sDocumentService.equalsAscii("web"))
356 	{
357 		OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!");
358 		sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.text.WebDocument");
359 	}
360 	else
361 	if (sDocumentService.equalsAscii("global"))
362 	{
363 		OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!");
364 		sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.text.GlobalDocument");
365 	}
366 	else
367 	if (sDocumentService.equalsAscii("calc"))
368 	{
369 		OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!");
370 		sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.sheet.SpreadsheetDocument");
371 	}
372 	else
373 	if (sDocumentService.equalsAscii("draw"))
374 	{
375 		OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!");
376 		sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.drawing.DrawingDocument");
377 	}
378 	else
379 	if (sDocumentService.equalsAscii("impress"))
380 	{
381 		OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!");
382 		sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.presentation.PresentationDocument");
383 	}
384 	else
385 	if (sDocumentService.equalsAscii("math"))
386 	{
387 		OSL_ENSURE(sal_False, "DEPRECATED!\nPlease use right document service for filter query!");
388 		sDocumentService = ::rtl::OUString::createFromAscii("com.sun.star.formula.FormulaProperties");
389 	}
390 #endif
391 
392     pIt = lTokens.find(QUERY_PARAM_IFLAGS);
393     if (pIt != lTokens.end())
394         nIFlags = ::rtl::OUString(pIt->second).toInt32();
395 
396     pIt = lTokens.find(QUERY_PARAM_EFLAGS);
397     if (pIt != lTokens.end())
398         nEFlags = ::rtl::OUString(pIt->second).toInt32();
399 
400     // SAFE -> ----------------------
401     ::osl::ResettableMutexGuard aLock(m_aLock);
402 
403     // search suitable filters
404     FilterCache* pCache       = impl_getWorkingCache();
405     OUStringList lFilterNames = pCache->getItemNames(FilterCache::E_FILTER);
406     OUStringList lResult      ;
407 
408     for (OUStringList::const_iterator pName  = lFilterNames.begin();
409                                       pName != lFilterNames.end()  ;
410                                     ++pName                        )
411     {
412         try
413         {
414             const ::rtl::OUString&          sName   = *pName;
415             const CacheItem                 aFilter = pCache->getItem(FilterCache::E_FILTER, sName);
416                 CacheItem::const_iterator pProp   ;
417 
418             // "matchByDocumentService="                    => any filter will be addressed here
419             // "matchByDocumentService=all"                 => any filter will be addressed here
420             // "matchByDocumentService=com.sun.star..."     => only filter matching this document service will be addressed
421             ::rtl::OUString sCheckValue = aFilter.getUnpackedValueOrDefault(PROPNAME_DOCUMENTSERVICE, ::rtl::OUString());
422             if (
423                 ( sDocumentService.getLength()                 ) &&
424                 (!sDocumentService.equals(QUERY_CONSTVALUE_ALL)) &&
425                 (!sCheckValue.equals(sDocumentService)         )
426             )
427             {
428                 continue; // ignore filter -> try next one!
429             }
430 
431             // "iflags="        => not allowed
432             // "iflags=-1"      => not allowed
433             // "iflags=0"       => not useful
434             // "iflags=283648"  => only filter, which has set these flag field will be addressed
435             sal_Int32 nCheckValue = aFilter.getUnpackedValueOrDefault(PROPNAME_FLAGS, (sal_Int32)0);
436             if (
437                 (nIFlags > 0                       ) &&
438                 ((nCheckValue & nIFlags) != nIFlags)
439             )
440             {
441                 continue; // ignore filter -> try next one!
442             }
443 
444             // "eflags="        => not allowed
445             // "eflags=-1"      => not allowed
446             // "eflags=0"       => not useful
447             // "eflags=283648"  => only filter, which has not set these flag field will be addressed
448             if (
449                 (nEFlags > 0                       ) &&
450                 ((nCheckValue & nEFlags) == nEFlags)
451             )
452             {
453                 continue; // ignore filter -> try next one!
454             }
455 
456             // OK - this filter passed all checks.
457             // It match the query ...
458             lResult.push_back(sName);
459         }
460         catch(const css::uno::RuntimeException& exRun)
461             { throw exRun; }
462         catch(const css::uno::Exception&)
463             { continue; }
464     }
465 
466     aLock.clear();
467     // <- SAFE ----------------------
468 
469     return lResult;
470 }
471 
472 /*-----------------------------------------------
473     21.01.2005 13:39
474 -----------------------------------------------*/
475 class stlcomp_removeIfMatchFlags
476 {
477     private:
478         FilterCache* m_pCache ;
479         sal_Int32    m_nFlags ;
480         sal_Bool     m_bIFlags;
481 
482     public:
stlcomp_removeIfMatchFlags(FilterCache * pCache,sal_Int32 nFlags,sal_Bool bIFlags)483         stlcomp_removeIfMatchFlags(FilterCache* pCache ,
484                                    sal_Int32    nFlags ,
485                                    sal_Bool     bIFlags)
486             : m_pCache (pCache )
487             , m_nFlags (nFlags )
488             , m_bIFlags(bIFlags)
489         {}
490 
operator ()(const::rtl::OUString & sFilter) const491         bool operator() (const ::rtl::OUString& sFilter) const
492         {
493             try
494             {
495                 const CacheItem aFilter = m_pCache->getItem(FilterCache::E_FILTER, sFilter);
496                         sal_Int32 nFlags  = aFilter.getUnpackedValueOrDefault(PROPNAME_FLAGS, ((sal_Int32)0));
497 
498                 bool bMatch = false;
499                 if (m_bIFlags)
500                     // IFlags are interpeted as ALL_FLAGS_MUST_MATCH !
501                     bMatch = ((nFlags & m_nFlags) == m_nFlags);
502                 else
503                     // EFlags are interpreted as ATE_LEAST_ONE_FLAG_MUST_MATCH !
504                     bMatch = !(nFlags & m_nFlags);
505                 // We are asked for bRemove ! And bMatch = !bRemove => so bRemove = !bMatch .-)
506                 return !bMatch;
507             }
508             catch(css::container::NoSuchElementException)
509             {
510                 return true;
511             }
512         }
513 };
514 
515 /*-----------------------------------------------
516     21.01.2005 13:39
517 -----------------------------------------------*/
impl_getSortedFilterList(const QueryTokenizer & lTokens) const518 OUStringList FilterFactory::impl_getSortedFilterList(const QueryTokenizer& lTokens) const
519 {
520     // analyze the given query parameter
521     QueryTokenizer::const_iterator pIt1;
522 
523     ::rtl::OUString sModule;
524     sal_Int32       nIFlags = -1;
525     sal_Int32       nEFlags = -1;
526 
527     pIt1 = lTokens.find(QUERY_PARAM_MODULE);
528     if (pIt1 != lTokens.end())
529         sModule = pIt1->second;
530     pIt1 = lTokens.find(QUERY_PARAM_IFLAGS);
531     if (pIt1 != lTokens.end())
532         nIFlags = ::rtl::OUString(pIt1->second).toInt32();
533     pIt1 = lTokens.find(QUERY_PARAM_EFLAGS);
534     if (pIt1 != lTokens.end())
535         nEFlags = ::rtl::OUString(pIt1->second).toInt32();
536 
537     // simple search for filters of one specific module.
538     OUStringList lFilterList;
539     if (sModule.getLength())
540         lFilterList = impl_getSortedFilterListForModule(sModule, nIFlags, nEFlags);
541     else
542     {
543         // more complex search for all filters
544         // We check first, which office modules are installed ...
545         OUStringList lModules = impl_getListOfInstalledModules();
546         OUStringList::const_iterator pIt2;
547         for (  pIt2  = lModules.begin();
548                pIt2 != lModules.end()  ;
549              ++pIt2                    )
550         {
551             sModule = *pIt2;
552             OUStringList lFilters4Module = impl_getSortedFilterListForModule(sModule, nIFlags, nEFlags);
553             OUStringList::const_iterator pIt3;
554             for (  pIt3  = lFilters4Module.begin();
555                    pIt3 != lFilters4Module.end()  ;
556                  ++pIt3                           )
557             {
558                 const ::rtl::OUString& sFilter = *pIt3;
559                 lFilterList.push_back(sFilter);
560             }
561         }
562     }
563 
564     return lFilterList;
565 }
566 
567 /*-----------------------------------------------
568     21.01.2005 10:19
569 -----------------------------------------------*/
impl_getListOfInstalledModules() const570 OUStringList FilterFactory::impl_getListOfInstalledModules() const
571 {
572     // SAFE -> ----------------------
573     ::osl::ResettableMutexGuard aLock(m_aLock);
574     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
575     aLock.clear();
576     // <- SAFE ----------------------
577 
578     try
579     {
580         css::uno::Reference< css::container::XNameAccess > xModuleConfig(
581             ::comphelper::ConfigurationHelper::openConfig(xSMGR,
582                                                           CFGPACKAGE_OOO_MODULES,
583                                                           ::comphelper::ConfigurationHelper::E_READONLY),
584             css::uno::UNO_QUERY_THROW);
585         OUStringList lModules(xModuleConfig->getElementNames());
586         return lModules;
587     }
588     catch(const css::uno::RuntimeException& exRun)
589         { throw exRun; }
590     catch(const css::uno::Exception&)
591         {}
592 
593     return OUStringList();
594 }
595 
596 /*-----------------------------------------------
597     21.01.2005 10:19
598 -----------------------------------------------*/
impl_getSortedFilterListForModule(const::rtl::OUString & sModule,sal_Int32 nIFlags,sal_Int32 nEFlags) const599 OUStringList FilterFactory::impl_getSortedFilterListForModule(const ::rtl::OUString& sModule,
600                                                                     sal_Int32        nIFlags,
601                                                                     sal_Int32        nEFlags) const
602 {
603     OUStringList lSortedFilters = impl_readSortedFilterListFromConfig(sModule);
604 
605     // get all filters for the requested module
606     CacheItem lIProps;
607     lIProps[PROPNAME_DOCUMENTSERVICE] <<= sModule;
608 
609     // SAFE -> ----------------------
610     ::osl::ResettableMutexGuard aLock(m_aLock);
611     FilterCache* pCache        = impl_getWorkingCache();
612     OUStringList lOtherFilters = pCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
613     aLock.clear();
614     // <- SAFE ----------------------
615 
616     // bring "other" filters in an alphabeticly order
617     // It's needed below.
618     ::std::sort(lOtherFilters.begin(), lOtherFilters.end());
619 
620     // merge both lists together
621 	OUStringList           lMergedFilters = lSortedFilters;
622     OUStringList::iterator pIt2;
623     OUStringList::iterator pIt3;
624     for (  pIt2  = lOtherFilters.begin();
625            pIt2 != lOtherFilters.end()  ;
626          ++pIt2                         )
627     {
628         const ::rtl::OUString& rFilter = *pIt2;
629         pIt3 = ::std::find(lSortedFilters.begin(), lSortedFilters.end(), rFilter);
630         if (pIt3 == lSortedFilters.end())
631             lMergedFilters.push_back(rFilter);
632     }
633 
634     // remove all filters from this merged list, which does not fit the flag specification
635     if (nIFlags != -1)
636     {
637         pIt2 = ::std::remove_if(lMergedFilters.begin(), lMergedFilters.end(), stlcomp_removeIfMatchFlags(pCache, nIFlags, sal_True));
638         lMergedFilters.erase(pIt2, lMergedFilters.end());
639     }
640     if (nEFlags != -1)
641     {
642         pIt2 = ::std::remove_if(lMergedFilters.begin(), lMergedFilters.end(), stlcomp_removeIfMatchFlags(pCache, nEFlags, sal_False));
643         lMergedFilters.erase(pIt2, lMergedFilters.end());
644     }
645 
646     // sort the default filter to the front of this list
647     // TODO
648 
649     return lMergedFilters;
650 }
651 
652 /*-----------------------------------------------
653     21.01.2005 10:19
654 -----------------------------------------------*/
impl_readSortedFilterListFromConfig(const::rtl::OUString & sModule) const655 OUStringList FilterFactory::impl_readSortedFilterListFromConfig(const ::rtl::OUString& sModule) const
656 {
657     // SAFE -> ----------------------
658     ::osl::ResettableMutexGuard aLock(m_aLock);
659     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
660     aLock.clear();
661     // <- SAFE ----------------------
662 
663     try
664     {
665         css::uno::Reference< css::container::XNameAccess > xUISortConfig(
666             ::comphelper::ConfigurationHelper::openConfig(xSMGR,
667                                                           CFGPACKAGE_TD_UISORT,
668                                                           ::comphelper::ConfigurationHelper::E_READONLY),
669             css::uno::UNO_QUERY_THROW);
670 
671         // dont ccheck the module name here. If it does not exists, an exception is thrown and catched below.
672         // We return an empty list as result then.
673         css::uno::Reference< css::container::XNameAccess > xModule;
674         xUISortConfig->getByName(sModule) >>= xModule;
675         if (xModule.is()) // only to be on the safe side of life if the exception was not thrown .-)
676         {
677             // Note: conversion of the returned Any to OUStringList throws
678             // an IllegalArgumentException if the type does not match ...
679             // but it resets the OUStringList to a length of 0 if the Any is empty!
680             OUStringList lSortedFilters(xModule->getByName(PROPNAME_SORTEDFILTERLIST));
681             return lSortedFilters;
682         }
683     }
684     catch(const css::uno::RuntimeException& exRun)
685         { throw exRun; }
686     catch(const css::uno::Exception&)
687         {}
688 
689     return OUStringList();
690 }
691 
692 /*-----------------------------------------------
693     09.07.2003 07:43
694 -----------------------------------------------*/
impl_getImplementationName()695 ::rtl::OUString FilterFactory::impl_getImplementationName()
696 {
697     return ::rtl::OUString::createFromAscii("com.sun.star.comp.filter.config.FilterFactory");
698 }
699 
700 /*-----------------------------------------------
701     09.07.2003 07:43
702 -----------------------------------------------*/
impl_getSupportedServiceNames()703 css::uno::Sequence< ::rtl::OUString > FilterFactory::impl_getSupportedServiceNames()
704 {
705     css::uno::Sequence< ::rtl::OUString > lServiceNames(1);
706     lServiceNames[0] = ::rtl::OUString::createFromAscii("com.sun.star.document.FilterFactory");
707     return lServiceNames;
708 }
709 
710 /*-----------------------------------------------
711     09.07.2003 07:43
712 -----------------------------------------------*/
impl_createInstance(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)713 css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::impl_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
714 {
715     FilterFactory* pNew = new FilterFactory(xSMGR);
716     return css::uno::Reference< css::uno::XInterface >(static_cast< css::lang::XMultiServiceFactory* >(pNew), css::uno::UNO_QUERY);
717 }
718 
719     } // namespace config
720 } // namespace filter
721