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