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