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 89 SfxObjectFactory_Impl() : 90 pNameResId ( NULL ), 91 pFilterContainer ( NULL ), 92 pModule ( NULL ), 93 nImageId ( 0 ), 94 bTemplateInitialized( sal_False ) 95 {} 96 }; 97 98 //======================================================================== 99 100 SfxFilterContainer* SfxObjectFactory::GetFilterContainer( sal_Bool /*bForceLoad*/ ) const 101 { 102 return pImpl->pFilterContainer; 103 } 104 105 //-------------------------------------------------------------------- 106 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 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 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 184 sal_uInt16 SfxObjectFactory::GetViewFactoryCount() const 185 { 186 return pImpl->aViewFactoryArr.Count(); 187 } 188 189 //-------------------------------------------------------------------- 190 191 SfxViewFactory& SfxObjectFactory::GetViewFactory(sal_uInt16 i) const 192 { 193 return *pImpl->aViewFactoryArr[i]; 194 } 195 196 //-------------------------------------------------------------------- 197 198 SfxModule* SfxObjectFactory::GetModule() const 199 { 200 return pImpl->pModule; 201 } 202 203 void SfxObjectFactory::SetModule_Impl( SfxModule *pMod ) 204 { 205 pImpl->pModule = pMod; 206 } 207 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 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 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 378 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 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 405 String SfxObjectFactory::GetDocumentTypeName() const 406 { 407 if ( pImpl->pNameResId ) 408 return String( *pImpl->pNameResId ); 409 return String(); 410 } 411 412 void SfxObjectFactory::SetDocumentServiceName( const ::rtl::OUString& rServiceName ) 413 { 414 pImpl->aServiceName = rServiceName; 415 } 416 417 const ::rtl::OUString& SfxObjectFactory::GetDocumentServiceName() const 418 { 419 return pImpl->aServiceName; 420 } 421 422 const SvGlobalName& SfxObjectFactory::GetClassId() const 423 { 424 return pImpl->aClassName; 425 } 426 427 String SfxObjectFactory::GetFactoryURL() const 428 { 429 ::rtl::OUStringBuffer aURLComposer; 430 aURLComposer.appendAscii( "private:factory/" ); 431 aURLComposer.appendAscii( GetShortName() ); 432 return aURLComposer.makeStringAndClear(); 433 } 434 435 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 462 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 473 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