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