1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svtools.hxx" 30 #include <svtools/templatefoldercache.hxx> 31 #include <unotools/ucbstreamhelper.hxx> 32 #include <unotools/localfilehelper.hxx> 33 #include <com/sun/star/beans/XPropertySet.hpp> 34 #include <com/sun/star/sdbc/XResultSet.hpp> 35 #include <com/sun/star/ucb/XDynamicResultSet.hpp> 36 #include <com/sun/star/sdbc/XRow.hpp> 37 #include <com/sun/star/ucb/XContentAccess.hpp> 38 #include <com/sun/star/uno/XComponentContext.hpp> 39 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp> 40 #include <ucbhelper/content.hxx> 41 #include <vos/ref.hxx> 42 #include <vos/refernce.hxx> 43 #include <tools/urlobj.hxx> 44 #include <tools/debug.hxx> 45 #include <unotools/pathoptions.hxx> 46 47 #include "comphelper/processfactory.hxx" 48 49 #include <vector> 50 #include <list> 51 #include <functional> 52 #include <algorithm> 53 54 //......................................................................... 55 namespace svt 56 { 57 //......................................................................... 58 59 using namespace ::utl; 60 using namespace ::com::sun::star; 61 using namespace ::com::sun::star::sdbc; 62 using namespace ::com::sun::star::ucb; 63 using namespace ::com::sun::star::uno; 64 65 //===================================================================== 66 //= helpers 67 //===================================================================== 68 //--------------------------------------------------------------------- 69 SvStream& operator << ( SvStream& _rStorage, const util::DateTime& _rDate ) 70 { 71 _rStorage << _rDate.HundredthSeconds; 72 _rStorage << _rDate.Seconds; 73 _rStorage << _rDate.Minutes; 74 _rStorage << _rDate.Hours; 75 _rStorage << _rDate.Day; 76 _rStorage << _rDate.Month; 77 _rStorage << _rDate.Year; 78 79 return _rStorage; 80 } 81 82 //--------------------------------------------------------------------- 83 SvStream& operator >> ( SvStream& _rStorage, util::DateTime& _rDate ) 84 { 85 _rStorage >> _rDate.HundredthSeconds; 86 _rStorage >> _rDate.Seconds; 87 _rStorage >> _rDate.Minutes; 88 _rStorage >> _rDate.Hours; 89 _rStorage >> _rDate.Day; 90 _rStorage >> _rDate.Month; 91 _rStorage >> _rDate.Year; 92 93 return _rStorage; 94 } 95 96 //--------------------------------------------------------------------- 97 sal_Bool operator == ( const util::DateTime& _rLHS, const util::DateTime& _rRHS ) 98 { 99 return _rLHS.HundredthSeconds == _rRHS.HundredthSeconds 100 && _rLHS.Seconds == _rRHS.Seconds 101 && _rLHS.Minutes == _rRHS.Minutes 102 && _rLHS.Hours == _rRHS.Hours 103 && _rLHS.Day == _rRHS.Day 104 && _rLHS.Month == _rRHS.Month 105 && _rLHS.Year == _rRHS.Year; 106 } 107 108 //--------------------------------------------------------------------- 109 sal_Bool operator != ( const util::DateTime& _rLHS, const util::DateTime& _rRHS ) 110 { 111 return !( _rLHS == _rRHS ); 112 } 113 114 //===================================================================== 115 //= TemplateContent 116 //===================================================================== 117 struct TemplateContent; 118 typedef ::std::vector< ::vos::ORef< TemplateContent > > TemplateFolderContent; 119 typedef TemplateFolderContent::const_iterator ConstFolderIterator; 120 typedef TemplateFolderContent::iterator FolderIterator; 121 122 /** a struct describing one content in one of the template dirs (or at least it's relevant aspects) 123 */ 124 struct TemplateContent : public ::vos::OReference 125 { 126 public: 127 128 private: 129 INetURLObject m_aURL; 130 String m_sLocalName; // redundant - last segment of m_aURL 131 util::DateTime m_aLastModified; // date of last modification as reported by UCP 132 TemplateFolderContent m_aSubContents; // sorted (by name) list of the children 133 134 private: 135 inline void implResetDate( ) 136 { 137 m_aLastModified.HundredthSeconds = m_aLastModified.Seconds = m_aLastModified.Minutes = m_aLastModified.Hours = 0; 138 m_aLastModified.Day = m_aLastModified.Month = m_aLastModified.Year = 0; 139 } 140 141 private: 142 ~TemplateContent(); 143 144 public: 145 TemplateContent(); 146 TemplateContent( const INetURLObject& _rURL ); 147 TemplateContent( const INetURLObject& _rURL, const util::DateTime& _rLastModified ); 148 149 // attribute access 150 inline String getName( ) const { return m_sLocalName; } 151 inline String getURL( ) const { return m_aURL.GetMainURL( INetURLObject::DECODE_TO_IURI ); } 152 inline void setModDate( const util::DateTime& _rDate ) { m_aLastModified = _rDate; } 153 inline const util::DateTime& getModDate( ) const { return m_aLastModified; } 154 155 inline TemplateFolderContent& getSubContents() { return m_aSubContents; } 156 inline const TemplateFolderContent& getSubContents() const { return m_aSubContents; } 157 158 inline ConstFolderIterator begin() const { return m_aSubContents.begin(); } 159 inline ConstFolderIterator end() const { return m_aSubContents.end(); } 160 inline TemplateFolderContent::size_type 161 size() const { return m_aSubContents.size(); } 162 163 inline void push_back( const ::vos::ORef< TemplateContent >& _rxNewElement ) 164 { m_aSubContents.push_back( _rxNewElement ); } 165 }; 166 167 //--------------------------------------------------------------------- 168 DBG_NAME( TemplateContent ) 169 170 //--------------------------------------------------------------------- 171 TemplateContent::TemplateContent() 172 { 173 DBG_CTOR( TemplateContent, NULL ); 174 implResetDate(); 175 } 176 177 //--------------------------------------------------------------------- 178 TemplateContent::TemplateContent( const INetURLObject& _rURL ) 179 :m_aURL( _rURL ) 180 { 181 DBG_CTOR( TemplateContent, NULL ); 182 DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" ); 183 m_sLocalName = m_aURL.getName(); 184 implResetDate(); 185 } 186 187 //--------------------------------------------------------------------- 188 TemplateContent::TemplateContent( const INetURLObject& _rURL, const util::DateTime& _rLastModified ) 189 :m_aURL( _rURL ) 190 ,m_aLastModified( _rLastModified ) 191 { 192 DBG_CTOR( TemplateContent, NULL ); 193 DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" ); 194 m_sLocalName = m_aURL.getName(); 195 } 196 197 //--------------------------------------------------------------------- 198 TemplateContent::~TemplateContent() 199 { 200 DBG_DTOR( TemplateContent, NULL ); 201 } 202 203 //===================================================================== 204 //= stl helpers 205 //===================================================================== 206 //--------------------------------------------------------------------- 207 /// compares two TemplateContent by URL 208 struct TemplateContentURLLess 209 :public ::std::binary_function < ::vos::ORef< TemplateContent > 210 , ::vos::ORef< TemplateContent > 211 , bool 212 > 213 { 214 bool operator() ( const ::vos::ORef< TemplateContent >& _rxLHS, const ::vos::ORef< TemplateContent >& _rxRHS ) const 215 { 216 return _rxLHS->getURL() < _rxRHS->getURL() 217 ? true 218 : false; 219 } 220 }; 221 222 //--------------------------------------------------------------------- 223 /// sorts the sib contents of a TemplateFolderContent 224 struct SubContentSort : public ::std::unary_function< ::vos::ORef< TemplateContent >, void > 225 { 226 void operator() ( TemplateFolderContent& _rFolder ) const 227 { 228 // sort the directory by name 229 ::std::sort( 230 _rFolder.begin(), 231 _rFolder.end(), 232 TemplateContentURLLess() 233 ); 234 235 // sort the sub directories by name 236 ::std::for_each( 237 _rFolder.begin(), 238 _rFolder.end(), 239 *this 240 ); 241 } 242 243 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const 244 { 245 if ( _rxContent.isValid() && _rxContent->size() ) 246 { 247 operator()( _rxContent->getSubContents() ); 248 } 249 } 250 }; 251 //--------------------------------------------------------------------- 252 /** does a deep compare of two template contents 253 */ 254 struct TemplateContentEqual 255 :public ::std::binary_function < ::vos::ORef< TemplateContent > 256 , ::vos::ORef< TemplateContent > 257 , bool 258 > 259 { 260 //................................................................. 261 bool operator() (const ::vos::ORef< TemplateContent >& _rLHS, const ::vos::ORef< TemplateContent >& _rRHS ) 262 { 263 if ( !_rLHS.isValid() || !_rRHS.isValid() ) 264 { 265 DBG_ERROR( "TemplateContentEqual::operator(): invalid contents!" ); 266 return true; 267 // this is not strictly true, in case only one is invalid - but this is a heavy error anyway 268 } 269 270 if ( _rLHS->getURL() != _rRHS->getURL() ) 271 return false; 272 273 if ( _rLHS->getModDate() != _rRHS->getModDate() ) 274 return false; 275 276 if ( _rLHS->getSubContents().size() != _rRHS->getSubContents().size() ) 277 return false; 278 279 if ( _rLHS->getSubContents().size() ) 280 { // there are children 281 // -> compare them 282 ::std::pair< FolderIterator, FolderIterator > aFirstDifferent = ::std::mismatch( 283 _rLHS->getSubContents().begin(), 284 _rLHS->getSubContents().end(), 285 _rRHS->getSubContents().begin(), 286 *this 287 ); 288 if ( aFirstDifferent.first != _rLHS->getSubContents().end() ) 289 return false;// the sub contents differ 290 } 291 292 return true; 293 } 294 }; 295 296 //--------------------------------------------------------------------- 297 /// base class for functors which act an an SvStream 298 struct StorageHelper 299 { 300 protected: 301 SvStream& m_rStorage; 302 StorageHelper( SvStream& _rStorage ) : m_rStorage( _rStorage ) { } 303 }; 304 305 //--------------------------------------------------------------------- 306 /// functor which allows storing a string 307 struct StoreString 308 :public ::std::unary_function< String, void > 309 ,public StorageHelper 310 { 311 StoreString( SvStream& _rStorage ) : StorageHelper( _rStorage ) { } 312 313 void operator() ( const String& _rString ) const 314 { 315 m_rStorage.WriteByteString( _rString ); 316 } 317 }; 318 319 //--------------------------------------------------------------------- 320 /// functor which stores the local name of a TemplateContent 321 struct StoreLocalContentName 322 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void > 323 ,public StoreString 324 { 325 StoreLocalContentName( SvStream& _rStorage ) : StoreString( _rStorage ) { } 326 327 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const 328 { 329 DBG_ERRORFILE( "This method must not be used, the whole URL must be stored!" ); 330 331 // use the base class operator with the local name of the content 332 StoreString::operator() ( _rxContent->getName() ); 333 } 334 }; 335 336 //--------------------------------------------------------------------- 337 struct StoreContentURL 338 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void > 339 ,public StoreString 340 { 341 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs; 342 343 StoreContentURL( SvStream& _rStorage, 344 const uno::Reference< 345 util::XOfficeInstallationDirectories > & 346 xOfficeInstDirs ) 347 : StoreString( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { } 348 349 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const 350 { 351 // use the base class operator with the local name of the content 352 String sURL = _rxContent->getURL(); 353 // #116281# Keep office installtion relocatable. Never store 354 // any direct references to office installation directory. 355 sURL = m_xOfficeInstDirs->makeRelocatableURL( sURL ); 356 StoreString::operator() ( sURL ); 357 } 358 }; 359 360 //--------------------------------------------------------------------- 361 /// functor which stores the complete content of a TemplateContent 362 struct StoreFolderContent 363 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void > 364 ,public StorageHelper 365 { 366 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs; 367 368 public: 369 StoreFolderContent( SvStream& _rStorage, 370 const uno::Reference< 371 util::XOfficeInstallationDirectories > & 372 xOfficeInstDirs ) 373 : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { } 374 375 //................................................................. 376 void operator() ( const TemplateContent& _rContent ) const 377 { 378 // store the info about this content 379 m_rStorage << _rContent.getModDate(); 380 381 // store the info about the children 382 // the number 383 m_rStorage << (sal_Int32)_rContent.size(); 384 // their URLs ( the local name is not enough, since URL might be not a hierarchical one, "expand:" for example ) 385 ::std::for_each( 386 _rContent.getSubContents().begin(), 387 _rContent.getSubContents().end(), 388 StoreContentURL( m_rStorage, m_xOfficeInstDirs ) 389 ); 390 // their content 391 ::std::for_each( 392 _rContent.getSubContents().begin(), 393 _rContent.getSubContents().end(), 394 *this 395 ); 396 } 397 398 //................................................................. 399 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const 400 { 401 if ( _rxContent.isValid() ) 402 { 403 operator()( *_rxContent ); 404 } 405 } 406 }; 407 408 //--------------------------------------------------------------------- 409 /// functor which reads a complete TemplateContent instance 410 struct ReadFolderContent 411 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void > 412 ,public StorageHelper 413 { 414 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs; 415 416 ReadFolderContent( SvStream& _rStorage, 417 const uno::Reference< 418 util::XOfficeInstallationDirectories > & 419 xOfficeInstDirs ) 420 : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { } 421 422 //................................................................. 423 void operator() ( TemplateContent& _rContent ) const 424 { 425 // store the info about this content 426 util::DateTime aModDate; 427 m_rStorage >> aModDate; 428 _rContent.setModDate( aModDate ); 429 430 // store the info about the children 431 // the number 432 sal_Int32 nChildren = 0; 433 m_rStorage >> nChildren; 434 TemplateFolderContent& rChildren = _rContent.getSubContents(); 435 rChildren.resize( 0 ); 436 rChildren.reserve( nChildren ); 437 // initialize them with their (local) names 438 while ( nChildren-- ) 439 { 440 String sURL; 441 m_rStorage.ReadByteString( sURL ); 442 sURL = m_xOfficeInstDirs->makeAbsoluteURL( sURL ); 443 INetURLObject aChildURL( sURL ); 444 rChildren.push_back( new TemplateContent( aChildURL ) ); 445 } 446 447 // their content 448 ::std::for_each( 449 _rContent.getSubContents().begin(), 450 _rContent.getSubContents().end(), 451 *this 452 ); 453 } 454 455 //................................................................. 456 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const 457 { 458 if ( _rxContent.isValid() ) 459 { 460 operator()( *_rxContent ); 461 } 462 } 463 }; 464 465 //===================================================================== 466 //= TemplateFolderCacheImpl 467 //===================================================================== 468 class TemplateFolderCacheImpl 469 { 470 private: 471 TemplateFolderContent m_aPreviousState; // the current state of the template dirs (as found on the HD) 472 TemplateFolderContent m_aCurrentState; // the previous state of the template dirs (as found in the cache file) 473 474 osl::Mutex m_aMutex; 475 // will be lazy inited; never access directly; use getOfficeInstDirs(). 476 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs; 477 478 SvStream* m_pCacheStream; 479 sal_Bool m_bNeedsUpdate : 1; 480 sal_Bool m_bKnowState : 1; 481 sal_Bool m_bValidCurrentState : 1; 482 sal_Bool m_bAutoStoreState : 1; 483 484 public: 485 TemplateFolderCacheImpl( sal_Bool _bAutoStoreState ); 486 ~TemplateFolderCacheImpl( ); 487 488 sal_Bool needsUpdate( sal_Bool _bForceCheck ); 489 void storeState( sal_Bool _bForceRetrieval ); 490 491 private: 492 void initTemplDirs( ::std::vector< String >& _rRootDirs ); 493 sal_Bool openCacheStream( sal_Bool _bForRead ); 494 void closeCacheStream( ); 495 496 /// read the state of the dirs from the cache file 497 sal_Bool readPreviousState(); 498 /// read the current state of the dirs 499 sal_Bool readCurrentState(); 500 501 String implParseSmart( const String& _rPath ); 502 503 sal_Bool implReadFolder( const ::vos::ORef< TemplateContent >& _rxRoot ); 504 505 static String getCacheFileName(); 506 static sal_Int32 getMagicNumber(); 507 static void normalize( TemplateFolderContent& _rState ); 508 509 // @return <TRUE/> if the states equal 510 static sal_Bool equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS ); 511 512 // late initialize m_xOfficeInstDirs 513 uno::Reference< util::XOfficeInstallationDirectories > getOfficeInstDirs(); 514 }; 515 516 //--------------------------------------------------------------------- 517 TemplateFolderCacheImpl::TemplateFolderCacheImpl( sal_Bool _bAutoStoreState ) 518 :m_pCacheStream ( NULL ) 519 ,m_bNeedsUpdate ( sal_True ) 520 ,m_bKnowState ( sal_False ) 521 ,m_bValidCurrentState ( sal_False ) 522 ,m_bAutoStoreState ( _bAutoStoreState ) 523 { 524 } 525 526 //--------------------------------------------------------------------- 527 TemplateFolderCacheImpl::~TemplateFolderCacheImpl( ) 528 { 529 // store the current state if possible and required 530 if ( m_bValidCurrentState && m_bAutoStoreState ) 531 storeState( sal_False ); 532 533 closeCacheStream( ); 534 } 535 536 //--------------------------------------------------------------------- 537 sal_Int32 TemplateFolderCacheImpl::getMagicNumber() 538 { 539 sal_Int32 nMagic = 0; 540 ( nMagic += (sal_Int8)'T' ) <<= 4; 541 ( nMagic += (sal_Int8)'D' ) <<= 4; 542 ( nMagic += (sal_Int8)'S' ) <<= 4; 543 ( nMagic += (sal_Int8)'C' ) <<= 0; 544 return nMagic; 545 } 546 547 //--------------------------------------------------------------------- 548 String TemplateFolderCacheImpl::getCacheFileName() 549 { 550 return String::CreateFromAscii( ".templdir.cache" ); 551 } 552 553 554 //--------------------------------------------------------------------- 555 void TemplateFolderCacheImpl::normalize( TemplateFolderContent& _rState ) 556 { 557 SubContentSort()( _rState ); 558 } 559 560 //--------------------------------------------------------------------- 561 sal_Bool TemplateFolderCacheImpl::equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS ) 562 { 563 if ( _rLHS.size() != _rRHS.size() ) 564 return sal_False; 565 566 // as both arrays are sorted (by definition - this is a precondition of this method) 567 // we can simply go from the front to the back and compare the single elements 568 569 ::std::pair< ConstFolderIterator, ConstFolderIterator > aFirstDifferent = ::std::mismatch( 570 _rLHS.begin(), 571 _rLHS.end(), 572 _rRHS.begin(), 573 TemplateContentEqual() 574 ); 575 576 return aFirstDifferent.first == _rLHS.end(); 577 } 578 579 //--------------------------------------------------------------------- 580 void TemplateFolderCacheImpl::storeState( sal_Bool _bForceRetrieval ) 581 { 582 if ( !m_bValidCurrentState || _bForceRetrieval ) 583 readCurrentState( ); 584 585 if ( m_bValidCurrentState && openCacheStream( sal_False ) ) 586 { 587 *m_pCacheStream << getMagicNumber(); 588 589 // store the template root folders 590 // the size 591 *m_pCacheStream << (sal_Int32)m_aCurrentState.size(); 592 // the complete URLs 593 ::std::for_each( 594 m_aCurrentState.begin(), 595 m_aCurrentState.end(), 596 StoreContentURL( *m_pCacheStream, getOfficeInstDirs() ) 597 ); 598 599 // the contents 600 ::std::for_each( 601 m_aCurrentState.begin(), 602 m_aCurrentState.end(), 603 StoreFolderContent( *m_pCacheStream, getOfficeInstDirs() ) 604 ); 605 } 606 } 607 608 //--------------------------------------------------------------------- 609 String TemplateFolderCacheImpl::implParseSmart( const String& _rPath ) 610 { 611 INetURLObject aParser; 612 aParser.SetSmartProtocol( INET_PROT_FILE ); 613 aParser.SetURL( _rPath, INetURLObject::WAS_ENCODED ); 614 if ( INET_PROT_NOT_VALID == aParser.GetProtocol() ) 615 { 616 String sURL; 617 LocalFileHelper::ConvertPhysicalNameToURL( _rPath, sURL ); 618 aParser.SetURL( sURL, INetURLObject::WAS_ENCODED ); 619 } 620 return aParser.GetMainURL( INetURLObject::DECODE_TO_IURI ); 621 } 622 623 //--------------------------------------------------------------------- 624 void TemplateFolderCacheImpl::closeCacheStream( ) 625 { 626 DELETEZ( m_pCacheStream ); 627 } 628 629 //--------------------------------------------------------------------- 630 sal_Bool TemplateFolderCacheImpl::implReadFolder( const ::vos::ORef< TemplateContent >& _rxRoot ) 631 { 632 try 633 { 634 // create a content for the current folder root 635 Reference< XResultSet > xResultSet; 636 Sequence< ::rtl::OUString > aContentProperties( 4); 637 aContentProperties[0] = ::rtl::OUString::createFromAscii( "Title" ); 638 aContentProperties[1] = ::rtl::OUString::createFromAscii( "DateModified" ); 639 aContentProperties[2] = ::rtl::OUString::createFromAscii( "DateCreated" ); 640 aContentProperties[3] = ::rtl::OUString::createFromAscii( "IsFolder" ); 641 642 // get the set of sub contents in the folder 643 try 644 { 645 Reference< XDynamicResultSet > xDynResultSet; 646 647 ::ucbhelper::Content aTemplateRoot( _rxRoot->getURL(), Reference< XCommandEnvironment >() ); 648 xDynResultSet = aTemplateRoot.createDynamicCursor( aContentProperties, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ); 649 if ( xDynResultSet.is() ) 650 xResultSet = xDynResultSet->getStaticResultSet(); 651 } 652 catch( CommandAbortedException& ) 653 { 654 DBG_ERRORFILE( "TemplateFolderCacheImpl::implReadFolder: caught a CommandAbortedException!" ); 655 return sal_False; 656 } 657 catch( ::com::sun::star::uno::Exception& ) 658 { 659 } 660 661 // collect the infos about the sub contents 662 if ( xResultSet.is() ) 663 { 664 Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW ); 665 Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW ); 666 667 while ( xResultSet->next() ) 668 { 669 INetURLObject aSubContentURL( xContentAccess->queryContentIdentifierString() ); 670 671 // a new content instance 672 ::vos::ORef< TemplateContent > xChild = new TemplateContent( aSubContentURL ); 673 674 // the modified date 675 xChild->setModDate( xRow->getTimestamp( 2 ) ); // date modified 676 if ( xRow->wasNull() ) 677 xChild->setModDate( xRow->getTimestamp( 3 ) ); // fallback: date created 678 679 // push back this content 680 _rxRoot->push_back( xChild ); 681 682 // is it a folder? 683 if ( xRow->getBoolean( 4 ) && !xRow->wasNull() ) 684 { // yes -> step down 685 ConstFolderIterator aNextLevelRoot = _rxRoot->end(); 686 --aNextLevelRoot; 687 implReadFolder( *aNextLevelRoot ); 688 } 689 } 690 } 691 } 692 catch( const Exception& ) 693 { 694 DBG_ERROR( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" ); 695 return sal_False; 696 } 697 return sal_True; 698 } 699 700 //--------------------------------------------------------------------- 701 sal_Bool TemplateFolderCacheImpl::readCurrentState() 702 { 703 // reset 704 m_bValidCurrentState = sal_False; 705 TemplateFolderContent aTemplateFolderContent; 706 m_aCurrentState.swap( aTemplateFolderContent ); 707 708 // the template directories from the config 709 const SvtPathOptions aPathOptions; 710 String aDirs = aPathOptions.GetTemplatePath(); 711 sal_uInt16 nDirs = aDirs.GetTokenCount( ';' ); 712 713 m_aCurrentState.reserve( nDirs ); 714 // loop through all the root-level template folders 715 for ( sal_uInt16 i=0; i<nDirs; ++i) 716 { 717 String sTemplatePath( aDirs.GetToken( i, ';' ) ); 718 sTemplatePath = aPathOptions.ExpandMacros( sTemplatePath ); 719 // create a new entry 720 m_aCurrentState.push_back( new TemplateContent( INetURLObject( sTemplatePath ) ) ); 721 TemplateFolderContent::iterator aCurrentRoot = m_aCurrentState.end(); 722 --aCurrentRoot; 723 724 if ( !implReadFolder( *aCurrentRoot ) ) 725 return sal_False; 726 } 727 728 // normalize the array (which basically means "sort it") 729 normalize( m_aCurrentState ); 730 731 m_bValidCurrentState = sal_True; 732 return m_bValidCurrentState; 733 } 734 735 //--------------------------------------------------------------------- 736 sal_Bool TemplateFolderCacheImpl::readPreviousState() 737 { 738 DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::readPreviousState: not to be called without stream!" ); 739 740 // reset 741 TemplateFolderContent aTemplateFolderContent; 742 m_aPreviousState.swap( aTemplateFolderContent ); 743 744 // check the magic number 745 sal_Int32 nMagic = 0; 746 *m_pCacheStream >> nMagic; 747 DBG_ASSERT( getMagicNumber() == nMagic, "TemplateFolderCacheImpl::readPreviousState: invalid cache file!" ); 748 if ( getMagicNumber() != nMagic ) 749 return sal_False; 750 751 // the root directories 752 // their number 753 sal_Int32 nRootDirectories = 0; 754 *m_pCacheStream >> nRootDirectories; 755 // init empty TemplateContens with the URLs 756 m_aPreviousState.reserve( nRootDirectories ); 757 while ( nRootDirectories-- ) 758 { 759 String sURL; 760 m_pCacheStream->ReadByteString( sURL ); 761 // #116281# Keep office installtion relocatable. Never store 762 // any direct references to office installation directory. 763 sURL = getOfficeInstDirs()->makeAbsoluteURL( sURL ); 764 m_aPreviousState.push_back( 765 new TemplateContent( INetURLObject(sURL) ) ); 766 } 767 768 // read the contents of the root folders 769 ::std::for_each( 770 m_aPreviousState.begin(), 771 m_aPreviousState.end(), 772 ReadFolderContent( *m_pCacheStream, getOfficeInstDirs() ) 773 ); 774 775 DBG_ASSERT( !m_pCacheStream->GetErrorCode(), "TemplateFolderCacheImpl::readPreviousState: unknown error during reading the state cache!" ); 776 777 // normalize the array (which basically means "sort it") 778 normalize( m_aPreviousState ); 779 780 return sal_True; 781 } 782 783 //--------------------------------------------------------------------- 784 sal_Bool TemplateFolderCacheImpl::openCacheStream( sal_Bool _bForRead ) 785 { 786 // close any old stream instance 787 closeCacheStream( ); 788 789 // get the storage directory 790 String sStorageURL = implParseSmart( SvtPathOptions().GetStoragePath() ); 791 INetURLObject aStorageURL( sStorageURL ); 792 if ( INET_PROT_NOT_VALID == aStorageURL.GetProtocol() ) 793 { 794 DBG_ERROR( "TemplateFolderCacheImpl::openCacheStream: invalid storage path!" ); 795 return sal_False; 796 } 797 798 // append our name 799 aStorageURL.Append( getCacheFileName() ); 800 801 // open the stream 802 m_pCacheStream = UcbStreamHelper::CreateStream( aStorageURL.GetMainURL( INetURLObject::DECODE_TO_IURI ), 803 _bForRead ? STREAM_READ | STREAM_NOCREATE : STREAM_WRITE | STREAM_TRUNC ); 804 DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::openCacheStream: could not open/create the cache stream!" ); 805 if ( m_pCacheStream && m_pCacheStream->GetErrorCode() ) 806 { 807 DELETEZ( m_pCacheStream ); 808 } 809 810 if ( m_pCacheStream ) 811 m_pCacheStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 ); 812 813 return NULL != m_pCacheStream; 814 } 815 816 //--------------------------------------------------------------------- 817 sal_Bool TemplateFolderCacheImpl::needsUpdate( sal_Bool _bForceCheck ) 818 { 819 if ( m_bKnowState && !_bForceCheck ) 820 return m_bNeedsUpdate; 821 822 m_bNeedsUpdate = sal_True; 823 m_bKnowState = sal_True; 824 825 if ( readCurrentState() ) 826 { 827 // open the stream which contains the cached state of the directories 828 if ( openCacheStream( sal_True ) ) 829 { // opening the stream succeeded 830 if ( readPreviousState() ) 831 { 832 m_bNeedsUpdate = !equalStates( m_aPreviousState, m_aCurrentState ); 833 } 834 else 835 { 836 closeCacheStream(); 837 } 838 } 839 } 840 return m_bNeedsUpdate; 841 } 842 843 //--------------------------------------------------------------------- 844 void TemplateFolderCacheImpl::initTemplDirs( ::std::vector< String >& ) 845 { 846 } 847 848 //--------------------------------------------------------------------- 849 uno::Reference< util::XOfficeInstallationDirectories > 850 TemplateFolderCacheImpl::getOfficeInstDirs() 851 { 852 if ( !m_xOfficeInstDirs.is() ) 853 { 854 osl::MutexGuard aGuard( m_aMutex ); 855 if ( !m_xOfficeInstDirs.is() ) 856 { 857 // @@@ This is bad! 858 uno::Reference< lang::XMultiServiceFactory > xSMgr 859 = comphelper::getProcessServiceFactory(); 860 OSL_ENSURE( xSMgr.is(), "No service manager!" ); 861 862 uno::Reference< beans::XPropertySet > xPropSet( 863 xSMgr, uno::UNO_QUERY ); 864 if ( xPropSet.is() ) 865 { 866 uno::Reference< uno::XComponentContext > xCtx; 867 xPropSet->getPropertyValue( 868 rtl::OUString( 869 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ) 870 >>= xCtx; 871 872 OSL_ENSURE( xCtx.is(), 873 "Unable to obtain component context from service manager!" ); 874 875 if ( xCtx.is() ) 876 { 877 xCtx->getValueByName( 878 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 879 "/singletons/com.sun.star.util.theOfficeInstallationDirectories" ) ) ) 880 >>= m_xOfficeInstDirs; 881 } 882 883 OSL_ENSURE( m_xOfficeInstDirs.is(), 884 "Unable to obtain office directories singleton!" ); 885 886 } 887 } 888 } 889 return m_xOfficeInstDirs; 890 } 891 892 //===================================================================== 893 //= TemplateFolderCache 894 //===================================================================== 895 //--------------------------------------------------------------------- 896 TemplateFolderCache::TemplateFolderCache( sal_Bool _bAutoStoreState ) 897 :m_pImpl( new TemplateFolderCacheImpl( _bAutoStoreState ) ) 898 { 899 } 900 901 //--------------------------------------------------------------------- 902 TemplateFolderCache::~TemplateFolderCache( ) 903 { 904 DELETEZ( m_pImpl ); 905 } 906 907 //--------------------------------------------------------------------- 908 sal_Bool TemplateFolderCache::needsUpdate( sal_Bool _bForceCheck ) 909 { 910 return m_pImpl->needsUpdate( _bForceCheck ); 911 } 912 913 //--------------------------------------------------------------------- 914 void TemplateFolderCache::storeState( sal_Bool _bForceRetrieval ) 915 { 916 m_pImpl->storeState( _bForceRetrieval ); 917 } 918 919 //......................................................................... 920 } // namespace sfx2 921 //......................................................................... 922 923