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