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

Generated by: LCOV version 1.10