LCOV - code coverage report
Current view: top level - svtools/source/misc - templatefoldercache.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 296 0.0 %
Date: 2014-11-03 Functions: 0 58 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10