xref: /trunk/main/sfx2/source/doc/docfac.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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