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 <rtl/ref.hxx>
31 #include <salhelper/simplereferenceobject.hxx>
32 #include <tools/time.hxx>
33 #include <tools/urlobj.hxx>
34 #include <tools/debug.hxx>
35 #include <unotools/pathoptions.hxx>
37 #include "comphelper/processfactory.hxx"
44 //.........................................................................
47 //.........................................................................
49 using namespace ::utl
;
50 using namespace ::com::sun::star
;
51 using namespace ::com::sun::star::sdbc
;
52 using namespace ::com::sun::star::ucb
;
53 using namespace ::com::sun::star::uno
;
55 //=====================================================================
57 //=====================================================================
58 //---------------------------------------------------------------------
59 SvStream
& operator << ( SvStream
& _rStorage
, const util::DateTime
& _rDate
)
61 sal_uInt16 hundredthSeconds
= static_cast< sal_uInt16
>( _rDate
.NanoSeconds
/ Time::nanoPerCenti
);
62 _rStorage
<< hundredthSeconds
;
64 _rStorage
<< _rDate
.Seconds
;
65 _rStorage
<< _rDate
.Minutes
;
66 _rStorage
<< _rDate
.Hours
;
67 _rStorage
<< _rDate
.Day
;
68 _rStorage
<< _rDate
.Month
;
69 _rStorage
<< _rDate
.Year
;
74 //---------------------------------------------------------------------
75 SvStream
& operator >> ( SvStream
& _rStorage
, util::DateTime
& _rDate
)
77 sal_uInt16 hundredthSeconds
;
78 _rStorage
>> hundredthSeconds
;
79 _rDate
.NanoSeconds
= static_cast< sal_uInt32
>( hundredthSeconds
) * Time::nanoPerCenti
;
81 _rStorage
>> _rDate
.Seconds
;
82 _rStorage
>> _rDate
.Minutes
;
83 _rStorage
>> _rDate
.Hours
;
84 _rStorage
>> _rDate
.Day
;
85 _rStorage
>> _rDate
.Month
;
86 _rStorage
>> _rDate
.Year
;
91 //---------------------------------------------------------------------
92 sal_Bool
operator == ( const util::DateTime
& _rLHS
, const util::DateTime
& _rRHS
)
94 return _rLHS
.NanoSeconds
== _rRHS
.NanoSeconds
95 && _rLHS
.Seconds
== _rRHS
.Seconds
96 && _rLHS
.Minutes
== _rRHS
.Minutes
97 && _rLHS
.Hours
== _rRHS
.Hours
98 && _rLHS
.Day
== _rRHS
.Day
99 && _rLHS
.Month
== _rRHS
.Month
100 && _rLHS
.Year
== _rRHS
.Year
101 && _rLHS
.IsUTC
== _rRHS
.IsUTC
;
104 //---------------------------------------------------------------------
105 sal_Bool
operator != ( const util::DateTime
& _rLHS
, const util::DateTime
& _rRHS
)
107 return !( _rLHS
== _rRHS
);
110 //=====================================================================
112 //=====================================================================
113 struct TemplateContent
;
114 typedef ::std::vector
< ::rtl::Reference
< TemplateContent
> > TemplateFolderContent
;
115 typedef TemplateFolderContent::const_iterator ConstFolderIterator
;
116 typedef TemplateFolderContent::iterator FolderIterator
;
118 /** a struct describing one content in one of the template dirs (or at least it's relevant aspects)
120 struct TemplateContent
: public ::salhelper::SimpleReferenceObject
125 INetURLObject m_aURL
;
126 String m_sLocalName
; // redundant - last segment of m_aURL
127 util::DateTime m_aLastModified
; // date of last modification as reported by UCP
128 TemplateFolderContent m_aSubContents
; // sorted (by name) list of the children
131 inline void implResetDate( )
133 m_aLastModified
.NanoSeconds
= m_aLastModified
.Seconds
= m_aLastModified
.Minutes
= m_aLastModified
.Hours
= 0;
134 m_aLastModified
.Day
= m_aLastModified
.Month
= m_aLastModified
.Year
= 0;
141 TemplateContent( const INetURLObject
& _rURL
);
144 inline String
getName( ) const { return m_sLocalName
; }
145 inline String
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
begin() const { return m_aSubContents
.begin(); }
153 inline ConstFolderIterator
end() const { return m_aSubContents
.end(); }
154 inline TemplateFolderContent::size_type
155 size() const { return m_aSubContents
.size(); }
157 inline void push_back( const ::rtl::Reference
< TemplateContent
>& _rxNewElement
)
158 { m_aSubContents
.push_back( _rxNewElement
); }
161 //---------------------------------------------------------------------
162 DBG_NAME( TemplateContent
)
164 //---------------------------------------------------------------------
165 TemplateContent::TemplateContent( const INetURLObject
& _rURL
)
168 DBG_CTOR( TemplateContent
, NULL
);
169 DBG_ASSERT( INET_PROT_NOT_VALID
!= m_aURL
.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
170 m_sLocalName
= m_aURL
.getName();
174 //---------------------------------------------------------------------
175 TemplateContent::~TemplateContent()
177 DBG_DTOR( TemplateContent
, NULL
);
180 //=====================================================================
182 //=====================================================================
183 //---------------------------------------------------------------------
184 /// compares two TemplateContent by URL
185 struct TemplateContentURLLess
186 :public ::std::binary_function
< ::rtl::Reference
< TemplateContent
>
187 , ::rtl::Reference
< TemplateContent
>
191 bool operator() ( const ::rtl::Reference
< TemplateContent
>& _rxLHS
, const ::rtl::Reference
< TemplateContent
>& _rxRHS
) const
193 return _rxLHS
->getURL() < _rxRHS
->getURL()
199 //---------------------------------------------------------------------
200 /// sorts the sib contents of a TemplateFolderContent
201 struct SubContentSort
: public ::std::unary_function
< ::rtl::Reference
< TemplateContent
>, void >
203 void operator() ( TemplateFolderContent
& _rFolder
) const
205 // sort the directory by name
209 TemplateContentURLLess()
212 // sort the sub directories by name
220 void operator() ( const ::rtl::Reference
< TemplateContent
>& _rxContent
) const
222 if ( _rxContent
.is() && _rxContent
->size() )
224 operator()( _rxContent
->getSubContents() );
228 //---------------------------------------------------------------------
229 /** does a deep compare of two template contents
231 struct TemplateContentEqual
232 :public ::std::binary_function
< ::rtl::Reference
< TemplateContent
>
233 , ::rtl::Reference
< TemplateContent
>
237 //.................................................................
238 bool operator() (const ::rtl::Reference
< TemplateContent
>& _rLHS
, const ::rtl::Reference
< TemplateContent
>& _rRHS
)
240 if ( !_rLHS
.is() || !_rRHS
.is() )
242 OSL_FAIL( "TemplateContentEqual::operator(): invalid contents!" );
244 // this is not strictly true, in case only one is invalid - but this is a heavy error anyway
247 if ( _rLHS
->getURL() != _rRHS
->getURL() )
250 if ( _rLHS
->getModDate() != _rRHS
->getModDate() )
253 if ( _rLHS
->getSubContents().size() != _rRHS
->getSubContents().size() )
256 if ( _rLHS
->getSubContents().size() )
257 { // there are children
259 ::std::pair
< FolderIterator
, FolderIterator
> aFirstDifferent
= ::std::mismatch(
260 _rLHS
->getSubContents().begin(),
261 _rLHS
->getSubContents().end(),
262 _rRHS
->getSubContents().begin(),
265 if ( aFirstDifferent
.first
!= _rLHS
->getSubContents().end() )
266 return false;// the sub contents differ
273 //---------------------------------------------------------------------
274 /// base class for functors which act an an SvStream
278 SvStream
& m_rStorage
;
279 StorageHelper( SvStream
& _rStorage
) : m_rStorage( _rStorage
) { }
282 //---------------------------------------------------------------------
283 /// functor which allows storing a string
285 :public ::std::unary_function
< String
, void >
286 ,public StorageHelper
288 StoreString( SvStream
& _rStorage
) : StorageHelper( _rStorage
) { }
290 void operator() ( const String
& _rString
) const
292 m_rStorage
.WriteUniOrByteString( _rString
, m_rStorage
.GetStreamCharSet() );
296 //---------------------------------------------------------------------
297 /// functor which stores the local name of a TemplateContent
298 struct StoreLocalContentName
299 :public ::std::unary_function
< ::rtl::Reference
< TemplateContent
>, void >
302 StoreLocalContentName( SvStream
& _rStorage
) : StoreString( _rStorage
) { }
304 void operator() ( const ::rtl::Reference
< TemplateContent
>& _rxContent
) const
306 SAL_WARN( "svtools.misc", "This method must not be used, the whole URL must be stored!" );
308 // use the base class operator with the local name of the content
309 StoreString::operator() ( _rxContent
->getName() );
313 //---------------------------------------------------------------------
314 struct StoreContentURL
315 :public ::std::unary_function
< ::rtl::Reference
< TemplateContent
>, void >
318 uno::Reference
< util::XOfficeInstallationDirectories
> m_xOfficeInstDirs
;
320 StoreContentURL( SvStream
& _rStorage
,
321 const uno::Reference
<
322 util::XOfficeInstallationDirectories
> &
324 : StoreString( _rStorage
), m_xOfficeInstDirs( xOfficeInstDirs
) { }
326 void operator() ( const ::rtl::Reference
< TemplateContent
>& _rxContent
) const
328 // use the base class operator with the local name of the content
329 String sURL
= _rxContent
->getURL();
330 // #116281# Keep office installtion relocatable. Never store
331 // any direct references to office installation directory.
332 sURL
= m_xOfficeInstDirs
->makeRelocatableURL( sURL
);
333 StoreString::operator() ( sURL
);
337 //---------------------------------------------------------------------
338 /// functor which stores the complete content of a TemplateContent
339 struct StoreFolderContent
340 :public ::std::unary_function
< ::rtl::Reference
< TemplateContent
>, void >
341 ,public StorageHelper
343 uno::Reference
< util::XOfficeInstallationDirectories
> m_xOfficeInstDirs
;
346 StoreFolderContent( SvStream
& _rStorage
,
347 const uno::Reference
<
348 util::XOfficeInstallationDirectories
> &
350 : StorageHelper( _rStorage
), m_xOfficeInstDirs( xOfficeInstDirs
) { }
352 //.................................................................
353 void operator() ( const TemplateContent
& _rContent
) const
355 // store the info about this content
356 m_rStorage
<< _rContent
.getModDate();
358 // store the info about the children
360 m_rStorage
<< (sal_Int32
)_rContent
.size();
361 // their URLs ( the local name is not enough, since URL might be not a hierarchical one, "expand:" for example )
363 _rContent
.getSubContents().begin(),
364 _rContent
.getSubContents().end(),
365 StoreContentURL( m_rStorage
, m_xOfficeInstDirs
)
369 _rContent
.getSubContents().begin(),
370 _rContent
.getSubContents().end(),
375 //.................................................................
376 void operator() ( const ::rtl::Reference
< TemplateContent
>& _rxContent
) const
378 if ( _rxContent
.is() )
380 operator()( *_rxContent
);
385 //---------------------------------------------------------------------
386 /// functor which reads a complete TemplateContent instance
387 struct ReadFolderContent
388 :public ::std::unary_function
< ::rtl::Reference
< TemplateContent
>, void >
389 ,public StorageHelper
391 uno::Reference
< util::XOfficeInstallationDirectories
> m_xOfficeInstDirs
;
393 ReadFolderContent( SvStream
& _rStorage
,
394 const uno::Reference
<
395 util::XOfficeInstallationDirectories
> &
397 : StorageHelper( _rStorage
), m_xOfficeInstDirs( xOfficeInstDirs
) { }
399 //.................................................................
400 void operator() ( TemplateContent
& _rContent
) const
402 // store the info about this content
403 util::DateTime aModDate
;
404 m_rStorage
>> aModDate
;
405 _rContent
.setModDate( aModDate
);
407 // store the info about the children
409 sal_Int32 nChildren
= 0;
410 m_rStorage
>> nChildren
;
411 TemplateFolderContent
& rChildren
= _rContent
.getSubContents();
412 rChildren
.resize( 0 );
413 rChildren
.reserve( nChildren
);
414 // initialize them with their (local) names
415 while ( nChildren
-- )
417 String sURL
= m_rStorage
.ReadUniOrByteString(m_rStorage
.GetStreamCharSet());
418 sURL
= m_xOfficeInstDirs
->makeAbsoluteURL( sURL
);
419 INetURLObject
aChildURL( sURL
);
420 rChildren
.push_back( new TemplateContent( aChildURL
) );
425 _rContent
.getSubContents().begin(),
426 _rContent
.getSubContents().end(),
431 //.................................................................
432 void operator() ( const ::rtl::Reference
< TemplateContent
>& _rxContent
) const
434 if ( _rxContent
.is() )
436 operator()( *_rxContent
);
441 //=====================================================================
442 //= TemplateFolderCacheImpl
443 //=====================================================================
444 class TemplateFolderCacheImpl
447 TemplateFolderContent m_aPreviousState
; // the current state of the template dirs (as found on the HD)
448 TemplateFolderContent m_aCurrentState
; // the previous state of the template dirs (as found in the cache file)
451 // will be lazy inited; never access directly; use getOfficeInstDirs().
452 uno::Reference
< util::XOfficeInstallationDirectories
> m_xOfficeInstDirs
;
454 SvStream
* m_pCacheStream
;
455 sal_Bool m_bNeedsUpdate
: 1;
456 sal_Bool m_bKnowState
: 1;
457 sal_Bool m_bValidCurrentState
: 1;
458 sal_Bool m_bAutoStoreState
: 1;
461 TemplateFolderCacheImpl( sal_Bool _bAutoStoreState
);
462 ~TemplateFolderCacheImpl( );
464 sal_Bool
needsUpdate( sal_Bool _bForceCheck
);
465 void storeState( sal_Bool _bForceRetrieval
);
468 sal_Bool
openCacheStream( sal_Bool _bForRead
);
469 void closeCacheStream( );
471 /// read the state of the dirs from the cache file
472 sal_Bool
readPreviousState();
473 /// read the current state of the dirs
474 sal_Bool
readCurrentState();
476 String
implParseSmart( const String
& _rPath
);
478 sal_Bool
implReadFolder( const ::rtl::Reference
< TemplateContent
>& _rxRoot
);
480 static OUString
getCacheFileName();
481 static sal_Int32
getMagicNumber();
482 static void normalize( TemplateFolderContent
& _rState
);
484 // @return <TRUE/> if the states equal
485 static sal_Bool
equalStates( const TemplateFolderContent
& _rLHS
, const TemplateFolderContent
& _rRHS
);
487 // late initialize m_xOfficeInstDirs
488 uno::Reference
< util::XOfficeInstallationDirectories
> getOfficeInstDirs();
491 //---------------------------------------------------------------------
492 TemplateFolderCacheImpl::TemplateFolderCacheImpl( sal_Bool _bAutoStoreState
)
493 :m_pCacheStream ( NULL
)
494 ,m_bNeedsUpdate ( sal_True
)
495 ,m_bKnowState ( sal_False
)
496 ,m_bValidCurrentState ( sal_False
)
497 ,m_bAutoStoreState ( _bAutoStoreState
)
501 //---------------------------------------------------------------------
502 TemplateFolderCacheImpl::~TemplateFolderCacheImpl( )
504 // store the current state if possible and required
505 if ( m_bValidCurrentState
&& m_bAutoStoreState
)
506 storeState( sal_False
);
511 //---------------------------------------------------------------------
512 sal_Int32
TemplateFolderCacheImpl::getMagicNumber()
514 sal_Int32 nMagic
= 0;
515 ( nMagic
+= (sal_Int8
)'T' ) <<= 4;
516 ( nMagic
+= (sal_Int8
)'D' ) <<= 4;
517 ( nMagic
+= (sal_Int8
)'S' ) <<= 4;
518 ( nMagic
+= (sal_Int8
)'C' ) <<= 0;
522 //---------------------------------------------------------------------
523 OUString
TemplateFolderCacheImpl::getCacheFileName()
525 return OUString(".templdir.cache");
529 //---------------------------------------------------------------------
530 void TemplateFolderCacheImpl::normalize( TemplateFolderContent
& _rState
)
532 SubContentSort()( _rState
);
535 //---------------------------------------------------------------------
536 sal_Bool
TemplateFolderCacheImpl::equalStates( const TemplateFolderContent
& _rLHS
, const TemplateFolderContent
& _rRHS
)
538 if ( _rLHS
.size() != _rRHS
.size() )
541 // as both arrays are sorted (by definition - this is a precondition of this method)
542 // we can simply go from the front to the back and compare the single elements
544 ::std::pair
< ConstFolderIterator
, ConstFolderIterator
> aFirstDifferent
= ::std::mismatch(
548 TemplateContentEqual()
551 return aFirstDifferent
.first
== _rLHS
.end();
554 //---------------------------------------------------------------------
555 void TemplateFolderCacheImpl::storeState( sal_Bool _bForceRetrieval
)
557 if ( !m_bValidCurrentState
|| _bForceRetrieval
)
560 if ( m_bValidCurrentState
&& openCacheStream( sal_False
) )
562 *m_pCacheStream
<< getMagicNumber();
564 // store the template root folders
566 *m_pCacheStream
<< (sal_Int32
)m_aCurrentState
.size();
569 m_aCurrentState
.begin(),
570 m_aCurrentState
.end(),
571 StoreContentURL( *m_pCacheStream
, getOfficeInstDirs() )
576 m_aCurrentState
.begin(),
577 m_aCurrentState
.end(),
578 StoreFolderContent( *m_pCacheStream
, getOfficeInstDirs() )
583 //---------------------------------------------------------------------
584 String
TemplateFolderCacheImpl::implParseSmart( const String
& _rPath
)
586 INetURLObject aParser
;
587 aParser
.SetSmartProtocol( INET_PROT_FILE
);
588 aParser
.SetURL( _rPath
, INetURLObject::WAS_ENCODED
);
589 if ( INET_PROT_NOT_VALID
== aParser
.GetProtocol() )
592 LocalFileHelper::ConvertPhysicalNameToURL( _rPath
, sURL
);
593 aParser
.SetURL( sURL
, INetURLObject::WAS_ENCODED
);
595 return aParser
.GetMainURL( INetURLObject::DECODE_TO_IURI
);
598 //---------------------------------------------------------------------
599 void TemplateFolderCacheImpl::closeCacheStream( )
601 DELETEZ( m_pCacheStream
);
604 //---------------------------------------------------------------------
605 sal_Bool
TemplateFolderCacheImpl::implReadFolder( const ::rtl::Reference
< TemplateContent
>& _rxRoot
)
609 // create a content for the current folder root
610 Reference
< XResultSet
> xResultSet
;
611 Sequence
< OUString
> aContentProperties( 4);
612 aContentProperties
[0] = OUString( "Title" );
613 aContentProperties
[1] = OUString( "DateModified" );
614 aContentProperties
[2] = OUString( "DateCreated" );
615 aContentProperties
[3] = OUString( "IsFolder" );
617 // get the set of sub contents in the folder
620 Reference
< XDynamicResultSet
> xDynResultSet
;
622 ::ucbhelper::Content
aTemplateRoot( _rxRoot
->getURL(), Reference
< XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
623 xDynResultSet
= aTemplateRoot
.createDynamicCursor( aContentProperties
, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS
);
624 if ( xDynResultSet
.is() )
625 xResultSet
= xDynResultSet
->getStaticResultSet();
627 catch( CommandAbortedException
& )
629 SAL_WARN( "svtools.misc", "TemplateFolderCacheImpl::implReadFolder: caught a CommandAbortedException!" );
632 catch( ::com::sun::star::uno::Exception
& )
636 // collect the infos about the sub contents
637 if ( xResultSet
.is() )
639 Reference
< XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
640 Reference
< XContentAccess
> xContentAccess( xResultSet
, UNO_QUERY_THROW
);
642 while ( xResultSet
->next() )
644 INetURLObject
aSubContentURL( xContentAccess
->queryContentIdentifierString() );
646 // a new content instance
647 ::rtl::Reference
< TemplateContent
> xChild
= new TemplateContent( aSubContentURL
);
650 xChild
->setModDate( xRow
->getTimestamp( 2 ) ); // date modified
651 if ( xRow
->wasNull() )
652 xChild
->setModDate( xRow
->getTimestamp( 3 ) ); // fallback: date created
654 // push back this content
655 _rxRoot
->push_back( xChild
);
658 if ( xRow
->getBoolean( 4 ) && !xRow
->wasNull() )
659 { // yes -> step down
660 ConstFolderIterator aNextLevelRoot
= _rxRoot
->end();
662 implReadFolder( *aNextLevelRoot
);
667 catch( const Exception
& )
669 OSL_FAIL( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" );
675 //---------------------------------------------------------------------
676 sal_Bool
TemplateFolderCacheImpl::readCurrentState()
679 m_bValidCurrentState
= sal_False
;
680 TemplateFolderContent aTemplateFolderContent
;
681 m_aCurrentState
.swap( aTemplateFolderContent
);
683 // the template directories from the config
684 const SvtPathOptions aPathOptions
;
685 OUString aDirs
= aPathOptions
.GetTemplatePath();
687 // loop through all the root-level template folders
688 sal_Int32 nIndex
= 0;
691 String
sTemplatePath( aDirs
.getToken(0, ';', nIndex
) );
692 sTemplatePath
= aPathOptions
.ExpandMacros( sTemplatePath
);
694 // Make sure excess ".." path segments (from expanding bootstrap
695 // variables in paths) are normalized in the same way they are
696 // normalized for paths read from the .templdir.cache file (where
697 // paths have gone through makeRelocatable URL on writing out and
698 // then through makeAbsoluteURL when reading back in), as otherwise
699 // equalStates() in needsUpdate() could erroneously consider
700 // m_aCurrentState and m_aPreviousState as different:
701 sTemplatePath
= getOfficeInstDirs()->makeAbsoluteURL(
702 getOfficeInstDirs()->makeRelocatableURL(sTemplatePath
));
704 // create a new entry
705 m_aCurrentState
.push_back( new TemplateContent( INetURLObject( sTemplatePath
) ) );
706 TemplateFolderContent::iterator aCurrentRoot
= m_aCurrentState
.end();
709 if ( !implReadFolder( *aCurrentRoot
) )
712 while ( nIndex
>= 0 );
714 // normalize the array (which basically means "sort it")
715 normalize( m_aCurrentState
);
717 m_bValidCurrentState
= sal_True
;
718 return m_bValidCurrentState
;
721 //---------------------------------------------------------------------
722 sal_Bool
TemplateFolderCacheImpl::readPreviousState()
724 DBG_ASSERT( m_pCacheStream
, "TemplateFolderCacheImpl::readPreviousState: not to be called without stream!" );
727 TemplateFolderContent aTemplateFolderContent
;
728 m_aPreviousState
.swap( aTemplateFolderContent
);
730 // check the magic number
731 sal_Int32 nMagic
= 0;
732 *m_pCacheStream
>> nMagic
;
733 DBG_ASSERT( getMagicNumber() == nMagic
, "TemplateFolderCacheImpl::readPreviousState: invalid cache file!" );
734 if ( getMagicNumber() != nMagic
)
737 // the root directories
739 sal_Int32 nRootDirectories
= 0;
740 *m_pCacheStream
>> nRootDirectories
;
741 // init empty TemplateContens with the URLs
742 m_aPreviousState
.reserve( nRootDirectories
);
743 while ( nRootDirectories
-- )
745 String sURL
= m_pCacheStream
->ReadUniOrByteString(m_pCacheStream
->GetStreamCharSet());
746 // #116281# Keep office installtion relocatable. Never store
747 // any direct references to office installation directory.
748 sURL
= getOfficeInstDirs()->makeAbsoluteURL( sURL
);
749 m_aPreviousState
.push_back(
750 new TemplateContent( INetURLObject(sURL
) ) );
753 // read the contents of the root folders
755 m_aPreviousState
.begin(),
756 m_aPreviousState
.end(),
757 ReadFolderContent( *m_pCacheStream
, getOfficeInstDirs() )
760 DBG_ASSERT( !m_pCacheStream
->GetErrorCode(), "TemplateFolderCacheImpl::readPreviousState: unknown error during reading the state cache!" );
762 // normalize the array (which basically means "sort it")
763 normalize( m_aPreviousState
);
768 //---------------------------------------------------------------------
769 sal_Bool
TemplateFolderCacheImpl::openCacheStream( sal_Bool _bForRead
)
771 // close any old stream instance
774 // get the storage directory
775 String sStorageURL
= implParseSmart( SvtPathOptions().GetStoragePath() );
776 INetURLObject
aStorageURL( sStorageURL
);
777 if ( INET_PROT_NOT_VALID
== aStorageURL
.GetProtocol() )
779 OSL_FAIL( "TemplateFolderCacheImpl::openCacheStream: invalid storage path!" );
784 aStorageURL
.Append( getCacheFileName() );
787 m_pCacheStream
= UcbStreamHelper::CreateStream( aStorageURL
.GetMainURL( INetURLObject::DECODE_TO_IURI
),
788 _bForRead
? STREAM_READ
| STREAM_NOCREATE
: STREAM_WRITE
| STREAM_TRUNC
);
789 DBG_ASSERT( m_pCacheStream
, "TemplateFolderCacheImpl::openCacheStream: could not open/create the cache stream!" );
790 if ( m_pCacheStream
&& m_pCacheStream
->GetErrorCode() )
792 DELETEZ( m_pCacheStream
);
795 if ( m_pCacheStream
)
796 m_pCacheStream
->SetStreamCharSet( RTL_TEXTENCODING_UTF8
);
798 return NULL
!= m_pCacheStream
;
801 //---------------------------------------------------------------------
802 sal_Bool
TemplateFolderCacheImpl::needsUpdate( sal_Bool _bForceCheck
)
804 if ( m_bKnowState
&& !_bForceCheck
)
805 return m_bNeedsUpdate
;
807 m_bNeedsUpdate
= sal_True
;
808 m_bKnowState
= sal_True
;
810 if ( readCurrentState() )
812 // open the stream which contains the cached state of the directories
813 if ( openCacheStream( sal_True
) )
814 { // opening the stream succeeded
815 if ( readPreviousState() )
817 m_bNeedsUpdate
= !equalStates( m_aPreviousState
, m_aCurrentState
);
825 return m_bNeedsUpdate
;
828 //---------------------------------------------------------------------
829 uno::Reference
< util::XOfficeInstallationDirectories
>
830 TemplateFolderCacheImpl::getOfficeInstDirs()
832 if ( !m_xOfficeInstDirs
.is() )
834 osl::MutexGuard
aGuard( m_aMutex
);
835 if ( !m_xOfficeInstDirs
.is() )
837 uno::Reference
< uno::XComponentContext
> xCtx(
838 comphelper::getProcessComponentContext() );
839 m_xOfficeInstDirs
= util::theOfficeInstallationDirectories::get(xCtx
);
842 return m_xOfficeInstDirs
;
845 //=====================================================================
846 //= TemplateFolderCache
847 //=====================================================================
848 //---------------------------------------------------------------------
849 TemplateFolderCache::TemplateFolderCache( sal_Bool _bAutoStoreState
)
850 :m_pImpl( new TemplateFolderCacheImpl( _bAutoStoreState
) )
854 //---------------------------------------------------------------------
855 TemplateFolderCache::~TemplateFolderCache( )
860 //---------------------------------------------------------------------
861 sal_Bool
TemplateFolderCache::needsUpdate( sal_Bool _bForceCheck
)
863 return m_pImpl
->needsUpdate( _bForceCheck
);
866 //---------------------------------------------------------------------
867 void TemplateFolderCache::storeState( sal_Bool _bForceRetrieval
)
869 m_pImpl
->storeState( _bForceRetrieval
);
872 //.........................................................................
874 //.........................................................................
876 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */