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 31 #include "doctemplates.hxx" 32 #include <vos/mutex.hxx> 33 #include <tools/debug.hxx> 34 #include <tools/diagnose_ex.h> 35 #include <tools/urlobj.hxx> 36 #include <rtl/ustring.hxx> 37 #include <rtl/ustrbuf.hxx> 38 #ifndef _SV_RESARY_HXX 39 #include <tools/resary.hxx> 40 #endif 41 #include <vcl/svapp.hxx> 42 #include <vcl/wrkwin.hxx> 43 #include <comphelper/sequenceashashmap.hxx> 44 #include <unotools/pathoptions.hxx> 45 #include <comphelper/processfactory.hxx> 46 #include <comphelper/componentcontext.hxx> 47 #include <com/sun/star/beans/PropertyAttribute.hpp> 48 #include <com/sun/star/beans/XPropertySet.hpp> 49 #include <com/sun/star/beans/XPropertySetInfo.hpp> 50 #include <com/sun/star/beans/XPropertyContainer.hpp> 51 #include <com/sun/star/beans/StringPair.hpp> 52 #include <com/sun/star/container/XContainerQuery.hpp> 53 #include <com/sun/star/document/XTypeDetection.hpp> 54 #include <com/sun/star/document/XStandaloneDocumentInfo.hpp> 55 #include <com/sun/star/sdbc/XResultSet.hpp> 56 #include <com/sun/star/sdbc/XRow.hpp> 57 #include <com/sun/star/ucb/NameClash.hpp> 58 #include <com/sun/star/ucb/NameClashException.hpp> 59 #include <com/sun/star/ucb/TransferInfo.hpp> 60 #include <com/sun/star/ucb/XCommandEnvironment.hpp> 61 #include <com/sun/star/ucb/XContentAccess.hpp> 62 #include <com/sun/star/frame/XModuleManager.hpp> 63 #include <com/sun/star/uno/Exception.hpp> 64 65 #include <svtools/templatefoldercache.hxx> 66 #include <unotools/configmgr.hxx> 67 #include <unotools/ucbhelper.hxx> 68 69 #include "sfx2/sfxresid.hxx" 70 #include "sfxurlrelocator.hxx" 71 #include "doctemplateslocal.hxx" 72 #include <sfx2/docfac.hxx> 73 #include <sfx2/docfile.hxx> 74 #include "doc.hrc" 75 76 //----------------------------------------------------------------------------- 77 78 //============================================================================= 79 80 #define TEMPLATE_SERVICE_NAME "com.sun.star.frame.DocumentTemplates" 81 #define TEMPLATE_IMPLEMENTATION_NAME "com.sun.star.comp.sfx2.DocumentTemplates" 82 83 #define SERVICENAME_TYPEDETECTION "com.sun.star.document.TypeDetection" 84 #define SERVICENAME_DOCINFO "com.sun.star.document.StandaloneDocumentInfo" 85 86 #define TEMPLATE_ROOT_URL "vnd.sun.star.hier:/templates" 87 #define TITLE "Title" 88 #define IS_FOLDER "IsFolder" 89 #define IS_DOCUMENT "IsDocument" 90 #define TARGET_URL "TargetURL" 91 #define TEMPLATE_VERSION "TemplateComponentVersion" 92 #define TEMPLATE_VERSION_VALUE "2" 93 #define TYPE_FOLDER "application/vnd.sun.star.hier-folder" 94 #define TYPE_LINK "application/vnd.sun.star.hier-link" 95 #define TYPE_FSYS_FOLDER "application/vnd.sun.staroffice.fsys-folder" 96 #define TYPE_FSYS_FILE "application/vnd.sun.staroffice.fsys-file" 97 98 #define PROPERTY_DIRLIST "DirectoryList" 99 #define PROPERTY_NEEDSUPDATE "NeedsUpdate" 100 #define PROPERTY_TYPE "TypeDescription" 101 102 #define TARGET_DIR_URL "TargetDirURL" 103 #define COMMAND_DELETE "delete" 104 #define COMMAND_TRANSFER "transfer" 105 106 #define STANDARD_FOLDER "standard" 107 108 #define C_DELIM ';' 109 110 //============================================================================= 111 112 using namespace ::com::sun::star; 113 using namespace ::com::sun::star::beans; 114 using namespace ::com::sun::star::document; 115 using namespace ::com::sun::star::io; 116 using namespace ::com::sun::star::lang; 117 using namespace ::com::sun::star::sdbc; 118 using namespace ::com::sun::star::ucb; 119 using namespace ::com::sun::star::uno; 120 using namespace ::com::sun::star::container; 121 using namespace ::com::sun::star::util; 122 123 using namespace ::rtl; 124 using namespace ::ucbhelper; 125 using namespace ::comphelper; 126 127 //============================================================================= 128 129 class WaitWindow_Impl : public WorkWindow 130 { 131 Rectangle _aRect; 132 sal_uInt16 _nTextStyle; 133 String _aText; 134 135 public: 136 WaitWindow_Impl(); 137 ~WaitWindow_Impl(); 138 virtual void Paint( const Rectangle& rRect ); 139 }; 140 141 #define X_OFFSET 15 142 #define Y_OFFSET 15 143 144 //============================================================================= 145 146 struct NamePair_Impl 147 { 148 OUString maShortName; 149 OUString maLongName; 150 }; 151 152 DECLARE_LIST( NameList_Impl, NamePair_Impl* ) 153 154 class Updater_Impl; 155 class GroupList_Impl; 156 class DocTemplates_EntryData_Impl; 157 class GroupData_Impl; 158 159 //============================================================================= 160 #include <com/sun/star/task/XInteractionHandler.hpp> 161 #include <com/sun/star/ucb/XProgressHandler.hpp> 162 #include <com/sun/star/ucb/XCommandEnvironment.hpp> 163 164 class TplTaskEnvironment : public ::cppu::WeakImplHelper1< ucb::XCommandEnvironment > 165 { 166 uno::Reference< task::XInteractionHandler > m_xInteractionHandler; 167 uno::Reference< ucb::XProgressHandler > m_xProgressHandler; 168 169 public: 170 TplTaskEnvironment( const uno::Reference< task::XInteractionHandler>& rxInteractionHandler ) 171 : m_xInteractionHandler( rxInteractionHandler ) 172 {} 173 174 virtual uno::Reference<task::XInteractionHandler> SAL_CALL getInteractionHandler() throw (uno::RuntimeException) 175 { return m_xInteractionHandler; } 176 177 virtual uno::Reference<ucb::XProgressHandler> SAL_CALL getProgressHandler() throw (uno::RuntimeException) 178 { return m_xProgressHandler; } 179 }; 180 181 class SfxDocTplService_Impl 182 { 183 uno::Reference< XMultiServiceFactory > mxFactory; 184 uno::Reference< XCommandEnvironment > maCmdEnv; 185 uno::Reference< XStandaloneDocumentInfo > mxInfo; 186 uno::Reference< XTypeDetection > mxType; 187 188 ::osl::Mutex maMutex; 189 Sequence< OUString > maTemplateDirs; 190 OUString maRootURL; 191 NameList_Impl maNames; 192 Locale maLocale; 193 Content maRootContent; 194 Updater_Impl* mpUpdater; 195 sal_Bool mbIsInitialized : 1; 196 sal_Bool mbLocaleSet : 1; 197 198 SfxURLRelocator_Impl maRelocator; 199 200 void init_Impl(); 201 void getDefaultLocale(); 202 void getDirList(); 203 void readFolderList(); 204 sal_Bool needsUpdate(); 205 OUString getLongName( const OUString& rShortName ); 206 sal_Bool setTitleForURL( const OUString& rURL, const OUString& aTitle ); 207 sal_Bool getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle ); 208 209 sal_Bool addEntry( Content& rParentFolder, 210 const OUString& rTitle, 211 const OUString& rTargetURL, 212 const OUString& rType ); 213 214 sal_Bool createFolder( const OUString& rNewFolderURL, 215 sal_Bool bCreateParent, 216 sal_Bool bFsysFolder, 217 Content &rNewFolder ); 218 219 sal_Bool CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath, 220 const ::rtl::OUString& aPrefix, 221 ::rtl::OUString& aNewFolderName, 222 ::rtl::OUString& aNewFolderURL, 223 Content& aNewFolder ); 224 ::rtl::OUString CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath, 225 const ::rtl::OUString& aPrefix, 226 const ::rtl::OUString& aExt ); 227 228 uno::Sequence< beans::StringPair > ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath ); 229 sal_Bool UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 230 const ::rtl::OUString& aGroupName, 231 const ::rtl::OUString& aNewFolderName ); 232 sal_Bool ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 233 const ::rtl::OUString& aFsysGroupName, 234 const ::rtl::OUString& aOldGroupName, 235 const ::rtl::OUString& aNewGroupName ); 236 sal_Bool RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 237 const ::rtl::OUString& aGroupName ); 238 sal_Bool WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 239 const uno::Sequence< beans::StringPair >& aUINames ); 240 241 ::rtl::OUString CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup ); 242 243 sal_Bool removeContent( Content& rContent ); 244 sal_Bool removeContent( const OUString& rContentURL ); 245 246 sal_Bool setProperty( Content& rContent, 247 const OUString& rPropName, 248 const Any& rPropValue ); 249 sal_Bool getProperty( Content& rContent, 250 const OUString& rPropName, 251 Any& rPropValue ); 252 253 void createFromContent( GroupList_Impl& rList, 254 Content &rContent, 255 sal_Bool bHierarchy, 256 sal_Bool bWriteableContent = sal_False ); 257 void addHierGroup( GroupList_Impl& rList, 258 const OUString& rTitle, 259 const OUString& rOwnURL ); 260 void addFsysGroup( GroupList_Impl& rList, 261 const OUString& rTitle, 262 const OUString& rUITitle, 263 const OUString& rOwnURL, 264 sal_Bool bWriteableGroup = sal_False ); 265 void removeFromHierarchy( DocTemplates_EntryData_Impl *pData ); 266 void addToHierarchy( GroupData_Impl *pGroup, 267 DocTemplates_EntryData_Impl *pData ); 268 269 void removeFromHierarchy( GroupData_Impl *pGroup ); 270 void addGroupToHierarchy( GroupData_Impl *pGroup ); 271 272 void updateData( DocTemplates_EntryData_Impl *pData ); 273 274 public: 275 SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory ); 276 ~SfxDocTplService_Impl(); 277 278 sal_Bool init() { if ( !mbIsInitialized ) init_Impl(); return mbIsInitialized; } 279 Content getContent() { return maRootContent; } 280 281 void setLocale( const Locale & rLocale ); 282 Locale getLocale(); 283 284 sal_Bool storeTemplate( const OUString& rGroupName, 285 const OUString& rTemplateName, 286 const uno::Reference< XSTORABLE >& rStorable ); 287 288 sal_Bool addTemplate( const OUString& rGroupName, 289 const OUString& rTemplateName, 290 const OUString& rSourceURL ); 291 sal_Bool removeTemplate( const OUString& rGroupName, 292 const OUString& rTemplateName ); 293 sal_Bool renameTemplate( const OUString& rGroupName, 294 const OUString& rOldName, 295 const OUString& rNewName ); 296 297 sal_Bool addGroup( const OUString& rGroupName ); 298 sal_Bool removeGroup( const OUString& rGroupName ); 299 sal_Bool renameGroup( const OUString& rOldName, 300 const OUString& rNewName ); 301 302 void update( sal_Bool bUpdateNow ); 303 void doUpdate(); 304 void finished() { mpUpdater = NULL; } 305 }; 306 307 //============================================================================= 308 309 class Updater_Impl : public ::vos::OThread 310 { 311 private: 312 SfxDocTplService_Impl *mpDocTemplates; 313 314 public: 315 Updater_Impl( SfxDocTplService_Impl* pTemplates ); 316 ~Updater_Impl(); 317 318 virtual void SAL_CALL run(); 319 virtual void SAL_CALL onTerminated(); 320 }; 321 322 //============================================================================= 323 324 class DocTemplates_EntryData_Impl 325 { 326 OUString maTitle; 327 OUString maType; 328 OUString maTargetURL; 329 OUString maHierarchyURL; 330 331 sal_Bool mbInHierarchy : 1; 332 sal_Bool mbInUse : 1; 333 sal_Bool mbUpdateType : 1; 334 sal_Bool mbUpdateLink : 1; 335 336 public: 337 DocTemplates_EntryData_Impl( const OUString& rTitle ); 338 339 void setInUse() { mbInUse = sal_True; } 340 void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; } 341 void setUpdateLink( sal_Bool bUpdateLink ) { mbUpdateLink = bUpdateLink; } 342 void setUpdateType( sal_Bool bUpdateType ) { mbUpdateType = bUpdateType; } 343 344 sal_Bool getInUse() const { return mbInUse; } 345 sal_Bool getInHierarchy() const { return mbInHierarchy; } 346 sal_Bool getUpdateLink() const { return mbUpdateLink; } 347 sal_Bool getUpdateType() const { return mbUpdateType; } 348 349 const OUString& getHierarchyURL() const { return maHierarchyURL; } 350 const OUString& getTargetURL() const { return maTargetURL; } 351 const OUString& getTitle() const { return maTitle; } 352 const OUString& getType() const { return maType; } 353 354 void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; } 355 void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; } 356 void setType( const OUString& rType ) { maType = rType; } 357 }; 358 359 //============================================================================= 360 361 class GroupData_Impl 362 { 363 DECLARE_LIST( EntryList_Impl, DocTemplates_EntryData_Impl* ) 364 EntryList_Impl maEntries; 365 OUString maTitle; 366 OUString maHierarchyURL; 367 OUString maTargetURL; 368 sal_Bool mbInUse : 1; 369 sal_Bool mbInHierarchy : 1; 370 371 public: 372 GroupData_Impl( const OUString& rTitle ); 373 ~GroupData_Impl(); 374 375 void setInUse() { mbInUse = sal_True; } 376 void setHierarchy( sal_Bool bInHierarchy ) { mbInHierarchy = bInHierarchy; } 377 void setHierarchyURL( const OUString& rURL ) { maHierarchyURL = rURL; } 378 void setTargetURL( const OUString& rURL ) { maTargetURL = rURL; } 379 380 sal_Bool getInUse() { return mbInUse; } 381 sal_Bool getInHierarchy() { return mbInHierarchy; } 382 const OUString& getHierarchyURL() const { return maHierarchyURL; } 383 const OUString& getTargetURL() const { return maTargetURL; } 384 const OUString& getTitle() const { return maTitle; } 385 386 DocTemplates_EntryData_Impl* addEntry( const OUString& rTitle, 387 const OUString& rTargetURL, 388 const OUString& rType, 389 const OUString& rHierURL ); 390 sal_uIntPtr count() { return maEntries.Count(); } 391 DocTemplates_EntryData_Impl* getEntry( sal_uIntPtr nPos ) { return maEntries.GetObject( nPos ); } 392 }; 393 394 DECLARE_LIST( GroupList_Impl, GroupData_Impl* ) 395 396 //============================================================================= 397 //============================================================================= 398 //============================================================================= 399 400 //----------------------------------------------------------------------------- 401 // private SfxDocTplService_Impl 402 //----------------------------------------------------------------------------- 403 void SfxDocTplService_Impl::init_Impl() 404 { 405 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 406 if ( xFactory.is() ) 407 { 408 uno::Reference < task::XInteractionHandler > xInteractionHandler( xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), uno::UNO_QUERY ); 409 maCmdEnv = new TplTaskEnvironment( xInteractionHandler ); 410 } 411 412 ::osl::ClearableMutexGuard aGuard( maMutex ); 413 sal_Bool bIsInitialized = sal_False; 414 sal_Bool bNeedsUpdate = sal_False; 415 416 if ( !mbLocaleSet ) 417 getDefaultLocale(); 418 419 // convert locale to string 420 OUString aLang = maLocale.Language; 421 aLang += String( '-' ); 422 aLang += maLocale.Country; 423 424 // set maRootContent to the root of the templates hierarchy. Create the 425 // entry if necessary 426 427 maRootURL = OUString( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_ROOT_URL ) ); 428 maRootURL += String( '/' ); 429 maRootURL += aLang; 430 431 ::rtl::OUString aTemplVersPropName( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_VERSION ) ); 432 ::rtl::OUString aTemplVers( RTL_CONSTASCII_USTRINGPARAM( TEMPLATE_VERSION_VALUE ) ); 433 if ( Content::create( maRootURL, maCmdEnv, maRootContent ) ) 434 { 435 uno::Any aValue; 436 ::rtl::OUString aPropValue; 437 if ( getProperty( maRootContent, aTemplVersPropName, aValue ) 438 && ( aValue >>= aPropValue ) 439 && aPropValue.equals( aTemplVers ) ) 440 { 441 bIsInitialized = sal_True; 442 } 443 else 444 removeContent( maRootContent ); 445 } 446 447 if ( !bIsInitialized ) 448 { 449 if ( createFolder( maRootURL, sal_True, sal_False, maRootContent ) 450 && setProperty( maRootContent, aTemplVersPropName, uno::makeAny( aTemplVers ) ) ) 451 bIsInitialized = sal_True; 452 453 bNeedsUpdate = sal_True; 454 } 455 456 if ( bIsInitialized ) 457 { 458 OUString aService( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DOCINFO ) ); 459 try { 460 mxInfo = uno::Reference< XStandaloneDocumentInfo > ( 461 mxFactory->createInstance( aService ), UNO_QUERY ); 462 } catch (uno::RuntimeException &) { 463 OSL_ENSURE(false, "SfxDocTplService_Impl::init_Impl: " 464 "cannot create DocumentProperties service"); 465 } 466 467 aService = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_TYPEDETECTION ) ); 468 mxType = uno::Reference< XTypeDetection > ( mxFactory->createInstance( aService ), UNO_QUERY ); 469 470 getDirList(); 471 readFolderList(); 472 473 if ( bNeedsUpdate ) 474 { 475 aGuard.clear(); 476 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() ); 477 478 WaitWindow_Impl* pWin = new WaitWindow_Impl(); 479 480 aSolarGuard.clear(); 481 ::osl::ClearableMutexGuard anotherGuard( maMutex ); 482 483 update( sal_True ); 484 485 anotherGuard.clear(); 486 ::vos::OGuard aSecondSolarGuard( Application::GetSolarMutex() ); 487 488 delete pWin; 489 } 490 else if ( needsUpdate() ) 491 // the UI should be shown only on the first update 492 update( sal_True ); 493 } 494 else 495 { 496 DBG_ERRORFILE( "init_Impl(): Could not create root" ); 497 } 498 499 mbIsInitialized = bIsInitialized; 500 } 501 502 //----------------------------------------------------------------------------- 503 void SfxDocTplService_Impl::getDefaultLocale() 504 { 505 if ( !mbLocaleSet ) 506 { 507 ::osl::MutexGuard aGuard( maMutex ); 508 if ( !mbLocaleSet ) 509 { 510 rtl::OUString aLocale; 511 utl::ConfigManager::GetDirectConfigProperty( utl::ConfigManager::LOCALE ) 512 >>= aLocale; 513 514 if ( aLocale.getLength() > 0 ) 515 { 516 sal_Int32 nPos = aLocale.indexOf( sal_Unicode( '-' ) ); 517 if ( nPos != -1 ) 518 { 519 maLocale.Language = aLocale.copy( 0, nPos ); 520 nPos = aLocale.indexOf( sal_Unicode( '_' ), nPos + 1 ); 521 if ( nPos != -1 ) 522 { 523 maLocale.Country 524 = aLocale.copy( maLocale.Language.getLength() + 1, 525 nPos - maLocale.Language.getLength() - 1 ); 526 maLocale.Variant 527 = aLocale.copy( nPos + 1 ); 528 } 529 else 530 { 531 maLocale.Country 532 = aLocale.copy( maLocale.Language.getLength() + 1 ); 533 } 534 } 535 536 } 537 538 mbLocaleSet = sal_True; 539 } 540 } 541 } 542 543 // ----------------------------------------------------------------------- 544 void SfxDocTplService_Impl::readFolderList() 545 { 546 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 547 548 ResStringArray aShortNames( SfxResId( TEMPLATE_SHORT_NAMES_ARY ) ); 549 ResStringArray aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) ); 550 551 NamePair_Impl* pPair; 552 553 sal_uInt16 nCount = (sal_uInt16)( Min( aShortNames.Count(), aLongNames.Count() ) ); 554 555 for ( sal_uInt16 i=0; i<nCount; i++ ) 556 { 557 pPair = new NamePair_Impl; 558 pPair->maShortName = aShortNames.GetString( i ); 559 pPair->maLongName = aLongNames.GetString( i ); 560 561 maNames.Insert( pPair, LIST_APPEND ); 562 } 563 } 564 565 // ----------------------------------------------------------------------- 566 OUString SfxDocTplService_Impl::getLongName( const OUString& rShortName ) 567 { 568 OUString aRet; 569 NamePair_Impl *pPair = maNames.First(); 570 571 while ( pPair ) 572 { 573 if ( pPair->maShortName == rShortName ) 574 { 575 aRet = pPair->maLongName; 576 break; 577 } 578 else 579 pPair = maNames.Next(); 580 } 581 582 if ( !aRet.getLength() ) 583 aRet = rShortName; 584 585 return aRet; 586 } 587 588 //----------------------------------------------------------------------------- 589 void SfxDocTplService_Impl::getDirList() 590 { 591 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_DIRLIST ) ); 592 Any aValue; 593 594 // Get the template dir list 595 // TODO/LATER: let use service, register listener 596 INetURLObject aURL; 597 String aDirs = SvtPathOptions().GetTemplatePath(); 598 sal_uInt16 nCount = aDirs.GetTokenCount( C_DELIM ); 599 600 maTemplateDirs = Sequence< OUString >( nCount ); 601 602 for ( sal_uInt16 i=0; i<nCount; i++ ) 603 { 604 aURL.SetSmartProtocol( INET_PROT_FILE ); 605 aURL.SetURL( aDirs.GetToken( i, C_DELIM ) ); 606 maTemplateDirs[i] = aURL.GetMainURL( INetURLObject::NO_DECODE ); 607 } 608 609 aValue <<= maTemplateDirs; 610 611 // Store the template dir list 612 setProperty( maRootContent, aPropName, aValue ); 613 } 614 615 //----------------------------------------------------------------------------- 616 sal_Bool SfxDocTplService_Impl::needsUpdate() 617 { 618 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_NEEDSUPDATE ) ); 619 sal_Bool bHasProperty = sal_False; 620 sal_Bool bNeedsUpdate = sal_True; 621 Any aValue; 622 623 // Get the template dir list 624 bHasProperty = getProperty( maRootContent, aPropName, aValue ); 625 626 if ( bHasProperty ) 627 aValue >>= bNeedsUpdate; 628 629 // the old template component also checks this state, but it is initialized from this component 630 // so if this componend was already updated the old component does not need such an update 631 ::svt::TemplateFolderCache aTempCache; 632 if ( !bNeedsUpdate ) 633 bNeedsUpdate = aTempCache.needsUpdate(); 634 635 if ( bNeedsUpdate ) 636 aTempCache.storeState(); 637 638 return bNeedsUpdate; 639 } 640 641 // ----------------------------------------------------------------------- 642 sal_Bool SfxDocTplService_Impl::setTitleForURL( const OUString& rURL, const OUString& aTitle ) 643 { 644 sal_Bool bResult = sal_False; 645 if ( mxInfo.is() ) 646 { 647 try 648 { 649 mxInfo->loadFromURL( rURL ); 650 uno::Reference< XPropertySet > xPropSet( mxInfo, UNO_QUERY_THROW ); 651 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 652 xPropSet->setPropertyValue( aPropName, uno::makeAny( aTitle ) ); 653 mxInfo->storeIntoURL( rURL ); 654 bResult = sal_True; 655 } 656 catch ( Exception& ) 657 { 658 } 659 } 660 661 return bResult; 662 } 663 664 // ----------------------------------------------------------------------- 665 sal_Bool SfxDocTplService_Impl::getTitleFromURL( const OUString& rURL, OUString& aTitle, OUString& aType, sal_Bool& bDocHasTitle ) 666 { 667 bDocHasTitle = sal_False; 668 669 if ( mxInfo.is() ) 670 { 671 try 672 { 673 mxInfo->loadFromURL( rURL ); 674 } 675 catch ( Exception& ) 676 { 677 // the document is not a StarOffice document 678 return sal_False; 679 } 680 681 try 682 { 683 uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY ); 684 if ( aPropSet.is() ) 685 { 686 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 687 Any aValue = aPropSet->getPropertyValue( aPropName ); 688 aValue >>= aTitle; 689 690 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( "MIMEType" ) ); 691 aValue = aPropSet->getPropertyValue( aPropName ); 692 aValue >>= aType; 693 } 694 } 695 catch ( UnknownPropertyException& ) {} 696 catch ( Exception& ) {} 697 } 698 699 if ( ! aType.getLength() && mxType.is() ) 700 { 701 ::rtl::OUString aDocType = mxType->queryTypeByURL( rURL ); 702 if ( aDocType.getLength() ) 703 try 704 { 705 uno::Reference< container::XNameAccess > xTypeDetection( mxType, uno::UNO_QUERY_THROW ); 706 SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aDocType ) ); 707 aType = aTypeProps.getUnpackedValueOrDefault( 708 ::rtl::OUString::createFromAscii( "MediaType" ), 709 ::rtl::OUString() ); 710 } 711 catch( uno::Exception& ) 712 {} 713 } 714 715 if ( ! aTitle.getLength() ) 716 { 717 INetURLObject aURL( rURL ); 718 aURL.CutExtension(); 719 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, 720 INetURLObject::DECODE_WITH_CHARSET ); 721 } 722 else 723 bDocHasTitle = sal_True; 724 725 return sal_True; 726 } 727 728 // ----------------------------------------------------------------------- 729 sal_Bool SfxDocTplService_Impl::addEntry( Content& rParentFolder, 730 const OUString& rTitle, 731 const OUString& rTargetURL, 732 const OUString& rType ) 733 { 734 sal_Bool bAddedEntry = sal_False; 735 736 INetURLObject aLinkObj( rParentFolder.getURL() ); 737 aLinkObj.insertName( rTitle, false, 738 INetURLObject::LAST_SEGMENT, true, 739 INetURLObject::ENCODE_ALL ); 740 OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE ); 741 742 Content aLink; 743 744 if ( ! Content::create( aLinkURL, maCmdEnv, aLink ) ) 745 { 746 Sequence< OUString > aNames(3); 747 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 748 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) ); 749 aNames[2] = OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); 750 751 Sequence< Any > aValues(3); 752 aValues[0] = makeAny( rTitle ); 753 aValues[1] = makeAny( sal_Bool( sal_False ) ); 754 aValues[2] = makeAny( rTargetURL ); 755 756 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_LINK ) ); 757 OUString aAdditionalProp( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_TYPE ) ); 758 759 try 760 { 761 rParentFolder.insertNewContent( aType, aNames, aValues, aLink ); 762 setProperty( aLink, aAdditionalProp, makeAny( rType ) ); 763 bAddedEntry = sal_True; 764 } 765 catch( Exception& ) 766 {} 767 } 768 return bAddedEntry; 769 } 770 771 // ----------------------------------------------------------------------- 772 sal_Bool SfxDocTplService_Impl::createFolder( const OUString& rNewFolderURL, 773 sal_Bool bCreateParent, 774 sal_Bool bFsysFolder, 775 Content &rNewFolder ) 776 { 777 Content aParent; 778 sal_Bool bCreatedFolder = sal_False; 779 INetURLObject aParentURL( rNewFolderURL ); 780 OUString aFolderName = aParentURL.getName( INetURLObject::LAST_SEGMENT, true, 781 INetURLObject::DECODE_WITH_CHARSET ); 782 783 // compute the parent folder url from the new folder url 784 // and remove the final slash, because Content::create doesn't 785 // like it 786 aParentURL.removeSegment(); 787 if ( aParentURL.getSegmentCount() >= 1 ) 788 aParentURL.removeFinalSlash(); 789 790 // if the parent exists, we can continue with the creation of the 791 // new folder, we have to create the parent otherwise ( as long as 792 // bCreateParent is set to true ) 793 if ( Content::create( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, aParent ) ) 794 { 795 try 796 { 797 Sequence< OUString > aNames(2); 798 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 799 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) ); 800 801 Sequence< Any > aValues(2); 802 aValues[0] = makeAny( aFolderName ); 803 aValues[1] = makeAny( sal_Bool( sal_True ) ); 804 805 OUString aType; 806 807 if ( bFsysFolder ) 808 aType = OUString( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FOLDER ) ); 809 else 810 aType = OUString( RTL_CONSTASCII_USTRINGPARAM( TYPE_FOLDER ) ); 811 812 aParent.insertNewContent( aType, aNames, aValues, rNewFolder ); 813 bCreatedFolder = sal_True; 814 } 815 catch( RuntimeException& ) 816 { 817 DBG_ERRORFILE( "createFolder(): got runtime exception" ); 818 } 819 catch( Exception& ) 820 { 821 DBG_ERRORFILE( "createFolder(): Could not create new folder" ); 822 } 823 } 824 else if ( bCreateParent ) 825 { 826 // if the parent doesn't exists and bCreateParent is set to true, 827 // we try to create the parent and if this was successful, we 828 // try to create the new folder again ( but this time, we set 829 // bCreateParent to false to avoid endless recusions ) 830 if ( ( aParentURL.getSegmentCount() >= 1 ) && 831 createFolder( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), bCreateParent, bFsysFolder, aParent ) ) 832 { 833 bCreatedFolder = createFolder( rNewFolderURL, sal_False, bFsysFolder, rNewFolder ); 834 } 835 } 836 837 return bCreatedFolder; 838 } 839 840 // ----------------------------------------------------------------------- 841 sal_Bool SfxDocTplService_Impl::CreateNewUniqueFolderWithPrefix( const ::rtl::OUString& aPath, 842 const ::rtl::OUString& aPrefix, 843 ::rtl::OUString& aNewFolderName, 844 ::rtl::OUString& aNewFolderURL, 845 Content& aNewFolder ) 846 { 847 sal_Bool bCreated = sal_False; 848 INetURLObject aDirPath( aPath ); 849 850 Content aParent; 851 if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), maCmdEnv, aParent ) ) 852 { 853 for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ ) 854 { 855 ::rtl::OUString aTryName = aPrefix; 856 if ( nInd ) 857 aTryName += ::rtl::OUString::valueOf( nInd ); 858 859 try 860 { 861 Sequence< OUString > aNames(2); 862 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 863 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_FOLDER ) ); 864 865 Sequence< Any > aValues(2); 866 aValues[0] = makeAny( aTryName ); 867 aValues[1] = makeAny( sal_Bool( sal_True ) ); 868 869 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FOLDER ) ); 870 871 bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFolder ); 872 } 873 catch( ucb::NameClashException& ) 874 { 875 // if there is already an element, retry 876 } 877 catch( Exception& ) 878 { 879 INetURLObject aObjPath( aDirPath ); 880 aObjPath.insertName( aTryName, false, 881 INetURLObject::LAST_SEGMENT, true, 882 INetURLObject::ENCODE_ALL ); 883 // if there is already an element, retry 884 // if there was another error, do not try any more 885 if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) ) 886 break; 887 } 888 889 if ( bCreated ) 890 { 891 aNewFolderName = aTryName; 892 aNewFolderURL = aNewFolder.get()->getIdentifier()->getContentIdentifier(); 893 break; 894 } 895 } 896 } 897 898 return bCreated; 899 } 900 901 // ----------------------------------------------------------------------- 902 ::rtl::OUString SfxDocTplService_Impl::CreateNewUniqueFileWithPrefix( const ::rtl::OUString& aPath, 903 const ::rtl::OUString& aPrefix, 904 const ::rtl::OUString& aExt ) 905 { 906 ::rtl::OUString aNewFileURL; 907 INetURLObject aDirPath( aPath ); 908 909 Content aParent; 910 911 uno::Reference< XCommandEnvironment > aQuietEnv; 912 if ( Content::create( aDirPath.GetMainURL( INetURLObject::NO_DECODE ), aQuietEnv, aParent ) ) 913 { 914 for ( sal_Int32 nInd = 0; nInd < 32000; nInd++ ) 915 { 916 Content aNewFile; 917 sal_Bool bCreated = sal_False; 918 ::rtl::OUString aTryName = aPrefix; 919 if ( nInd ) 920 aTryName += ::rtl::OUString::valueOf( nInd ); 921 if ( aExt.toChar() != '.' ) 922 aTryName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ); 923 aTryName += aExt; 924 925 try 926 { 927 Sequence< OUString > aNames(2); 928 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 929 aNames[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( IS_DOCUMENT ) ); 930 931 Sequence< Any > aValues(2); 932 aValues[0] = makeAny( aTryName ); 933 aValues[1] = makeAny( sal_Bool( sal_True ) ); 934 935 OUString aType( RTL_CONSTASCII_USTRINGPARAM( TYPE_FSYS_FILE ) ); 936 937 bCreated = aParent.insertNewContent( aType, aNames, aValues, aNewFile ); 938 } 939 catch( ucb::NameClashException& ) 940 { 941 // if there is already an element, retry 942 } 943 catch( Exception& ) 944 { 945 INetURLObject aObjPath( aPath ); 946 aObjPath.insertName( aTryName, false, 947 INetURLObject::LAST_SEGMENT, true, 948 INetURLObject::ENCODE_ALL ); 949 // if there is already an element, retry 950 // if there was another error, do not try any more 951 if ( !::utl::UCBContentHelper::Exists( aObjPath.GetMainURL( INetURLObject::NO_DECODE ) ) ) 952 break; 953 } 954 955 if ( bCreated ) 956 { 957 aNewFileURL = aNewFile.get()->getIdentifier()->getContentIdentifier(); 958 break; 959 } 960 } 961 } 962 963 return aNewFileURL; 964 } 965 966 // ----------------------------------------------------------------------- 967 sal_Bool SfxDocTplService_Impl::removeContent( Content& rContent ) 968 { 969 sal_Bool bRemoved = sal_False; 970 try 971 { 972 OUString aCmd( RTL_CONSTASCII_USTRINGPARAM( COMMAND_DELETE ) ); 973 Any aArg = makeAny( sal_Bool( sal_True ) ); 974 975 rContent.executeCommand( aCmd, aArg ); 976 bRemoved = sal_True; 977 } 978 catch ( RuntimeException& ) {} 979 catch ( Exception& ) {} 980 981 return bRemoved; 982 } 983 984 // ----------------------------------------------------------------------- 985 sal_Bool SfxDocTplService_Impl::removeContent( const OUString& rContentURL ) 986 { 987 Content aContent; 988 989 if ( Content::create( rContentURL, maCmdEnv, aContent ) ) 990 return removeContent( aContent ); 991 else 992 return sal_False; 993 } 994 995 // ----------------------------------------------------------------------- 996 sal_Bool SfxDocTplService_Impl::setProperty( Content& rContent, 997 const OUString& rPropName, 998 const Any& rPropValue ) 999 { 1000 sal_Bool bPropertySet = sal_False; 1001 1002 // Store the property 1003 try 1004 { 1005 Any aPropValue( rPropValue ); 1006 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties(); 1007 1008 // check, wether or not the property exists, create it, when not 1009 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) ) 1010 { 1011 uno::Reference< XPropertyContainer > xProperties( rContent.get(), UNO_QUERY ); 1012 if ( xProperties.is() ) 1013 { 1014 try 1015 { 1016 xProperties->addProperty( rPropName, PropertyAttribute::MAYBEVOID, rPropValue ); 1017 } 1018 catch( PropertyExistException& ) {} 1019 catch( IllegalTypeException& ) { DBG_ERRORFILE( "IllegalTypeException" ); } 1020 catch( IllegalArgumentException& ) { DBG_ERRORFILE( "IllegalArgumentException" ); } 1021 } 1022 } 1023 1024 // To ensure a reloctable office installation, the path to the 1025 // office installtion directory must never be stored directly. 1026 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) ) 1027 { 1028 OUString aValue; 1029 if ( rPropValue >>= aValue ) 1030 { 1031 maRelocator.makeRelocatableURL( aValue ); 1032 aPropValue = makeAny( aValue ); 1033 } 1034 else 1035 { 1036 Sequence< OUString > aValues; 1037 if ( rPropValue >>= aValues ) 1038 { 1039 for ( sal_Int32 n = 0; n < aValues.getLength(); n++ ) 1040 { 1041 maRelocator.makeRelocatableURL( aValues[ n ] ); 1042 } 1043 aPropValue = makeAny( aValues ); 1044 } 1045 else 1046 { 1047 OSL_ENSURE( false, "Unsupported property value type" ); 1048 } 1049 } 1050 } 1051 1052 // now set the property 1053 1054 rContent.setPropertyValue( rPropName, aPropValue ); 1055 bPropertySet = sal_True; 1056 } 1057 catch ( RuntimeException& ) {} 1058 catch ( Exception& ) {} 1059 1060 return bPropertySet; 1061 } 1062 1063 // ----------------------------------------------------------------------- 1064 sal_Bool SfxDocTplService_Impl::getProperty( Content& rContent, 1065 const OUString& rPropName, 1066 Any& rPropValue ) 1067 { 1068 sal_Bool bGotProperty = sal_False; 1069 1070 // Get the property 1071 try 1072 { 1073 uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties(); 1074 1075 // check, wether or not the property exists 1076 if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) ) 1077 { 1078 return sal_False; 1079 } 1080 1081 // now get the property 1082 1083 rPropValue = rContent.getPropertyValue( rPropName ); 1084 1085 // To ensure a reloctable office installation, the path to the 1086 // office installtion directory must never be stored directly. 1087 if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) ) 1088 { 1089 OUString aValue; 1090 if ( rPropValue >>= aValue ) 1091 { 1092 maRelocator.makeAbsoluteURL( aValue ); 1093 rPropValue = makeAny( aValue ); 1094 } 1095 else 1096 { 1097 Sequence< OUString > aValues; 1098 if ( rPropValue >>= aValues ) 1099 { 1100 for ( sal_Int32 n = 0; n < aValues.getLength(); n++ ) 1101 { 1102 maRelocator.makeAbsoluteURL( aValues[ n ] ); 1103 } 1104 rPropValue = makeAny( aValues ); 1105 } 1106 else 1107 { 1108 OSL_ENSURE( false, "Unsupported property value type" ); 1109 } 1110 } 1111 } 1112 1113 bGotProperty = sal_True; 1114 } 1115 catch ( RuntimeException& ) {} 1116 catch ( Exception& ) {} 1117 1118 return bGotProperty; 1119 } 1120 1121 // ----------------------------------------------------------------------- 1122 // static 1123 bool SfxURLRelocator_Impl::propertyCanContainOfficeDir( 1124 const rtl::OUString & rPropName ) 1125 { 1126 // Note: TargetURL is handled by UCB itself (because it is a property 1127 // with a predefined semantic). Additional Core properties introduced 1128 // be a client app must be handled by the client app itself, because 1129 // the UCB does not know the semantics of those properties. 1130 return ( rPropName.equalsAsciiL( 1131 RTL_CONSTASCII_STRINGPARAM( TARGET_DIR_URL ) ) || 1132 rPropName.equalsAsciiL( 1133 RTL_CONSTASCII_STRINGPARAM( PROPERTY_DIRLIST ) ) ); 1134 } 1135 1136 //----------------------------------------------------------------------------- 1137 // public SfxDocTplService_Impl 1138 //----------------------------------------------------------------------------- 1139 1140 SfxDocTplService_Impl::SfxDocTplService_Impl( uno::Reference< XMultiServiceFactory > xFactory ) 1141 : maRelocator( xFactory ) 1142 { 1143 mxFactory = xFactory; 1144 mpUpdater = NULL; 1145 mbIsInitialized = sal_False; 1146 mbLocaleSet = sal_False; 1147 } 1148 1149 //----------------------------------------------------------------------------- 1150 SfxDocTplService_Impl::~SfxDocTplService_Impl() 1151 { 1152 ::osl::MutexGuard aGuard( maMutex ); 1153 1154 if ( mpUpdater ) 1155 { 1156 mpUpdater->kill(); 1157 delete mpUpdater; 1158 } 1159 } 1160 1161 //----------------------------------------------------------------------------- 1162 Locale SfxDocTplService_Impl::getLocale() 1163 { 1164 ::osl::MutexGuard aGuard( maMutex ); 1165 1166 if ( !mbLocaleSet ) 1167 getDefaultLocale(); 1168 1169 return maLocale; 1170 } 1171 1172 //----------------------------------------------------------------------------- 1173 void SfxDocTplService_Impl::setLocale( const Locale &rLocale ) 1174 { 1175 ::osl::MutexGuard aGuard( maMutex ); 1176 1177 if ( mbLocaleSet && 1178 ( maLocale.Language != rLocale.Language ) && 1179 ( maLocale.Country != rLocale.Country ) ) 1180 mbIsInitialized = sal_False; 1181 1182 maLocale = rLocale; 1183 mbLocaleSet = sal_True; 1184 } 1185 1186 //----------------------------------------------------------------------------- 1187 void SfxDocTplService_Impl::update( sal_Bool bUpdateNow ) 1188 { 1189 ::osl::MutexGuard aGuard( maMutex ); 1190 1191 if ( bUpdateNow ) 1192 doUpdate(); 1193 else 1194 { 1195 mpUpdater = new Updater_Impl( this ); 1196 mpUpdater->create(); 1197 } 1198 } 1199 1200 //----------------------------------------------------------------------------- 1201 void SfxDocTplService_Impl::doUpdate() 1202 { 1203 ::osl::MutexGuard aGuard( maMutex ); 1204 1205 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_NEEDSUPDATE ) ); 1206 Any aValue; 1207 1208 aValue <<= sal_True; 1209 setProperty( maRootContent, aPropName, aValue ); 1210 1211 GroupList_Impl aGroupList; 1212 1213 // get the entries from the hierarchy 1214 createFromContent( aGroupList, maRootContent, sal_True ); 1215 1216 // get the entries from the template directories 1217 sal_Int32 nCountDir = maTemplateDirs.getLength(); 1218 OUString* pDirs = maTemplateDirs.getArray(); 1219 Content aDirContent; 1220 1221 // the last directory in the list must be writable 1222 sal_Bool bWriteableDirectory = sal_True; 1223 1224 // the target folder might not exist, for this reason no interaction handler should be used 1225 uno::Reference< XCommandEnvironment > aQuietEnv; 1226 1227 while ( nCountDir ) 1228 { 1229 nCountDir--; 1230 if ( Content::create( pDirs[ nCountDir ], aQuietEnv, aDirContent ) ) 1231 { 1232 createFromContent( aGroupList, aDirContent, sal_False, bWriteableDirectory ); 1233 } 1234 1235 bWriteableDirectory = sal_False; 1236 } 1237 1238 // now check the list 1239 GroupData_Impl *pGroup = aGroupList.First(); 1240 while ( pGroup ) 1241 { 1242 if ( pGroup->getInUse() ) 1243 { 1244 if ( pGroup->getInHierarchy() ) 1245 { 1246 Content aGroup; 1247 if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) ) 1248 setProperty( aGroup, 1249 OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ), 1250 makeAny( pGroup->getTargetURL() ) ); 1251 1252 sal_uIntPtr nCount = pGroup->count(); 1253 for ( sal_uIntPtr i=0; i<nCount; i++ ) 1254 { 1255 DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i ); 1256 if ( ! pData->getInUse() ) 1257 { 1258 if ( pData->getInHierarchy() ) 1259 removeFromHierarchy( pData ); // delete entry in hierarchy 1260 else 1261 addToHierarchy( pGroup, pData ); // add entry to hierarchy 1262 } 1263 else if ( pData->getUpdateType() || 1264 pData->getUpdateLink() ) 1265 { 1266 updateData( pData ); 1267 } 1268 } 1269 } 1270 else 1271 { 1272 addGroupToHierarchy( pGroup ); // add group to hierarchy 1273 } 1274 } 1275 else 1276 removeFromHierarchy( pGroup ); // delete group from hierarchy 1277 1278 delete pGroup; 1279 pGroup = aGroupList.Next(); 1280 } 1281 1282 aValue <<= sal_False; 1283 setProperty( maRootContent, aPropName, aValue ); 1284 } 1285 1286 //----------------------------------------------------------------------------- 1287 uno::Sequence< beans::StringPair > SfxDocTplService_Impl::ReadUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath ) 1288 { 1289 INetURLObject aLocObj( aUserPath ); 1290 aLocObj.insertName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "groupuinames.xml" ) ), false, 1291 INetURLObject::LAST_SEGMENT, true, 1292 INetURLObject::ENCODE_ALL ); 1293 Content aLocContent; 1294 1295 // TODO/LATER: Use hashmap in future 1296 uno::Sequence< beans::StringPair > aUINames; 1297 if ( Content::create( aLocObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference < ucb::XCommandEnvironment >(), aLocContent ) ) 1298 { 1299 try 1300 { 1301 uno::Reference< io::XInputStream > xLocStream = aLocContent.openStream(); 1302 if ( xLocStream.is() ) 1303 aUINames = DocTemplLocaleHelper::ReadGroupLocalizationSequence( xLocStream, mxFactory ); 1304 } 1305 catch( uno::Exception& ) 1306 {} 1307 } 1308 1309 return aUINames; 1310 } 1311 1312 //----------------------------------------------------------------------------- 1313 sal_Bool SfxDocTplService_Impl::UpdateUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 1314 const ::rtl::OUString& aGroupName, 1315 const ::rtl::OUString& aNewFolderName ) 1316 { 1317 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath ); 1318 sal_Int32 nLen = aUINames.getLength(); 1319 1320 // it is possible that the name is used already, but it should be checked before 1321 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ ) 1322 if ( aUINames[nInd].First.equals( aNewFolderName ) ) 1323 return sal_False; 1324 1325 aUINames.realloc( ++nLen ); 1326 aUINames[nLen-1].First = aNewFolderName; 1327 aUINames[nLen-1].Second = aGroupName; 1328 1329 return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames ); 1330 } 1331 1332 //----------------------------------------------------------------------------- 1333 sal_Bool SfxDocTplService_Impl::ReplaceUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 1334 const ::rtl::OUString& aDefaultFsysGroupName, 1335 const ::rtl::OUString& aOldGroupName, 1336 const ::rtl::OUString& aNewGroupName ) 1337 { 1338 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath ); 1339 sal_Int32 nLen = aUINames.getLength(); 1340 1341 sal_Bool bChanged = sal_False; 1342 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ ) 1343 if ( aUINames[nInd].Second.equals( aOldGroupName ) ) 1344 { 1345 aUINames[nInd].Second = aNewGroupName; 1346 bChanged = sal_True; 1347 } 1348 1349 if ( !bChanged ) 1350 { 1351 aUINames.realloc( ++nLen ); 1352 aUINames[nLen-1].First = aDefaultFsysGroupName; 1353 aUINames[nLen-1].Second = aNewGroupName; 1354 } 1355 return WriteUINamesForTemplateDir_Impl( aUserPath, aUINames ); 1356 } 1357 1358 //----------------------------------------------------------------------------- 1359 sal_Bool SfxDocTplService_Impl::RemoveUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 1360 const ::rtl::OUString& aGroupName ) 1361 { 1362 uno::Sequence< beans::StringPair > aUINames = ReadUINamesForTemplateDir_Impl( aUserPath ); 1363 sal_Int32 nLen = aUINames.getLength(); 1364 uno::Sequence< beans::StringPair > aNewUINames( nLen ); 1365 sal_Int32 nNewLen = 0; 1366 1367 sal_Bool bChanged = sal_False; 1368 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ ) 1369 if ( aUINames[nInd].Second.equals( aGroupName ) ) 1370 bChanged = sal_True; 1371 else 1372 { 1373 nNewLen++; 1374 aNewUINames[nNewLen-1].First = aUINames[nInd].First; 1375 aNewUINames[nNewLen-1].Second = aUINames[nInd].Second; 1376 } 1377 1378 aNewUINames.realloc( nNewLen ); 1379 1380 return bChanged ? WriteUINamesForTemplateDir_Impl( aUserPath, aNewUINames ) : sal_True; 1381 } 1382 1383 1384 //----------------------------------------------------------------------------- 1385 sal_Bool SfxDocTplService_Impl::WriteUINamesForTemplateDir_Impl( const ::rtl::OUString& aUserPath, 1386 const uno::Sequence< beans::StringPair >& aUINames ) 1387 { 1388 sal_Bool bResult = sal_False; 1389 try { 1390 uno::Reference< beans::XPropertySet > xTempFile( 1391 mxFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 1392 uno::UNO_QUERY_THROW ); 1393 1394 ::rtl::OUString aTempURL; 1395 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); 1396 aUrl >>= aTempURL; 1397 1398 uno::Reference< io::XStream > xStream( xTempFile, uno::UNO_QUERY_THROW ); 1399 uno::Reference< io::XOutputStream > xOutStream = xStream->getOutputStream(); 1400 if ( !xOutStream.is() ) 1401 throw uno::RuntimeException(); 1402 1403 DocTemplLocaleHelper::WriteGroupLocalizationSequence( xOutStream, aUINames, mxFactory ); 1404 try { 1405 // the SAX writer might close the stream 1406 xOutStream->closeOutput(); 1407 } catch( uno::Exception& ) 1408 {} 1409 1410 Content aTargetContent( aUserPath, maCmdEnv ); 1411 Content aSourceContent( aTempURL, maCmdEnv ); 1412 aTargetContent.transferContent( aSourceContent, 1413 InsertOperation_COPY, 1414 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "groupuinames.xml" ) ), 1415 ucb::NameClash::OVERWRITE ); 1416 bResult = sal_True; 1417 } 1418 catch ( uno::Exception& ) 1419 { 1420 } 1421 1422 return bResult; 1423 } 1424 1425 //----------------------------------------------------------------------------- 1426 ::rtl::OUString SfxDocTplService_Impl::CreateNewGroupFsys( const ::rtl::OUString& rGroupName, Content& aGroup ) 1427 { 1428 ::rtl::OUString aResultURL; 1429 1430 if ( maTemplateDirs.getLength() ) 1431 { 1432 ::rtl::OUString aTargetPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ]; 1433 1434 // create a new folder with the given name 1435 Content aNewFolder; 1436 ::rtl::OUString aNewFolderName; 1437 1438 // the Fsys name instead of GroupName should be used, the groupuinames must be added also 1439 if ( !CreateNewUniqueFolderWithPrefix( aTargetPath, 1440 rGroupName, 1441 aNewFolderName, 1442 aResultURL, 1443 aNewFolder ) 1444 && !CreateNewUniqueFolderWithPrefix( aTargetPath, 1445 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserGroup" ) ), 1446 aNewFolderName, 1447 aResultURL, 1448 aNewFolder ) ) 1449 1450 return ::rtl::OUString(); 1451 1452 if ( !UpdateUINamesForTemplateDir_Impl( aTargetPath, rGroupName, aNewFolderName ) ) 1453 { 1454 // we could not create the groupuinames for the folder, so we delete the group in the 1455 // the folder and return 1456 removeContent( aNewFolder ); 1457 return ::rtl::OUString(); 1458 } 1459 1460 // Now set the target url for this group and we are done 1461 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); 1462 Any aValue = makeAny( aResultURL ); 1463 1464 if ( ! setProperty( aGroup, aPropName, aValue ) ) 1465 { 1466 removeContent( aNewFolder ); 1467 return ::rtl::OUString(); 1468 } 1469 } 1470 1471 return aResultURL; 1472 } 1473 1474 //----------------------------------------------------------------------------- 1475 sal_Bool SfxDocTplService_Impl::addGroup( const OUString& rGroupName ) 1476 { 1477 ::osl::MutexGuard aGuard( maMutex ); 1478 1479 // Check, wether or not there is a group with this name 1480 Content aNewGroup; 1481 OUString aNewGroupURL; 1482 INetURLObject aNewGroupObj( maRootURL ); 1483 1484 aNewGroupObj.insertName( rGroupName, false, 1485 INetURLObject::LAST_SEGMENT, true, 1486 INetURLObject::ENCODE_ALL ); 1487 1488 aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1489 1490 if ( Content::create( aNewGroupURL, maCmdEnv, aNewGroup ) || 1491 ! createFolder( aNewGroupURL, sal_False, sal_False, aNewGroup ) ) 1492 { 1493 // if there already was a group with this name or the new group 1494 // could not be created, we return here 1495 return sal_False; 1496 } 1497 1498 // Get the user template path entry ( new group will always 1499 // be added in the user template path ) 1500 sal_Int32 nIndex; 1501 OUString aUserPath; 1502 1503 nIndex = maTemplateDirs.getLength(); 1504 if ( nIndex ) 1505 nIndex--; 1506 else 1507 return sal_False; // We don't know where to add the group 1508 1509 aUserPath = maTemplateDirs[ nIndex ]; 1510 1511 // create a new folder with the given name 1512 Content aNewFolder; 1513 OUString aNewFolderName; 1514 OUString aNewFolderURL; 1515 1516 // the Fsys name instead of GroupName should be used, the groupuinames must be added also 1517 if ( !CreateNewUniqueFolderWithPrefix( aUserPath, 1518 rGroupName, 1519 aNewFolderName, 1520 aNewFolderURL, 1521 aNewFolder ) 1522 && !CreateNewUniqueFolderWithPrefix( aUserPath, 1523 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserGroup" ) ), 1524 aNewFolderName, 1525 aNewFolderURL, 1526 aNewFolder ) ) 1527 { 1528 // we could not create the folder, so we delete the group in the 1529 // hierarchy and return 1530 removeContent( aNewGroup ); 1531 return sal_False; 1532 } 1533 1534 if ( !UpdateUINamesForTemplateDir_Impl( aUserPath, rGroupName, aNewFolderName ) ) 1535 { 1536 // we could not create the groupuinames for the folder, so we delete the group in the 1537 // hierarchy, the folder and return 1538 removeContent( aNewGroup ); 1539 removeContent( aNewFolder ); 1540 return sal_False; 1541 } 1542 1543 // Now set the target url for this group and we are done 1544 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); 1545 Any aValue = makeAny( aNewFolderURL ); 1546 1547 if ( ! setProperty( aNewGroup, aPropName, aValue ) ) 1548 { 1549 removeContent( aNewGroup ); 1550 removeContent( aNewFolder ); 1551 return sal_False; 1552 } 1553 1554 return sal_True; 1555 } 1556 1557 //----------------------------------------------------------------------------- 1558 sal_Bool SfxDocTplService_Impl::removeGroup( const OUString& rGroupName ) 1559 { 1560 // remove all the elements that have the prefix aTargetURL 1561 // if the group does not have other elements remove it 1562 1563 ::osl::MutexGuard aGuard( maMutex ); 1564 1565 sal_Bool bResult = sal_False; 1566 1567 // create the group url 1568 INetURLObject aGroupObj( maRootURL ); 1569 aGroupObj.insertName( rGroupName, false, 1570 INetURLObject::LAST_SEGMENT, true, 1571 INetURLObject::ENCODE_ALL ); 1572 1573 // Get the target url 1574 Content aGroup; 1575 OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1576 1577 if ( Content::create( aGroupURL, maCmdEnv, aGroup ) ) 1578 { 1579 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); 1580 Any aValue; 1581 1582 OUString aGroupTargetURL; 1583 if ( getProperty( aGroup, aPropName, aValue ) ) 1584 aValue >>= aGroupTargetURL; 1585 1586 if ( !aGroupTargetURL.getLength() ) 1587 return sal_False; // nothing is allowed to be removed 1588 1589 if ( !maTemplateDirs.getLength() ) 1590 return sal_False; 1591 ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ]; 1592 1593 // check that the fs location is in writeble folder and this is not a "My templates" folder 1594 INetURLObject aGroupParentFolder( aGroupTargetURL ); 1595 if ( !aGroupParentFolder.removeSegment() 1596 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath, 1597 aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) ) 1598 return sal_False; 1599 1600 // now get the content of the Group 1601 uno::Reference< XResultSet > xResultSet; 1602 Sequence< OUString > aProps( 1 ); 1603 1604 aProps[0] = OUString::createFromAscii( TARGET_URL ); 1605 1606 try 1607 { 1608 sal_Bool bHasNonRemovable = sal_False; 1609 sal_Bool bHasShared = sal_False; 1610 1611 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY; 1612 xResultSet = aGroup.createCursor( aProps, eInclude ); 1613 1614 if ( xResultSet.is() ) 1615 { 1616 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW ); 1617 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW ); 1618 1619 while ( xResultSet->next() ) 1620 { 1621 OUString aTemplTargetURL( xRow->getString( 1 ) ); 1622 OUString aHierURL = xContentAccess->queryContentIdentifierString(); 1623 1624 if ( ::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) ) 1625 { 1626 // this is a user template, and it can be removed 1627 if ( removeContent( aTemplTargetURL ) ) 1628 removeContent( aHierURL ); 1629 else 1630 bHasNonRemovable = sal_True; 1631 } 1632 else 1633 bHasShared = sal_True; 1634 } 1635 1636 if ( !bHasNonRemovable && !bHasShared ) 1637 { 1638 if ( removeContent( aGroupTargetURL ) 1639 || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) ) 1640 { 1641 removeContent( aGroupURL ); 1642 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName ); 1643 bResult = sal_True; // the operation is successful only if the whole group is removed 1644 } 1645 } 1646 else if ( !bHasNonRemovable ) 1647 { 1648 if ( removeContent( aGroupTargetURL ) 1649 || !::utl::UCBContentHelper::Exists( aGroupTargetURL ) ) 1650 { 1651 RemoveUINamesForTemplateDir_Impl( aGeneralTempPath, rGroupName ); 1652 setProperty( aGroup, aPropName, uno::makeAny( ::rtl::OUString() ) ); 1653 } 1654 } 1655 } 1656 } 1657 catch ( Exception& ) {} 1658 } 1659 1660 return bResult; 1661 } 1662 1663 //----------------------------------------------------------------------------- 1664 sal_Bool SfxDocTplService_Impl::renameGroup( const OUString& rOldName, 1665 const OUString& rNewName ) 1666 { 1667 ::osl::MutexGuard aGuard( maMutex ); 1668 1669 // create the group url 1670 Content aGroup; 1671 INetURLObject aGroupObj( maRootURL ); 1672 aGroupObj.insertName( rNewName, false, 1673 INetURLObject::LAST_SEGMENT, true, 1674 INetURLObject::ENCODE_ALL ); 1675 OUString aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1676 1677 // Check, if there is a group with the new name, return false 1678 // if there is one. 1679 if ( Content::create( aGroupURL, maCmdEnv, aGroup ) ) 1680 return sal_False; 1681 1682 aGroupObj.removeSegment(); 1683 aGroupObj.insertName( rOldName, false, 1684 INetURLObject::LAST_SEGMENT, true, 1685 INetURLObject::ENCODE_ALL ); 1686 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1687 1688 // When there is no group with the old name, we can't rename it 1689 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) ) 1690 return sal_False; 1691 1692 OUString aGroupTargetURL; 1693 // there is no need to check whether target dir url is in target path, since if the target path is changed 1694 // the target dir url should be already generated new 1695 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); 1696 Any aValue; 1697 if ( getProperty( aGroup, aPropName, aValue ) ) 1698 aValue >>= aGroupTargetURL; 1699 1700 if ( !aGroupTargetURL.getLength() ) 1701 return sal_False; 1702 1703 if ( !maTemplateDirs.getLength() ) 1704 return sal_False; 1705 ::rtl::OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ]; 1706 1707 // check that the fs location is in writeble folder and this is not a "My templates" folder 1708 INetURLObject aGroupParentFolder( aGroupTargetURL ); 1709 if ( !aGroupParentFolder.removeSegment() 1710 || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath, 1711 aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) ) 1712 return sal_False; 1713 1714 // check that the group can be renamed ( all the contents must be in target location ) 1715 sal_Bool bCanBeRenamed = sal_False; 1716 try 1717 { 1718 uno::Reference< XResultSet > xResultSet; 1719 Sequence< OUString > aProps( 1 ); 1720 1721 aProps[0] = OUString::createFromAscii( TARGET_URL ); 1722 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY; 1723 xResultSet = aGroup.createCursor( aProps, eInclude ); 1724 1725 if ( xResultSet.is() ) 1726 { 1727 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW ); 1728 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW ); 1729 1730 while ( xResultSet->next() ) 1731 { 1732 OUString aTemplTargetURL( xRow->getString( 1 ) ); 1733 1734 if ( !::utl::UCBContentHelper::IsSubPath( aGroupTargetURL, aTemplTargetURL ) ) 1735 throw uno::Exception(); 1736 } 1737 1738 bCanBeRenamed = sal_True; 1739 } 1740 } 1741 catch ( Exception& ) {} 1742 1743 if ( bCanBeRenamed ) 1744 { 1745 INetURLObject aGroupTargetObj( aGroupTargetURL ); 1746 ::rtl::OUString aFsysName = aGroupTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 1747 1748 if ( aGroupTargetObj.removeSegment() 1749 && ReplaceUINamesForTemplateDir_Impl( aGroupTargetObj.GetMainURL( INetURLObject::NO_DECODE ), 1750 aFsysName, 1751 rOldName, 1752 rNewName ) ) 1753 { 1754 // rename the group in the hierarchy 1755 OUString aTitleProp( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 1756 Any aTitleValue; 1757 aTitleValue <<= rNewName; 1758 1759 return setProperty( aGroup, aTitleProp, aTitleValue ); 1760 } 1761 } 1762 1763 return sal_False; 1764 } 1765 1766 //----------------------------------------------------------------------------- 1767 sal_Bool SfxDocTplService_Impl::storeTemplate( const OUString& rGroupName, 1768 const OUString& rTemplateName, 1769 const uno::Reference< XSTORABLE >& rStorable ) 1770 { 1771 ::osl::MutexGuard aGuard( maMutex ); 1772 1773 // Check, wether or not there is a group with this name 1774 // Return false, if there is no group with the given name 1775 Content aGroup, aTemplate, aTargetGroup, aTemplateToRemove; 1776 OUString aGroupURL, aTemplateURL, aTemplateToRemoveTargetURL; 1777 INetURLObject aGroupObj( maRootURL ); 1778 sal_Bool bRemoveOldTemplateContent = sal_False; 1779 ::rtl::OUString sDocServiceName; 1780 1781 aGroupObj.insertName( rGroupName, false, 1782 INetURLObject::LAST_SEGMENT, true, 1783 INetURLObject::ENCODE_ALL ); 1784 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1785 1786 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) ) 1787 return sal_False; 1788 1789 ::rtl::OUString aGroupTargetURL; 1790 ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); 1791 Any aValue; 1792 if ( getProperty( aGroup, aPropName, aValue ) ) 1793 aValue >>= aGroupTargetURL; 1794 1795 1796 // Check, if there's a template with the given name in this group 1797 // the target template should be overwritten if it is imported by user 1798 // in case the template is installed by office installation of by an add-in 1799 // it can not be replaced 1800 aGroupObj.insertName( rTemplateName, false, 1801 INetURLObject::LAST_SEGMENT, true, 1802 INetURLObject::ENCODE_ALL ); 1803 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1804 1805 if ( Content::create( aTemplateURL, maCmdEnv, aTemplateToRemove ) ) 1806 { 1807 OUString aTargetTemplPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); 1808 1809 bRemoveOldTemplateContent = sal_True; 1810 if ( getProperty( aTemplateToRemove, aTargetTemplPropName, aValue ) ) 1811 aValue >>= aTemplateToRemoveTargetURL; 1812 1813 if ( !aGroupTargetURL.getLength() || !maTemplateDirs.getLength() 1814 || (aTemplateToRemoveTargetURL.getLength() && !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTemplateToRemoveTargetURL )) ) 1815 return sal_False; // it is not allowed to remove the template 1816 } 1817 1818 try 1819 { 1820 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 1821 if ( !xFactory.is() ) 1822 throw uno::RuntimeException(); 1823 1824 // get document service name 1825 uno::Reference< frame::XModuleManager > xModuleManager( 1826 xFactory->createInstance( 1827 ::rtl::OUString::createFromAscii( "com.sun.star.frame.ModuleManager" ) ), 1828 uno::UNO_QUERY_THROW ); 1829 sDocServiceName = xModuleManager->identify( uno::Reference< uno::XInterface >( rStorable, uno::UNO_QUERY ) ); 1830 if ( !sDocServiceName.getLength() ) 1831 throw uno::RuntimeException(); 1832 1833 // get the actual filter name 1834 ::rtl::OUString aFilterName; 1835 1836 uno::Reference< lang::XMultiServiceFactory > xConfigProvider( 1837 xFactory->createInstance( 1838 ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ) ), 1839 uno::UNO_QUERY_THROW ); 1840 1841 uno::Sequence< uno::Any > aArgs( 1 ); 1842 beans::PropertyValue aPathProp; 1843 aPathProp.Name = ::rtl::OUString::createFromAscii( "nodepath" ); 1844 aPathProp.Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Setup/Office/Factories/" ) ); 1845 aArgs[0] <<= aPathProp; 1846 1847 uno::Reference< container::XNameAccess > xSOFConfig( 1848 xConfigProvider->createInstanceWithArguments( 1849 ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ), 1850 aArgs ), 1851 uno::UNO_QUERY_THROW ); 1852 1853 uno::Reference< container::XNameAccess > xApplConfig; 1854 xSOFConfig->getByName( sDocServiceName ) >>= xApplConfig; 1855 if ( !xApplConfig.is() ) 1856 throw uno::RuntimeException(); 1857 1858 xApplConfig->getByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooSetupFactoryActualTemplateFilter" ) ) ) >>= aFilterName; 1859 if ( !aFilterName.getLength() ) 1860 throw uno::RuntimeException(); 1861 1862 // find the related type name 1863 ::rtl::OUString aTypeName; 1864 uno::Reference< container::XNameAccess > xFilterFactory( 1865 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), 1866 uno::UNO_QUERY_THROW ); 1867 1868 uno::Sequence< beans::PropertyValue > aFilterData; 1869 xFilterFactory->getByName( aFilterName ) >>= aFilterData; 1870 for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ ) 1871 if ( aFilterData[nInd].Name.equalsAscii( "Type" ) ) 1872 aFilterData[nInd].Value >>= aTypeName; 1873 1874 if ( !aTypeName.getLength() ) 1875 throw uno::RuntimeException(); 1876 1877 // find the mediatype and extension 1878 uno::Reference< container::XNameAccess > xTypeDetection = 1879 mxType.is() ? 1880 uno::Reference< container::XNameAccess >( mxType, uno::UNO_QUERY_THROW ) : 1881 uno::Reference< container::XNameAccess >( 1882 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ), 1883 uno::UNO_QUERY_THROW ); 1884 1885 SequenceAsHashMap aTypeProps( xTypeDetection->getByName( aTypeName ) ); 1886 uno::Sequence< ::rtl::OUString > aAllExt = 1887 aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Extensions" ), Sequence< ::rtl::OUString >() ); 1888 if ( !aAllExt.getLength() ) 1889 throw uno::RuntimeException(); 1890 1891 ::rtl::OUString aMediaType = aTypeProps.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "MediaType" ), ::rtl::OUString() ); 1892 ::rtl::OUString aExt = aAllExt[0]; 1893 1894 if ( !aMediaType.getLength() || !aExt.getLength() ) 1895 throw uno::RuntimeException(); 1896 1897 // construct destination url 1898 if ( !aGroupTargetURL.getLength() ) 1899 { 1900 aGroupTargetURL = CreateNewGroupFsys( rGroupName, aGroup ); 1901 1902 if ( !aGroupTargetURL.getLength() ) 1903 throw uno::RuntimeException(); 1904 } 1905 1906 ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, rTemplateName, aExt ); 1907 if ( !aNewTemplateTargetURL.getLength() ) 1908 { 1909 aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aGroupTargetURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserTemplate" ) ), aExt ); 1910 1911 if ( !aNewTemplateTargetURL.getLength() ) 1912 throw uno::RuntimeException(); 1913 } 1914 1915 // store template 1916 uno::Sequence< PropertyValue > aStoreArgs( 2 ); 1917 aStoreArgs[0].Name = ::rtl::OUString::createFromAscii( "FilterName" ); 1918 aStoreArgs[0].Value <<= aFilterName; 1919 aStoreArgs[1].Name = ::rtl::OUString::createFromAscii( "DocumentTitle" ); 1920 aStoreArgs[1].Value <<= rTemplateName; 1921 1922 ::rtl::OUString aCurrentDocumentURL = rStorable->getLocation(); 1923 if( !::utl::UCBContentHelper::EqualURLs( aNewTemplateTargetURL, rStorable->getLocation() )) 1924 rStorable->storeToURL( aNewTemplateTargetURL, aStoreArgs ); 1925 else 1926 rStorable->store(); 1927 1928 // the storing was successful, now the old template with the same name can be removed if it existed 1929 if ( aTemplateToRemoveTargetURL.getLength() ) 1930 { 1931 removeContent( aTemplateToRemoveTargetURL ); 1932 1933 /* 1934 * pb: #i79496# 1935 * if the old template was the standard template 1936 * it is necessary to change the standard template with the new file name 1937 */ 1938 String sStdTmplFile = SfxObjectFactory::GetStandardTemplate( sDocServiceName ); 1939 if ( INetURLObject( sStdTmplFile ) == INetURLObject( aTemplateToRemoveTargetURL ) ) 1940 { 1941 SfxObjectFactory::SetStandardTemplate( sDocServiceName, aNewTemplateTargetURL ); 1942 } 1943 } 1944 1945 if ( bRemoveOldTemplateContent ) 1946 removeContent( aTemplateToRemove ); 1947 1948 // add the template to hierarchy 1949 return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aMediaType ); 1950 } 1951 catch( Exception& ) 1952 { 1953 // the template was not stored 1954 return sal_False; 1955 } 1956 } 1957 1958 //----------------------------------------------------------------------------- 1959 sal_Bool SfxDocTplService_Impl::addTemplate( const OUString& rGroupName, 1960 const OUString& rTemplateName, 1961 const OUString& rSourceURL ) 1962 { 1963 ::osl::MutexGuard aGuard( maMutex ); 1964 1965 // Check, wether or not there is a group with this name 1966 // Return false, if there is no group with the given name 1967 Content aGroup, aTemplate, aTargetGroup; 1968 OUString aGroupURL, aTemplateURL; 1969 INetURLObject aGroupObj( maRootURL ); 1970 1971 aGroupObj.insertName( rGroupName, false, 1972 INetURLObject::LAST_SEGMENT, true, 1973 INetURLObject::ENCODE_ALL ); 1974 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1975 1976 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) ) 1977 return sal_False; 1978 1979 // Check, if there's a template with the given name in this group 1980 // Return false, if there already is a template 1981 aGroupObj.insertName( rTemplateName, false, 1982 INetURLObject::LAST_SEGMENT, true, 1983 INetURLObject::ENCODE_ALL ); 1984 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 1985 1986 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) ) 1987 return sal_False; 1988 1989 // get the target url of the group 1990 OUString aTargetURL; 1991 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); 1992 Any aValue; 1993 1994 if ( getProperty( aGroup, aPropName, aValue ) ) 1995 aValue >>= aTargetURL; 1996 1997 if ( !aTargetURL.getLength() ) 1998 { 1999 aTargetURL = CreateNewGroupFsys( rGroupName, aGroup ); 2000 2001 if ( !aTargetURL.getLength() ) 2002 return sal_False; 2003 } 2004 2005 // Get the content type 2006 OUString aTitle, aType, aTargetURL2, aFullName; 2007 2008 // only StarOffice documents are acceptable 2009 sal_Bool bDocHasTitle = sal_False; 2010 if( !getTitleFromURL( rSourceURL, aTitle, aType, bDocHasTitle ) ) 2011 return sal_False; 2012 2013 INetURLObject aSourceObj( rSourceURL ); 2014 if ( rTemplateName.equals( aTitle ) ) 2015 { 2016 ///////////////////////////////////////////////////// 2017 // addTemplate will sometimes be called just to add an entry in the 2018 // hierarchy; the target URL and the source URL will be the same in 2019 // this scenario 2020 // TODO/LATER: get rid of this old hack 2021 2022 INetURLObject aTargetObj( aTargetURL ); 2023 2024 aTargetObj.insertName( rTemplateName, false, 2025 INetURLObject::LAST_SEGMENT, true, 2026 INetURLObject::ENCODE_ALL ); 2027 aTargetObj.setExtension( aSourceObj.getExtension() ); 2028 2029 aTargetURL2 = aTargetObj.GetMainURL( INetURLObject::NO_DECODE ); 2030 2031 if ( aTargetURL2 == rSourceURL ) 2032 return addEntry( aGroup, rTemplateName, aTargetURL2, aType ); 2033 } 2034 2035 ///////////////////////////////////////////////////// 2036 // copy the template into the new group (targeturl) 2037 2038 INetURLObject aTmpURL( aSourceObj ); 2039 aTmpURL.CutExtension(); 2040 ::rtl::OUString aPattern = aTmpURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 2041 2042 ::rtl::OUString aNewTemplateTargetURL = CreateNewUniqueFileWithPrefix( aTargetURL, aPattern, aSourceObj.getExtension() ); 2043 INetURLObject aNewTemplateTargetObj( aNewTemplateTargetURL ); 2044 ::rtl::OUString aNewTemplateTargetName = aNewTemplateTargetObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 2045 if ( !aNewTemplateTargetURL.getLength() || !aNewTemplateTargetName.getLength() ) 2046 return sal_False; 2047 2048 // get access to source file 2049 Content aSourceContent; 2050 uno::Reference < ucb::XCommandEnvironment > xEnv; 2051 INetURLObject aSourceURL( rSourceURL ); 2052 if( ! Content::create( aSourceURL.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) ) 2053 return sal_False; 2054 2055 if( ! Content::create( aTargetURL, xEnv, aTargetGroup ) ) 2056 return sal_False; 2057 2058 // transfer source file 2059 try 2060 { 2061 if( ! aTargetGroup.transferContent( aSourceContent, 2062 InsertOperation_COPY, 2063 aNewTemplateTargetName, 2064 NameClash::OVERWRITE ) ) 2065 return sal_False; 2066 2067 // allow to edit the added template 2068 Content aResultContent; 2069 if ( Content::create( aNewTemplateTargetURL, xEnv, aResultContent ) ) 2070 { 2071 ::rtl::OUString aPropertyName( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ); 2072 uno::Any aProperty; 2073 sal_Bool bReadOnly = sal_False; 2074 if ( getProperty( aResultContent, aPropertyName, aProperty ) && ( aProperty >>= bReadOnly ) && bReadOnly ) 2075 setProperty( aResultContent, aPropertyName, uno::makeAny( (sal_Bool)sal_False ) ); 2076 } 2077 } 2078 catch ( ContentCreationException& ) 2079 { return sal_False; } 2080 catch ( Exception& ) 2081 { return sal_False; } 2082 2083 2084 // either the document has title and it is the same as requested, or we have to set it 2085 sal_Bool bCorrectTitle = ( bDocHasTitle && aTitle.equals( rTemplateName ) ); 2086 if ( !bCorrectTitle ) 2087 { 2088 if ( !bDocHasTitle ) 2089 { 2090 INetURLObject aNewTmpObj( aNewTemplateTargetObj ); 2091 aNewTmpObj.CutExtension(); 2092 bCorrectTitle = ( aNewTmpObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).equals( rTemplateName ) ); 2093 } 2094 2095 if ( !bCorrectTitle ) 2096 bCorrectTitle = setTitleForURL( aNewTemplateTargetURL, rTemplateName ); 2097 } 2098 2099 if ( bCorrectTitle ) 2100 { 2101 // create a new entry in the hierarchy 2102 return addEntry( aGroup, rTemplateName, aNewTemplateTargetURL, aType ); 2103 } 2104 2105 // TODO/LATER: The user could be notified here that the renaming has failed 2106 // create a new entry in the hierarchy 2107 addEntry( aGroup, aTitle, aNewTemplateTargetURL, aType ); 2108 return sal_False; 2109 } 2110 2111 //----------------------------------------------------------------------------- 2112 sal_Bool SfxDocTplService_Impl::removeTemplate( const OUString& rGroupName, 2113 const OUString& rTemplateName ) 2114 { 2115 ::osl::MutexGuard aGuard( maMutex ); 2116 2117 // Check, wether or not there is a group with this name 2118 // Return false, if there is no group with the given name 2119 Content aGroup, aTemplate; 2120 OUString aGroupURL, aTemplateURL; 2121 INetURLObject aGroupObj( maRootURL ); 2122 2123 aGroupObj.insertName( rGroupName, false, 2124 INetURLObject::LAST_SEGMENT, true, 2125 INetURLObject::ENCODE_ALL ); 2126 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 2127 2128 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) ) 2129 return sal_False; 2130 2131 // Check, if there's a template with the given name in this group 2132 // Return false, if there is no template 2133 aGroupObj.insertName( rTemplateName, false, 2134 INetURLObject::LAST_SEGMENT, true, 2135 INetURLObject::ENCODE_ALL ); 2136 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 2137 2138 if ( !Content::create( aTemplateURL, maCmdEnv, aTemplate ) ) 2139 return sal_False; 2140 2141 // get the target URL from the template 2142 OUString aTargetURL; 2143 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); 2144 Any aValue; 2145 2146 if ( getProperty( aTemplate, aPropName, aValue ) ) 2147 aValue >>= aTargetURL; 2148 2149 // delete the target template 2150 if ( aTargetURL.getLength() ) 2151 { 2152 if ( !maTemplateDirs.getLength() 2153 || !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTargetURL ) ) 2154 return sal_False; 2155 2156 removeContent( aTargetURL ); 2157 } 2158 2159 // delete the template entry 2160 return removeContent( aTemplate ); 2161 } 2162 2163 //----------------------------------------------------------------------------- 2164 sal_Bool SfxDocTplService_Impl::renameTemplate( const OUString& rGroupName, 2165 const OUString& rOldName, 2166 const OUString& rNewName ) 2167 { 2168 ::osl::MutexGuard aGuard( maMutex ); 2169 2170 // Check, wether or not there is a group with this name 2171 // Return false, if there is no group with the given name 2172 Content aGroup, aTemplate; 2173 OUString aGroupURL, aTemplateURL; 2174 INetURLObject aGroupObj( maRootURL ); 2175 2176 aGroupObj.insertName( rGroupName, false, 2177 INetURLObject::LAST_SEGMENT, true, 2178 INetURLObject::ENCODE_ALL ); 2179 aGroupURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 2180 2181 if ( ! Content::create( aGroupURL, maCmdEnv, aGroup ) ) 2182 return sal_False; 2183 2184 // Check, if there's a template with the new name in this group 2185 // Return false, if there is one 2186 aGroupObj.insertName( rNewName, false, 2187 INetURLObject::LAST_SEGMENT, true, 2188 INetURLObject::ENCODE_ALL ); 2189 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 2190 2191 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) ) 2192 return sal_False; 2193 2194 // Check, if there's a template with the old name in this group 2195 // Return false, if there is no template 2196 aGroupObj.removeSegment(); 2197 aGroupObj.insertName( rOldName, false, 2198 INetURLObject::LAST_SEGMENT, true, 2199 INetURLObject::ENCODE_ALL ); 2200 aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 2201 2202 if ( !Content::create( aTemplateURL, maCmdEnv, aTemplate ) ) 2203 return sal_False; 2204 2205 OUString aTemplateTargetURL; 2206 OUString aTargetProp( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); 2207 Any aTargetValue; 2208 2209 if ( getProperty( aTemplate, aTargetProp, aTargetValue ) ) 2210 aTargetValue >>= aTemplateTargetURL; 2211 2212 if ( !setTitleForURL( aTemplateTargetURL, rNewName ) ) 2213 return sal_False; 2214 2215 // rename the template entry in the cache 2216 OUString aTitleProp( RTL_CONSTASCII_USTRINGPARAM( TITLE ) ); 2217 Any aTitleValue; 2218 aTitleValue <<= rNewName; 2219 2220 return setProperty( aTemplate, aTitleProp, aTitleValue ); 2221 } 2222 2223 //----------------------------------------------------------------------------- 2224 //----------------------------------------------------------------------------- 2225 //----------------------------------------------------------------------------- 2226 2227 SFX_IMPL_XSERVICEINFO( SfxDocTplService, TEMPLATE_SERVICE_NAME, TEMPLATE_IMPLEMENTATION_NAME ) 2228 SFX_IMPL_SINGLEFACTORY( SfxDocTplService ) 2229 2230 //----------------------------------------------------------------------------- 2231 SfxDocTplService::SfxDocTplService( const uno::Reference< XMultiServiceFactory >& xFactory ) 2232 { 2233 pImp = new SfxDocTplService_Impl( xFactory ); 2234 } 2235 2236 //----------------------------------------------------------------------------- 2237 2238 SfxDocTplService::~SfxDocTplService() 2239 { 2240 delete pImp; 2241 } 2242 2243 //----------------------------------------------------------------------------- 2244 //--- XLocalizable --- 2245 //----------------------------------------------------------------------------- 2246 2247 Locale SAL_CALL SfxDocTplService::getLocale() 2248 throw( RUNTIMEEXCEPTION ) 2249 { 2250 return pImp->getLocale(); 2251 } 2252 2253 //----------------------------------------------------------------------------- 2254 2255 void SAL_CALL SfxDocTplService::setLocale( const Locale & rLocale ) 2256 throw( RUNTIMEEXCEPTION ) 2257 { 2258 pImp->setLocale( rLocale ); 2259 } 2260 2261 //----------------------------------------------------------------------------- 2262 //--- XDocumentTemplates --- 2263 //----------------------------------------------------------------------------- 2264 uno::Reference< XCONTENT > SAL_CALL SfxDocTplService::getContent() 2265 throw( RUNTIMEEXCEPTION ) 2266 { 2267 if ( pImp->init() ) 2268 return pImp->getContent().get(); 2269 else 2270 return NULL; 2271 } 2272 2273 //----------------------------------------------------------------------------- 2274 sal_Bool SAL_CALL SfxDocTplService::storeTemplate( const OUString& GroupName, 2275 const OUString& TemplateName, 2276 const uno::Reference< XSTORABLE >& Storable ) 2277 throw( RUNTIMEEXCEPTION ) 2278 { 2279 if ( pImp->init() ) 2280 return pImp->storeTemplate( GroupName, TemplateName, Storable ); 2281 else 2282 return sal_False; 2283 } 2284 2285 //----------------------------------------------------------------------------- 2286 sal_Bool SAL_CALL SfxDocTplService::addTemplate( const OUString& rGroupName, 2287 const OUString& rTemplateName, 2288 const OUString& rSourceURL ) 2289 throw( RUNTIMEEXCEPTION ) 2290 { 2291 if ( pImp->init() ) 2292 return pImp->addTemplate( rGroupName, rTemplateName, rSourceURL ); 2293 else 2294 return sal_False; 2295 } 2296 2297 //----------------------------------------------------------------------------- 2298 sal_Bool SAL_CALL SfxDocTplService::removeTemplate( const OUString& rGroupName, 2299 const OUString& rTemplateName ) 2300 throw( RUNTIMEEXCEPTION ) 2301 { 2302 if ( pImp->init() ) 2303 return pImp->removeTemplate( rGroupName, rTemplateName ); 2304 else 2305 return sal_False; 2306 } 2307 2308 //----------------------------------------------------------------------------- 2309 sal_Bool SAL_CALL SfxDocTplService::renameTemplate( const OUString& rGroupName, 2310 const OUString& rOldName, 2311 const OUString& rNewName ) 2312 throw( RUNTIMEEXCEPTION ) 2313 { 2314 if ( rOldName == rNewName ) 2315 return sal_True; 2316 2317 if ( pImp->init() ) 2318 return pImp->renameTemplate( rGroupName, rOldName, rNewName ); 2319 else 2320 return sal_False; 2321 } 2322 2323 //----------------------------------------------------------------------------- 2324 sal_Bool SAL_CALL SfxDocTplService::addGroup( const OUString& rGroupName ) 2325 throw( RUNTIMEEXCEPTION ) 2326 { 2327 if ( pImp->init() ) 2328 return pImp->addGroup( rGroupName ); 2329 else 2330 return sal_False; 2331 } 2332 2333 //----------------------------------------------------------------------------- 2334 sal_Bool SAL_CALL SfxDocTplService::removeGroup( const OUString& rGroupName ) 2335 throw( RUNTIMEEXCEPTION ) 2336 { 2337 if ( pImp->init() ) 2338 return pImp->removeGroup( rGroupName ); 2339 else 2340 return sal_False; 2341 } 2342 2343 //----------------------------------------------------------------------------- 2344 sal_Bool SAL_CALL SfxDocTplService::renameGroup( const OUString& rOldName, 2345 const OUString& rNewName ) 2346 throw( RUNTIMEEXCEPTION ) 2347 { 2348 if ( rOldName == rNewName ) 2349 return sal_True; 2350 2351 if ( pImp->init() ) 2352 return pImp->renameGroup( rOldName, rNewName ); 2353 else 2354 return sal_False; 2355 } 2356 2357 //----------------------------------------------------------------------------- 2358 void SAL_CALL SfxDocTplService::update() 2359 throw( RUNTIMEEXCEPTION ) 2360 { 2361 if ( pImp->init() ) 2362 pImp->update( sal_True ); 2363 } 2364 2365 //----------------------------------------------------------------------------- 2366 //----------------------------------------------------------------------------- 2367 //------------------------------------------------------------------------ 2368 2369 Updater_Impl::Updater_Impl( SfxDocTplService_Impl* pTemplates ) 2370 { 2371 mpDocTemplates = pTemplates; 2372 } 2373 2374 //------------------------------------------------------------------------ 2375 Updater_Impl::~Updater_Impl() 2376 { 2377 } 2378 2379 //------------------------------------------------------------------------ 2380 void SAL_CALL Updater_Impl::run() 2381 { 2382 mpDocTemplates->doUpdate(); 2383 } 2384 2385 //------------------------------------------------------------------------ 2386 void SAL_CALL Updater_Impl::onTerminated() 2387 { 2388 mpDocTemplates->finished(); 2389 delete this; 2390 } 2391 2392 //----------------------------------------------------------------------------- 2393 //----------------------------------------------------------------------------- 2394 //----------------------------------------------------------------------------- 2395 WaitWindow_Impl::WaitWindow_Impl() 2396 : WorkWindow( NULL, WB_BORDER | WB_3DLOOK ) 2397 { 2398 Rectangle aRect = Rectangle( 0, 0, 300, 30000 ); 2399 _nTextStyle = TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE; 2400 _aText = String( SfxResId( RID_CNT_STR_WAITING ) ); 2401 _aRect = GetTextRect( aRect, _aText, _nTextStyle ); 2402 aRect = _aRect; 2403 aRect.Right() += 2*X_OFFSET; 2404 aRect.Bottom() += 2*Y_OFFSET; 2405 _aRect.SetPos( Point( X_OFFSET, Y_OFFSET ) ); 2406 SetOutputSizePixel( aRect.GetSize() ); 2407 Show(); 2408 Update(); 2409 Flush(); 2410 } 2411 2412 //----------------------------------------------------------------------------- 2413 WaitWindow_Impl::~WaitWindow_Impl() 2414 { 2415 Hide(); 2416 } 2417 2418 //----------------------------------------------------------------------------- 2419 void WaitWindow_Impl::Paint( const Rectangle& /*rRect*/ ) 2420 { 2421 DrawText( _aRect, _aText, _nTextStyle ); 2422 } 2423 2424 //----------------------------------------------------------------------------- 2425 //----------------------------------------------------------------------------- 2426 //----------------------------------------------------------------------------- 2427 void SfxDocTplService_Impl::addHierGroup( GroupList_Impl& rList, 2428 const OUString& rTitle, 2429 const OUString& rOwnURL ) 2430 { 2431 // now get the content of the Group 2432 Content aContent; 2433 uno::Reference< XResultSet > xResultSet; 2434 Sequence< OUString > aProps(3); 2435 2436 aProps[0] = OUString::createFromAscii( TITLE ); 2437 aProps[1] = OUString::createFromAscii( TARGET_URL ); 2438 aProps[2] = OUString::createFromAscii( PROPERTY_TYPE ); 2439 2440 try 2441 { 2442 aContent = Content( rOwnURL, maCmdEnv ); 2443 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY; 2444 xResultSet = aContent.createCursor( aProps, eInclude ); 2445 } 2446 catch ( ContentCreationException& ) 2447 { 2448 DBG_ERRORFILE( "addHierGroup: ContentCreationException" ); 2449 } 2450 catch ( Exception& ) {} 2451 2452 if ( xResultSet.is() ) 2453 { 2454 GroupData_Impl *pGroup = new GroupData_Impl( rTitle ); 2455 pGroup->setHierarchy( sal_True ); 2456 pGroup->setHierarchyURL( rOwnURL ); 2457 rList.Insert( pGroup ); 2458 2459 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); 2460 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY ); 2461 2462 try 2463 { 2464 while ( xResultSet->next() ) 2465 { 2466 sal_Bool bUpdateType = sal_False; 2467 DocTemplates_EntryData_Impl *pData; 2468 2469 OUString aTitle( xRow->getString( 1 ) ); 2470 OUString aTargetDir( xRow->getString( 2 ) ); 2471 OUString aType( xRow->getString( 3 ) ); 2472 OUString aHierURL = xContentAccess->queryContentIdentifierString(); 2473 2474 if ( !aType.getLength() ) 2475 { 2476 OUString aTmpTitle; 2477 2478 sal_Bool bDocHasTitle = sal_False; 2479 if( !getTitleFromURL( aTargetDir, aTmpTitle, aType, bDocHasTitle ) ) 2480 { 2481 DBG_ERRORFILE( "addHierGroup(): template of alien format" ); 2482 continue; 2483 } 2484 2485 if ( aType.getLength() ) 2486 bUpdateType = sal_True; 2487 } 2488 2489 pData = pGroup->addEntry( aTitle, aTargetDir, aType, aHierURL ); 2490 pData->setUpdateType( bUpdateType ); 2491 } 2492 } 2493 catch ( Exception& ) {} 2494 } 2495 } 2496 2497 //----------------------------------------------------------------------------- 2498 void SfxDocTplService_Impl::addFsysGroup( GroupList_Impl& rList, 2499 const OUString& rTitle, 2500 const OUString& rUITitle, 2501 const OUString& rOwnURL, 2502 sal_Bool bWriteableGroup ) 2503 { 2504 ::rtl::OUString aTitle; 2505 2506 if ( !rUITitle.getLength() ) 2507 { 2508 // reserved FS names that should not be used 2509 if ( rTitle.compareToAscii( "wizard" ) == 0 ) 2510 return; 2511 else if ( rTitle.compareToAscii( "internal" ) == 0 ) 2512 return; 2513 2514 aTitle = getLongName( rTitle ); 2515 } 2516 else 2517 aTitle = rUITitle; 2518 2519 if ( !aTitle.getLength() ) 2520 return; 2521 2522 GroupData_Impl *pGroup = rList.First(); 2523 2524 while ( pGroup && pGroup->getTitle() != aTitle ) 2525 pGroup = rList.Next(); 2526 2527 if ( !pGroup ) 2528 { 2529 pGroup = new GroupData_Impl( aTitle ); 2530 rList.Insert( pGroup ); 2531 } 2532 2533 if ( bWriteableGroup ) 2534 pGroup->setTargetURL( rOwnURL ); 2535 2536 pGroup->setInUse(); 2537 2538 // now get the content of the Group 2539 Content aContent; 2540 uno::Reference< XResultSet > xResultSet; 2541 Sequence< OUString > aProps(1); 2542 aProps[0] = OUString::createFromAscii( TITLE ); 2543 2544 try 2545 { 2546 // this method is only used during checking of the available template-folders 2547 // that should happen quietly 2548 uno::Reference< XCommandEnvironment > aQuietEnv; 2549 aContent = Content( rOwnURL, aQuietEnv ); 2550 ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY; 2551 xResultSet = aContent.createCursor( aProps, eInclude ); 2552 } 2553 catch ( Exception& ) {} 2554 2555 if ( xResultSet.is() ) 2556 { 2557 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); 2558 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY ); 2559 2560 try 2561 { 2562 while ( xResultSet->next() ) 2563 { 2564 OUString aChildTitle( xRow->getString( 1 ) ); 2565 OUString aTargetURL = xContentAccess->queryContentIdentifierString(); 2566 OUString aType; 2567 OUString aHierURL; 2568 2569 if ( aChildTitle.compareToAscii( "sfx.tlx" ) == 0 2570 || aChildTitle.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "groupuinames.xml" ) ) ) 2571 continue; 2572 2573 // only StarOffice templates are accepted 2574 sal_Bool bDocHasTitle = sal_False; 2575 if( !getTitleFromURL( aTargetURL, aChildTitle, aType, bDocHasTitle ) ) 2576 continue; 2577 2578 pGroup->addEntry( aChildTitle, aTargetURL, aType, aHierURL ); 2579 } 2580 } 2581 catch ( Exception& ) {} 2582 } 2583 } 2584 2585 // ----------------------------------------------------------------------- 2586 void SfxDocTplService_Impl::createFromContent( GroupList_Impl& rList, 2587 Content &rContent, 2588 sal_Bool bHierarchy, 2589 sal_Bool bWriteableContent ) 2590 { 2591 OUString aTargetURL = rContent.get()->getIdentifier()->getContentIdentifier(); 2592 2593 // when scanning the file system, we have to add the 'standard' group, too 2594 if ( ! bHierarchy ) 2595 { 2596 OUString aUIStdTitle = getLongName( OUString( RTL_CONSTASCII_USTRINGPARAM( STANDARD_FOLDER ) ) ); 2597 addFsysGroup( rList, ::rtl::OUString(), aUIStdTitle, aTargetURL, bWriteableContent ); 2598 } 2599 2600 // search for predefined UI names 2601 INetURLObject aLayerObj( aTargetURL ); 2602 2603 // TODO/LATER: Use hashmap in future 2604 uno::Sequence< beans::StringPair > aUINames; 2605 if ( !bHierarchy ) 2606 aUINames = ReadUINamesForTemplateDir_Impl( aLayerObj.GetMainURL( INetURLObject::NO_DECODE ) ); 2607 2608 uno::Reference< XResultSet > xResultSet; 2609 Sequence< OUString > aProps(1); 2610 aProps[0] = OUString::createFromAscii( TITLE ); 2611 2612 try 2613 { 2614 ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY; 2615 xResultSet = rContent.createCursor( aProps, eInclude ); 2616 } 2617 catch ( Exception& ) {} 2618 2619 if ( xResultSet.is() ) 2620 { 2621 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); 2622 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY ); 2623 2624 try 2625 { 2626 while ( xResultSet->next() ) 2627 { 2628 // TODO/LATER: clarify the encoding of the Title 2629 OUString aTitle( xRow->getString( 1 ) ); 2630 OUString aTargetSubfolderURL( xContentAccess->queryContentIdentifierString() ); 2631 2632 if ( bHierarchy ) 2633 addHierGroup( rList, aTitle, aTargetSubfolderURL ); 2634 else 2635 { 2636 ::rtl::OUString aUITitle; 2637 for ( sal_Int32 nInd = 0; nInd < aUINames.getLength(); nInd++ ) 2638 if ( aUINames[nInd].First.equals( aTitle ) ) 2639 { 2640 aUITitle = aUINames[nInd].Second; 2641 break; 2642 } 2643 2644 addFsysGroup( rList, aTitle, aUITitle, aTargetSubfolderURL, bWriteableContent ); 2645 } 2646 } 2647 } 2648 catch ( Exception& ) {} 2649 } 2650 } 2651 2652 //----------------------------------------------------------------------------- 2653 void SfxDocTplService_Impl::removeFromHierarchy( DocTemplates_EntryData_Impl *pData ) 2654 { 2655 Content aTemplate; 2656 2657 if ( Content::create( pData->getHierarchyURL(), maCmdEnv, aTemplate ) ) 2658 { 2659 removeContent( aTemplate ); 2660 } 2661 } 2662 2663 //----------------------------------------------------------------------------- 2664 void SfxDocTplService_Impl::addToHierarchy( GroupData_Impl *pGroup, 2665 DocTemplates_EntryData_Impl *pData ) 2666 { 2667 Content aGroup, aTemplate; 2668 2669 if ( ! Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) ) 2670 return; 2671 2672 // Check, if there's a template with the given name in this group 2673 // Return if there is already a template 2674 INetURLObject aGroupObj( pGroup->getHierarchyURL() ); 2675 2676 aGroupObj.insertName( pData->getTitle(), false, 2677 INetURLObject::LAST_SEGMENT, true, 2678 INetURLObject::ENCODE_ALL ); 2679 2680 OUString aTemplateURL = aGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 2681 2682 if ( Content::create( aTemplateURL, maCmdEnv, aTemplate ) ) 2683 return; 2684 2685 addEntry( aGroup, pData->getTitle(), 2686 pData->getTargetURL(), 2687 pData->getType() ); 2688 } 2689 2690 //----------------------------------------------------------------------------- 2691 void SfxDocTplService_Impl::updateData( DocTemplates_EntryData_Impl *pData ) 2692 { 2693 Content aTemplate; 2694 2695 if ( ! Content::create( pData->getHierarchyURL(), maCmdEnv, aTemplate ) ) 2696 return; 2697 2698 OUString aPropName; 2699 2700 if ( pData->getUpdateType() ) 2701 { 2702 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( PROPERTY_TYPE ) ); 2703 setProperty( aTemplate, aPropName, makeAny( pData->getType() ) ); 2704 } 2705 2706 if ( pData->getUpdateLink() ) 2707 { 2708 aPropName = OUString( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) ); 2709 setProperty( aTemplate, aPropName, makeAny( pData->getTargetURL() ) ); 2710 } 2711 } 2712 2713 //----------------------------------------------------------------------------- 2714 void SfxDocTplService_Impl::addGroupToHierarchy( GroupData_Impl *pGroup ) 2715 { 2716 OUString aAdditionalProp( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) ); 2717 Content aGroup; 2718 2719 INetURLObject aNewGroupObj( maRootURL ); 2720 aNewGroupObj.insertName( pGroup->getTitle(), false, 2721 INetURLObject::LAST_SEGMENT, true, 2722 INetURLObject::ENCODE_ALL ); 2723 2724 OUString aNewGroupURL = aNewGroupObj.GetMainURL( INetURLObject::NO_DECODE ); 2725 2726 if ( createFolder( aNewGroupURL, sal_False, sal_False, aGroup ) ) 2727 { 2728 setProperty( aGroup, aAdditionalProp, makeAny( pGroup->getTargetURL() ) ); 2729 pGroup->setHierarchyURL( aNewGroupURL ); 2730 2731 sal_uIntPtr nCount = pGroup->count(); 2732 for ( sal_uIntPtr i=0; i<nCount; i++ ) 2733 { 2734 DocTemplates_EntryData_Impl *pData = pGroup->getEntry( i ); 2735 addToHierarchy( pGroup, pData ); // add entry to hierarchy 2736 } 2737 } 2738 } 2739 2740 //----------------------------------------------------------------------------- 2741 void SfxDocTplService_Impl::removeFromHierarchy( GroupData_Impl *pGroup ) 2742 { 2743 Content aGroup; 2744 2745 if ( Content::create( pGroup->getHierarchyURL(), maCmdEnv, aGroup ) ) 2746 { 2747 removeContent( aGroup ); 2748 } 2749 } 2750 2751 // ----------------------------------------------------------------------- 2752 // ----------------------------------------------------------------------- 2753 // ----------------------------------------------------------------------- 2754 GroupData_Impl::GroupData_Impl( const OUString& rTitle ) 2755 { 2756 maTitle = rTitle; 2757 mbInUse = sal_False; 2758 mbInHierarchy = sal_False; 2759 } 2760 2761 // ----------------------------------------------------------------------- 2762 GroupData_Impl::~GroupData_Impl() 2763 { 2764 DocTemplates_EntryData_Impl *pData = maEntries.First(); 2765 while ( pData ) 2766 { 2767 delete pData; 2768 pData = maEntries.Next(); 2769 } 2770 } 2771 2772 // ----------------------------------------------------------------------- 2773 DocTemplates_EntryData_Impl* GroupData_Impl::addEntry( const OUString& rTitle, 2774 const OUString& rTargetURL, 2775 const OUString& rType, 2776 const OUString& rHierURL ) 2777 { 2778 DocTemplates_EntryData_Impl *pData = maEntries.First(); 2779 2780 while ( pData && pData->getTitle() != rTitle ) 2781 pData = maEntries.Next(); 2782 2783 if ( !pData ) 2784 { 2785 pData = new DocTemplates_EntryData_Impl( rTitle ); 2786 pData->setTargetURL( rTargetURL ); 2787 pData->setType( rType ); 2788 if ( rHierURL.getLength() ) 2789 { 2790 pData->setHierarchyURL( rHierURL ); 2791 pData->setHierarchy( sal_True ); 2792 } 2793 maEntries.Insert( pData ); 2794 } 2795 else 2796 { 2797 if ( rHierURL.getLength() ) 2798 { 2799 pData->setHierarchyURL( rHierURL ); 2800 pData->setHierarchy( sal_True ); 2801 } 2802 2803 if ( pData->getInHierarchy() ) 2804 pData->setInUse(); 2805 2806 if ( rTargetURL != pData->getTargetURL() ) 2807 { 2808 pData->setTargetURL( rTargetURL ); 2809 pData->setUpdateLink( sal_True ); 2810 } 2811 } 2812 2813 return pData; 2814 } 2815 2816 // ----------------------------------------------------------------------- 2817 // ----------------------------------------------------------------------- 2818 // ----------------------------------------------------------------------- 2819 DocTemplates_EntryData_Impl::DocTemplates_EntryData_Impl( const OUString& rTitle ) 2820 { 2821 maTitle = rTitle; 2822 mbInUse = sal_False; 2823 mbInHierarchy = sal_False; 2824 mbUpdateType = sal_False; 2825 mbUpdateLink = sal_False; 2826 } 2827 2828 // ----------------------------------------------------------------------- 2829 SfxURLRelocator_Impl::SfxURLRelocator_Impl( uno::Reference< XMultiServiceFactory > xFactory ) 2830 : mxFactory( xFactory ) 2831 { 2832 } 2833 2834 // ----------------------------------------------------------------------- 2835 SfxURLRelocator_Impl::~SfxURLRelocator_Impl() 2836 { 2837 } 2838 2839 // ----------------------------------------------------------------------- 2840 void SfxURLRelocator_Impl::initOfficeInstDirs() 2841 { 2842 if ( !mxOfficeInstDirs.is() ) 2843 { 2844 osl::MutexGuard aGuard( maMutex ); 2845 if ( !mxOfficeInstDirs.is() ) 2846 { 2847 OSL_ENSURE( mxFactory.is(), "No service manager!" ); 2848 2849 uno::Reference< XComponentContext > xCtx; 2850 uno::Reference< XPropertySet > xPropSet( mxFactory, UNO_QUERY ); 2851 if ( xPropSet.is() ) 2852 { 2853 xPropSet->getPropertyValue( 2854 rtl::OUString( 2855 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ) 2856 >>= xCtx; 2857 } 2858 2859 OSL_ENSURE( xCtx.is(), 2860 "Unable to obtain component context from " 2861 "service manager!" ); 2862 2863 if ( xCtx.is() ) 2864 { 2865 xCtx->getValueByName( 2866 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 2867 "/singletons/" 2868 "com.sun.star.util.theOfficeInstallationDirectories" ) ) ) 2869 >>= mxOfficeInstDirs; 2870 } 2871 2872 OSL_ENSURE( mxOfficeInstDirs.is(), 2873 "Unable to obtain office installation directory " 2874 "singleton!" ); 2875 } 2876 } 2877 } 2878 2879 // ----------------------------------------------------------------------- 2880 void SfxURLRelocator_Impl::implExpandURL( ::rtl::OUString& io_url ) 2881 { 2882 const INetURLObject aParser( io_url ); 2883 if ( aParser.GetProtocol() != INET_PROT_VND_SUN_STAR_EXPAND ) 2884 return; 2885 2886 io_url = aParser.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ); 2887 try 2888 { 2889 if ( !mxMacroExpander.is() ) 2890 { 2891 ::comphelper::ComponentContext aContext( mxFactory ); 2892 mxMacroExpander.set( aContext.getSingleton( "com.sun.star.util.theMacroExpander" ), UNO_QUERY_THROW ); 2893 } 2894 io_url = mxMacroExpander->expandMacros( io_url ); 2895 } 2896 catch( const Exception& ) 2897 { 2898 DBG_UNHANDLED_EXCEPTION(); 2899 } 2900 } 2901 2902 // ----------------------------------------------------------------------- 2903 void SfxURLRelocator_Impl::makeRelocatableURL( rtl::OUString & rURL ) 2904 { 2905 if ( rURL.getLength() > 0 ) 2906 { 2907 initOfficeInstDirs(); 2908 implExpandURL( rURL ); 2909 rURL = mxOfficeInstDirs->makeRelocatableURL( rURL ); 2910 } 2911 } 2912 2913 // ----------------------------------------------------------------------- 2914 void SfxURLRelocator_Impl::makeAbsoluteURL( rtl::OUString & rURL ) 2915 { 2916 if ( rURL.getLength() > 0 ) 2917 { 2918 initOfficeInstDirs(); 2919 implExpandURL( rURL ); 2920 rURL = mxOfficeInstDirs->makeAbsoluteURL( rURL ); 2921 } 2922 } 2923 2924 2925