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