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