fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svtools / source / misc / templatefoldercache.cxx
blob9866c95211d507bb6835b564ea08c08801bce785
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 <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"
39 #include <vector>
40 #include <list>
41 #include <functional>
42 #include <algorithm>
44 //.........................................................................
45 namespace svt
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 //=====================================================================
56 //= helpers
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;
71 return _rStorage;
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;
88 return _rStorage;
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 //=====================================================================
111 //= TemplateContent
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
122 public:
124 private:
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
130 private:
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;
137 private:
138 ~TemplateContent();
140 public:
141 TemplateContent( const INetURLObject& _rURL );
143 // attribute access
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 )
166 :m_aURL( _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();
171 implResetDate();
174 //---------------------------------------------------------------------
175 TemplateContent::~TemplateContent()
177 DBG_DTOR( TemplateContent, NULL );
180 //=====================================================================
181 //= stl helpers
182 //=====================================================================
183 //---------------------------------------------------------------------
184 /// compares two TemplateContent by URL
185 struct TemplateContentURLLess
186 :public ::std::binary_function < ::rtl::Reference< TemplateContent >
187 , ::rtl::Reference< TemplateContent >
188 , bool
191 bool operator() ( const ::rtl::Reference< TemplateContent >& _rxLHS, const ::rtl::Reference< TemplateContent >& _rxRHS ) const
193 return _rxLHS->getURL() < _rxRHS->getURL()
194 ? true
195 : false;
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
206 ::std::sort(
207 _rFolder.begin(),
208 _rFolder.end(),
209 TemplateContentURLLess()
212 // sort the sub directories by name
213 ::std::for_each(
214 _rFolder.begin(),
215 _rFolder.end(),
216 *this
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 >
234 , bool
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!" );
243 return true;
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() )
248 return false;
250 if ( _rLHS->getModDate() != _rRHS->getModDate() )
251 return false;
253 if ( _rLHS->getSubContents().size() != _rRHS->getSubContents().size() )
254 return false;
256 if ( _rLHS->getSubContents().size() )
257 { // there are children
258 // -> compare them
259 ::std::pair< FolderIterator, FolderIterator > aFirstDifferent = ::std::mismatch(
260 _rLHS->getSubContents().begin(),
261 _rLHS->getSubContents().end(),
262 _rRHS->getSubContents().begin(),
263 *this
265 if ( aFirstDifferent.first != _rLHS->getSubContents().end() )
266 return false;// the sub contents differ
269 return true;
273 //---------------------------------------------------------------------
274 /// base class for functors which act an an SvStream
275 struct StorageHelper
277 protected:
278 SvStream& m_rStorage;
279 StorageHelper( SvStream& _rStorage ) : m_rStorage( _rStorage ) { }
282 //---------------------------------------------------------------------
283 /// functor which allows storing a string
284 struct StoreString
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 >
300 ,public StoreString
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 >
316 ,public StoreString
318 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
320 StoreContentURL( SvStream& _rStorage,
321 const uno::Reference<
322 util::XOfficeInstallationDirectories > &
323 xOfficeInstDirs )
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;
345 public:
346 StoreFolderContent( SvStream& _rStorage,
347 const uno::Reference<
348 util::XOfficeInstallationDirectories > &
349 xOfficeInstDirs )
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
359 // the number
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 )
362 ::std::for_each(
363 _rContent.getSubContents().begin(),
364 _rContent.getSubContents().end(),
365 StoreContentURL( m_rStorage, m_xOfficeInstDirs )
367 // their content
368 ::std::for_each(
369 _rContent.getSubContents().begin(),
370 _rContent.getSubContents().end(),
371 *this
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 > &
396 xOfficeInstDirs )
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
408 // the number
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 ) );
423 // their content
424 ::std::for_each(
425 _rContent.getSubContents().begin(),
426 _rContent.getSubContents().end(),
427 *this
431 //.................................................................
432 void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
434 if ( _rxContent.is() )
436 operator()( *_rxContent );
441 //=====================================================================
442 //= TemplateFolderCacheImpl
443 //=====================================================================
444 class TemplateFolderCacheImpl
446 private:
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)
450 osl::Mutex m_aMutex;
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;
460 public:
461 TemplateFolderCacheImpl( sal_Bool _bAutoStoreState );
462 ~TemplateFolderCacheImpl( );
464 sal_Bool needsUpdate( sal_Bool _bForceCheck );
465 void storeState( sal_Bool _bForceRetrieval );
467 private:
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 );
508 closeCacheStream( );
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;
519 return nMagic;
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() )
539 return sal_False;
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(
545 _rLHS.begin(),
546 _rLHS.end(),
547 _rRHS.begin(),
548 TemplateContentEqual()
551 return aFirstDifferent.first == _rLHS.end();
554 //---------------------------------------------------------------------
555 void TemplateFolderCacheImpl::storeState( sal_Bool _bForceRetrieval )
557 if ( !m_bValidCurrentState || _bForceRetrieval )
558 readCurrentState( );
560 if ( m_bValidCurrentState && openCacheStream( sal_False ) )
562 *m_pCacheStream << getMagicNumber();
564 // store the template root folders
565 // the size
566 *m_pCacheStream << (sal_Int32)m_aCurrentState.size();
567 // the complete URLs
568 ::std::for_each(
569 m_aCurrentState.begin(),
570 m_aCurrentState.end(),
571 StoreContentURL( *m_pCacheStream, getOfficeInstDirs() )
574 // the contents
575 ::std::for_each(
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() )
591 OUString sURL;
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!" );
630 return sal_False;
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 );
649 // the modified date
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 );
657 // is it a folder?
658 if ( xRow->getBoolean( 4 ) && !xRow->wasNull() )
659 { // yes -> step down
660 ConstFolderIterator aNextLevelRoot = _rxRoot->end();
661 --aNextLevelRoot;
662 implReadFolder( *aNextLevelRoot );
667 catch( const Exception& )
669 OSL_FAIL( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" );
670 return sal_False;
672 return sal_True;
675 //---------------------------------------------------------------------
676 sal_Bool TemplateFolderCacheImpl::readCurrentState()
678 // reset
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();
707 --aCurrentRoot;
709 if ( !implReadFolder( *aCurrentRoot ) )
710 return sal_False;
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!" );
726 // reset
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 )
735 return sal_False;
737 // the root directories
738 // their number
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
754 ::std::for_each(
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 );
765 return sal_True;
768 //---------------------------------------------------------------------
769 sal_Bool TemplateFolderCacheImpl::openCacheStream( sal_Bool _bForRead )
771 // close any old stream instance
772 closeCacheStream( );
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!" );
780 return sal_False;
783 // append our name
784 aStorageURL.Append( getCacheFileName() );
786 // open the stream
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 );
819 else
821 closeCacheStream();
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( )
857 DELETEZ( m_pImpl );
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 //.........................................................................
873 } // namespace sfx2
874 //.........................................................................
876 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */