1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
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
);
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
);
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
);
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
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
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;
139 virtual ~TemplateContent();
142 TemplateContent( const INetURLObject
& _rURL
);
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
)
166 DBG_ASSERT( INetProtocol::NotValid
!= m_aURL
.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
167 m_sLocalName
= m_aURL
.getName();
172 TemplateContent::~TemplateContent()
180 /// compares two TemplateContent by URL
181 struct TemplateContentURLLess
182 :public ::std::binary_function
< ::rtl::Reference
< TemplateContent
>
183 , ::rtl::Reference
< TemplateContent
>
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
203 TemplateContentURLLess()
206 // sort the sub directories by name
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
>
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!" );
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() )
244 if ( _rLHS
->getModDate() != _rRHS
->getModDate() )
247 if ( _rLHS
->getSubContents().size() != _rRHS
->getSubContents().size() )
250 if ( _rLHS
->getSubContents().size() )
251 { // there are children
253 ::std::pair
< FolderIterator
, FolderIterator
> aFirstDifferent
= ::std::mismatch(
254 _rLHS
->getSubContents().begin(),
255 _rLHS
->getSubContents().end(),
256 _rRHS
->getSubContents().begin(),
259 if ( aFirstDifferent
.first
!= _rLHS
->getSubContents().end() )
260 return false;// the sub contents differ
268 /// base class for functors which act on a SvStream
272 SvStream
& m_rStorage
;
273 StorageHelper( SvStream
& _rStorage
) : m_rStorage( _rStorage
) { }
277 /// functor which allows storing a string
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 >
294 uno::Reference
< util::XOfficeInstallationDirectories
> m_xOfficeInstDirs
;
296 StoreContentURL( SvStream
& _rStorage
,
297 const uno::Reference
<
298 util::XOfficeInstallationDirectories
> &
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
;
322 StoreFolderContent( SvStream
& _rStorage
,
323 const uno::Reference
<
324 util::XOfficeInstallationDirectories
> &
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
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 )
339 _rContent
.getSubContents().begin(),
340 _rContent
.getSubContents().end(),
341 StoreContentURL( m_rStorage
, m_xOfficeInstDirs
)
345 _rContent
.getSubContents().begin(),
346 _rContent
.getSubContents().end(),
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
> &
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
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
) );
401 _rContent
.getSubContents().begin(),
402 _rContent
.getSubContents().end(),
408 void operator() ( const ::rtl::Reference
< TemplateContent
>& _rxContent
) const
410 if ( _rxContent
.is() )
412 operator()( *_rxContent
);
418 //= TemplateFolderCacheImpl
420 class TemplateFolderCacheImpl
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)
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;
437 TemplateFolderCacheImpl( bool _bAutoStoreState
);
438 ~TemplateFolderCacheImpl( );
440 bool needsUpdate( bool _bForceCheck
);
441 void storeState( bool _bForceRetrieval
);
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
)
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;
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() )
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(
524 TemplateContentEqual()
527 return aFirstDifferent
.first
== _rLHS
.end();
531 void TemplateFolderCacheImpl::storeState( bool _bForceRetrieval
)
533 if ( !m_bValidCurrentState
|| _bForceRetrieval
)
536 if ( m_bValidCurrentState
&& openCacheStream( false ) )
538 m_pCacheStream
->WriteInt32( getMagicNumber() );
540 // store the template root folders
542 m_pCacheStream
->WriteInt32( m_aCurrentState
.size() );
545 m_aCurrentState
.begin(),
546 m_aCurrentState
.end(),
547 StoreContentURL( *m_pCacheStream
, getOfficeInstDirs() )
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() )
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!" );
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
);
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
);
634 if ( xRow
->getBoolean( 4 ) && !xRow
->wasNull() )
635 { // yes -> step down
636 ConstFolderIterator aNextLevelRoot
= _rxRoot
->end();
638 implReadFolder( *aNextLevelRoot
);
643 catch( const Exception
& )
645 OSL_FAIL( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" );
652 bool TemplateFolderCacheImpl::readCurrentState()
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();
685 if ( !implReadFolder( *aCurrentRoot
) )
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!" );
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
)
713 // the root directories
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
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
);
745 bool TemplateFolderCacheImpl::openCacheStream( bool _bForRead
)
747 // close any old stream instance
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!" );
760 aStorageURL
.Append( getCacheFileName() );
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;
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
);
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( )
837 bool TemplateFolderCache::needsUpdate( bool _bForceCheck
)
839 return m_pImpl
->needsUpdate( _bForceCheck
);
843 void TemplateFolderCache::storeState( bool _bForceRetrieval
)
845 m_pImpl
->storeState( _bForceRetrieval
);
852 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */