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

Generated by: LCOV version 1.11