xref: /aoo41x/main/sfx2/source/bastyp/fltfnc.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include "fltfnc.hxx"
32 #include <com/sun/star/uno/Exception.hpp>
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/beans/NamedValue.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/container/XEnumeration.hpp>
37 #include <com/sun/star/datatransfer/DataFlavor.hpp>
38 #include <com/sun/star/document/XTypeDetection.hpp>
39 #include <com/sun/star/container/XContainerQuery.hpp>
40 
41 #include <comphelper/sequenceashashmap.hxx>
42 
43 #ifndef _EXCHANGE_HXX //autogen
44 #include <sot/exchange.hxx>
45 #endif
46 #include <tools/config.hxx>
47 #include <basic/sbmeth.hxx>
48 #include <basic/basmgr.hxx>
49 #include <basic/sbstar.hxx>
50 #include <basic/sbxobj.hxx>
51 #include <basic/sbxmeth.hxx>
52 #include <basic/sbxcore.hxx>
53 #ifndef _MSGBOX_HXX //autogen
54 #include <vcl/msgbox.hxx>
55 #endif
56 #ifndef _RTL_USTRING_HXX //autogen
57 #include <rtl/ustring.hxx>
58 #endif
59 #include <rtl/ustrbuf.hxx>
60 #include <svl/eitem.hxx>
61 #include <svl/intitem.hxx>
62 #include <svl/stritem.hxx>
63 #include <svl/lckbitem.hxx>
64 #include <svl/inettype.hxx>
65 #include <svl/rectitem.hxx>
66 
67 #include <sot/storage.hxx>
68 #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
69 #include <com/sun/star/frame/XDispatch.hpp>
70 #include <com/sun/star/frame/XDispatchProvider.hpp>
71 #include <com/sun/star/frame/XStatusListener.hpp>
72 #include <com/sun/star/frame/FrameSearchFlag.hpp>
73 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
74 #include <com/sun/star/frame/FeatureStateEvent.hpp>
75 #include <com/sun/star/frame/DispatchDescriptor.hpp>
76 #include <com/sun/star/frame/XController.hpp>
77 #include <com/sun/star/frame/XFrameActionListener.hpp>
78 #include <com/sun/star/frame/XComponentLoader.hpp>
79 #include <com/sun/star/frame/XFrame.hpp>
80 #include <com/sun/star/frame/FrameActionEvent.hpp>
81 #include <com/sun/star/frame/FrameAction.hpp>
82 #include <com/sun/star/frame/XFrameLoader.hpp>
83 #include <com/sun/star/frame/XLoadEventListener.hpp>
84 #include <com/sun/star/frame/XFilterDetect.hpp>
85 #include <com/sun/star/loader/XImplementationLoader.hpp>
86 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
87 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX
88 #include <comphelper/processfactory.hxx>
89 #endif
90 #include <com/sun/star/beans/PropertyValue.hpp>
91 
92 #include <sal/types.h>
93 #include <com/sun/star/uno/Reference.hxx>
94 #include <com/sun/star/ucb/XContent.hpp>
95 #include <rtl/ustring.hxx>
96 #include <vos/process.hxx>
97 #include <unotools/pathoptions.hxx>
98 #include <unotools/moduleoptions.hxx>
99 #include <comphelper/mediadescriptor.hxx>
100 #include <tools/urlobj.hxx>
101 
102 #include <rtl/logfile.hxx>
103 
104 using namespace ::com::sun::star::uno;
105 using namespace ::com::sun::star::ucb;
106 using namespace ::com::sun::star::document;
107 using namespace ::com::sun::star::beans;
108 using namespace ::vos;
109 #include <svl/ctypeitm.hxx>
110 #include <svtools/sfxecode.hxx>
111 #include <unotools/syslocale.hxx>
112 
113 #include "sfx2/sfxhelp.hxx"
114 #include <sfx2/docfilt.hxx>
115 #include <sfx2/docfac.hxx>
116 #include "sfxtypes.hxx"
117 #include <sfx2/sfxuno.hxx>
118 #include <sfx2/docfile.hxx>
119 #include <sfx2/progress.hxx>
120 #include "openflag.hxx"
121 #include "bastyp.hrc"
122 #include "sfx2/sfxresid.hxx"
123 #include <sfx2/doctempl.hxx>
124 #include <sfx2/frame.hxx>
125 #include <sfx2/dispatch.hxx>
126 #include <sfx2/viewfrm.hxx>
127 #include "helper.hxx"
128 #include "fltlst.hxx"
129 #include <sfx2/request.hxx>
130 #include "arrdecl.hxx"
131 #include <sfx2/appuno.hxx>
132 #include <sfx2/viewfrm.hxx>
133 
134 static SfxFilterList_Impl* pFilterArr = 0;
135 static sal_Bool bFirstRead = sal_True;
136 
137 static void CreateFilterArr()
138 {
139 	pFilterArr = new SfxFilterList_Impl;
140 	new SfxFilterListener();
141 }
142 
143 //----------------------------------------------------------------
144 inline String ToUpper_Impl( const String &rStr )
145 {
146     return SvtSysLocale().GetCharClass().upper( rStr );
147 }
148 
149 //----------------------------------------------------------------
150 class SfxFilterContainer_Impl
151 {
152 public:
153     String 				aName;
154     String 				aServiceName;
155 
156 						SfxFilterContainer_Impl( const String& rName )
157 							: aName( rName )
158 						{
159 							aServiceName = SfxObjectShell::GetServiceNameFromFactory( rName );
160 						}
161 };
162 
163 #define IMPL_FORWARD_LOOP( aMethod, ArgType, aArg )         \
164 const SfxFilter* SfxFilterContainer::aMethod( ArgType aArg, SfxFilterFlags nMust, SfxFilterFlags nDont ) const \
165 {\
166 	SfxFilterMatcher aMatch( pImpl->aName ); \
167 	return aMatch.aMethod( aArg, nMust, nDont ); \
168 }
169 
170 IMPL_FORWARD_LOOP( GetFilter4Mime, const String&, rMime );
171 IMPL_FORWARD_LOOP( GetFilter4ClipBoardId, sal_uInt32, nId );
172 IMPL_FORWARD_LOOP( GetFilter4EA, const String&, rEA );
173 IMPL_FORWARD_LOOP( GetFilter4Extension, const String&, rExt );
174 IMPL_FORWARD_LOOP( GetFilter4FilterName, const String&, rName );
175 IMPL_FORWARD_LOOP( GetFilter4UIName, const String&, rName );
176 
177 const SfxFilter* SfxFilterContainer::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
178 {
179 	SfxFilterMatcher aMatch( pImpl->aName );
180 	return aMatch.GetAnyFilter( nMust, nDont );
181 }
182 
183 //----------------------------------------------------------------
184 
185 SfxFilterContainer::SfxFilterContainer( const String& rName )
186 {
187 	pImpl = new SfxFilterContainer_Impl( rName );
188 }
189 
190 //----------------------------------------------------------------
191 
192 SfxFilterContainer::~SfxFilterContainer()
193 {
194 }
195 
196 //----------------------------------------------------------------
197 
198 const String SfxFilterContainer::GetName() const
199 {
200     return pImpl->aName;
201 }
202 
203 const SfxFilter* SfxFilterContainer::GetDefaultFilter_Impl( const String& rName )
204 {
205 	// Try to find out the type of factory.
206 	// Interpret given name as Service- and ShortName!
207 	SvtModuleOptions aOpt;
208     SvtModuleOptions::EFactory eFactory = aOpt.ClassifyFactoryByServiceName(rName);
209     if (eFactory == SvtModuleOptions::E_UNKNOWN_FACTORY)
210 		eFactory = aOpt.ClassifyFactoryByShortName(rName);
211 
212 	// could not classify factory by its service nor by its short name.
213 	// Must be an unknown factory! => return NULL
214 	if (eFactory == SvtModuleOptions::E_UNKNOWN_FACTORY)
215 		return NULL;
216 
217 	// For the following code we need some additional informations.
218 	String sServiceName   = aOpt.GetFactoryName(eFactory);
219 	String sShortName     = aOpt.GetFactoryShortName(eFactory);
220     String sDefaultFilter = aOpt.GetFactoryDefaultFilter(eFactory);
221 
222 	// Try to get the default filter. Dont fiorget to verify it.
223 	// May the set default filter does not exists any longer or
224 	// does not fit the given factory.
225     const SfxFilterMatcher aMatcher;
226     const SfxFilter* pFilter = aMatcher.GetFilter4FilterName(sDefaultFilter);
227 
228 	if (
229 		(pFilter																			) &&
230 		(pFilter->GetServiceName().CompareIgnoreCaseToAscii( sServiceName ) != COMPARE_EQUAL)
231 	   )
232 	{
233 		pFilter = 0;
234 	}
235 
236 	// If at least no default filter could be located - use any filter of this
237 	// factory.
238 	if (!pFilter)
239     {
240         if ( bFirstRead )
241             ReadFilters_Impl();
242 
243         sal_uInt16 nCount = ( sal_uInt16 ) pFilterArr->Count();
244         for( sal_uInt16 n = 0; n < nCount; n++ )
245         {
246             const SfxFilter* pCheckFilter = pFilterArr->GetObject( n );
247             if ( pCheckFilter->GetServiceName().CompareIgnoreCaseToAscii( sServiceName ) == COMPARE_EQUAL )
248             {
249                 pFilter = pCheckFilter;
250                 break;
251             }
252         }
253     }
254 
255     return pFilter;
256 }
257 
258 
259 //----------------------------------------------------------------
260 
261 class SfxFilterMatcherArr_Impl;
262 static SfxFilterMatcherArr_Impl* pImplArr = 0;
263 
264 // Impl-Data is shared between all FilterMatchers of the same factory
265 class SfxFilterMatcher_Impl
266 {
267 public:
268 	::rtl::OUString 	aName;
269 	SfxFilterList_Impl* pList;		// is created on demand
270 
271 	void				InitForIterating() const;
272 	void				Update();
273 						SfxFilterMatcher_Impl()
274 							: pList(0)
275 						{}
276 };
277 
278 DECL_PTRARRAY( SfxFilterMatcherArr_Impl, SfxFilterMatcher_Impl*, 2, 2 )
279 
280 SfxFilterMatcher::SfxFilterMatcher( const String& rName )
281 	: pImpl( 0 )
282 {
283 	if ( !pImplArr )
284 		// keep track of created filter matchers to recycle the FilterLists
285 		pImplArr = new SfxFilterMatcherArr_Impl;
286 
287 	String aName = SfxObjectShell::GetServiceNameFromFactory( rName );
288     DBG_ASSERT(aName.Len(), "Found boes type :-)");
289 	for ( sal_uInt16 n=0; n<pImplArr->Count(); n++ )
290 	{
291 		// find the impl-Data of any comparable FilterMatcher that was created before
292 		SfxFilterMatcher_Impl* pImp = pImplArr->GetObject(n);
293 		if ( String(pImp->aName) == aName )
294 			pImpl = pImp;
295 	}
296 
297 	if ( !pImpl )
298 	{
299 		// first Matcher created for this factory
300     	pImpl = new SfxFilterMatcher_Impl;
301 		pImpl->aName = aName;
302 		pImplArr->Insert( pImplArr->Count(), pImpl );
303 	}
304 }
305 
306 SfxFilterMatcher::SfxFilterMatcher()
307 {
308 	// global FilterMatcher always uses global filter array (also created on demand)
309     pImpl = new SfxFilterMatcher_Impl;
310 }
311 
312 SfxFilterMatcher::~SfxFilterMatcher()
313 {
314 	if ( !pImpl->aName.getLength() )
315 		// only the global Matcher owns his ImplData
316 		delete pImpl;
317 }
318 
319 void SfxFilterMatcher_Impl::Update()
320 {
321 	if ( pList )
322 	{
323 		// this List was already used
324 		pList->Clear();
325 		for ( sal_uInt16 n=0; n<pFilterArr->Count(); n++ )
326 		{
327 			SfxFilter* pFilter = pFilterArr->GetObject(n);
328 			if ( pFilter->GetServiceName() == String(aName) )
329 				pList->Insert( pFilter, LIST_APPEND );
330 		}
331 	}
332 }
333 
334 void SfxFilterMatcher_Impl::InitForIterating() const
335 {
336 	if ( pList )
337 		return;
338 
339 	if ( bFirstRead )
340 		// global filter array has not been created yet
341 		SfxFilterContainer::ReadFilters_Impl();
342 
343 	if ( aName.getLength() )
344 	{
345 		// matcher of factory: use only filters of that document type
346 		((SfxFilterMatcher_Impl*)this)->pList = new SfxFilterList_Impl;
347 		((SfxFilterMatcher_Impl*)this)->Update();
348 	}
349 	else
350 	{
351 		// global matcher: use global filter array
352 		((SfxFilterMatcher_Impl*)this)->pList = pFilterArr;
353 	}
354 }
355 
356 const SfxFilter* SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
357 {
358 	pImpl->InitForIterating();
359     sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count();
360     for( sal_uInt16 n = 0; n < nCount; n++ )
361     {
362         const SfxFilter* pFilter = pImpl->pList->GetObject( n );
363         SfxFilterFlags nFlags = pFilter->GetFilterFlags();
364         if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) )
365             return pFilter;
366     }
367 
368     return NULL;
369 }
370 
371 //----------------------------------------------------------------
372 
373 sal_uInt32  SfxFilterMatcher::GuessFilterIgnoringContent(
374     SfxMedium& rMedium,
375     const SfxFilter**ppFilter,
376     SfxFilterFlags /*nMust*/,
377     SfxFilterFlags /*nDont*/ ) const
378 {
379     Reference< XTypeDetection > xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection")), UNO_QUERY );
380     ::rtl::OUString sTypeName;
381     try
382     {
383 		//!MBA: nmust, ndont?
384         sTypeName = xDetection->queryTypeByURL( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
385     }
386     catch( Exception& )
387     {
388     }
389 
390 	*ppFilter = NULL;
391 	if ( sTypeName.getLength() )
392 		*ppFilter = GetFilter4EA( sTypeName );
393 
394 	return *ppFilter ? ERRCODE_NONE : ERRCODE_ABORT;
395 }
396 
397 //----------------------------------------------------------------
398 
399 #define CHECKERROR()											\
400 if( nErr == 1 || nErr == USHRT_MAX || nErr == ULONG_MAX )		\
401 {																\
402 	ByteString aText = "Fehler in FilterDetection: Returnwert ";\
403 	aText += ByteString::CreateFromInt32(nErr);					\
404 	if( pFilter )												\
405 	{															\
406 		aText += ' ';											\
407         aText += ByteString(U2S(pFilter->GetFilterName()));     \
408 	}															\
409 	DBG_ERROR( aText.GetBuffer() );								\
410 	nErr = ERRCODE_ABORT;										\
411 }
412 
413 //----------------------------------------------------------------
414 
415 sal_uInt32  SfxFilterMatcher::GuessFilter( SfxMedium& rMedium, const SfxFilter**ppFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
416 {
417 	return GuessFilterControlDefaultUI( rMedium, ppFilter, nMust, nDont, sal_True );
418 }
419 
420 //----------------------------------------------------------------
421 
422 sal_uInt32  SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium& rMedium, const SfxFilter** ppFilter, SfxFilterFlags nMust, SfxFilterFlags nDont, sal_Bool /*bDefUI*/ ) const
423 {
424     const SfxFilter* pOldFilter = *ppFilter;
425 
426     // no detection service -> nothing to do !
427     Reference< XTypeDetection > xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection")), UNO_QUERY );
428     if (!xDetection.is())
429         return ERRCODE_ABORT;
430 
431     ::rtl::OUString sTypeName;
432     try
433     {
434         // open the stream one times only ...
435         // Otherwhise it will be tried more then once and show the same interaction more then once ...
436 
437         ::rtl::OUString sURL( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
438         ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInStream = rMedium.GetInputStream();
439 
440         // stream exists => deep detection (with preselection ... if possible)
441         if (xInStream.is())
442         {
443             ::comphelper::MediaDescriptor aDescriptor;
444 
445             aDescriptor[::comphelper::MediaDescriptor::PROP_URL()               ] <<= sURL;
446             aDescriptor[::comphelper::MediaDescriptor::PROP_INPUTSTREAM()       ] <<= xInStream;
447             aDescriptor[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= rMedium.GetInteractionHandler();
448 
449             if ( pImpl->aName.getLength() )
450                 aDescriptor[::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE()] <<= pImpl->aName;
451 
452             if ( pOldFilter )
453             {
454                 aDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()  ] <<= ::rtl::OUString( pOldFilter->GetTypeName()   );
455                 aDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= ::rtl::OUString( pOldFilter->GetFilterName() );
456             }
457 
458             ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lDescriptor = aDescriptor.getAsConstPropertyValueList();
459             sTypeName = xDetection->queryTypeByDescriptor(lDescriptor, sal_True); // lDescriptor is used as In/Out param ... dont use aDescriptor.getAsConstPropertyValueList() directly!
460         }
461         // no stream exists => try flat detection without preselection as fallback
462         else
463             sTypeName = xDetection->queryTypeByURL(sURL);
464 
465         if (sTypeName.getLength())
466         {
467             // detect filter by given type
468             // In case of this matcher is bound to a particular document type:
469             // If there is no acceptable type for this document at all, the type detection has possibly returned something else.
470             // The DocumentService property is only a preselection, and all preselections are considered as optional!
471             // This "wrong" type will be sorted out now because we match only allowed filters to the detected type
472             ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > lQuery(1);
473             lQuery[0].Name = ::rtl::OUString::createFromAscii("Name");
474             lQuery[0].Value <<= sTypeName;
475 
476             const SfxFilter* pFilter = GetFilterForProps(lQuery, nMust, nDont);
477             if (pFilter)
478             {
479                 *ppFilter = pFilter;
480                 return ERRCODE_NONE;
481             }
482         }
483     }
484     catch(const Exception&)
485     {}
486 
487     return ERRCODE_ABORT;
488 }
489 
490 //----------------------------------------------------------------
491 sal_Bool SfxFilterMatcher::IsFilterInstalled_Impl( const SfxFilter* pFilter )
492 {
493 	if ( pFilter->GetFilterFlags() & SFX_FILTER_MUSTINSTALL )
494 	{
495 		// Hier k"onnte noch eine Nachinstallation angeboten werden
496 		String aText( SfxResId( STR_FILTER_NOT_INSTALLED ) );
497 		aText.SearchAndReplaceAscii( "$(FILTER)", pFilter->GetUIName() );
498         QueryBox aQuery( NULL, WB_YES_NO | WB_DEF_YES, aText );
499 		short nRet = aQuery.Execute();
500 		if ( nRet == RET_YES )
501 		{
502 #ifdef DBG_UTIL
503 			// Setup starten
504             InfoBox( NULL, DEFINE_CONST_UNICODE("Hier soll jetzt das Setup starten!") ).Execute();
505 #endif
506 			// Installation mu\s hier noch mitteilen, ob es geklappt hat, dann kann das
507 			// Filterflag gel"oscht werden
508 		}
509 
510 		return ( !(pFilter->GetFilterFlags() & SFX_FILTER_MUSTINSTALL) );
511 	}
512 	else if ( pFilter->GetFilterFlags() & SFX_FILTER_CONSULTSERVICE )
513 	{
514 		String aText( SfxResId( STR_FILTER_CONSULT_SERVICE ) );
515 		aText.SearchAndReplaceAscii( "$(FILTER)", pFilter->GetUIName() );
516         InfoBox ( NULL, aText ).Execute();
517 		return sal_False;
518 	}
519 	else
520 		return sal_True;
521 }
522 
523 
524 sal_uInt32 SfxFilterMatcher::DetectFilter( SfxMedium& rMedium, const SfxFilter**ppFilter, sal_Bool /*bPlugIn*/, sal_Bool bAPI ) const
525 /*  [Beschreibung]
526 
527     Hier wird noch die Filterauswahlbox hochgezogen. Sonst GuessFilter
528  */
529 
530 {
531     const SfxFilter* pOldFilter = rMedium.GetFilter();
532     if ( pOldFilter )
533     {
534         if( !IsFilterInstalled_Impl( pOldFilter ) )
535             pOldFilter = 0;
536         else
537         {
538             SFX_ITEMSET_ARG( rMedium.GetItemSet(), pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False);
539             if ( ( pOldFilter->GetFilterFlags() & SFX_FILTER_PACKED ) && pSalvageItem )
540                 // Salvage is always done without packing
541                 pOldFilter = 0;
542         }
543     }
544 
545     const SfxFilter* pFilter = pOldFilter;
546 
547     sal_Bool bPreview = rMedium.IsPreview_Impl();
548 	SFX_ITEMSET_ARG(rMedium.GetItemSet(), pReferer, SfxStringItem, SID_REFERER, sal_False);
549     if ( bPreview && rMedium.IsRemote() && ( !pReferer || pReferer->GetValue().CompareToAscii("private:searchfolder:",21 ) != COMPARE_EQUAL ) )
550         return ERRCODE_ABORT;
551 
552 	ErrCode nErr = GuessFilter( rMedium, &pFilter );
553 	if ( nErr == ERRCODE_ABORT )
554 		return nErr;
555 
556 	if ( nErr == ERRCODE_IO_PENDING )
557 	{
558 		*ppFilter = pFilter;
559 		return nErr;
560 	}
561 
562 	if ( !pFilter )
563 	{
564     	const SfxFilter* pInstallFilter = NULL;
565 
566 		// Jetzt auch Filter testen, die nicht installiert sind ( ErrCode ist irrelevant )
567 		GuessFilter( rMedium, &pInstallFilter, SFX_FILTER_IMPORT, SFX_FILTER_CONSULTSERVICE );
568 		if ( pInstallFilter )
569 		{
570 			if ( IsFilterInstalled_Impl( pInstallFilter ) )
571 				// Eventuell wurde der Filter nachinstalliert
572 				pFilter = pInstallFilter;
573 		}
574 		else
575 		{
576 			// Jetzt auch Filter testen, die erst von Star bezogen werden m"ussen ( ErrCode ist irrelevant )
577 			GuessFilter( rMedium, &pInstallFilter, SFX_FILTER_IMPORT, 0 );
578 			if ( pInstallFilter )
579 				IsFilterInstalled_Impl( pInstallFilter );
580 		}
581 	}
582 
583     sal_Bool bHidden = bPreview;
584 	SFX_ITEMSET_ARG( rMedium.GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False);
585     if ( !bHidden && pFlags )
586     {
587         String aFlags( pFlags->GetValue() );
588         aFlags.ToUpperAscii();
589         if( STRING_NOTFOUND != aFlags.Search( 'H' ) )
590             bHidden = sal_True;
591     }
592     *ppFilter = pFilter;
593 
594     if ( bHidden || (bAPI && nErr == ERRCODE_SFX_CONSULTUSER) )
595 		nErr = pFilter ? ERRCODE_NONE : ERRCODE_ABORT;
596     return nErr;
597 }
598 
599 const SfxFilter* SfxFilterMatcher::GetFilterForProps( const com::sun::star::uno::Sequence < ::com::sun::star::beans::NamedValue >& aSeq, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
600 {
601     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
602     ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery > xTypeCFG;
603     if( xServiceManager.is() == sal_True )
604         xTypeCFG   = ::com::sun::star::uno::Reference < com::sun::star::container::XContainerQuery >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY );
605     if ( xTypeCFG.is() )
606     {
607         // make query for all types matching the properties
608         ::com::sun::star::uno::Reference < com::sun::star::container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq );
609         while ( xEnum->hasMoreElements() )
610         {
611             ::comphelper::SequenceAsHashMap aProps( xEnum->nextElement() );
612             ::rtl::OUString aValue;
613 
614             // try to get the preferred filter (works without loading all filters!)
615             if ( (aProps[::rtl::OUString::createFromAscii("PreferredFilter")] >>= aValue) && aValue.getLength() )
616             {
617                 const SfxFilter* pFilter = SfxFilter::GetFilterByName( aValue );
618                 if ( !pFilter || (pFilter->GetFilterFlags() & nMust) != nMust || (pFilter->GetFilterFlags() & nDont ) )
619                     // check for filter flags
620                     // pFilter == 0: if preferred filter is a Writer filter, but Writer module is not installed
621 					continue;
622 
623                 if ( pImpl->aName.getLength() )
624                 {
625                     // if this is not the global FilterMatcher: check if filter matches the document type
626                     ::rtl::OUString aService;
627                     if ( pFilter->GetServiceName() != String(pImpl->aName) )
628                     {
629                         // preferred filter belongs to another document type; now we must search the filter
630                         pImpl->InitForIterating();
631                         aProps[::rtl::OUString::createFromAscii("Name")] >>= aValue;
632                         pFilter = GetFilter4EA( aValue, nMust, nDont );
633                         if ( pFilter )
634                             return pFilter;
635                     }
636                     else
637                         return pFilter;
638                 }
639                 else
640                     return pFilter;
641             }
642         }
643     }
644 
645     return 0;
646 }
647 
648 const SfxFilter* SfxFilterMatcher::GetFilter4Mime( const String& rMediaType,SfxFilterFlags nMust, SfxFilterFlags nDont ) const
649 {
650 	if ( pImpl->pList )
651 	{
652 	    sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count();
653 	    for( sal_uInt16 n = 0; n < nCount; n++ )
654 	    {
655 	        const SfxFilter* pFilter = pImpl->pList->GetObject( n );
656 	        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
657 	        if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetMimeType() == rMediaType )
658 				return pFilter;
659 		}
660 
661 		return 0;
662 	}
663 
664 	com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
665 	aSeq[0].Name = ::rtl::OUString::createFromAscii("MediaType");
666 	aSeq[0].Value <<= ::rtl::OUString( rMediaType );
667 	return GetFilterForProps( aSeq, nMust, nDont );
668 }
669 
670 const SfxFilter* SfxFilterMatcher::GetFilter4EA( const String& rType,SfxFilterFlags nMust, SfxFilterFlags nDont ) const
671 {
672 	if ( pImpl->pList )
673 	{
674 	    sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count();
675         const SfxFilter* pFirst = 0;
676 	    for( sal_uInt16 n = 0; n < nCount; n++ )
677 	    {
678 	        const SfxFilter* pFilter = pImpl->pList->GetObject( n );
679 	        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
680 	        if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetTypeName() == rType )
681             {
682                 if (nFlags & SFX_FILTER_PREFERED)
683                     return pFilter;
684                 if (!pFirst)
685                     pFirst = pFilter;
686             }
687 		}
688         if (pFirst)
689             return pFirst;
690 
691 		return 0;
692 	}
693 
694 	com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
695 	aSeq[0].Name = ::rtl::OUString::createFromAscii("Name");
696 	aSeq[0].Value <<= ::rtl::OUString( rType );
697 	return GetFilterForProps( aSeq, nMust, nDont );
698 }
699 
700 const SfxFilter* SfxFilterMatcher::GetFilter4Extension( const String& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
701 {
702 	if ( pImpl->pList )
703 	{
704 	    sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count();
705 	    for( sal_uInt16 n = 0; n < nCount; n++ )
706 	    {
707 	        const SfxFilter* pFilter = pImpl->pList->GetObject( n );
708 	        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
709 	        if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) )
710 			{
711 				String sWildCard = ToUpper_Impl( pFilter->GetWildcard().GetWildCard() );
712 				String sExt      = ToUpper_Impl( rExt );
713 
714 				if (!sExt.Len())
715 					continue;
716 
717 				if (sExt.GetChar(0) != (sal_Unicode)'.')
718 					sExt.Insert((sal_Unicode)'.', 0);
719 
720 				WildCard aCheck(sWildCard, ';');
721 				if (aCheck.Matches(sExt))
722 					return pFilter;
723 			}
724 		}
725 
726 		return 0;
727 	}
728 
729     // Use extension without dot!
730     String sExt( rExt );
731     if ( sExt.Len() && ( sExt.GetChar(0) == (sal_Unicode)'.' ))
732         sExt.Erase(0,1);
733 
734     com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
735 	aSeq[0].Name = ::rtl::OUString::createFromAscii("Extensions");
736 	::com::sun::star::uno::Sequence < ::rtl::OUString > aExts(1);
737 	aExts[0] = sExt;
738 	aSeq[0].Value <<= aExts;
739 	return GetFilterForProps( aSeq, nMust, nDont );
740 }
741 
742 const SfxFilter* SfxFilterMatcher::GetFilter4ClipBoardId( sal_uInt32 nId, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
743 {
744 	if (nId == 0)
745 		return 0;
746 
747 	com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
748 	::rtl::OUString aName = SotExchange::GetFormatName( nId );
749 	aSeq[0].Name = ::rtl::OUString::createFromAscii("ClipboardFormat");
750 	aSeq[0].Value <<= aName;
751 	return GetFilterForProps( aSeq, nMust, nDont );
752 }
753 
754 const SfxFilter* SfxFilterMatcher::GetFilter4UIName( const String& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
755 {
756 	pImpl->InitForIterating();
757     const SfxFilter* pFirstFilter=0;
758     sal_uInt16 nCount = ( sal_uInt16 ) pImpl->pList->Count();
759     for( sal_uInt16 n = 0; n < nCount; n++ )
760     {
761         const SfxFilter* pFilter = pImpl->pList->GetObject( n );
762         SfxFilterFlags nFlags = pFilter->GetFilterFlags();
763         if ( (nFlags & nMust) == nMust &&
764              !(nFlags & nDont ) && pFilter->GetUIName() == rName )
765         {
766             if ( pFilter->GetFilterFlags() & SFX_FILTER_PREFERED )
767                 return pFilter;
768             else if ( !pFirstFilter )
769                 pFirstFilter = pFilter;
770         }
771     }
772     return pFirstFilter;
773 }
774 
775 const SfxFilter* SfxFilterMatcher::GetFilter4FilterName( const String& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
776 {
777 	String aName( rName );
778 	sal_uInt16 nIndex = aName.SearchAscii(": ");
779 	if (  nIndex != STRING_NOTFOUND )
780 	{
781 		DBG_ERROR("Old filter name used!");
782 		aName = rName.Copy( nIndex + 2 );
783 	}
784 
785 	if ( bFirstRead )
786 	{
787         ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
788         ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >     xFilterCFG                                                ;
789         ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >     xTypeCFG                                                  ;
790         if( xServiceManager.is() == sal_True )
791         {
792             xFilterCFG = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), ::com::sun::star::uno::UNO_QUERY );
793             xTypeCFG   = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY );
794         }
795 
796 		if( xFilterCFG.is() && xTypeCFG.is() )
797 		{
798 			if ( !pFilterArr )
799 				CreateFilterArr();
800 			else
801 			{
802 			    for( sal_uInt16 n=0; n<pFilterArr->Count(); n++ )
803 			    {
804 	        		const SfxFilter* pFilter = pFilterArr->GetObject( n );
805 			        SfxFilterFlags nFlags = pFilter->GetFilterFlags();
806 			        if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().CompareIgnoreCaseToAscii( aName ) == COMPARE_EQUAL )
807 			        	return pFilter;
808 				}
809 			}
810 
811 			SfxFilterContainer::ReadSingleFilter_Impl( rName, xTypeCFG, xFilterCFG, sal_False );
812 		}
813 	}
814 
815     SfxFilterList_Impl* pList = pImpl->pList;
816 	if ( !pList )
817 		pList = pFilterArr;
818 
819     sal_uInt16 nCount = ( sal_uInt16 ) pList->Count();
820     for( sal_uInt16 n = 0; n < nCount; n++ )
821     {
822         const SfxFilter* pFilter = pList->GetObject( n );
823         SfxFilterFlags nFlags = pFilter->GetFilterFlags();
824         if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().CompareIgnoreCaseToAscii( aName ) == COMPARE_EQUAL )
825         	return pFilter;
826     }
827 
828     return NULL;
829 }
830 
831 IMPL_STATIC_LINK( SfxFilterMatcher, MaybeFileHdl_Impl, String*, pString )
832 {
833 	const SfxFilter* pFilter = pThis->GetFilter4Extension( *pString, SFX_FILTER_IMPORT );
834 	if( pFilter && !pFilter->GetWildcard().Matches( String() ) &&
835 		pFilter->GetWildcard() != DEFINE_CONST_UNICODE("*.*") && pFilter->GetWildcard() != '*' )
836 		return sal_True;
837 	return sal_False;
838 }
839 
840 //----------------------------------------------------------------
841 
842 SfxFilterMatcherIter::SfxFilterMatcherIter(
843     const SfxFilterMatcher* pMatchP,
844 	SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP )
845     : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ),
846       nCurrent(0), pMatch( pMatchP->pImpl)
847 {
848     if( nOrMask == 0xffff ) //Wg. Fehlbuild auf s
849         nOrMask = 0;
850 	pMatch->InitForIterating();
851 }
852 
853 //----------------------------------------------------------------
854 
855 const SfxFilter* SfxFilterMatcherIter::Find_Impl()
856 {
857     const SfxFilter* pFilter = 0;
858     while( nCurrent < pMatch->pList->Count() )
859     {
860     	pFilter = pMatch->pList->GetObject(nCurrent++);
861         SfxFilterFlags nFlags = pFilter->GetFilterFlags();
862         if( ((nFlags & nOrMask) == nOrMask ) && !(nFlags & nAndMask ) )
863             break;
864 		pFilter = 0;
865     }
866 
867     return pFilter;
868 }
869 
870 const SfxFilter* SfxFilterMatcherIter::First()
871 {
872 	nCurrent = 0;
873 	return Find_Impl();
874 }
875 
876 //----------------------------------------------------------------
877 
878 const SfxFilter* SfxFilterMatcherIter::Next()
879 {
880 	return Find_Impl();
881 }
882 
883 /*---------------------------------------------------------------
884     helper to build own formated string from given stringlist by
885     using given seperator
886   ---------------------------------------------------------------*/
887 ::rtl::OUString implc_convertStringlistToString( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& lList     ,
888                                                  const sal_Unicode&                                        cSeperator,
889                                                  const ::rtl::OUString&                                    sPrefix   )
890 {
891     ::rtl::OUStringBuffer   sString ( 1000 )           ;
892     sal_Int32               nCount  = lList.getLength();
893     sal_Int32               nItem   = 0                ;
894     for( nItem=0; nItem<nCount; ++nItem )
895     {
896         if( sPrefix.getLength() > 0 )
897         {
898             sString.append( sPrefix );
899         }
900         sString.append( lList[nItem] );
901         if( nItem+1<nCount )
902         {
903             sString.append( cSeperator );
904         }
905     }
906     return sString.makeStringAndClear();
907 }
908 
909 
910 void SfxFilterContainer::ReadSingleFilter_Impl(
911 	const ::rtl::OUString& rName,
912     const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xTypeCFG,
913 	const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xFilterCFG,
914 	sal_Bool bUpdate
915 	)
916 {
917 	::rtl::OUString sFilterName( rName );
918 	SfxFilterList_Impl& rList = *pFilterArr;
919 	::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lFilterProperties                           ;
920     ::com::sun::star::uno::Any aResult;
921     try
922     {
923         aResult = xFilterCFG->getByName( sFilterName );
924     }
925     catch( ::com::sun::star::container::NoSuchElementException& )
926     {
927         aResult = ::com::sun::star::uno::Any();
928     }
929 
930     if( aResult >>= lFilterProperties )
931     {
932         // collect informations to add filter to container
933         // (attention: some informations aren't available on filter directly ... you must search for corresponding type too!)
934         sal_Int32       nFlags          = 0 ;
935         sal_Int32       nClipboardId    = 0 ;
936         sal_Int32       nDocumentIconId = 0 ;
937         sal_Int32       nFormatVersion  = 0 ;
938         ::rtl::OUString sMimeType           ;
939         ::rtl::OUString sType               ;
940         ::rtl::OUString sUIName             ;
941         ::rtl::OUString sHumanName          ;
942         ::rtl::OUString sDefaultTemplate    ;
943         ::rtl::OUString sUserData           ;
944         ::rtl::OUString sExtension          ;
945         ::rtl::OUString sPattern            ;
946         ::rtl::OUString sServiceName        ;
947 
948         // first get directly available properties
949         sal_Int32 nFilterPropertyCount = lFilterProperties.getLength();
950         sal_Int32 nFilterProperty      = 0                            ;
951         for( nFilterProperty=0; nFilterProperty<nFilterPropertyCount; ++nFilterProperty )
952         {
953             if( lFilterProperties[nFilterProperty].Name.compareToAscii( "FileFormatVersion" ) == 0 )
954             {
955                 lFilterProperties[nFilterProperty].Value >>= nFormatVersion;
956             }
957             else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "TemplateName" ) == 0 )
958             {
959                 lFilterProperties[nFilterProperty].Value >>= sDefaultTemplate;
960             }
961             else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "Flags" ) == 0 )
962             {
963                 lFilterProperties[nFilterProperty].Value >>= nFlags;
964             }
965             else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "UIName" ) == 0 )
966             {
967                 lFilterProperties[nFilterProperty].Value >>= sUIName;
968             }
969             else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "UserData" ) == 0 )
970             {
971                 ::com::sun::star::uno::Sequence< ::rtl::OUString > lUserData;
972                 lFilterProperties[nFilterProperty].Value >>= lUserData;
973                 sUserData = implc_convertStringlistToString( lUserData, ',', ::rtl::OUString() );
974             }
975             else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "DocumentService" ) == 0 )
976             {
977                 lFilterProperties[nFilterProperty].Value >>= sServiceName;
978             }
979             else if( lFilterProperties[nFilterProperty].Name.compareToAscii( "Type" ) == 0 )
980             {
981                 lFilterProperties[nFilterProperty].Value >>= sType;
982                 // Try to get filter .. but look for any exceptions!
983                 // May be filter was deleted by another thread ...
984                 try
985                 {
986                     aResult = xTypeCFG->getByName( sType );
987                 }
988                 catch( ::com::sun::star::container::NoSuchElementException& )
989                 {
990                     aResult = ::com::sun::star::uno::Any();
991                 }
992 
993                 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lTypeProperties;
994                 if( aResult >>= lTypeProperties )
995                 {
996                     // get indirect available properties then (types)
997                     sal_Int32 nTypePropertyCount = lTypeProperties.getLength();
998                     sal_Int32 nTypeProperty      = 0                          ;
999                     for( nTypeProperty=0; nTypeProperty<nTypePropertyCount; ++nTypeProperty )
1000                     {
1001                         if( lTypeProperties[nTypeProperty].Name.compareToAscii( "ClipboardFormat" ) == 0 )
1002                         {
1003                             lTypeProperties[nTypeProperty].Value >>= sHumanName;
1004                         }
1005                         else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "DocumentIconID" ) == 0 )
1006                         {
1007                             lTypeProperties[nTypeProperty].Value >>= nDocumentIconId;
1008                         }
1009                         else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "MediaType" ) == 0 )
1010                         {
1011                             lTypeProperties[nTypeProperty].Value >>= sMimeType;
1012                         }
1013                         else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "Extensions" ) == 0 )
1014                         {
1015                             ::com::sun::star::uno::Sequence< ::rtl::OUString > lExtensions;
1016                             lTypeProperties[nTypeProperty].Value >>= lExtensions;
1017                             sExtension = implc_convertStringlistToString( lExtensions, ';', DEFINE_CONST_UNICODE("*.") );
1018                         }
1019                         else if( lTypeProperties[nTypeProperty].Name.compareToAscii( "URLPattern" ) == 0 )
1020                         {
1021                                 ::com::sun::star::uno::Sequence< ::rtl::OUString > lPattern;
1022                                 lTypeProperties[nTypeProperty].Value >>= lPattern;
1023                                 sPattern = implc_convertStringlistToString( lPattern, ';', ::rtl::OUString() );
1024                         }
1025                     }
1026                 }
1027             }
1028         }
1029 
1030 		if ( !sServiceName.getLength() )
1031 			return;
1032 
1033         // old formats are found ... using HumanPresentableName!
1034         if( sHumanName.getLength() )
1035         {
1036             nClipboardId = SotExchange::RegisterFormatName( sHumanName );
1037 
1038 			// #100570# For external filters ignore clipboard IDs
1039 			if((nFlags & SFX_FILTER_STARONEFILTER) == SFX_FILTER_STARONEFILTER)
1040 			{
1041 				nClipboardId = 0;
1042 			}
1043         }
1044         // register SfxFilter
1045         // first erase module name from old filter names!
1046         // e.g: "scalc: DIF" => "DIF"
1047         sal_Int32 nStartRealName = sFilterName.indexOf( DEFINE_CONST_UNICODE(": "), 0 );
1048         if( nStartRealName != -1 )
1049         {
1050             DBG_ERROR("Old format, not supported!");
1051             sFilterName = sFilterName.copy( nStartRealName+2 );
1052         }
1053 
1054 		SfxFilter* pFilter = bUpdate ? (SfxFilter*) SfxFilter::GetFilterByName( sFilterName ) : 0;
1055         sal_Bool bNew = sal_False;
1056         if (!pFilter)
1057         {
1058             bNew = sal_True;
1059             pFilter = new SfxFilter( sFilterName             ,
1060                                      sExtension              ,
1061                                      nFlags                  ,
1062                                      nClipboardId            ,
1063                                      sType                   ,
1064                                      (sal_uInt16)nDocumentIconId ,
1065                                      sMimeType               ,
1066                                      sUserData               ,
1067 									 sServiceName );
1068         }
1069         else
1070         {
1071             pFilter->aFilterName  = sFilterName;
1072             pFilter->aWildCard    = WildCard(sExtension, ';');
1073             pFilter->nFormatType  = nFlags;
1074             pFilter->lFormat      = nClipboardId;
1075             pFilter->aTypeName    = sType;
1076             pFilter->nDocIcon     = (sal_uInt16)nDocumentIconId;
1077             pFilter->aMimeType    = sMimeType;
1078             pFilter->aUserData    = sUserData;
1079 			pFilter->aServiceName = sServiceName;
1080         }
1081 
1082         // Don't forget to set right UIName!
1083         // Otherwise internal name is used as fallback ...
1084         pFilter->SetUIName( sUIName );
1085         pFilter->SetDefaultTemplate( sDefaultTemplate );
1086         if( nFormatVersion )
1087         {
1088             pFilter->SetVersion( nFormatVersion );
1089         }
1090         pFilter->SetURLPattern(sPattern);
1091 
1092         if (bNew)
1093 			rList.Insert( pFilter, USHRT_MAX );
1094     }
1095 }
1096 
1097 void SfxFilterContainer::ReadFilters_Impl( sal_Bool bUpdate )
1098 {
1099     RTL_LOGFILE_CONTEXT( aMeasure, "sfx2 (as96863) ::SfxFilterContainer::ReadFilters" );
1100 	if ( !pFilterArr )
1101 		CreateFilterArr();
1102 
1103 	bFirstRead = sal_False;
1104 	SfxFilterList_Impl& rList = *pFilterArr;
1105 
1106     try
1107     {
1108         // get the FilterFactory service to access the registered filters ... and types!
1109         ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
1110         ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >     xFilterCFG                                                ;
1111         ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >     xTypeCFG                                                  ;
1112         if( xServiceManager.is() == sal_True )
1113         {
1114             xFilterCFG = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), ::com::sun::star::uno::UNO_QUERY );
1115             xTypeCFG   = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY );
1116         }
1117 
1118         if(
1119             ( xFilterCFG.is() == sal_True ) &&
1120             ( xTypeCFG.is()   == sal_True )
1121           )
1122         {
1123             // select right query to get right set of filters for search modul
1124             ::com::sun::star::uno::Sequence< ::rtl::OUString > lFilterNames = xFilterCFG->getElementNames();
1125 			if ( lFilterNames.getLength() )
1126             {
1127                 // If list of filters already exist ...
1128                 // ReadExternalFilters must work in update mode.
1129                 // Best way seams to mark all filters NOT_INSTALLED
1130                 // and change it back for all valid filters afterwards.
1131                 if( rList.Count() > 0 )
1132                 {
1133                     bUpdate = sal_True;
1134                     sal_uInt16 nCount = (sal_uInt16)rList.Count();
1135                     SfxFilter* pFilter;
1136                     for (sal_uInt16 f=0; f<nCount; ++f)
1137                     {
1138 						pFilter = NULL;
1139                         pFilter = rList.GetObject(f);
1140                         pFilter->nFormatType |= SFX_FILTER_NOTINSTALLED;
1141                     }
1142                 }
1143 
1144                 // get all properties of filters ... put it into the filter container
1145                 sal_Int32 nFilterCount = lFilterNames.getLength();
1146                 sal_Int32 nFilter=0;
1147                 for( nFilter=0; nFilter<nFilterCount; ++nFilter )
1148                 {
1149                     // Try to get filter .. but look for any exceptions!
1150                     // May be filter was deleted by another thread ...
1151                     ::rtl::OUString sFilterName = lFilterNames[nFilter];
1152 
1153                     // This debug code can be used to break on inserting/updating
1154                     // special debug filters at runtime.
1155                     // Otherwise you have to check more then 300 filter names manually .-)
1156                     // And conditional breakpoints on unicode values seams not to be supported .-(
1157                     #ifdef DEBUG
1158                     bool bDBGStop = sal_False;
1159                     if (sFilterName.indexOf(::rtl::OUString::createFromAscii("DBG_"))>-1)
1160                         bDBGStop = sal_True;
1161                     #endif
1162 
1163 					ReadSingleFilter_Impl( sFilterName, xTypeCFG, xFilterCFG, bUpdate );
1164                 }
1165             }
1166         }
1167     }
1168     catch( ::com::sun::star::uno::Exception& )
1169     {
1170         DBG_ASSERT( sal_False, "SfxFilterContainer::ReadFilter()\nException detected. Possible not all filters could be cached.\n" );
1171     }
1172 
1173 	if ( pImplArr && bUpdate )
1174 	{
1175 		// global filter arry was modified, factory specific ones might need an update too
1176 		for ( sal_uInt16 n=0; n<pImplArr->Count(); n++ )
1177 			pImplArr->GetObject(n)->Update();
1178 	}
1179 }
1180