xref: /aoo4110/main/sfx2/source/doc/docfac.cxx (revision b1cdbd2c)
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_sfx2.hxx"
26 #include <com/sun/star/registry/MergeConflictException.hpp>
27 #include <com/sun/star/registry/XSimpleRegistry.hpp>
28 #include <com/sun/star/container/XNameAccess.hpp>
29 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
30 #include <com/sun/star/document/XTypeDetection.hpp>
31 #include <com/sun/star/frame/XLoadable.hpp>
32 #include <com/sun/star/frame/XStorable.hpp>
33 #include <comphelper/processfactory.hxx>
34 #include <tools/config.hxx>
35 #include <unotools/pathoptions.hxx>
36 #include <unotools/moduleoptions.hxx>
37 #include <tools/urlobj.hxx>
38 #include <unotools/ucbstreamhelper.hxx>
39 #include <unotools/localfilehelper.hxx>
40 #include <comphelper/sequenceashashmap.hxx>
41 #include <comphelper/configurationhelper.hxx>
42 
43 #include <sfx2/sfx.hrc>
44 #include <sfx2/docfilt.hxx>
45 #include <sfx2/docfac.hxx>
46 #include "sfx2/viewfac.hxx"
47 #include "fltfnc.hxx"
48 #include "arrdecl.hxx"
49 #include <sfx2/app.hxx>
50 #include <sfx2/module.hxx>
51 #include <sfx2/mnumgr.hxx>
52 #include "sfx2/sfxresid.hxx"
53 #include <sfx2/sfxuno.hxx>
54 #include "syspath.hxx"
55 #include <osl/file.hxx>
56 #include <osl/security.hxx>
57 #include "doc.hrc"
58 
59 #include <assert.h>
60 
61 namespace css = ::com::sun::star;
62 using namespace ::com::sun::star;
63 
64 //========================================================================
65 
66 DECL_PTRARRAY( SfxViewFactoryArr_Impl, SfxViewFactory*, 2, 2 )
67 
68 //========================================================================
69 
70 DBG_NAME(SfxObjectFactory)
71 
72 //static SfxObjectFactoryArr_Impl* pObjFac = 0;
73 
74 //========================================================================
75 
76 struct SfxObjectFactory_Impl
77 {
78 	SfxViewFactoryArr_Impl		aViewFactoryArr;// Liste von <SfxViewFactory>s
79 	SfxFilterArr_Impl			aFilterArr;     // Liste von <SFxFilter>n
80 	ResId*						pNameResId;
81 	::rtl::OUString				aServiceName;
82 	SfxFilterContainer*			pFilterContainer;
83 	SfxModule*					pModule;
84 	sal_uInt16					nImageId;
85 	String						aStandardTemplate;
86 	sal_Bool					bTemplateInitialized;
87 	SvGlobalName				aClassName;
88 
SfxObjectFactory_ImplSfxObjectFactory_Impl89 	SfxObjectFactory_Impl() :
90 		pNameResId			( NULL ),
91 		pFilterContainer	( NULL ),
92 		pModule				( NULL ),
93 		nImageId			( 0 ),
94 		bTemplateInitialized( sal_False )
95 		{}
96 };
97 
98 //========================================================================
99 
GetFilterContainer(sal_Bool) const100 SfxFilterContainer* SfxObjectFactory::GetFilterContainer( sal_Bool /*bForceLoad*/ ) const
101 {
102 	return pImpl->pFilterContainer;
103 }
104 
105 //--------------------------------------------------------------------
106 
SfxObjectFactory(const SvGlobalName & rName,SfxObjectShellFlags nFlagsP,const char * pName)107 SfxObjectFactory::SfxObjectFactory
108 (
109 	const SvGlobalName& 	rName,
110 	SfxObjectShellFlags 	nFlagsP,
111 	const char*				pName
112 ) :    pShortName( pName ),
113        pImpl( new SfxObjectFactory_Impl ),
114        nFlags( nFlagsP )
115 {
116 	DBG_CTOR(SfxObjectFactory, 0);
117 	pImpl->pFilterContainer = new SfxFilterContainer( String::CreateFromAscii( pName ) );
118 
119 	String aShortName( String::CreateFromAscii( pShortName ) );
120 	aShortName.ToLowerAscii();
121 	pImpl->aClassName = rName;
122 	if ( aShortName.EqualsAscii( "swriter" ) )
123 		pImpl->pNameResId = new SfxResId( STR_DOCTYPENAME_SW );
124 	else if ( aShortName.EqualsAscii( "swriter/web" ) )
125 		pImpl->pNameResId = new SfxResId( STR_DOCTYPENAME_SWWEB );
126 	else if ( aShortName.EqualsAscii( "swriter/globaldocument" ) )
127 		pImpl->pNameResId = new SfxResId( STR_DOCTYPENAME_SWGLOB );
128 	else if ( aShortName.EqualsAscii( "scalc" ) )
129 		pImpl->pNameResId = new SfxResId( STR_DOCTYPENAME_SC );
130 	else if ( aShortName.EqualsAscii( "simpress" ) )
131 		pImpl->pNameResId = new SfxResId( STR_DOCTYPENAME_SI );
132 	else if ( aShortName.EqualsAscii( "sdraw" ) )
133 		pImpl->pNameResId = new SfxResId( STR_DOCTYPENAME_SD );
134 	else if ( aShortName.EqualsAscii( "message" ) )
135 		pImpl->pNameResId = new SfxResId( STR_DOCTYPENAME_MESSAGE );
136 }
137 
138 //--------------------------------------------------------------------
139 
~SfxObjectFactory()140 SfxObjectFactory::~SfxObjectFactory()
141 {
142 	DBG_DTOR(SfxObjectFactory, 0);
143 
144 	const sal_uInt16 nCount = pImpl->aFilterArr.Count();
145 	for ( sal_uInt16 i = 0; i < nCount; ++i )
146 		delete pImpl->aFilterArr[i];
147 	delete pImpl->pNameResId;
148 	delete pImpl;
149 }
150 
151 //--------------------------------------------------------------------
152 
RegisterViewFactory(SfxViewFactory & rFactory)153 void SfxObjectFactory::RegisterViewFactory
154 (
155 	SfxViewFactory &rFactory
156 )
157 {
158 #if OSL_DEBUG_LEVEL > 0
159     {
160         const String sViewName( rFactory.GetAPIViewName() );
161 	    for ( sal_uInt16 i = 0; i < pImpl->aViewFactoryArr.Count(); ++i )
162         {
163             if ( !pImpl->aViewFactoryArr[i]->GetAPIViewName().Equals( sViewName ) )
164                 continue;
165             ByteString sMessage( "SfxObjectFactory::RegisterViewFactory: duplicate view name '" );
166             sMessage += ByteString( sViewName, RTL_TEXTENCODING_ASCII_US );
167             sMessage += "'!";
168             OSL_ENSURE( false, sMessage.GetBuffer() );
169             break;
170         }
171     }
172 #endif
173 	sal_uInt16 nPos;
174 	for ( nPos = 0;
175 		  nPos < pImpl->aViewFactoryArr.Count() &&
176 		  pImpl->aViewFactoryArr[nPos]->GetOrdinal() <= rFactory.GetOrdinal();
177 		  ++nPos )
178 	/* empty loop */;
179 	pImpl->aViewFactoryArr.Insert(nPos, &rFactory);
180 }
181 
182 //--------------------------------------------------------------------
183 
GetViewFactoryCount() const184 sal_uInt16 SfxObjectFactory::GetViewFactoryCount() const
185 {
186 	return pImpl->aViewFactoryArr.Count();
187 }
188 
189 //--------------------------------------------------------------------
190 
GetViewFactory(sal_uInt16 i) const191 SfxViewFactory& SfxObjectFactory::GetViewFactory(sal_uInt16 i) const
192 {
193 	return *pImpl->aViewFactoryArr[i];
194 }
195 
196 //--------------------------------------------------------------------
197 
GetModule() const198 SfxModule* SfxObjectFactory::GetModule() const
199 {
200 	return pImpl->pModule;
201 }
202 
SetModule_Impl(SfxModule * pMod)203 void SfxObjectFactory::SetModule_Impl( SfxModule *pMod )
204 {
205 	pImpl->pModule = pMod;
206 }
207 
SetSystemTemplate(const String & rServiceName,const String & rTemplateName)208 void SfxObjectFactory::SetSystemTemplate( const String& rServiceName, const String& rTemplateName )
209 {
210     static const int nMaxPathSize = 16000;
211 	static ::rtl::OUString SERVICE_FILTER_FACTORY = ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" );
212 	static ::rtl::OUString SERVICE_TYPE_DECTECTION = ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" );
213 	static ::rtl::OUString SERVICE_SIMPLE_ACCESS = ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" );
214 
215 	static ::rtl::OUString CONF_ROOT  = ::rtl::OUString::createFromAscii( "/org.openoffice.Setup");
216 	static ::rtl::OUString CONF_PATH  = ::rtl::OUString::createFromAscii( "Office/Factories/" ) + ::rtl::OUString( rServiceName );
217 	static ::rtl::OUString PROP_DEF_TEMPL_CHANGED  = ::rtl::OUString::createFromAscii( "ooSetupFactorySystemDefaultTemplateChanged" );
218 	static ::rtl::OUString PROP_ACTUAL_FILTER  = ::rtl::OUString::createFromAscii( "ooSetupFactoryActualFilter" );
219 
220 	static ::rtl::OUString DEF_TPL_STR = ::rtl::OUString::createFromAscii("/soffice.");
221 
222 	String      sURL;
223     String      sPath;
224     sal_Unicode aPathBuffer[nMaxPathSize];
225     if ( SystemPath::GetUserTemplateLocation( aPathBuffer, nMaxPathSize ))
226         sPath = String( aPathBuffer );
227 	::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPath, sURL );
228 
229 	::rtl::OUString aUserTemplateURL( sURL );
230 	if ( aUserTemplateURL.getLength() != 0)
231 	{
232 		try
233 		{
234 			uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
235 			uno::Reference< uno::XInterface > xConfig = ::comphelper::ConfigurationHelper::openConfig(
236 				xFactory, CONF_ROOT, ::comphelper::ConfigurationHelper::E_STANDARD );
237 
238 			::rtl::OUString aActualFilter;
239 			::comphelper::ConfigurationHelper::readRelativeKey( xConfig, CONF_PATH, PROP_ACTUAL_FILTER ) >>= aActualFilter;
240 			sal_Bool bChanged(sal_False);
241 			::comphelper::ConfigurationHelper::readRelativeKey( xConfig, CONF_PATH, PROP_DEF_TEMPL_CHANGED ) >>= bChanged;
242 
243 			uno::Reference< container::XNameAccess > xFilterFactory(
244 				xFactory->createInstance( SERVICE_FILTER_FACTORY ), uno::UNO_QUERY_THROW );
245 			uno::Reference< container::XNameAccess > xTypeDetection(
246 				xFactory->createInstance( SERVICE_TYPE_DECTECTION ), uno::UNO_QUERY_THROW );
247 
248 			::rtl::OUString aActualFilterTypeName;
249 			uno::Sequence< beans::PropertyValue > aActuralFilterData;
250 			xFilterFactory->getByName( aActualFilter ) >>= aActuralFilterData;
251 			for ( sal_Int32 nInd = 0; nInd < aActuralFilterData.getLength(); nInd++ )
252 				if ( aActuralFilterData[nInd].Name.equalsAscii( "Type" ) )
253 					aActuralFilterData[nInd].Value >>= aActualFilterTypeName;
254 			::comphelper::SequenceAsHashMap aProps1( xTypeDetection->getByName( aActualFilterTypeName ) );
255 			uno::Sequence< ::rtl::OUString > aAllExt =
256 				aProps1.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Extensions" ), uno::Sequence< ::rtl::OUString >() );
257 			//To-do: check if aAllExt is empty first
258 			::rtl::OUString aExt = aAllExt[0];
259 
260 			aUserTemplateURL += DEF_TPL_STR;
261 			aUserTemplateURL += aExt;
262 
263 			uno::Reference< ucb::XSimpleFileAccess > xSimpleFileAccess(
264 				xFactory->createInstance( SERVICE_SIMPLE_ACCESS ), uno::UNO_QUERY_THROW );
265 
266 			::rtl::OUString aBackupURL;
267 			::osl::Security().getConfigDir(aBackupURL);
268 			aBackupURL += ::rtl::OUString::createFromAscii( "/temp" );
269 
270 			if ( !xSimpleFileAccess->exists( aBackupURL ) )
271 				xSimpleFileAccess->createFolder( aBackupURL );
272 
273 			aBackupURL += DEF_TPL_STR;
274 			aBackupURL += aExt;
275 
276 			if ( rTemplateName.Len() != 0 )
277 			{
278 				if ( xSimpleFileAccess->exists( aUserTemplateURL ) && !bChanged )
279 					xSimpleFileAccess->copy( aUserTemplateURL, aBackupURL );
280 
281 				uno::Reference< document::XTypeDetection > xTypeDetector( xTypeDetection, uno::UNO_QUERY );
282 				::comphelper::SequenceAsHashMap aProps2( xTypeDetection->getByName( xTypeDetector->queryTypeByURL( rTemplateName ) ) );
283 				::rtl::OUString aFilterName =
284 					aProps2.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii("PreferredFilter"), ::rtl::OUString() );
285 
286 				uno::Sequence< beans::PropertyValue > aArgs( 3 );
287 				aArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" );
288 				aArgs[0].Value <<= aFilterName;
289 				aArgs[1].Name = ::rtl::OUString::createFromAscii( "AsTemplate" );
290 				aArgs[1].Value <<= sal_True;
291 				aArgs[2].Name = ::rtl::OUString::createFromAscii( "URL" );
292 				aArgs[2].Value <<= ::rtl::OUString( rTemplateName );
293 
294 				uno::Reference< frame::XLoadable > xLoadable( xFactory->createInstance( ::rtl::OUString( rServiceName ) ), uno::UNO_QUERY );
295 				xLoadable->load( aArgs );
296 
297 				aArgs.realloc( 2 );
298 				aArgs[1].Name = ::rtl::OUString::createFromAscii( "Overwrite" );
299 				aArgs[1].Value <<= sal_True;
300 
301 				uno::Reference< frame::XStorable > xStorable( xLoadable, uno::UNO_QUERY );
302 				xStorable->storeToURL( aUserTemplateURL, aArgs );
303 				::comphelper::ConfigurationHelper::writeRelativeKey( xConfig, CONF_PATH, PROP_DEF_TEMPL_CHANGED, uno::makeAny( sal_True ));
304 				::comphelper::ConfigurationHelper::flush( xConfig );
305 			}
306 			else
307 			{
308 				DBG_ASSERT( bChanged, "invalid ooSetupFactorySystemDefaultTemplateChanged value!" );
309 
310 				xSimpleFileAccess->copy( aBackupURL, aUserTemplateURL );
311 				xSimpleFileAccess->kill( aBackupURL );
312 				::comphelper::ConfigurationHelper::writeRelativeKey( xConfig, CONF_PATH, PROP_DEF_TEMPL_CHANGED, uno::makeAny( sal_False ));
313 				::comphelper::ConfigurationHelper::flush( xConfig );
314 			}
315 		}
316 		catch( uno::Exception& )
317 		{
318 		}
319 	}
320 }
321 
SetStandardTemplate(const String & rServiceName,const String & rTemplate)322 void SfxObjectFactory::SetStandardTemplate( const String& rServiceName, const String& rTemplate )
323 {
324 	SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(rServiceName);
325     if (eFac == SvtModuleOptions::E_UNKNOWN_FACTORY)
326         eFac = SvtModuleOptions::ClassifyFactoryByShortName(rServiceName);
327     if (eFac != SvtModuleOptions::E_UNKNOWN_FACTORY)
328 	{
329 		SetSystemTemplate( rServiceName, rTemplate );
330 		SvtModuleOptions().SetFactoryStandardTemplate(eFac, rTemplate);
331 	}
332 }
333 
GetStandardTemplate(const String & rServiceName)334 String SfxObjectFactory::GetStandardTemplate( const String& rServiceName )
335 {
336 	SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(rServiceName);
337     if (eFac == SvtModuleOptions::E_UNKNOWN_FACTORY)
338         eFac = SvtModuleOptions::ClassifyFactoryByShortName(rServiceName);
339 
340     String sTemplate;
341     if (eFac != SvtModuleOptions::E_UNKNOWN_FACTORY)
342         sTemplate = SvtModuleOptions().GetFactoryStandardTemplate(eFac);
343 
344 	return sTemplate;
345 }
346 
347 /*
348 const SfxObjectFactory* SfxObjectFactory::GetFactory( const String& rFactoryURL )
349 {
350 	const SfxObjectFactory* pFactory = 0;
351 	String aFact( rFactoryURL );
352 	String aPrefix( DEFINE_CONST_UNICODE( "private:factory/" ) );
353 	if ( aPrefix.Len() == aFact.Match( aPrefix ) )
354 		// Aufruf m"oglich mit z.B. "swriter" oder "private:factory/swriter"
355 		aFact.Erase( 0, aPrefix.Len() );
356 	sal_uInt16 nPos = aFact.Search( '?' );
357 
358 	// Etwaige Parameter abschneiden
359 	aFact.Erase( nPos, aFact.Len() );
360 
361 	SfxApplication *pApp = SFX_APP();
362 
363 	// "swriter4" durch "swriter" ersetzen, zum Vergleichen uppercase verwenden
364 	WildCard aSearchedFac( aFact.EraseAllChars('4').ToUpperAscii() );
365     for( sal_uInt16 n = GetObjectFactoryCount_Impl(); !pFactory && n--; )
366 	{
367         pFactory = &GetObjectFactory_Impl( n );
368 		String aCompareTo = String::CreateFromAscii( pFactory->GetShortName() );
369 		aCompareTo.ToUpperAscii();
370 		if( !aSearchedFac.Matches( aCompareTo ) )
371 			pFactory = 0;
372 	}
373 
374 	return pFactory;
375 }
376 */
377 
GetTemplateFilter() const378 const SfxFilter* SfxObjectFactory::GetTemplateFilter() const
379 {
380 	sal_uInt16 nVersion=0;
381 	SfxFilterMatcher aMatcher ( String::CreateFromAscii( pShortName ) );
382 	SfxFilterMatcherIter aIter( &aMatcher );
383 	const SfxFilter *pFilter = 0;
384 	const SfxFilter *pTemp = aIter.First();
385 	while ( pTemp )
386 	{
387 		if( pTemp->IsOwnFormat() && pTemp->IsOwnTemplateFormat() && ( pTemp->GetVersion() > nVersion ) )
388 		{
389 			pFilter = pTemp;
390 			nVersion = (sal_uInt16) pTemp->GetVersion();
391 		}
392 
393 		pTemp = aIter.Next();
394 	}
395 
396 	return pFilter;
397 }
398 
SetDocumentTypeNameResource(const ResId & rId)399 void SfxObjectFactory::SetDocumentTypeNameResource( const ResId& rId )
400 {
401 	DBG_ASSERT( !pImpl->pNameResId, "UI-Namensresource mehrfach gesetzt!" );
402 	pImpl->pNameResId = new ResId( rId );
403 }
404 
GetDocumentTypeName() const405 String SfxObjectFactory::GetDocumentTypeName() const
406 {
407 	if ( pImpl->pNameResId )
408 		return String( *pImpl->pNameResId );
409 	return String();
410 }
411 
SetDocumentServiceName(const::rtl::OUString & rServiceName)412 void SfxObjectFactory::SetDocumentServiceName( const ::rtl::OUString& rServiceName )
413 {
414 	pImpl->aServiceName = rServiceName;
415 }
416 
GetDocumentServiceName() const417 const ::rtl::OUString& SfxObjectFactory::GetDocumentServiceName() const
418 {
419 	return pImpl->aServiceName;
420 }
421 
GetClassId() const422 const SvGlobalName& SfxObjectFactory::GetClassId() const
423 {
424 	return pImpl->aClassName;
425 }
426 
GetFactoryURL() const427 String SfxObjectFactory::GetFactoryURL() const
428 {
429     ::rtl::OUStringBuffer aURLComposer;
430     aURLComposer.appendAscii( "private:factory/" );
431     aURLComposer.appendAscii( GetShortName() );
432     return aURLComposer.makeStringAndClear();
433 }
434 
GetModuleName() const435 String SfxObjectFactory::GetModuleName() const
436 {
437     static ::rtl::OUString SERVICENAME_MODULEMANAGER = ::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager");
438     static ::rtl::OUString PROP_MODULEUINAME         = ::rtl::OUString::createFromAscii("ooSetupFactoryUIName");
439 
440     try
441     {
442         css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
443 
444         css::uno::Reference< css::container::XNameAccess > xModuleManager(
445             xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
446             css::uno::UNO_QUERY_THROW);
447 
448         ::rtl::OUString sDocService(GetDocumentServiceName());
449         ::comphelper::SequenceAsHashMap aPropSet( xModuleManager->getByName(sDocService) );
450         ::rtl::OUString sModuleName = aPropSet.getUnpackedValueOrDefault(PROP_MODULEUINAME, ::rtl::OUString());
451         return String(sModuleName);
452     }
453     catch(const css::uno::RuntimeException&)
454         { throw; }
455     catch(const css::uno::Exception&)
456         {}
457 
458     return String();
459 }
460 
461 
GetViewNo_Impl(const sal_uInt16 i_nViewId,const sal_uInt16 i_nFallback) const462 sal_uInt16 SfxObjectFactory::GetViewNo_Impl( const sal_uInt16 i_nViewId, const sal_uInt16 i_nFallback ) const
463 {
464     for ( sal_uInt16 curViewNo = 0; curViewNo < GetViewFactoryCount(); ++curViewNo )
465     {
466         const sal_uInt16 curViewId = GetViewFactory( curViewNo ).GetOrdinal();
467         if ( i_nViewId == curViewId )
468            return curViewNo;
469     }
470     return i_nFallback;
471 }
472 
GetViewFactoryByViewName(const String & i_rViewName) const473 SfxViewFactory* SfxObjectFactory::GetViewFactoryByViewName( const String& i_rViewName ) const
474 {
475     for (   sal_uInt16 nViewNo = 0;
476             nViewNo < GetViewFactoryCount();
477             ++nViewNo
478         )
479     {
480         SfxViewFactory& rViewFac( GetViewFactory( nViewNo ) );
481         if  (   ( rViewFac.GetAPIViewName() == i_rViewName )
482             ||  ( rViewFac.GetLegacyViewName() == i_rViewName )
483             )
484             return &rViewFac;
485     }
486     return NULL;
487 }
488