Bump version to 5.0-14
[LibreOffice.git] / svtools / source / misc / templatefoldercache.cxx
blobf5eb681ea4ab52a1e987623792029cd2f3b8df1f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
38 #include <comphelper/processfactory.hxx>
40 #include <vector>
41 #include <list>
42 #include <functional>
43 #include <algorithm>
46 namespace svt
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;
57 //= helpers
60 SvStream& WriteDateTime( SvStream& _rStorage, const util::DateTime& _rDate )
62 sal_uInt16 hundredthSeconds = static_cast< sal_uInt16 >( _rDate.NanoSeconds / tools::Time::nanoPerCenti );
63 _rStorage.WriteUInt16( hundredthSeconds );
65 _rStorage.WriteUInt16( _rDate.Seconds );
66 _rStorage.WriteUInt16( _rDate.Minutes );
67 _rStorage.WriteUInt16( _rDate.Hours );
68 _rStorage.WriteUInt16( _rDate.Day );
69 _rStorage.WriteUInt16( _rDate.Month );
70 _rStorage.WriteInt16( _rDate.Year );
72 return _rStorage;
76 SvStream& operator >> ( SvStream& _rStorage, util::DateTime& _rDate )
78 sal_uInt16 hundredthSeconds;
79 _rStorage.ReadUInt16( hundredthSeconds );
80 _rDate.NanoSeconds = static_cast< sal_uInt32 >( hundredthSeconds ) * tools::Time::nanoPerCenti;
82 _rStorage.ReadUInt16( _rDate.Seconds );
83 _rStorage.ReadUInt16( _rDate.Minutes );
84 _rStorage.ReadUInt16( _rDate.Hours );
85 _rStorage.ReadUInt16( _rDate.Day );
86 _rStorage.ReadUInt16( _rDate.Month );
87 _rStorage.ReadInt16( _rDate.Year );
89 return _rStorage;
93 bool operator == ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
95 return _rLHS.NanoSeconds == _rRHS.NanoSeconds
96 && _rLHS.Seconds == _rRHS.Seconds
97 && _rLHS.Minutes == _rRHS.Minutes
98 && _rLHS.Hours == _rRHS.Hours
99 && _rLHS.Day == _rRHS.Day
100 && _rLHS.Month == _rRHS.Month
101 && _rLHS.Year == _rRHS.Year
102 && _rLHS.IsUTC == _rRHS.IsUTC;
106 bool operator != ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
108 return !( _rLHS == _rRHS );
112 //= TemplateContent
114 struct TemplateContent;
115 typedef ::std::vector< ::rtl::Reference< TemplateContent > > TemplateFolderContent;
116 typedef TemplateFolderContent::const_iterator ConstFolderIterator;
117 typedef TemplateFolderContent::iterator FolderIterator;
119 /** a struct describing one content in one of the template dirs (or at least it's relevant aspects)
121 struct TemplateContent : public ::salhelper::SimpleReferenceObject
123 public:
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
131 private:
132 inline void implResetDate( )
134 m_aLastModified.NanoSeconds = m_aLastModified.Seconds = m_aLastModified.Minutes = m_aLastModified.Hours = 0;
135 m_aLastModified.Day = m_aLastModified.Month = m_aLastModified.Year = 0;
138 private:
139 virtual ~TemplateContent();
141 public:
142 TemplateContent( const INetURLObject& _rURL );
144 // attribute access
145 inline OUString getURL( ) const { return m_aURL.GetMainURL( INetURLObject::DECODE_TO_IURI ); }
146 inline void setModDate( const util::DateTime& _rDate ) { m_aLastModified = _rDate; }
147 inline const util::DateTime& getModDate( ) const { return m_aLastModified; }
149 inline TemplateFolderContent& getSubContents() { return m_aSubContents; }
150 inline const TemplateFolderContent& getSubContents() const { return m_aSubContents; }
152 inline ConstFolderIterator end() const { return m_aSubContents.end(); }
153 inline TemplateFolderContent::size_type
154 size() const { return m_aSubContents.size(); }
156 inline void push_back( const ::rtl::Reference< TemplateContent >& _rxNewElement )
157 { m_aSubContents.push_back( _rxNewElement ); }
163 TemplateContent::TemplateContent( const INetURLObject& _rURL )
164 :m_aURL( _rURL )
166 DBG_ASSERT( INetProtocol::NotValid != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
167 m_sLocalName = m_aURL.getName();
168 implResetDate();
172 TemplateContent::~TemplateContent()
177 //= stl helpers
180 /// compares two TemplateContent by URL
181 struct TemplateContentURLLess
182 :public ::std::binary_function < ::rtl::Reference< TemplateContent >
183 , ::rtl::Reference< TemplateContent >
184 , bool
187 bool operator() ( const ::rtl::Reference< TemplateContent >& _rxLHS, const ::rtl::Reference< TemplateContent >& _rxRHS ) const
189 return _rxLHS->getURL() < _rxRHS->getURL();
194 /// sorts the sib contents of a TemplateFolderContent
195 struct SubContentSort : public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
197 void operator() ( TemplateFolderContent& _rFolder ) const
199 // sort the directory by name
200 ::std::sort(
201 _rFolder.begin(),
202 _rFolder.end(),
203 TemplateContentURLLess()
206 // sort the sub directories by name
207 ::std::for_each(
208 _rFolder.begin(),
209 _rFolder.end(),
210 *this
214 void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
216 if ( _rxContent.is() && _rxContent->size() )
218 operator()( _rxContent->getSubContents() );
223 /** does a deep compare of two template contents
225 struct TemplateContentEqual
226 :public ::std::binary_function < ::rtl::Reference< TemplateContent >
227 , ::rtl::Reference< TemplateContent >
228 , bool
232 bool operator() (const ::rtl::Reference< TemplateContent >& _rLHS, const ::rtl::Reference< TemplateContent >& _rRHS )
234 if ( !_rLHS.is() || !_rRHS.is() )
236 OSL_FAIL( "TemplateContentEqual::operator(): invalid contents!" );
237 return true;
238 // this is not strictly true, in case only one is invalid - but this is a heavy error anyway
241 if ( _rLHS->getURL() != _rRHS->getURL() )
242 return false;
244 if ( _rLHS->getModDate() != _rRHS->getModDate() )
245 return false;
247 if ( _rLHS->getSubContents().size() != _rRHS->getSubContents().size() )
248 return false;
250 if ( _rLHS->getSubContents().size() )
251 { // there are children
252 // -> compare them
253 ::std::pair< FolderIterator, FolderIterator > aFirstDifferent = ::std::mismatch(
254 _rLHS->getSubContents().begin(),
255 _rLHS->getSubContents().end(),
256 _rRHS->getSubContents().begin(),
257 *this
259 if ( aFirstDifferent.first != _rLHS->getSubContents().end() )
260 return false;// the sub contents differ
263 return true;
268 /// base class for functors which act on a SvStream
269 struct StorageHelper
271 protected:
272 SvStream& m_rStorage;
273 StorageHelper( SvStream& _rStorage ) : m_rStorage( _rStorage ) { }
277 /// functor which allows storing a string
278 struct StoreString
279 :public ::std::unary_function< OUString, void >
280 ,public StorageHelper
282 StoreString( SvStream& _rStorage ) : StorageHelper( _rStorage ) { }
284 void operator() ( const OUString& _rString ) const
286 m_rStorage.WriteUniOrByteString( _rString, m_rStorage.GetStreamCharSet() );
290 struct StoreContentURL
291 :public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
292 ,public StoreString
294 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
296 StoreContentURL( SvStream& _rStorage,
297 const uno::Reference<
298 util::XOfficeInstallationDirectories > &
299 xOfficeInstDirs )
300 : StoreString( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
302 void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
304 // use the base class operator with the local name of the content
305 OUString sURL = _rxContent->getURL();
306 // #116281# Keep office installtion relocatable. Never store
307 // any direct references to office installation directory.
308 sURL = m_xOfficeInstDirs->makeRelocatableURL( sURL );
309 StoreString::operator() ( sURL );
314 /// functor which stores the complete content of a TemplateContent
315 struct StoreFolderContent
316 :public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
317 ,public StorageHelper
319 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
321 public:
322 StoreFolderContent( SvStream& _rStorage,
323 const uno::Reference<
324 util::XOfficeInstallationDirectories > &
325 xOfficeInstDirs )
326 : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
329 void operator() ( const TemplateContent& _rContent ) const
331 // store the info about this content
332 WriteDateTime( m_rStorage, _rContent.getModDate() );
334 // store the info about the children
335 // the number
336 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 _rContent.getSubContents().begin(),
340 _rContent.getSubContents().end(),
341 StoreContentURL( m_rStorage, m_xOfficeInstDirs )
343 // their content
344 ::std::for_each(
345 _rContent.getSubContents().begin(),
346 _rContent.getSubContents().end(),
347 *this
352 void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
354 if ( _rxContent.is() )
356 operator()( *_rxContent );
362 /// functor which reads a complete TemplateContent instance
363 struct ReadFolderContent
364 :public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
365 ,public StorageHelper
367 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
369 ReadFolderContent( SvStream& _rStorage,
370 const uno::Reference<
371 util::XOfficeInstallationDirectories > &
372 xOfficeInstDirs )
373 : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
376 void operator() ( TemplateContent& _rContent ) const
378 // store the info about this content
379 util::DateTime aModDate;
380 m_rStorage >> aModDate;
381 _rContent.setModDate( aModDate );
383 // store the info about the children
384 // the number
385 sal_Int32 nChildren = 0;
386 m_rStorage.ReadInt32( nChildren );
387 TemplateFolderContent& rChildren = _rContent.getSubContents();
388 rChildren.resize( 0 );
389 rChildren.reserve( nChildren );
390 // initialize them with their (local) names
391 while ( nChildren-- )
393 OUString sURL = m_rStorage.ReadUniOrByteString(m_rStorage.GetStreamCharSet());
394 sURL = m_xOfficeInstDirs->makeAbsoluteURL( sURL );
395 INetURLObject aChildURL( sURL );
396 rChildren.push_back( new TemplateContent( aChildURL ) );
399 // their content
400 ::std::for_each(
401 _rContent.getSubContents().begin(),
402 _rContent.getSubContents().end(),
403 *this
408 void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
410 if ( _rxContent.is() )
412 operator()( *_rxContent );
418 //= TemplateFolderCacheImpl
420 class TemplateFolderCacheImpl
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)
426 osl::Mutex m_aMutex;
427 // will be lazy inited; never access directly; use getOfficeInstDirs().
428 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
430 SvStream* m_pCacheStream;
431 bool m_bNeedsUpdate : 1;
432 bool m_bKnowState : 1;
433 bool m_bValidCurrentState : 1;
434 bool m_bAutoStoreState : 1;
436 public:
437 TemplateFolderCacheImpl( bool _bAutoStoreState );
438 ~TemplateFolderCacheImpl( );
440 bool needsUpdate( bool _bForceCheck );
441 void storeState( bool _bForceRetrieval );
443 private:
444 bool openCacheStream( bool _bForRead );
445 void closeCacheStream( );
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();
452 static OUString implParseSmart( const OUString& _rPath );
454 bool implReadFolder( const ::rtl::Reference< TemplateContent >& _rxRoot );
456 static OUString getCacheFileName();
457 static sal_Int32 getMagicNumber();
458 static void normalize( TemplateFolderContent& _rState );
460 // @return <TRUE/> if the states equal
461 static bool equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS );
463 // late initialize m_xOfficeInstDirs
464 uno::Reference< util::XOfficeInstallationDirectories > getOfficeInstDirs();
468 TemplateFolderCacheImpl::TemplateFolderCacheImpl( bool _bAutoStoreState )
469 :m_pCacheStream ( NULL )
470 ,m_bNeedsUpdate ( true )
471 ,m_bKnowState ( false )
472 ,m_bValidCurrentState ( false )
473 ,m_bAutoStoreState ( _bAutoStoreState )
478 TemplateFolderCacheImpl::~TemplateFolderCacheImpl( )
480 // store the current state if possible and required
481 if ( m_bValidCurrentState && m_bAutoStoreState )
482 storeState( false );
484 closeCacheStream( );
488 sal_Int32 TemplateFolderCacheImpl::getMagicNumber()
490 sal_Int32 nMagic = 0;
491 ( nMagic += (sal_Int8)'T' ) <<= 4;
492 ( nMagic += (sal_Int8)'D' ) <<= 4;
493 ( nMagic += (sal_Int8)'S' ) <<= 4;
494 ( nMagic += (sal_Int8)'C' ) <<= 0;
495 return nMagic;
499 OUString TemplateFolderCacheImpl::getCacheFileName()
501 return OUString(".templdir.cache");
506 void TemplateFolderCacheImpl::normalize( TemplateFolderContent& _rState )
508 SubContentSort()( _rState );
512 bool TemplateFolderCacheImpl::equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS )
514 if ( _rLHS.size() != _rRHS.size() )
515 return false;
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
520 ::std::pair< ConstFolderIterator, ConstFolderIterator > aFirstDifferent = ::std::mismatch(
521 _rLHS.begin(),
522 _rLHS.end(),
523 _rRHS.begin(),
524 TemplateContentEqual()
527 return aFirstDifferent.first == _rLHS.end();
531 void TemplateFolderCacheImpl::storeState( bool _bForceRetrieval )
533 if ( !m_bValidCurrentState || _bForceRetrieval )
534 readCurrentState( );
536 if ( m_bValidCurrentState && openCacheStream( false ) )
538 m_pCacheStream->WriteInt32( getMagicNumber() );
540 // store the template root folders
541 // the size
542 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() )
550 // the contents
551 ::std::for_each(
552 m_aCurrentState.begin(),
553 m_aCurrentState.end(),
554 StoreFolderContent( *m_pCacheStream, getOfficeInstDirs() )
560 OUString TemplateFolderCacheImpl::implParseSmart( const OUString& _rPath )
562 INetURLObject aParser;
563 aParser.SetSmartProtocol( INetProtocol::File );
564 aParser.SetURL( _rPath, INetURLObject::WAS_ENCODED );
565 if ( INetProtocol::NotValid == aParser.GetProtocol() )
567 OUString sURL;
568 LocalFileHelper::ConvertPhysicalNameToURL( _rPath, sURL );
569 aParser.SetURL( sURL, INetURLObject::WAS_ENCODED );
571 return aParser.GetMainURL( INetURLObject::DECODE_TO_IURI );
575 void TemplateFolderCacheImpl::closeCacheStream( )
577 DELETEZ( m_pCacheStream );
581 bool TemplateFolderCacheImpl::implReadFolder( const ::rtl::Reference< TemplateContent >& _rxRoot )
585 // create a content for the current folder root
586 Reference< XResultSet > xResultSet;
587 Sequence< OUString > aContentProperties( 4);
588 aContentProperties[0] = "Title";
589 aContentProperties[1] = "DateModified";
590 aContentProperties[2] = "DateCreated";
591 aContentProperties[3] = "IsFolder";
593 // get the set of sub contents in the folder
596 Reference< XDynamicResultSet > xDynResultSet;
598 ::ucbhelper::Content aTemplateRoot( _rxRoot->getURL(), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext() );
599 xDynResultSet = aTemplateRoot.createDynamicCursor( aContentProperties, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS );
600 if ( xDynResultSet.is() )
601 xResultSet = xDynResultSet->getStaticResultSet();
603 catch( CommandAbortedException& )
605 SAL_WARN( "svtools.misc", "TemplateFolderCacheImpl::implReadFolder: caught a CommandAbortedException!" );
606 return false;
608 catch( ::com::sun::star::uno::Exception& )
612 // collect the infos about the sub contents
613 if ( xResultSet.is() )
615 Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
616 Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
618 while ( xResultSet->next() )
620 INetURLObject aSubContentURL( xContentAccess->queryContentIdentifierString() );
622 // a new content instance
623 ::rtl::Reference< TemplateContent > xChild = new TemplateContent( aSubContentURL );
625 // the modified date
626 xChild->setModDate( xRow->getTimestamp( 2 ) ); // date modified
627 if ( xRow->wasNull() )
628 xChild->setModDate( xRow->getTimestamp( 3 ) ); // fallback: date created
630 // push back this content
631 _rxRoot->push_back( xChild );
633 // is it a folder?
634 if ( xRow->getBoolean( 4 ) && !xRow->wasNull() )
635 { // yes -> step down
636 ConstFolderIterator aNextLevelRoot = _rxRoot->end();
637 --aNextLevelRoot;
638 implReadFolder( *aNextLevelRoot );
643 catch( const Exception& )
645 OSL_FAIL( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" );
646 return false;
648 return true;
652 bool TemplateFolderCacheImpl::readCurrentState()
654 // reset
655 m_bValidCurrentState = false;
656 TemplateFolderContent aTemplateFolderContent;
657 m_aCurrentState.swap( aTemplateFolderContent );
659 // the template directories from the config
660 const SvtPathOptions aPathOptions;
661 OUString aDirs = aPathOptions.GetTemplatePath();
663 // loop through all the root-level template folders
664 sal_Int32 nIndex = 0;
667 OUString sTemplatePath( aDirs.getToken(0, ';', nIndex) );
668 sTemplatePath = aPathOptions.ExpandMacros( sTemplatePath );
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 sTemplatePath = getOfficeInstDirs()->makeAbsoluteURL(
678 getOfficeInstDirs()->makeRelocatableURL(sTemplatePath));
680 // create a new entry
681 m_aCurrentState.push_back( new TemplateContent( INetURLObject( sTemplatePath ) ) );
682 TemplateFolderContent::iterator aCurrentRoot = m_aCurrentState.end();
683 --aCurrentRoot;
685 if ( !implReadFolder( *aCurrentRoot ) )
686 return false;
688 while ( nIndex >= 0 );
690 // normalize the array (which basically means "sort it")
691 normalize( m_aCurrentState );
693 m_bValidCurrentState = true;
694 return m_bValidCurrentState;
698 bool TemplateFolderCacheImpl::readPreviousState()
700 DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::readPreviousState: not to be called without stream!" );
702 // reset
703 TemplateFolderContent aTemplateFolderContent;
704 m_aPreviousState.swap( aTemplateFolderContent );
706 // check the magic number
707 sal_Int32 nMagic = 0;
708 m_pCacheStream->ReadInt32( nMagic );
709 DBG_ASSERT( getMagicNumber() == nMagic, "TemplateFolderCacheImpl::readPreviousState: invalid cache file!" );
710 if ( getMagicNumber() != nMagic )
711 return false;
713 // the root directories
714 // their number
715 sal_Int32 nRootDirectories = 0;
716 m_pCacheStream->ReadInt32( nRootDirectories );
717 // init empty TemplateContens with the URLs
718 m_aPreviousState.reserve( nRootDirectories );
719 while ( nRootDirectories-- )
721 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 sURL = getOfficeInstDirs()->makeAbsoluteURL( sURL );
725 m_aPreviousState.push_back(
726 new TemplateContent( INetURLObject(sURL) ) );
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() )
736 DBG_ASSERT( !m_pCacheStream->GetErrorCode(), "TemplateFolderCacheImpl::readPreviousState: unknown error during reading the state cache!" );
738 // normalize the array (which basically means "sort it")
739 normalize( m_aPreviousState );
741 return true;
745 bool TemplateFolderCacheImpl::openCacheStream( bool _bForRead )
747 // close any old stream instance
748 closeCacheStream( );
750 // get the storage directory
751 OUString sStorageURL = implParseSmart( SvtPathOptions().GetStoragePath() );
752 INetURLObject aStorageURL( sStorageURL );
753 if ( INetProtocol::NotValid == aStorageURL.GetProtocol() )
755 OSL_FAIL( "TemplateFolderCacheImpl::openCacheStream: invalid storage path!" );
756 return false;
759 // append our name
760 aStorageURL.Append( getCacheFileName() );
762 // open the stream
763 m_pCacheStream = UcbStreamHelper::CreateStream( aStorageURL.GetMainURL( INetURLObject::DECODE_TO_IURI ),
764 _bForRead ? StreamMode::READ | StreamMode::NOCREATE : StreamMode::WRITE | StreamMode::TRUNC );
765 DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::openCacheStream: could not open/create the cache stream!" );
766 if ( m_pCacheStream && m_pCacheStream->GetErrorCode() )
768 DELETEZ( m_pCacheStream );
771 if ( m_pCacheStream )
772 m_pCacheStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
774 return NULL != m_pCacheStream;
778 bool TemplateFolderCacheImpl::needsUpdate( bool _bForceCheck )
780 if ( m_bKnowState && !_bForceCheck )
781 return m_bNeedsUpdate;
783 m_bNeedsUpdate = true;
784 m_bKnowState = true;
786 if ( readCurrentState() )
788 // open the stream which contains the cached state of the directories
789 if ( openCacheStream( true ) )
790 { // opening the stream succeeded
791 if ( readPreviousState() )
793 m_bNeedsUpdate = !equalStates( m_aPreviousState, m_aCurrentState );
795 else
797 closeCacheStream();
801 return m_bNeedsUpdate;
805 uno::Reference< util::XOfficeInstallationDirectories >
806 TemplateFolderCacheImpl::getOfficeInstDirs()
808 if ( !m_xOfficeInstDirs.is() )
810 osl::MutexGuard aGuard( m_aMutex );
811 if ( !m_xOfficeInstDirs.is() )
813 uno::Reference< uno::XComponentContext > xCtx(
814 comphelper::getProcessComponentContext() );
815 m_xOfficeInstDirs = util::theOfficeInstallationDirectories::get(xCtx);
818 return m_xOfficeInstDirs;
822 //= TemplateFolderCache
825 TemplateFolderCache::TemplateFolderCache( bool _bAutoStoreState )
826 :m_pImpl( new TemplateFolderCacheImpl( _bAutoStoreState ) )
831 TemplateFolderCache::~TemplateFolderCache( )
833 DELETEZ( m_pImpl );
837 bool TemplateFolderCache::needsUpdate( bool _bForceCheck )
839 return m_pImpl->needsUpdate( _bForceCheck );
843 void TemplateFolderCache::storeState( bool _bForceRetrieval )
845 m_pImpl->storeState( _bForceRetrieval );
849 } // namespace sfx2
852 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */