merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / misc / templatefoldercache.cxx
blobf6e5b7c4fdfb9700200d1fc3c720dd87f6e25249
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: templatefoldercache.cxx,v $
10 * $Revision: 1.16 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include "templatefoldercache.hxx"
34 #include <unotools/ucbstreamhelper.hxx>
35 #include <unotools/localfilehelper.hxx>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/sdbc/XResultSet.hpp>
38 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
39 #include <com/sun/star/sdbc/XRow.hpp>
40 #include <com/sun/star/ucb/XContentAccess.hpp>
41 #include <com/sun/star/uno/XComponentContext.hpp>
42 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
43 #include <ucbhelper/content.hxx>
44 #include <vos/ref.hxx>
45 #include <vos/refernce.hxx>
46 #include <tools/urlobj.hxx>
47 #include <tools/debug.hxx>
48 #include <svtools/pathoptions.hxx>
50 #include "comphelper/processfactory.hxx"
52 #include <vector>
53 #include <list>
54 #include <functional>
55 #include <algorithm>
57 //.........................................................................
58 namespace svt
60 //.........................................................................
62 using namespace ::utl;
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::sdbc;
65 using namespace ::com::sun::star::ucb;
66 using namespace ::com::sun::star::uno;
68 //=====================================================================
69 //= helpers
70 //=====================================================================
71 //---------------------------------------------------------------------
72 SvStream& operator << ( SvStream& _rStorage, const util::DateTime& _rDate )
74 _rStorage << _rDate.HundredthSeconds;
75 _rStorage << _rDate.Seconds;
76 _rStorage << _rDate.Minutes;
77 _rStorage << _rDate.Hours;
78 _rStorage << _rDate.Day;
79 _rStorage << _rDate.Month;
80 _rStorage << _rDate.Year;
82 return _rStorage;
85 //---------------------------------------------------------------------
86 SvStream& operator >> ( SvStream& _rStorage, util::DateTime& _rDate )
88 _rStorage >> _rDate.HundredthSeconds;
89 _rStorage >> _rDate.Seconds;
90 _rStorage >> _rDate.Minutes;
91 _rStorage >> _rDate.Hours;
92 _rStorage >> _rDate.Day;
93 _rStorage >> _rDate.Month;
94 _rStorage >> _rDate.Year;
96 return _rStorage;
99 //---------------------------------------------------------------------
100 sal_Bool operator == ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
102 return _rLHS.HundredthSeconds == _rRHS.HundredthSeconds
103 && _rLHS.Seconds == _rRHS.Seconds
104 && _rLHS.Minutes == _rRHS.Minutes
105 && _rLHS.Hours == _rRHS.Hours
106 && _rLHS.Day == _rRHS.Day
107 && _rLHS.Month == _rRHS.Month
108 && _rLHS.Year == _rRHS.Year;
111 //---------------------------------------------------------------------
112 sal_Bool operator != ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
114 return !( _rLHS == _rRHS );
117 //=====================================================================
118 //= TemplateContent
119 //=====================================================================
120 struct TemplateContent;
121 typedef ::std::vector< ::vos::ORef< TemplateContent > > TemplateFolderContent;
122 typedef TemplateFolderContent::const_iterator ConstFolderIterator;
123 typedef TemplateFolderContent::iterator FolderIterator;
125 /** a struct describing one content in one of the template dirs (or at least it's relevant aspects)
127 struct TemplateContent : public ::vos::OReference
129 public:
131 private:
132 INetURLObject m_aURL;
133 String m_sLocalName; // redundant - last segment of m_aURL
134 util::DateTime m_aLastModified; // date of last modification as reported by UCP
135 TemplateFolderContent m_aSubContents; // sorted (by name) list of the children
137 private:
138 inline void implResetDate( )
140 m_aLastModified.HundredthSeconds = m_aLastModified.Seconds = m_aLastModified.Minutes = m_aLastModified.Hours = 0;
141 m_aLastModified.Day = m_aLastModified.Month = m_aLastModified.Year = 0;
144 private:
145 ~TemplateContent();
147 public:
148 TemplateContent();
149 TemplateContent( const INetURLObject& _rURL );
150 TemplateContent( const INetURLObject& _rURL, const util::DateTime& _rLastModified );
152 // attribute access
153 inline String getName( ) const { return m_sLocalName; }
154 inline String getURL( ) const { return m_aURL.GetMainURL( INetURLObject::DECODE_TO_IURI ); }
155 inline void setModDate( const util::DateTime& _rDate ) { m_aLastModified = _rDate; }
156 inline const util::DateTime& getModDate( ) const { return m_aLastModified; }
158 inline TemplateFolderContent& getSubContents() { return m_aSubContents; }
159 inline const TemplateFolderContent& getSubContents() const { return m_aSubContents; }
161 inline ConstFolderIterator begin() const { return m_aSubContents.begin(); }
162 inline ConstFolderIterator end() const { return m_aSubContents.end(); }
163 inline TemplateFolderContent::size_type
164 size() const { return m_aSubContents.size(); }
166 inline void push_back( const ::vos::ORef< TemplateContent >& _rxNewElement )
167 { m_aSubContents.push_back( _rxNewElement ); }
170 //---------------------------------------------------------------------
171 DBG_NAME( TemplateContent )
173 //---------------------------------------------------------------------
174 TemplateContent::TemplateContent()
176 DBG_CTOR( TemplateContent, NULL );
177 implResetDate();
180 //---------------------------------------------------------------------
181 TemplateContent::TemplateContent( const INetURLObject& _rURL )
182 :m_aURL( _rURL )
184 DBG_CTOR( TemplateContent, NULL );
185 DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
186 m_sLocalName = m_aURL.getName();
187 implResetDate();
190 //---------------------------------------------------------------------
191 TemplateContent::TemplateContent( const INetURLObject& _rURL, const util::DateTime& _rLastModified )
192 :m_aURL( _rURL )
193 ,m_aLastModified( _rLastModified )
195 DBG_CTOR( TemplateContent, NULL );
196 DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
197 m_sLocalName = m_aURL.getName();
200 //---------------------------------------------------------------------
201 TemplateContent::~TemplateContent()
203 DBG_DTOR( TemplateContent, NULL );
206 //=====================================================================
207 //= stl helpers
208 //=====================================================================
209 //---------------------------------------------------------------------
210 /// compares two TemplateContent by URL
211 struct TemplateContentURLLess
212 :public ::std::binary_function < ::vos::ORef< TemplateContent >
213 , ::vos::ORef< TemplateContent >
214 , bool
217 bool operator() ( const ::vos::ORef< TemplateContent >& _rxLHS, const ::vos::ORef< TemplateContent >& _rxRHS ) const
219 return _rxLHS->getURL() < _rxRHS->getURL()
220 ? true
221 : false;
225 //---------------------------------------------------------------------
226 /// sorts the sib contents of a TemplateFolderContent
227 struct SubContentSort : public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
229 void operator() ( TemplateFolderContent& _rFolder ) const
231 // sort the directory by name
232 ::std::sort(
233 _rFolder.begin(),
234 _rFolder.end(),
235 TemplateContentURLLess()
238 // sort the sub directories by name
239 ::std::for_each(
240 _rFolder.begin(),
241 _rFolder.end(),
242 *this
246 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
248 if ( _rxContent.isValid() && _rxContent->size() )
250 operator()( _rxContent->getSubContents() );
254 //---------------------------------------------------------------------
255 /** does a deep compare of two template contents
257 struct TemplateContentEqual
258 :public ::std::binary_function < ::vos::ORef< TemplateContent >
259 , ::vos::ORef< TemplateContent >
260 , bool
263 //.................................................................
264 bool operator() (const ::vos::ORef< TemplateContent >& _rLHS, const ::vos::ORef< TemplateContent >& _rRHS )
266 if ( !_rLHS.isValid() || !_rRHS.isValid() )
268 DBG_ERROR( "TemplateContentEqual::operator(): invalid contents!" );
269 return true;
270 // this is not strictly true, in case only one is invalid - but this is a heavy error anyway
273 if ( _rLHS->getURL() != _rRHS->getURL() )
274 return false;
276 if ( _rLHS->getModDate() != _rRHS->getModDate() )
277 return false;
279 if ( _rLHS->getSubContents().size() != _rRHS->getSubContents().size() )
280 return false;
282 if ( _rLHS->getSubContents().size() )
283 { // there are children
284 // -> compare them
285 ::std::pair< FolderIterator, FolderIterator > aFirstDifferent = ::std::mismatch(
286 _rLHS->getSubContents().begin(),
287 _rLHS->getSubContents().end(),
288 _rRHS->getSubContents().begin(),
289 *this
291 if ( aFirstDifferent.first != _rLHS->getSubContents().end() )
292 return false;// the sub contents differ
295 return true;
299 //---------------------------------------------------------------------
300 /// base class for functors which act an an SvStream
301 struct StorageHelper
303 protected:
304 SvStream& m_rStorage;
305 StorageHelper( SvStream& _rStorage ) : m_rStorage( _rStorage ) { }
308 //---------------------------------------------------------------------
309 /// functor which allows storing a string
310 struct StoreString
311 :public ::std::unary_function< String, void >
312 ,public StorageHelper
314 StoreString( SvStream& _rStorage ) : StorageHelper( _rStorage ) { }
316 void operator() ( const String& _rString ) const
318 m_rStorage.WriteByteString( _rString );
322 //---------------------------------------------------------------------
323 /// functor which stores the local name of a TemplateContent
324 struct StoreLocalContentName
325 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
326 ,public StoreString
328 StoreLocalContentName( SvStream& _rStorage ) : StoreString( _rStorage ) { }
330 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
332 DBG_ERRORFILE( "This method must not be used, the whole URL must be stored!" );
334 // use the base class operator with the local name of the content
335 StoreString::operator() ( _rxContent->getName() );
339 //---------------------------------------------------------------------
340 struct StoreContentURL
341 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
342 ,public StoreString
344 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
346 StoreContentURL( SvStream& _rStorage,
347 const uno::Reference<
348 util::XOfficeInstallationDirectories > &
349 xOfficeInstDirs )
350 : StoreString( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
352 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
354 // use the base class operator with the local name of the content
355 String sURL = _rxContent->getURL();
356 // #116281# Keep office installtion relocatable. Never store
357 // any direct references to office installation directory.
358 sURL = m_xOfficeInstDirs->makeRelocatableURL( sURL );
359 StoreString::operator() ( sURL );
363 //---------------------------------------------------------------------
364 /// functor which stores the complete content of a TemplateContent
365 struct StoreFolderContent
366 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
367 ,public StorageHelper
369 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
371 public:
372 StoreFolderContent( SvStream& _rStorage,
373 const uno::Reference<
374 util::XOfficeInstallationDirectories > &
375 xOfficeInstDirs )
376 : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
378 //.................................................................
379 void operator() ( const TemplateContent& _rContent ) const
381 // store the info about this content
382 m_rStorage << _rContent.getModDate();
384 // store the info about the children
385 // the number
386 m_rStorage << (sal_Int32)_rContent.size();
387 // their URLs ( the local name is not enough, since URL might be not a hierarchical one, "expand:" for example )
388 ::std::for_each(
389 _rContent.getSubContents().begin(),
390 _rContent.getSubContents().end(),
391 StoreContentURL( m_rStorage, m_xOfficeInstDirs )
393 // their content
394 ::std::for_each(
395 _rContent.getSubContents().begin(),
396 _rContent.getSubContents().end(),
397 *this
401 //.................................................................
402 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
404 if ( _rxContent.isValid() )
406 operator()( *_rxContent );
411 //---------------------------------------------------------------------
412 /// functor which reads a complete TemplateContent instance
413 struct ReadFolderContent
414 :public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
415 ,public StorageHelper
417 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
419 ReadFolderContent( SvStream& _rStorage,
420 const uno::Reference<
421 util::XOfficeInstallationDirectories > &
422 xOfficeInstDirs )
423 : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
425 //.................................................................
426 void operator() ( TemplateContent& _rContent ) const
428 // store the info about this content
429 util::DateTime aModDate;
430 m_rStorage >> aModDate;
431 _rContent.setModDate( aModDate );
433 // store the info about the children
434 // the number
435 sal_Int32 nChildren = 0;
436 m_rStorage >> nChildren;
437 TemplateFolderContent& rChildren = _rContent.getSubContents();
438 rChildren.resize( 0 );
439 rChildren.reserve( nChildren );
440 // initialize them with their (local) names
441 while ( nChildren-- )
443 String sURL;
444 m_rStorage.ReadByteString( sURL );
445 sURL = m_xOfficeInstDirs->makeAbsoluteURL( sURL );
446 INetURLObject aChildURL( sURL );
447 rChildren.push_back( new TemplateContent( aChildURL ) );
450 // their content
451 ::std::for_each(
452 _rContent.getSubContents().begin(),
453 _rContent.getSubContents().end(),
454 *this
458 //.................................................................
459 void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
461 if ( _rxContent.isValid() )
463 operator()( *_rxContent );
468 //=====================================================================
469 //= TemplateFolderCacheImpl
470 //=====================================================================
471 class TemplateFolderCacheImpl
473 private:
474 TemplateFolderContent m_aPreviousState; // the current state of the template dirs (as found on the HD)
475 TemplateFolderContent m_aCurrentState; // the previous state of the template dirs (as found in the cache file)
477 osl::Mutex m_aMutex;
478 // will be lazy inited; never access directly; use getOfficeInstDirs().
479 uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
481 SvStream* m_pCacheStream;
482 sal_Bool m_bNeedsUpdate : 1;
483 sal_Bool m_bKnowState : 1;
484 sal_Bool m_bValidCurrentState : 1;
485 sal_Bool m_bAutoStoreState : 1;
487 public:
488 TemplateFolderCacheImpl( sal_Bool _bAutoStoreState );
489 ~TemplateFolderCacheImpl( );
491 sal_Bool needsUpdate( sal_Bool _bForceCheck );
492 void storeState( sal_Bool _bForceRetrieval );
494 private:
495 void initTemplDirs( ::std::vector< String >& _rRootDirs );
496 sal_Bool openCacheStream( sal_Bool _bForRead );
497 void closeCacheStream( );
499 /// read the state of the dirs from the cache file
500 sal_Bool readPreviousState();
501 /// read the current state of the dirs
502 sal_Bool readCurrentState();
504 String implParseSmart( const String& _rPath );
506 sal_Bool implReadFolder( const ::vos::ORef< TemplateContent >& _rxRoot );
508 static String getCacheFileName();
509 static sal_Int32 getMagicNumber();
510 static void normalize( TemplateFolderContent& _rState );
512 // @return <TRUE/> if the states equal
513 static sal_Bool equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS );
515 // late initialize m_xOfficeInstDirs
516 uno::Reference< util::XOfficeInstallationDirectories > getOfficeInstDirs();
519 //---------------------------------------------------------------------
520 TemplateFolderCacheImpl::TemplateFolderCacheImpl( sal_Bool _bAutoStoreState )
521 :m_pCacheStream ( NULL )
522 ,m_bNeedsUpdate ( sal_True )
523 ,m_bKnowState ( sal_False )
524 ,m_bValidCurrentState ( sal_False )
525 ,m_bAutoStoreState ( _bAutoStoreState )
529 //---------------------------------------------------------------------
530 TemplateFolderCacheImpl::~TemplateFolderCacheImpl( )
532 // store the current state if possible and required
533 if ( m_bValidCurrentState && m_bAutoStoreState )
534 storeState( sal_False );
536 closeCacheStream( );
539 //---------------------------------------------------------------------
540 sal_Int32 TemplateFolderCacheImpl::getMagicNumber()
542 sal_Int32 nMagic = 0;
543 ( nMagic += (sal_Int8)'T' ) <<= 4;
544 ( nMagic += (sal_Int8)'D' ) <<= 4;
545 ( nMagic += (sal_Int8)'S' ) <<= 4;
546 ( nMagic += (sal_Int8)'C' ) <<= 0;
547 return nMagic;
550 //---------------------------------------------------------------------
551 String TemplateFolderCacheImpl::getCacheFileName()
553 return String::CreateFromAscii( ".templdir.cache" );
557 //---------------------------------------------------------------------
558 void TemplateFolderCacheImpl::normalize( TemplateFolderContent& _rState )
560 SubContentSort()( _rState );
563 //---------------------------------------------------------------------
564 sal_Bool TemplateFolderCacheImpl::equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS )
566 if ( _rLHS.size() != _rRHS.size() )
567 return sal_False;
569 // as both arrays are sorted (by definition - this is a precondition of this method)
570 // we can simply go from the front to the back and compare the single elements
572 ::std::pair< ConstFolderIterator, ConstFolderIterator > aFirstDifferent = ::std::mismatch(
573 _rLHS.begin(),
574 _rLHS.end(),
575 _rRHS.begin(),
576 TemplateContentEqual()
579 return aFirstDifferent.first == _rLHS.end();
582 //---------------------------------------------------------------------
583 void TemplateFolderCacheImpl::storeState( sal_Bool _bForceRetrieval )
585 if ( !m_bValidCurrentState || _bForceRetrieval )
586 readCurrentState( );
588 if ( m_bValidCurrentState && openCacheStream( sal_False ) )
590 *m_pCacheStream << getMagicNumber();
592 // store the template root folders
593 // the size
594 *m_pCacheStream << (sal_Int32)m_aCurrentState.size();
595 // the complete URLs
596 ::std::for_each(
597 m_aCurrentState.begin(),
598 m_aCurrentState.end(),
599 StoreContentURL( *m_pCacheStream, getOfficeInstDirs() )
602 // the contents
603 ::std::for_each(
604 m_aCurrentState.begin(),
605 m_aCurrentState.end(),
606 StoreFolderContent( *m_pCacheStream, getOfficeInstDirs() )
611 //---------------------------------------------------------------------
612 String TemplateFolderCacheImpl::implParseSmart( const String& _rPath )
614 INetURLObject aParser;
615 aParser.SetSmartProtocol( INET_PROT_FILE );
616 aParser.SetURL( _rPath, INetURLObject::WAS_ENCODED );
617 if ( INET_PROT_NOT_VALID == aParser.GetProtocol() )
619 String sURL;
620 LocalFileHelper::ConvertPhysicalNameToURL( _rPath, sURL );
621 aParser.SetURL( sURL, INetURLObject::WAS_ENCODED );
623 return aParser.GetMainURL( INetURLObject::DECODE_TO_IURI );
626 //---------------------------------------------------------------------
627 void TemplateFolderCacheImpl::closeCacheStream( )
629 DELETEZ( m_pCacheStream );
632 //---------------------------------------------------------------------
633 sal_Bool TemplateFolderCacheImpl::implReadFolder( const ::vos::ORef< TemplateContent >& _rxRoot )
637 // create a content for the current folder root
638 Reference< XResultSet > xResultSet;
639 Sequence< ::rtl::OUString > aContentProperties( 4);
640 aContentProperties[0] = ::rtl::OUString::createFromAscii( "Title" );
641 aContentProperties[1] = ::rtl::OUString::createFromAscii( "DateModified" );
642 aContentProperties[2] = ::rtl::OUString::createFromAscii( "DateCreated" );
643 aContentProperties[3] = ::rtl::OUString::createFromAscii( "IsFolder" );
645 // get the set of sub contents in the folder
648 Reference< XDynamicResultSet > xDynResultSet;
650 ::ucbhelper::Content aTemplateRoot( _rxRoot->getURL(), Reference< XCommandEnvironment >() );
651 xDynResultSet = aTemplateRoot.createDynamicCursor( aContentProperties, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS );
652 if ( xDynResultSet.is() )
653 xResultSet = xDynResultSet->getStaticResultSet();
655 catch( CommandAbortedException& )
657 DBG_ERRORFILE( "TemplateFolderCacheImpl::implReadFolder: caught a CommandAbortedException!" );
658 return sal_False;
660 catch( ::com::sun::star::uno::Exception& )
664 // collect the infos about the sub contents
665 if ( xResultSet.is() )
667 Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
668 Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
670 while ( xResultSet->next() )
672 INetURLObject aSubContentURL( xContentAccess->queryContentIdentifierString() );
674 // a new content instance
675 ::vos::ORef< TemplateContent > xChild = new TemplateContent( aSubContentURL );
677 // the modified date
678 xChild->setModDate( xRow->getTimestamp( 2 ) ); // date modified
679 if ( xRow->wasNull() )
680 xChild->setModDate( xRow->getTimestamp( 3 ) ); // fallback: date created
682 // push back this content
683 _rxRoot->push_back( xChild );
685 // is it a folder?
686 if ( xRow->getBoolean( 4 ) && !xRow->wasNull() )
687 { // yes -> step down
688 ConstFolderIterator aNextLevelRoot = _rxRoot->end();
689 --aNextLevelRoot;
690 implReadFolder( *aNextLevelRoot );
695 catch( const Exception& )
697 DBG_ERROR( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" );
698 return sal_False;
700 return sal_True;
703 //---------------------------------------------------------------------
704 sal_Bool TemplateFolderCacheImpl::readCurrentState()
706 // reset
707 m_bValidCurrentState = sal_False;
708 TemplateFolderContent aTemplateFolderContent;
709 m_aCurrentState.swap( aTemplateFolderContent );
711 // the template directories from the config
712 String aDirs = SvtPathOptions().GetTemplatePath();
713 sal_uInt16 nDirs = aDirs.GetTokenCount( ';' );
715 m_aCurrentState.reserve( nDirs );
716 // loop through all the root-level template folders
717 for ( sal_uInt16 i=0; i<nDirs; ++i)
719 // create a new entry
720 m_aCurrentState.push_back( new TemplateContent( INetURLObject( aDirs.GetToken( i, ';' ) ) ) );
721 TemplateFolderContent::iterator aCurrentRoot = m_aCurrentState.end();
722 --aCurrentRoot;
724 if ( !implReadFolder( *aCurrentRoot ) )
725 return sal_False;
728 // normalize the array (which basically means "sort it")
729 normalize( m_aCurrentState );
731 m_bValidCurrentState = sal_True;
732 return m_bValidCurrentState;
735 //---------------------------------------------------------------------
736 sal_Bool TemplateFolderCacheImpl::readPreviousState()
738 DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::readPreviousState: not to be called without stream!" );
740 // reset
741 TemplateFolderContent aTemplateFolderContent;
742 m_aPreviousState.swap( aTemplateFolderContent );
744 // check the magic number
745 sal_Int32 nMagic = 0;
746 *m_pCacheStream >> nMagic;
747 DBG_ASSERT( getMagicNumber() == nMagic, "TemplateFolderCacheImpl::readPreviousState: invalid cache file!" );
748 if ( getMagicNumber() != nMagic )
749 return sal_False;
751 // the root directories
752 // their number
753 sal_Int32 nRootDirectories = 0;
754 *m_pCacheStream >> nRootDirectories;
755 // init empty TemplateContens with the URLs
756 m_aPreviousState.reserve( nRootDirectories );
757 while ( nRootDirectories-- )
759 String sURL;
760 m_pCacheStream->ReadByteString( sURL );
761 // #116281# Keep office installtion relocatable. Never store
762 // any direct references to office installation directory.
763 sURL = getOfficeInstDirs()->makeAbsoluteURL( sURL );
764 m_aPreviousState.push_back(
765 new TemplateContent( INetURLObject(sURL) ) );
768 // read the contents of the root folders
769 ::std::for_each(
770 m_aPreviousState.begin(),
771 m_aPreviousState.end(),
772 ReadFolderContent( *m_pCacheStream, getOfficeInstDirs() )
775 DBG_ASSERT( !m_pCacheStream->GetErrorCode(), "TemplateFolderCacheImpl::readPreviousState: unknown error during reading the state cache!" );
777 // normalize the array (which basically means "sort it")
778 normalize( m_aPreviousState );
780 return sal_True;
783 //---------------------------------------------------------------------
784 sal_Bool TemplateFolderCacheImpl::openCacheStream( sal_Bool _bForRead )
786 // close any old stream instance
787 closeCacheStream( );
789 // get the storage directory
790 String sStorageURL = implParseSmart( SvtPathOptions().GetStoragePath() );
791 INetURLObject aStorageURL( sStorageURL );
792 if ( INET_PROT_NOT_VALID == aStorageURL.GetProtocol() )
794 DBG_ERROR( "TemplateFolderCacheImpl::openCacheStream: invalid storage path!" );
795 return sal_False;
798 // append our name
799 aStorageURL.Append( getCacheFileName() );
801 // open the stream
802 m_pCacheStream = UcbStreamHelper::CreateStream( aStorageURL.GetMainURL( INetURLObject::DECODE_TO_IURI ),
803 _bForRead ? STREAM_READ | STREAM_NOCREATE : STREAM_WRITE | STREAM_TRUNC );
804 DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::openCacheStream: could not open/create the cache stream!" );
805 if ( m_pCacheStream && m_pCacheStream->GetErrorCode() )
807 DELETEZ( m_pCacheStream );
810 if ( m_pCacheStream )
811 m_pCacheStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
813 return NULL != m_pCacheStream;
816 //---------------------------------------------------------------------
817 sal_Bool TemplateFolderCacheImpl::needsUpdate( sal_Bool _bForceCheck )
819 if ( m_bKnowState && !_bForceCheck )
820 return m_bNeedsUpdate;
822 m_bNeedsUpdate = sal_True;
823 m_bKnowState = sal_True;
825 if ( readCurrentState() )
827 // open the stream which contains the cached state of the directories
828 if ( openCacheStream( sal_True ) )
829 { // opening the stream succeeded
830 if ( readPreviousState() )
832 m_bNeedsUpdate = !equalStates( m_aPreviousState, m_aCurrentState );
834 else
836 closeCacheStream();
840 return m_bNeedsUpdate;
843 //---------------------------------------------------------------------
844 void TemplateFolderCacheImpl::initTemplDirs( ::std::vector< String >& )
848 //---------------------------------------------------------------------
849 uno::Reference< util::XOfficeInstallationDirectories >
850 TemplateFolderCacheImpl::getOfficeInstDirs()
852 if ( !m_xOfficeInstDirs.is() )
854 osl::MutexGuard aGuard( m_aMutex );
855 if ( !m_xOfficeInstDirs.is() )
857 // @@@ This is bad!
858 uno::Reference< lang::XMultiServiceFactory > xSMgr
859 = comphelper::getProcessServiceFactory();
860 OSL_ENSURE( xSMgr.is(), "No service manager!" );
862 uno::Reference< beans::XPropertySet > xPropSet(
863 xSMgr, uno::UNO_QUERY );
864 if ( xPropSet.is() )
866 uno::Reference< uno::XComponentContext > xCtx;
867 xPropSet->getPropertyValue(
868 rtl::OUString(
869 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
870 >>= xCtx;
872 OSL_ENSURE( xCtx.is(),
873 "Unable to obtain component context from service manager!" );
875 if ( xCtx.is() )
877 xCtx->getValueByName(
878 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
879 "/singletons/com.sun.star.util.theOfficeInstallationDirectories" ) ) )
880 >>= m_xOfficeInstDirs;
883 OSL_ENSURE( m_xOfficeInstDirs.is(),
884 "Unable to obtain office directories singleton!" );
889 return m_xOfficeInstDirs;
892 //=====================================================================
893 //= TemplateFolderCache
894 //=====================================================================
895 //---------------------------------------------------------------------
896 TemplateFolderCache::TemplateFolderCache( sal_Bool _bAutoStoreState )
897 :m_pImpl( new TemplateFolderCacheImpl( _bAutoStoreState ) )
901 //---------------------------------------------------------------------
902 TemplateFolderCache::~TemplateFolderCache( )
904 DELETEZ( m_pImpl );
907 //---------------------------------------------------------------------
908 sal_Bool TemplateFolderCache::needsUpdate( sal_Bool _bForceCheck )
910 return m_pImpl->needsUpdate( _bForceCheck );
913 //---------------------------------------------------------------------
914 void TemplateFolderCache::storeState( sal_Bool _bForceRetrieval )
916 m_pImpl->storeState( _bForceRetrieval );
919 //.........................................................................
920 } // namespace sfx2
921 //.........................................................................