1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_svtools.hxx"
26*b1cdbd2cSJim Jagielski #include <svtools/templatefoldercache.hxx>
27*b1cdbd2cSJim Jagielski #include <unotools/ucbstreamhelper.hxx>
28*b1cdbd2cSJim Jagielski #include <unotools/localfilehelper.hxx>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/XPropertySet.hpp>
30*b1cdbd2cSJim Jagielski #include <com/sun/star/sdbc/XResultSet.hpp>
31*b1cdbd2cSJim Jagielski #include <com/sun/star/ucb/XDynamicResultSet.hpp>
32*b1cdbd2cSJim Jagielski #include <com/sun/star/sdbc/XRow.hpp>
33*b1cdbd2cSJim Jagielski #include <com/sun/star/ucb/XContentAccess.hpp>
34*b1cdbd2cSJim Jagielski #include <com/sun/star/uno/XComponentContext.hpp>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
36*b1cdbd2cSJim Jagielski #include <ucbhelper/content.hxx>
37*b1cdbd2cSJim Jagielski #include <vos/ref.hxx>
38*b1cdbd2cSJim Jagielski #include <vos/refernce.hxx>
39*b1cdbd2cSJim Jagielski #include <tools/urlobj.hxx>
40*b1cdbd2cSJim Jagielski #include <tools/debug.hxx>
41*b1cdbd2cSJim Jagielski #include <unotools/pathoptions.hxx>
42*b1cdbd2cSJim Jagielski 
43*b1cdbd2cSJim Jagielski #include "comphelper/processfactory.hxx"
44*b1cdbd2cSJim Jagielski 
45*b1cdbd2cSJim Jagielski #include <vector>
46*b1cdbd2cSJim Jagielski #include <list>
47*b1cdbd2cSJim Jagielski #include <functional>
48*b1cdbd2cSJim Jagielski #include <algorithm>
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski //.........................................................................
51*b1cdbd2cSJim Jagielski namespace svt
52*b1cdbd2cSJim Jagielski {
53*b1cdbd2cSJim Jagielski //.........................................................................
54*b1cdbd2cSJim Jagielski 
55*b1cdbd2cSJim Jagielski 	using namespace ::utl;
56*b1cdbd2cSJim Jagielski 	using namespace ::com::sun::star;
57*b1cdbd2cSJim Jagielski 	using namespace ::com::sun::star::sdbc;
58*b1cdbd2cSJim Jagielski 	using namespace ::com::sun::star::ucb;
59*b1cdbd2cSJim Jagielski 	using namespace ::com::sun::star::uno;
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski 	//=====================================================================
62*b1cdbd2cSJim Jagielski 	//= helpers
63*b1cdbd2cSJim Jagielski 	//=====================================================================
64*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
operator <<(SvStream & _rStorage,const util::DateTime & _rDate)65*b1cdbd2cSJim Jagielski 	SvStream& operator << ( SvStream& _rStorage, const util::DateTime& _rDate )
66*b1cdbd2cSJim Jagielski 	{
67*b1cdbd2cSJim Jagielski 		_rStorage << _rDate.HundredthSeconds;
68*b1cdbd2cSJim Jagielski 		_rStorage << _rDate.Seconds;
69*b1cdbd2cSJim Jagielski 		_rStorage << _rDate.Minutes;
70*b1cdbd2cSJim Jagielski 		_rStorage << _rDate.Hours;
71*b1cdbd2cSJim Jagielski 		_rStorage << _rDate.Day;
72*b1cdbd2cSJim Jagielski 		_rStorage << _rDate.Month;
73*b1cdbd2cSJim Jagielski 		_rStorage << _rDate.Year;
74*b1cdbd2cSJim Jagielski 
75*b1cdbd2cSJim Jagielski 		return _rStorage;
76*b1cdbd2cSJim Jagielski 	}
77*b1cdbd2cSJim Jagielski 
78*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
operator >>(SvStream & _rStorage,util::DateTime & _rDate)79*b1cdbd2cSJim Jagielski 	SvStream& operator >> ( SvStream& _rStorage, util::DateTime& _rDate )
80*b1cdbd2cSJim Jagielski 	{
81*b1cdbd2cSJim Jagielski 		_rStorage >> _rDate.HundredthSeconds;
82*b1cdbd2cSJim Jagielski 		_rStorage >> _rDate.Seconds;
83*b1cdbd2cSJim Jagielski 		_rStorage >> _rDate.Minutes;
84*b1cdbd2cSJim Jagielski 		_rStorage >> _rDate.Hours;
85*b1cdbd2cSJim Jagielski 		_rStorage >> _rDate.Day;
86*b1cdbd2cSJim Jagielski 		_rStorage >> _rDate.Month;
87*b1cdbd2cSJim Jagielski 		_rStorage >> _rDate.Year;
88*b1cdbd2cSJim Jagielski 
89*b1cdbd2cSJim Jagielski 		return _rStorage;
90*b1cdbd2cSJim Jagielski 	}
91*b1cdbd2cSJim Jagielski 
92*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
operator ==(const util::DateTime & _rLHS,const util::DateTime & _rRHS)93*b1cdbd2cSJim Jagielski 	sal_Bool operator == ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
94*b1cdbd2cSJim Jagielski 	{
95*b1cdbd2cSJim Jagielski 		return	_rLHS.HundredthSeconds == _rRHS.HundredthSeconds
96*b1cdbd2cSJim Jagielski 			&&	_rLHS.Seconds	== _rRHS.Seconds
97*b1cdbd2cSJim Jagielski 			&&	_rLHS.Minutes	== _rRHS.Minutes
98*b1cdbd2cSJim Jagielski 			&&	_rLHS.Hours		== _rRHS.Hours
99*b1cdbd2cSJim Jagielski 			&&	_rLHS.Day		== _rRHS.Day
100*b1cdbd2cSJim Jagielski 			&&	_rLHS.Month		== _rRHS.Month
101*b1cdbd2cSJim Jagielski 			&&	_rLHS.Year		== _rRHS.Year;
102*b1cdbd2cSJim Jagielski 	}
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
operator !=(const util::DateTime & _rLHS,const util::DateTime & _rRHS)105*b1cdbd2cSJim Jagielski 	sal_Bool operator != ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
106*b1cdbd2cSJim Jagielski 	{
107*b1cdbd2cSJim Jagielski 		return !( _rLHS == _rRHS );
108*b1cdbd2cSJim Jagielski 	}
109*b1cdbd2cSJim Jagielski 
110*b1cdbd2cSJim Jagielski 	//=====================================================================
111*b1cdbd2cSJim Jagielski 	//= TemplateContent
112*b1cdbd2cSJim Jagielski 	//=====================================================================
113*b1cdbd2cSJim Jagielski 	struct TemplateContent;
114*b1cdbd2cSJim Jagielski 	typedef	::std::vector< ::vos::ORef< TemplateContent > >	TemplateFolderContent;
115*b1cdbd2cSJim Jagielski     typedef TemplateFolderContent::const_iterator           ConstFolderIterator;
116*b1cdbd2cSJim Jagielski     typedef TemplateFolderContent::iterator                 FolderIterator;
117*b1cdbd2cSJim Jagielski 
118*b1cdbd2cSJim Jagielski 	/** a struct describing one content in one of the template dirs (or at least it's relevant aspects)
119*b1cdbd2cSJim Jagielski 	*/
120*b1cdbd2cSJim Jagielski 	struct TemplateContent : public ::vos::OReference
121*b1cdbd2cSJim Jagielski 	{
122*b1cdbd2cSJim Jagielski 	public:
123*b1cdbd2cSJim Jagielski 
124*b1cdbd2cSJim Jagielski 	private:
125*b1cdbd2cSJim Jagielski 		INetURLObject			m_aURL;
126*b1cdbd2cSJim Jagielski 		String					m_sLocalName;		// redundant - last segment of m_aURL
127*b1cdbd2cSJim Jagielski 		util::DateTime			m_aLastModified;	// date of last modification as reported by UCP
128*b1cdbd2cSJim Jagielski 		TemplateFolderContent	m_aSubContents;		// sorted (by name) list of the children
129*b1cdbd2cSJim Jagielski 
130*b1cdbd2cSJim Jagielski 	private:
implResetDatesvt::TemplateContent131*b1cdbd2cSJim Jagielski 		inline	void	implResetDate( )
132*b1cdbd2cSJim Jagielski 		{
133*b1cdbd2cSJim Jagielski 			m_aLastModified.HundredthSeconds = m_aLastModified.Seconds = m_aLastModified.Minutes = m_aLastModified.Hours = 0;
134*b1cdbd2cSJim Jagielski 			m_aLastModified.Day = m_aLastModified.Month = m_aLastModified.Year = 0;
135*b1cdbd2cSJim Jagielski 		}
136*b1cdbd2cSJim Jagielski 
137*b1cdbd2cSJim Jagielski 	private:
138*b1cdbd2cSJim Jagielski 		~TemplateContent();
139*b1cdbd2cSJim Jagielski 
140*b1cdbd2cSJim Jagielski 	public:
141*b1cdbd2cSJim Jagielski 		TemplateContent();
142*b1cdbd2cSJim Jagielski 		TemplateContent( const INetURLObject& _rURL );
143*b1cdbd2cSJim Jagielski 		TemplateContent( const INetURLObject& _rURL, const util::DateTime& _rLastModified );
144*b1cdbd2cSJim Jagielski 
145*b1cdbd2cSJim Jagielski 		// attribute access
getNamesvt::TemplateContent146*b1cdbd2cSJim Jagielski 		inline String					getName( ) const							{ return m_sLocalName; }
getURLsvt::TemplateContent147*b1cdbd2cSJim Jagielski 		inline String					getURL( ) const								{ return m_aURL.GetMainURL( INetURLObject::DECODE_TO_IURI ); }
setModDatesvt::TemplateContent148*b1cdbd2cSJim Jagielski 		inline void						setModDate( const util::DateTime& _rDate )	{ m_aLastModified = _rDate; }
getModDatesvt::TemplateContent149*b1cdbd2cSJim Jagielski 		inline const util::DateTime&	getModDate( ) const							{ return m_aLastModified; }
150*b1cdbd2cSJim Jagielski 
getSubContentssvt::TemplateContent151*b1cdbd2cSJim Jagielski 		inline TemplateFolderContent&	getSubContents()			{ return m_aSubContents; }
getSubContentssvt::TemplateContent152*b1cdbd2cSJim Jagielski 		inline const TemplateFolderContent&	getSubContents() const	{ return m_aSubContents; }
153*b1cdbd2cSJim Jagielski 
beginsvt::TemplateContent154*b1cdbd2cSJim Jagielski                 inline ConstFolderIterator              begin() const   { return m_aSubContents.begin(); }
endsvt::TemplateContent155*b1cdbd2cSJim Jagielski                 inline ConstFolderIterator              end() const             { return m_aSubContents.end(); }
156*b1cdbd2cSJim Jagielski 		inline TemplateFolderContent::size_type
sizesvt::TemplateContent157*b1cdbd2cSJim Jagielski 										size() const	{ return m_aSubContents.size(); }
158*b1cdbd2cSJim Jagielski 
push_backsvt::TemplateContent159*b1cdbd2cSJim Jagielski 		inline void						push_back( const ::vos::ORef< TemplateContent >& _rxNewElement )
160*b1cdbd2cSJim Jagielski 														{ m_aSubContents.push_back( _rxNewElement ); }
161*b1cdbd2cSJim Jagielski 	};
162*b1cdbd2cSJim Jagielski 
163*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
DBG_NAME(TemplateContent)164*b1cdbd2cSJim Jagielski 	DBG_NAME( TemplateContent )
165*b1cdbd2cSJim Jagielski 
166*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
167*b1cdbd2cSJim Jagielski 	TemplateContent::TemplateContent()
168*b1cdbd2cSJim Jagielski 	{
169*b1cdbd2cSJim Jagielski 		DBG_CTOR( TemplateContent, NULL );
170*b1cdbd2cSJim Jagielski 		implResetDate();
171*b1cdbd2cSJim Jagielski 	}
172*b1cdbd2cSJim Jagielski 
173*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
TemplateContent(const INetURLObject & _rURL)174*b1cdbd2cSJim Jagielski 	TemplateContent::TemplateContent( const INetURLObject& _rURL )
175*b1cdbd2cSJim Jagielski 		:m_aURL( _rURL )
176*b1cdbd2cSJim Jagielski 	{
177*b1cdbd2cSJim Jagielski 		DBG_CTOR( TemplateContent, NULL );
178*b1cdbd2cSJim Jagielski 		DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
179*b1cdbd2cSJim Jagielski 		m_sLocalName = m_aURL.getName();
180*b1cdbd2cSJim Jagielski 		implResetDate();
181*b1cdbd2cSJim Jagielski 	}
182*b1cdbd2cSJim Jagielski 
183*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
TemplateContent(const INetURLObject & _rURL,const util::DateTime & _rLastModified)184*b1cdbd2cSJim Jagielski 	TemplateContent::TemplateContent( const INetURLObject& _rURL, const util::DateTime& _rLastModified )
185*b1cdbd2cSJim Jagielski 		:m_aURL( _rURL )
186*b1cdbd2cSJim Jagielski 		,m_aLastModified( _rLastModified )
187*b1cdbd2cSJim Jagielski 	{
188*b1cdbd2cSJim Jagielski 		DBG_CTOR( TemplateContent, NULL );
189*b1cdbd2cSJim Jagielski 		DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
190*b1cdbd2cSJim Jagielski 		m_sLocalName = m_aURL.getName();
191*b1cdbd2cSJim Jagielski 	}
192*b1cdbd2cSJim Jagielski 
193*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
~TemplateContent()194*b1cdbd2cSJim Jagielski 	TemplateContent::~TemplateContent()
195*b1cdbd2cSJim Jagielski 	{
196*b1cdbd2cSJim Jagielski 		DBG_DTOR( TemplateContent, NULL );
197*b1cdbd2cSJim Jagielski 	}
198*b1cdbd2cSJim Jagielski 
199*b1cdbd2cSJim Jagielski 	//=====================================================================
200*b1cdbd2cSJim Jagielski 	//= stl helpers
201*b1cdbd2cSJim Jagielski 	//=====================================================================
202*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
203*b1cdbd2cSJim Jagielski 	/// compares two TemplateContent by URL
204*b1cdbd2cSJim Jagielski 	struct TemplateContentURLLess
205*b1cdbd2cSJim Jagielski 		:public ::std::binary_function	<	::vos::ORef< TemplateContent >
206*b1cdbd2cSJim Jagielski 										,	::vos::ORef< TemplateContent >
207*b1cdbd2cSJim Jagielski 										,	bool
208*b1cdbd2cSJim Jagielski 										>
209*b1cdbd2cSJim Jagielski 	{
operator ()svt::TemplateContentURLLess210*b1cdbd2cSJim Jagielski 		bool operator() ( const ::vos::ORef< TemplateContent >& _rxLHS, const ::vos::ORef< TemplateContent >& _rxRHS ) const
211*b1cdbd2cSJim Jagielski 		{
212*b1cdbd2cSJim Jagielski 			return	_rxLHS->getURL() < _rxRHS->getURL()
213*b1cdbd2cSJim Jagielski 				?	true
214*b1cdbd2cSJim Jagielski 				:	false;
215*b1cdbd2cSJim Jagielski 		}
216*b1cdbd2cSJim Jagielski 	};
217*b1cdbd2cSJim Jagielski 
218*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
219*b1cdbd2cSJim Jagielski 	/// sorts the sib contents of a TemplateFolderContent
220*b1cdbd2cSJim Jagielski 	struct SubContentSort : public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
221*b1cdbd2cSJim Jagielski 	{
operator ()svt::SubContentSort222*b1cdbd2cSJim Jagielski 		void operator() ( TemplateFolderContent& _rFolder ) const
223*b1cdbd2cSJim Jagielski 		{
224*b1cdbd2cSJim Jagielski 			// sort the directory by name
225*b1cdbd2cSJim Jagielski 			::std::sort(
226*b1cdbd2cSJim Jagielski 				_rFolder.begin(),
227*b1cdbd2cSJim Jagielski 				_rFolder.end(),
228*b1cdbd2cSJim Jagielski 				TemplateContentURLLess()
229*b1cdbd2cSJim Jagielski 			);
230*b1cdbd2cSJim Jagielski 
231*b1cdbd2cSJim Jagielski 			// sort the sub directories by name
232*b1cdbd2cSJim Jagielski 			::std::for_each(
233*b1cdbd2cSJim Jagielski 				_rFolder.begin(),
234*b1cdbd2cSJim Jagielski 				_rFolder.end(),
235*b1cdbd2cSJim Jagielski 				*this
236*b1cdbd2cSJim Jagielski 			);
237*b1cdbd2cSJim Jagielski 		}
238*b1cdbd2cSJim Jagielski 
operator ()svt::SubContentSort239*b1cdbd2cSJim Jagielski 		void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
240*b1cdbd2cSJim Jagielski 		{
241*b1cdbd2cSJim Jagielski 			if ( _rxContent.isValid() && _rxContent->size() )
242*b1cdbd2cSJim Jagielski 			{
243*b1cdbd2cSJim Jagielski 				operator()( _rxContent->getSubContents() );
244*b1cdbd2cSJim Jagielski 			}
245*b1cdbd2cSJim Jagielski 		}
246*b1cdbd2cSJim Jagielski 	};
247*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
248*b1cdbd2cSJim Jagielski 	/** does a deep compare of two template contents
249*b1cdbd2cSJim Jagielski 	*/
250*b1cdbd2cSJim Jagielski 	struct TemplateContentEqual
251*b1cdbd2cSJim Jagielski 		:public ::std::binary_function	<	::vos::ORef< TemplateContent >
252*b1cdbd2cSJim Jagielski 										,	::vos::ORef< TemplateContent >
253*b1cdbd2cSJim Jagielski 										,	bool
254*b1cdbd2cSJim Jagielski 										>
255*b1cdbd2cSJim Jagielski 	{
256*b1cdbd2cSJim Jagielski 		//.................................................................
operator ()svt::TemplateContentEqual257*b1cdbd2cSJim Jagielski 		bool operator() (const ::vos::ORef< TemplateContent >& _rLHS, const ::vos::ORef< TemplateContent >& _rRHS )
258*b1cdbd2cSJim Jagielski 		{
259*b1cdbd2cSJim Jagielski 			if ( !_rLHS.isValid() || !_rRHS.isValid() )
260*b1cdbd2cSJim Jagielski 			{
261*b1cdbd2cSJim Jagielski 				DBG_ERROR( "TemplateContentEqual::operator(): invalid contents!" );
262*b1cdbd2cSJim Jagielski 				return true;
263*b1cdbd2cSJim Jagielski 					// this is not strictly true, in case only one is invalid - but this is a heavy error anyway
264*b1cdbd2cSJim Jagielski 			}
265*b1cdbd2cSJim Jagielski 
266*b1cdbd2cSJim Jagielski 			if ( _rLHS->getURL() != _rRHS->getURL() )
267*b1cdbd2cSJim Jagielski 				return false;
268*b1cdbd2cSJim Jagielski 
269*b1cdbd2cSJim Jagielski 			if ( _rLHS->getModDate() != _rRHS->getModDate() )
270*b1cdbd2cSJim Jagielski 				return false;
271*b1cdbd2cSJim Jagielski 
272*b1cdbd2cSJim Jagielski 			if ( _rLHS->getSubContents().size() != _rRHS->getSubContents().size() )
273*b1cdbd2cSJim Jagielski 				return false;
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski 			if ( _rLHS->getSubContents().size() )
276*b1cdbd2cSJim Jagielski 			{	// there are children
277*b1cdbd2cSJim Jagielski 				// -> compare them
278*b1cdbd2cSJim Jagielski 				::std::pair< FolderIterator, FolderIterator > aFirstDifferent = ::std::mismatch(
279*b1cdbd2cSJim Jagielski 					_rLHS->getSubContents().begin(),
280*b1cdbd2cSJim Jagielski 					_rLHS->getSubContents().end(),
281*b1cdbd2cSJim Jagielski 					_rRHS->getSubContents().begin(),
282*b1cdbd2cSJim Jagielski 					*this
283*b1cdbd2cSJim Jagielski 				);
284*b1cdbd2cSJim Jagielski 				if ( aFirstDifferent.first != _rLHS->getSubContents().end() )
285*b1cdbd2cSJim Jagielski 					return false;// the sub contents differ
286*b1cdbd2cSJim Jagielski 			}
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski 			return true;
289*b1cdbd2cSJim Jagielski 		}
290*b1cdbd2cSJim Jagielski 	};
291*b1cdbd2cSJim Jagielski 
292*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
293*b1cdbd2cSJim Jagielski 	/// base class for functors which act an an SvStream
294*b1cdbd2cSJim Jagielski 	struct StorageHelper
295*b1cdbd2cSJim Jagielski 	{
296*b1cdbd2cSJim Jagielski 	protected:
297*b1cdbd2cSJim Jagielski 		SvStream&	m_rStorage;
StorageHelpersvt::StorageHelper298*b1cdbd2cSJim Jagielski 		StorageHelper( SvStream& _rStorage ) : m_rStorage( _rStorage ) { }
299*b1cdbd2cSJim Jagielski 	};
300*b1cdbd2cSJim Jagielski 
301*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
302*b1cdbd2cSJim Jagielski 	/// functor which allows storing a string
303*b1cdbd2cSJim Jagielski 	struct StoreString
304*b1cdbd2cSJim Jagielski 			:public ::std::unary_function< String, void >
305*b1cdbd2cSJim Jagielski 			,public StorageHelper
306*b1cdbd2cSJim Jagielski 	{
StoreStringsvt::StoreString307*b1cdbd2cSJim Jagielski 		StoreString( SvStream& _rStorage ) : StorageHelper( _rStorage ) { }
308*b1cdbd2cSJim Jagielski 
operator ()svt::StoreString309*b1cdbd2cSJim Jagielski 		void operator() ( const String& _rString ) const
310*b1cdbd2cSJim Jagielski 		{
311*b1cdbd2cSJim Jagielski 			m_rStorage.WriteByteString( _rString );
312*b1cdbd2cSJim Jagielski 		}
313*b1cdbd2cSJim Jagielski 	};
314*b1cdbd2cSJim Jagielski 
315*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
316*b1cdbd2cSJim Jagielski 	/// functor which stores the local name of a TemplateContent
317*b1cdbd2cSJim Jagielski 	struct StoreLocalContentName
318*b1cdbd2cSJim Jagielski 			:public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
319*b1cdbd2cSJim Jagielski 			,public StoreString
320*b1cdbd2cSJim Jagielski 	{
StoreLocalContentNamesvt::StoreLocalContentName321*b1cdbd2cSJim Jagielski 		StoreLocalContentName( SvStream& _rStorage ) : StoreString( _rStorage ) { }
322*b1cdbd2cSJim Jagielski 
operator ()svt::StoreLocalContentName323*b1cdbd2cSJim Jagielski 		void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
324*b1cdbd2cSJim Jagielski 		{
325*b1cdbd2cSJim Jagielski 			DBG_ERRORFILE( "This method must not be used, the whole URL must be stored!" );
326*b1cdbd2cSJim Jagielski 
327*b1cdbd2cSJim Jagielski 			// use the base class operator with the local name of the content
328*b1cdbd2cSJim Jagielski 			StoreString::operator() ( _rxContent->getName() );
329*b1cdbd2cSJim Jagielski 		}
330*b1cdbd2cSJim Jagielski 	};
331*b1cdbd2cSJim Jagielski 
332*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
333*b1cdbd2cSJim Jagielski 	struct StoreContentURL
334*b1cdbd2cSJim Jagielski 			:public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
335*b1cdbd2cSJim Jagielski 			,public StoreString
336*b1cdbd2cSJim Jagielski 	{
337*b1cdbd2cSJim Jagielski         uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
338*b1cdbd2cSJim Jagielski 
StoreContentURLsvt::StoreContentURL339*b1cdbd2cSJim Jagielski         StoreContentURL( SvStream& _rStorage,
340*b1cdbd2cSJim Jagielski                          const uno::Reference<
341*b1cdbd2cSJim Jagielski                             util::XOfficeInstallationDirectories > &
342*b1cdbd2cSJim Jagielski                                 xOfficeInstDirs )
343*b1cdbd2cSJim Jagielski         : StoreString( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
344*b1cdbd2cSJim Jagielski 
operator ()svt::StoreContentURL345*b1cdbd2cSJim Jagielski 		void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
346*b1cdbd2cSJim Jagielski 		{
347*b1cdbd2cSJim Jagielski 			// use the base class operator with the local name of the content
348*b1cdbd2cSJim Jagielski             String sURL = _rxContent->getURL();
349*b1cdbd2cSJim Jagielski             // #116281# Keep office installtion relocatable. Never store
350*b1cdbd2cSJim Jagielski             // any direct references to office installation directory.
351*b1cdbd2cSJim Jagielski             sURL = m_xOfficeInstDirs->makeRelocatableURL( sURL );
352*b1cdbd2cSJim Jagielski             StoreString::operator() ( sURL );
353*b1cdbd2cSJim Jagielski 		}
354*b1cdbd2cSJim Jagielski 	};
355*b1cdbd2cSJim Jagielski 
356*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
357*b1cdbd2cSJim Jagielski 	/// functor which stores the complete content of a TemplateContent
358*b1cdbd2cSJim Jagielski 	struct StoreFolderContent
359*b1cdbd2cSJim Jagielski 			:public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
360*b1cdbd2cSJim Jagielski 			,public StorageHelper
361*b1cdbd2cSJim Jagielski 	{
362*b1cdbd2cSJim Jagielski         uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
363*b1cdbd2cSJim Jagielski 
364*b1cdbd2cSJim Jagielski 	public:
StoreFolderContentsvt::StoreFolderContent365*b1cdbd2cSJim Jagielski 		StoreFolderContent( SvStream& _rStorage,
366*b1cdbd2cSJim Jagielski                          const uno::Reference<
367*b1cdbd2cSJim Jagielski                             util::XOfficeInstallationDirectories > &
368*b1cdbd2cSJim Jagielski                                 xOfficeInstDirs )
369*b1cdbd2cSJim Jagielski         : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
370*b1cdbd2cSJim Jagielski 
371*b1cdbd2cSJim Jagielski 		//.................................................................
operator ()svt::StoreFolderContent372*b1cdbd2cSJim Jagielski 		void operator() ( const TemplateContent& _rContent ) const
373*b1cdbd2cSJim Jagielski 		{
374*b1cdbd2cSJim Jagielski 			// store the info about this content
375*b1cdbd2cSJim Jagielski 			m_rStorage << _rContent.getModDate();
376*b1cdbd2cSJim Jagielski 
377*b1cdbd2cSJim Jagielski 			// store the info about the children
378*b1cdbd2cSJim Jagielski 			// the number
379*b1cdbd2cSJim Jagielski 			m_rStorage << (sal_Int32)_rContent.size();
380*b1cdbd2cSJim Jagielski 			// their URLs ( the local name is not enough, since URL might be not a hierarchical one, "expand:" for example )
381*b1cdbd2cSJim Jagielski 			::std::for_each(
382*b1cdbd2cSJim Jagielski 				_rContent.getSubContents().begin(),
383*b1cdbd2cSJim Jagielski 				_rContent.getSubContents().end(),
384*b1cdbd2cSJim Jagielski 				StoreContentURL( m_rStorage, m_xOfficeInstDirs )
385*b1cdbd2cSJim Jagielski 			);
386*b1cdbd2cSJim Jagielski 			// their content
387*b1cdbd2cSJim Jagielski 			::std::for_each(
388*b1cdbd2cSJim Jagielski 				_rContent.getSubContents().begin(),
389*b1cdbd2cSJim Jagielski 				_rContent.getSubContents().end(),
390*b1cdbd2cSJim Jagielski 				*this
391*b1cdbd2cSJim Jagielski 			);
392*b1cdbd2cSJim Jagielski 		}
393*b1cdbd2cSJim Jagielski 
394*b1cdbd2cSJim Jagielski 		//.................................................................
operator ()svt::StoreFolderContent395*b1cdbd2cSJim Jagielski 		void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
396*b1cdbd2cSJim Jagielski 		{
397*b1cdbd2cSJim Jagielski 			if ( _rxContent.isValid() )
398*b1cdbd2cSJim Jagielski 			{
399*b1cdbd2cSJim Jagielski 				operator()( *_rxContent );
400*b1cdbd2cSJim Jagielski 			}
401*b1cdbd2cSJim Jagielski 		}
402*b1cdbd2cSJim Jagielski 	};
403*b1cdbd2cSJim Jagielski 
404*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
405*b1cdbd2cSJim Jagielski 	/// functor which reads a complete TemplateContent instance
406*b1cdbd2cSJim Jagielski 	struct ReadFolderContent
407*b1cdbd2cSJim Jagielski 			:public ::std::unary_function< ::vos::ORef< TemplateContent >, void >
408*b1cdbd2cSJim Jagielski 			,public StorageHelper
409*b1cdbd2cSJim Jagielski 	{
410*b1cdbd2cSJim Jagielski         uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
411*b1cdbd2cSJim Jagielski 
ReadFolderContentsvt::ReadFolderContent412*b1cdbd2cSJim Jagielski 		ReadFolderContent( SvStream& _rStorage,
413*b1cdbd2cSJim Jagielski                          const uno::Reference<
414*b1cdbd2cSJim Jagielski                             util::XOfficeInstallationDirectories > &
415*b1cdbd2cSJim Jagielski                                 xOfficeInstDirs )
416*b1cdbd2cSJim Jagielski         : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
417*b1cdbd2cSJim Jagielski 
418*b1cdbd2cSJim Jagielski 		//.................................................................
operator ()svt::ReadFolderContent419*b1cdbd2cSJim Jagielski 		void operator() ( TemplateContent& _rContent ) const
420*b1cdbd2cSJim Jagielski 		{
421*b1cdbd2cSJim Jagielski 			// store the info about this content
422*b1cdbd2cSJim Jagielski 			util::DateTime aModDate;
423*b1cdbd2cSJim Jagielski 			m_rStorage >> aModDate;
424*b1cdbd2cSJim Jagielski 			_rContent.setModDate( aModDate );
425*b1cdbd2cSJim Jagielski 
426*b1cdbd2cSJim Jagielski 			// store the info about the children
427*b1cdbd2cSJim Jagielski 			// the number
428*b1cdbd2cSJim Jagielski 			sal_Int32 nChildren = 0;
429*b1cdbd2cSJim Jagielski 			m_rStorage >> nChildren;
430*b1cdbd2cSJim Jagielski 			TemplateFolderContent& rChildren = _rContent.getSubContents();
431*b1cdbd2cSJim Jagielski 			rChildren.resize( 0 );
432*b1cdbd2cSJim Jagielski 			rChildren.reserve( nChildren );
433*b1cdbd2cSJim Jagielski 			// initialize them with their (local) names
434*b1cdbd2cSJim Jagielski 			while ( nChildren-- )
435*b1cdbd2cSJim Jagielski 			{
436*b1cdbd2cSJim Jagielski 				String sURL;
437*b1cdbd2cSJim Jagielski 				m_rStorage.ReadByteString( sURL );
438*b1cdbd2cSJim Jagielski                 sURL = m_xOfficeInstDirs->makeAbsoluteURL( sURL );
439*b1cdbd2cSJim Jagielski 				INetURLObject aChildURL( sURL );
440*b1cdbd2cSJim Jagielski 				rChildren.push_back( new TemplateContent( aChildURL ) );
441*b1cdbd2cSJim Jagielski 			}
442*b1cdbd2cSJim Jagielski 
443*b1cdbd2cSJim Jagielski 			// their content
444*b1cdbd2cSJim Jagielski 			::std::for_each(
445*b1cdbd2cSJim Jagielski 				_rContent.getSubContents().begin(),
446*b1cdbd2cSJim Jagielski 				_rContent.getSubContents().end(),
447*b1cdbd2cSJim Jagielski 				*this
448*b1cdbd2cSJim Jagielski 			);
449*b1cdbd2cSJim Jagielski 		}
450*b1cdbd2cSJim Jagielski 
451*b1cdbd2cSJim Jagielski 		//.................................................................
operator ()svt::ReadFolderContent452*b1cdbd2cSJim Jagielski 		void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const
453*b1cdbd2cSJim Jagielski 		{
454*b1cdbd2cSJim Jagielski 			if ( _rxContent.isValid() )
455*b1cdbd2cSJim Jagielski 			{
456*b1cdbd2cSJim Jagielski 				operator()( *_rxContent );
457*b1cdbd2cSJim Jagielski 			}
458*b1cdbd2cSJim Jagielski 		}
459*b1cdbd2cSJim Jagielski 	};
460*b1cdbd2cSJim Jagielski 
461*b1cdbd2cSJim Jagielski 	//=====================================================================
462*b1cdbd2cSJim Jagielski 	//= TemplateFolderCacheImpl
463*b1cdbd2cSJim Jagielski 	//=====================================================================
464*b1cdbd2cSJim Jagielski     class TemplateFolderCacheImpl
465*b1cdbd2cSJim Jagielski 	{
466*b1cdbd2cSJim Jagielski 	private:
467*b1cdbd2cSJim Jagielski 		TemplateFolderContent			m_aPreviousState;	// the current state of the template dirs (as found on the HD)
468*b1cdbd2cSJim Jagielski 		TemplateFolderContent			m_aCurrentState;	// the previous state of the template dirs (as found in the cache file)
469*b1cdbd2cSJim Jagielski 
470*b1cdbd2cSJim Jagielski         osl::Mutex                      m_aMutex;
471*b1cdbd2cSJim Jagielski         // will be lazy inited; never access directly; use getOfficeInstDirs().
472*b1cdbd2cSJim Jagielski         uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
473*b1cdbd2cSJim Jagielski 
474*b1cdbd2cSJim Jagielski 		SvStream*						m_pCacheStream;
475*b1cdbd2cSJim Jagielski 		sal_Bool						m_bNeedsUpdate : 1;
476*b1cdbd2cSJim Jagielski 		sal_Bool						m_bKnowState : 1;
477*b1cdbd2cSJim Jagielski 		sal_Bool						m_bValidCurrentState : 1;
478*b1cdbd2cSJim Jagielski 		sal_Bool						m_bAutoStoreState : 1;
479*b1cdbd2cSJim Jagielski 
480*b1cdbd2cSJim Jagielski 	public:
481*b1cdbd2cSJim Jagielski 		TemplateFolderCacheImpl( sal_Bool _bAutoStoreState );
482*b1cdbd2cSJim Jagielski 		~TemplateFolderCacheImpl( );
483*b1cdbd2cSJim Jagielski 
484*b1cdbd2cSJim Jagielski 		sal_Bool	needsUpdate( sal_Bool _bForceCheck );
485*b1cdbd2cSJim Jagielski 		void		storeState( sal_Bool _bForceRetrieval );
486*b1cdbd2cSJim Jagielski 
487*b1cdbd2cSJim Jagielski 	private:
488*b1cdbd2cSJim Jagielski 		void		initTemplDirs( ::std::vector< String >& _rRootDirs );
489*b1cdbd2cSJim Jagielski 		sal_Bool	openCacheStream( sal_Bool _bForRead );
490*b1cdbd2cSJim Jagielski 		void		closeCacheStream( );
491*b1cdbd2cSJim Jagielski 
492*b1cdbd2cSJim Jagielski 		/// read the state of the dirs from the cache file
493*b1cdbd2cSJim Jagielski 		sal_Bool	readPreviousState();
494*b1cdbd2cSJim Jagielski 		/// read the current state of the dirs
495*b1cdbd2cSJim Jagielski 		sal_Bool	readCurrentState();
496*b1cdbd2cSJim Jagielski 
497*b1cdbd2cSJim Jagielski 		String		implParseSmart( const String& _rPath );
498*b1cdbd2cSJim Jagielski 
499*b1cdbd2cSJim Jagielski 		sal_Bool	implReadFolder( const ::vos::ORef< TemplateContent >& _rxRoot );
500*b1cdbd2cSJim Jagielski 
501*b1cdbd2cSJim Jagielski 		static	String		getCacheFileName();
502*b1cdbd2cSJim Jagielski 		static	sal_Int32	getMagicNumber();
503*b1cdbd2cSJim Jagielski 		static	void		normalize( TemplateFolderContent& _rState );
504*b1cdbd2cSJim Jagielski 
505*b1cdbd2cSJim Jagielski 		// @return <TRUE/> if the states equal
506*b1cdbd2cSJim Jagielski 		static	sal_Bool	equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS );
507*b1cdbd2cSJim Jagielski 
508*b1cdbd2cSJim Jagielski         // late initialize m_xOfficeInstDirs
509*b1cdbd2cSJim Jagielski         uno::Reference< util::XOfficeInstallationDirectories > getOfficeInstDirs();
510*b1cdbd2cSJim Jagielski 	};
511*b1cdbd2cSJim Jagielski 
512*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
TemplateFolderCacheImpl(sal_Bool _bAutoStoreState)513*b1cdbd2cSJim Jagielski 	TemplateFolderCacheImpl::TemplateFolderCacheImpl( sal_Bool _bAutoStoreState )
514*b1cdbd2cSJim Jagielski 		:m_pCacheStream			( NULL )
515*b1cdbd2cSJim Jagielski 		,m_bNeedsUpdate			( sal_True )
516*b1cdbd2cSJim Jagielski 		,m_bKnowState			( sal_False )
517*b1cdbd2cSJim Jagielski 		,m_bValidCurrentState	( sal_False )
518*b1cdbd2cSJim Jagielski 		,m_bAutoStoreState		( _bAutoStoreState )
519*b1cdbd2cSJim Jagielski 	{
520*b1cdbd2cSJim Jagielski 	}
521*b1cdbd2cSJim Jagielski 
522*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
~TemplateFolderCacheImpl()523*b1cdbd2cSJim Jagielski 	TemplateFolderCacheImpl::~TemplateFolderCacheImpl( )
524*b1cdbd2cSJim Jagielski 	{
525*b1cdbd2cSJim Jagielski 		// store the current state if possible and required
526*b1cdbd2cSJim Jagielski 		if ( m_bValidCurrentState && m_bAutoStoreState )
527*b1cdbd2cSJim Jagielski 			storeState( sal_False );
528*b1cdbd2cSJim Jagielski 
529*b1cdbd2cSJim Jagielski 		closeCacheStream( );
530*b1cdbd2cSJim Jagielski 	}
531*b1cdbd2cSJim Jagielski 
532*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
getMagicNumber()533*b1cdbd2cSJim Jagielski 	sal_Int32 TemplateFolderCacheImpl::getMagicNumber()
534*b1cdbd2cSJim Jagielski 	{
535*b1cdbd2cSJim Jagielski 		sal_Int32 nMagic = 0;
536*b1cdbd2cSJim Jagielski 		( nMagic += (sal_Int8)'T' ) <<= 4;
537*b1cdbd2cSJim Jagielski 		( nMagic += (sal_Int8)'D' ) <<= 4;
538*b1cdbd2cSJim Jagielski 		( nMagic += (sal_Int8)'S' ) <<= 4;
539*b1cdbd2cSJim Jagielski 		( nMagic += (sal_Int8)'C' ) <<= 0;
540*b1cdbd2cSJim Jagielski 		return nMagic;
541*b1cdbd2cSJim Jagielski 	}
542*b1cdbd2cSJim Jagielski 
543*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
getCacheFileName()544*b1cdbd2cSJim Jagielski 	String TemplateFolderCacheImpl::getCacheFileName()
545*b1cdbd2cSJim Jagielski 	{
546*b1cdbd2cSJim Jagielski 		return String::CreateFromAscii( ".templdir.cache" );
547*b1cdbd2cSJim Jagielski 	}
548*b1cdbd2cSJim Jagielski 
549*b1cdbd2cSJim Jagielski 
550*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
normalize(TemplateFolderContent & _rState)551*b1cdbd2cSJim Jagielski 	void TemplateFolderCacheImpl::normalize( TemplateFolderContent& _rState )
552*b1cdbd2cSJim Jagielski 	{
553*b1cdbd2cSJim Jagielski 		SubContentSort()( _rState );
554*b1cdbd2cSJim Jagielski 	}
555*b1cdbd2cSJim Jagielski 
556*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
equalStates(const TemplateFolderContent & _rLHS,const TemplateFolderContent & _rRHS)557*b1cdbd2cSJim Jagielski 	sal_Bool TemplateFolderCacheImpl::equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS )
558*b1cdbd2cSJim Jagielski 	{
559*b1cdbd2cSJim Jagielski 		if ( _rLHS.size() != _rRHS.size() )
560*b1cdbd2cSJim Jagielski 			return sal_False;
561*b1cdbd2cSJim Jagielski 
562*b1cdbd2cSJim Jagielski 		// as both arrays are sorted (by definition - this is a precondition of this method)
563*b1cdbd2cSJim Jagielski 		// we can simply go from the front to the back and compare the single elements
564*b1cdbd2cSJim Jagielski 
565*b1cdbd2cSJim Jagielski 		::std::pair< ConstFolderIterator, ConstFolderIterator > aFirstDifferent = ::std::mismatch(
566*b1cdbd2cSJim Jagielski 			_rLHS.begin(),
567*b1cdbd2cSJim Jagielski 			_rLHS.end(),
568*b1cdbd2cSJim Jagielski 			_rRHS.begin(),
569*b1cdbd2cSJim Jagielski 			TemplateContentEqual()
570*b1cdbd2cSJim Jagielski 		);
571*b1cdbd2cSJim Jagielski 
572*b1cdbd2cSJim Jagielski 		return aFirstDifferent.first == _rLHS.end();
573*b1cdbd2cSJim Jagielski 	}
574*b1cdbd2cSJim Jagielski 
575*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
storeState(sal_Bool _bForceRetrieval)576*b1cdbd2cSJim Jagielski 	void TemplateFolderCacheImpl::storeState( sal_Bool _bForceRetrieval )
577*b1cdbd2cSJim Jagielski 	{
578*b1cdbd2cSJim Jagielski 		if ( !m_bValidCurrentState || _bForceRetrieval )
579*b1cdbd2cSJim Jagielski 			readCurrentState( );
580*b1cdbd2cSJim Jagielski 
581*b1cdbd2cSJim Jagielski 		if ( m_bValidCurrentState && openCacheStream( sal_False ) )
582*b1cdbd2cSJim Jagielski 		{
583*b1cdbd2cSJim Jagielski 			*m_pCacheStream	<< getMagicNumber();
584*b1cdbd2cSJim Jagielski 
585*b1cdbd2cSJim Jagielski 			// store the template root folders
586*b1cdbd2cSJim Jagielski 			// the size
587*b1cdbd2cSJim Jagielski 			*m_pCacheStream << (sal_Int32)m_aCurrentState.size();
588*b1cdbd2cSJim Jagielski 			// the complete URLs
589*b1cdbd2cSJim Jagielski 			::std::for_each(
590*b1cdbd2cSJim Jagielski 				m_aCurrentState.begin(),
591*b1cdbd2cSJim Jagielski 				m_aCurrentState.end(),
592*b1cdbd2cSJim Jagielski                 StoreContentURL( *m_pCacheStream, getOfficeInstDirs() )
593*b1cdbd2cSJim Jagielski 			);
594*b1cdbd2cSJim Jagielski 
595*b1cdbd2cSJim Jagielski 			// the contents
596*b1cdbd2cSJim Jagielski 			::std::for_each(
597*b1cdbd2cSJim Jagielski 				m_aCurrentState.begin(),
598*b1cdbd2cSJim Jagielski 				m_aCurrentState.end(),
599*b1cdbd2cSJim Jagielski 				StoreFolderContent( *m_pCacheStream, getOfficeInstDirs() )
600*b1cdbd2cSJim Jagielski 			);
601*b1cdbd2cSJim Jagielski 		}
602*b1cdbd2cSJim Jagielski 	}
603*b1cdbd2cSJim Jagielski 
604*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
implParseSmart(const String & _rPath)605*b1cdbd2cSJim Jagielski 	String TemplateFolderCacheImpl::implParseSmart( const String& _rPath )
606*b1cdbd2cSJim Jagielski 	{
607*b1cdbd2cSJim Jagielski 		INetURLObject aParser;
608*b1cdbd2cSJim Jagielski 		aParser.SetSmartProtocol( INET_PROT_FILE );
609*b1cdbd2cSJim Jagielski 		aParser.SetURL( _rPath, INetURLObject::WAS_ENCODED );
610*b1cdbd2cSJim Jagielski 		if ( INET_PROT_NOT_VALID == aParser.GetProtocol() )
611*b1cdbd2cSJim Jagielski 		{
612*b1cdbd2cSJim Jagielski 			String sURL;
613*b1cdbd2cSJim Jagielski 			LocalFileHelper::ConvertPhysicalNameToURL( _rPath, sURL );
614*b1cdbd2cSJim Jagielski 			aParser.SetURL( sURL, INetURLObject::WAS_ENCODED );
615*b1cdbd2cSJim Jagielski 		}
616*b1cdbd2cSJim Jagielski 		return aParser.GetMainURL( INetURLObject::DECODE_TO_IURI );
617*b1cdbd2cSJim Jagielski 	}
618*b1cdbd2cSJim Jagielski 
619*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
closeCacheStream()620*b1cdbd2cSJim Jagielski 	void TemplateFolderCacheImpl::closeCacheStream( )
621*b1cdbd2cSJim Jagielski 	{
622*b1cdbd2cSJim Jagielski 		DELETEZ( m_pCacheStream );
623*b1cdbd2cSJim Jagielski 	}
624*b1cdbd2cSJim Jagielski 
625*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
implReadFolder(const::vos::ORef<TemplateContent> & _rxRoot)626*b1cdbd2cSJim Jagielski 	sal_Bool TemplateFolderCacheImpl::implReadFolder( const ::vos::ORef< TemplateContent >& _rxRoot )
627*b1cdbd2cSJim Jagielski 	{
628*b1cdbd2cSJim Jagielski 		try
629*b1cdbd2cSJim Jagielski 		{
630*b1cdbd2cSJim Jagielski 			// create a content for the current folder root
631*b1cdbd2cSJim Jagielski 			Reference< XResultSet > xResultSet;
632*b1cdbd2cSJim Jagielski 			Sequence< ::rtl::OUString > aContentProperties( 4);
633*b1cdbd2cSJim Jagielski 			aContentProperties[0] = ::rtl::OUString::createFromAscii( "Title" );
634*b1cdbd2cSJim Jagielski 			aContentProperties[1] = ::rtl::OUString::createFromAscii( "DateModified" );
635*b1cdbd2cSJim Jagielski 			aContentProperties[2] = ::rtl::OUString::createFromAscii( "DateCreated" );
636*b1cdbd2cSJim Jagielski 			aContentProperties[3] = ::rtl::OUString::createFromAscii( "IsFolder" );
637*b1cdbd2cSJim Jagielski 
638*b1cdbd2cSJim Jagielski 			// get the set of sub contents in the folder
639*b1cdbd2cSJim Jagielski     		try
640*b1cdbd2cSJim Jagielski 			{
641*b1cdbd2cSJim Jagielski 				Reference< XDynamicResultSet > xDynResultSet;
642*b1cdbd2cSJim Jagielski 
643*b1cdbd2cSJim Jagielski 				::ucbhelper::Content aTemplateRoot( _rxRoot->getURL(), Reference< XCommandEnvironment >() );
644*b1cdbd2cSJim Jagielski 				xDynResultSet = aTemplateRoot.createDynamicCursor( aContentProperties, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS );
645*b1cdbd2cSJim Jagielski 				if ( xDynResultSet.is() )
646*b1cdbd2cSJim Jagielski 					xResultSet = xDynResultSet->getStaticResultSet();
647*b1cdbd2cSJim Jagielski 			}
648*b1cdbd2cSJim Jagielski 			catch( CommandAbortedException& )
649*b1cdbd2cSJim Jagielski 			{
650*b1cdbd2cSJim Jagielski 				DBG_ERRORFILE( "TemplateFolderCacheImpl::implReadFolder: caught a CommandAbortedException!" );
651*b1cdbd2cSJim Jagielski 				return sal_False;
652*b1cdbd2cSJim Jagielski 			}
653*b1cdbd2cSJim Jagielski 			catch( ::com::sun::star::uno::Exception& )
654*b1cdbd2cSJim Jagielski 			{
655*b1cdbd2cSJim Jagielski 			}
656*b1cdbd2cSJim Jagielski 
657*b1cdbd2cSJim Jagielski 			// collect the infos about the sub contents
658*b1cdbd2cSJim Jagielski 			if ( xResultSet.is() )
659*b1cdbd2cSJim Jagielski 			{
660*b1cdbd2cSJim Jagielski 				Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
661*b1cdbd2cSJim Jagielski 				Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
662*b1cdbd2cSJim Jagielski 
663*b1cdbd2cSJim Jagielski 				while ( xResultSet->next() )
664*b1cdbd2cSJim Jagielski 				{
665*b1cdbd2cSJim Jagielski 					INetURLObject aSubContentURL( xContentAccess->queryContentIdentifierString() );
666*b1cdbd2cSJim Jagielski 
667*b1cdbd2cSJim Jagielski 					// a new content instance
668*b1cdbd2cSJim Jagielski 					::vos::ORef< TemplateContent > xChild = new TemplateContent( aSubContentURL );
669*b1cdbd2cSJim Jagielski 
670*b1cdbd2cSJim Jagielski 					// the modified date
671*b1cdbd2cSJim Jagielski 					xChild->setModDate( xRow->getTimestamp( 2 ) );	// date modified
672*b1cdbd2cSJim Jagielski 					if ( xRow->wasNull() )
673*b1cdbd2cSJim Jagielski 						xChild->setModDate( xRow->getTimestamp( 3 ) );	// fallback: date created
674*b1cdbd2cSJim Jagielski 
675*b1cdbd2cSJim Jagielski 					// push back this content
676*b1cdbd2cSJim Jagielski 					_rxRoot->push_back( xChild );
677*b1cdbd2cSJim Jagielski 
678*b1cdbd2cSJim Jagielski 					// is it a folder?
679*b1cdbd2cSJim Jagielski 					if ( xRow->getBoolean( 4 ) && !xRow->wasNull() )
680*b1cdbd2cSJim Jagielski 					{	// yes -> step down
681*b1cdbd2cSJim Jagielski                                                 ConstFolderIterator aNextLevelRoot = _rxRoot->end();
682*b1cdbd2cSJim Jagielski 						--aNextLevelRoot;
683*b1cdbd2cSJim Jagielski 						implReadFolder( *aNextLevelRoot );
684*b1cdbd2cSJim Jagielski 					}
685*b1cdbd2cSJim Jagielski 				}
686*b1cdbd2cSJim Jagielski 			}
687*b1cdbd2cSJim Jagielski 		}
688*b1cdbd2cSJim Jagielski 		catch( const Exception& )
689*b1cdbd2cSJim Jagielski 		{
690*b1cdbd2cSJim Jagielski 			DBG_ERROR( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" );
691*b1cdbd2cSJim Jagielski 			return sal_False;
692*b1cdbd2cSJim Jagielski 		}
693*b1cdbd2cSJim Jagielski 		return sal_True;
694*b1cdbd2cSJim Jagielski 	}
695*b1cdbd2cSJim Jagielski 
696*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
readCurrentState()697*b1cdbd2cSJim Jagielski 	sal_Bool TemplateFolderCacheImpl::readCurrentState()
698*b1cdbd2cSJim Jagielski 	{
699*b1cdbd2cSJim Jagielski 		// reset
700*b1cdbd2cSJim Jagielski 		m_bValidCurrentState = sal_False;
701*b1cdbd2cSJim Jagielski         TemplateFolderContent aTemplateFolderContent;
702*b1cdbd2cSJim Jagielski 		m_aCurrentState.swap( aTemplateFolderContent );
703*b1cdbd2cSJim Jagielski 
704*b1cdbd2cSJim Jagielski 		// the template directories from the config
705*b1cdbd2cSJim Jagielski         const SvtPathOptions aPathOptions;
706*b1cdbd2cSJim Jagielski 	    String		aDirs = aPathOptions.GetTemplatePath();
707*b1cdbd2cSJim Jagielski 		sal_uInt16	nDirs = aDirs.GetTokenCount( ';' );
708*b1cdbd2cSJim Jagielski 
709*b1cdbd2cSJim Jagielski 		m_aCurrentState.reserve( nDirs );
710*b1cdbd2cSJim Jagielski 		// loop through all the root-level template folders
711*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 i=0; i<nDirs; ++i)
712*b1cdbd2cSJim Jagielski 		{
713*b1cdbd2cSJim Jagielski             String sTemplatePath( aDirs.GetToken( i, ';' ) );
714*b1cdbd2cSJim Jagielski             sTemplatePath = aPathOptions.ExpandMacros( sTemplatePath );
715*b1cdbd2cSJim Jagielski 			// create a new entry
716*b1cdbd2cSJim Jagielski 			m_aCurrentState.push_back( new TemplateContent( INetURLObject( sTemplatePath ) ) );
717*b1cdbd2cSJim Jagielski 			TemplateFolderContent::iterator aCurrentRoot = m_aCurrentState.end();
718*b1cdbd2cSJim Jagielski 			--aCurrentRoot;
719*b1cdbd2cSJim Jagielski 
720*b1cdbd2cSJim Jagielski 			if ( !implReadFolder( *aCurrentRoot ) )
721*b1cdbd2cSJim Jagielski 				return sal_False;
722*b1cdbd2cSJim Jagielski 		}
723*b1cdbd2cSJim Jagielski 
724*b1cdbd2cSJim Jagielski 		// normalize the array (which basically means "sort it")
725*b1cdbd2cSJim Jagielski 		normalize( m_aCurrentState );
726*b1cdbd2cSJim Jagielski 
727*b1cdbd2cSJim Jagielski 		m_bValidCurrentState = sal_True;
728*b1cdbd2cSJim Jagielski 		return m_bValidCurrentState;
729*b1cdbd2cSJim Jagielski 	}
730*b1cdbd2cSJim Jagielski 
731*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
readPreviousState()732*b1cdbd2cSJim Jagielski 	sal_Bool TemplateFolderCacheImpl::readPreviousState()
733*b1cdbd2cSJim Jagielski 	{
734*b1cdbd2cSJim Jagielski 		DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::readPreviousState: not to be called without stream!" );
735*b1cdbd2cSJim Jagielski 
736*b1cdbd2cSJim Jagielski 		// reset
737*b1cdbd2cSJim Jagielski         TemplateFolderContent aTemplateFolderContent;
738*b1cdbd2cSJim Jagielski 		m_aPreviousState.swap( aTemplateFolderContent );
739*b1cdbd2cSJim Jagielski 
740*b1cdbd2cSJim Jagielski 		// check the magic number
741*b1cdbd2cSJim Jagielski 		sal_Int32 nMagic = 0;
742*b1cdbd2cSJim Jagielski 		*m_pCacheStream >> nMagic;
743*b1cdbd2cSJim Jagielski 		DBG_ASSERT( getMagicNumber() == nMagic, "TemplateFolderCacheImpl::readPreviousState: invalid cache file!" );
744*b1cdbd2cSJim Jagielski 		if ( getMagicNumber() != nMagic )
745*b1cdbd2cSJim Jagielski 			return sal_False;
746*b1cdbd2cSJim Jagielski 
747*b1cdbd2cSJim Jagielski 		// the root directories
748*b1cdbd2cSJim Jagielski 		// their number
749*b1cdbd2cSJim Jagielski 		sal_Int32 nRootDirectories = 0;
750*b1cdbd2cSJim Jagielski 		*m_pCacheStream >> nRootDirectories;
751*b1cdbd2cSJim Jagielski 		// init empty TemplateContens with the URLs
752*b1cdbd2cSJim Jagielski 		m_aPreviousState.reserve( nRootDirectories );
753*b1cdbd2cSJim Jagielski 		while ( nRootDirectories-- )
754*b1cdbd2cSJim Jagielski 		{
755*b1cdbd2cSJim Jagielski 			String sURL;
756*b1cdbd2cSJim Jagielski 			m_pCacheStream->ReadByteString( sURL );
757*b1cdbd2cSJim Jagielski             // #116281# Keep office installtion relocatable. Never store
758*b1cdbd2cSJim Jagielski             // any direct references to office installation directory.
759*b1cdbd2cSJim Jagielski             sURL = getOfficeInstDirs()->makeAbsoluteURL( sURL );
760*b1cdbd2cSJim Jagielski 			m_aPreviousState.push_back(
761*b1cdbd2cSJim Jagielski 				new TemplateContent( INetURLObject(sURL) ) );
762*b1cdbd2cSJim Jagielski 		}
763*b1cdbd2cSJim Jagielski 
764*b1cdbd2cSJim Jagielski 		// read the contents of the root folders
765*b1cdbd2cSJim Jagielski 		::std::for_each(
766*b1cdbd2cSJim Jagielski 			m_aPreviousState.begin(),
767*b1cdbd2cSJim Jagielski 			m_aPreviousState.end(),
768*b1cdbd2cSJim Jagielski 			ReadFolderContent( *m_pCacheStream, getOfficeInstDirs() )
769*b1cdbd2cSJim Jagielski 		);
770*b1cdbd2cSJim Jagielski 
771*b1cdbd2cSJim Jagielski 		DBG_ASSERT( !m_pCacheStream->GetErrorCode(), "TemplateFolderCacheImpl::readPreviousState: unknown error during reading the state cache!" );
772*b1cdbd2cSJim Jagielski 
773*b1cdbd2cSJim Jagielski 		// normalize the array (which basically means "sort it")
774*b1cdbd2cSJim Jagielski 		normalize( m_aPreviousState );
775*b1cdbd2cSJim Jagielski 
776*b1cdbd2cSJim Jagielski 		return sal_True;
777*b1cdbd2cSJim Jagielski 	}
778*b1cdbd2cSJim Jagielski 
779*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
openCacheStream(sal_Bool _bForRead)780*b1cdbd2cSJim Jagielski 	sal_Bool TemplateFolderCacheImpl::openCacheStream( sal_Bool _bForRead )
781*b1cdbd2cSJim Jagielski 	{
782*b1cdbd2cSJim Jagielski 		// close any old stream instance
783*b1cdbd2cSJim Jagielski 		closeCacheStream( );
784*b1cdbd2cSJim Jagielski 
785*b1cdbd2cSJim Jagielski 		// get the storage directory
786*b1cdbd2cSJim Jagielski 		String sStorageURL = implParseSmart( SvtPathOptions().GetStoragePath() );
787*b1cdbd2cSJim Jagielski 		INetURLObject aStorageURL( sStorageURL );
788*b1cdbd2cSJim Jagielski 		if ( INET_PROT_NOT_VALID == aStorageURL.GetProtocol() )
789*b1cdbd2cSJim Jagielski 		{
790*b1cdbd2cSJim Jagielski 			DBG_ERROR( "TemplateFolderCacheImpl::openCacheStream: invalid storage path!" );
791*b1cdbd2cSJim Jagielski 			return sal_False;
792*b1cdbd2cSJim Jagielski 		}
793*b1cdbd2cSJim Jagielski 
794*b1cdbd2cSJim Jagielski 		// append our name
795*b1cdbd2cSJim Jagielski 		aStorageURL.Append( getCacheFileName() );
796*b1cdbd2cSJim Jagielski 
797*b1cdbd2cSJim Jagielski 		// open the stream
798*b1cdbd2cSJim Jagielski 		m_pCacheStream = UcbStreamHelper::CreateStream( aStorageURL.GetMainURL( INetURLObject::DECODE_TO_IURI ),
799*b1cdbd2cSJim Jagielski 			_bForRead ?	STREAM_READ | STREAM_NOCREATE : STREAM_WRITE | STREAM_TRUNC );
800*b1cdbd2cSJim Jagielski 		DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::openCacheStream: could not open/create the cache stream!" );
801*b1cdbd2cSJim Jagielski 		if ( m_pCacheStream && m_pCacheStream->GetErrorCode() )
802*b1cdbd2cSJim Jagielski 		{
803*b1cdbd2cSJim Jagielski 			DELETEZ( m_pCacheStream );
804*b1cdbd2cSJim Jagielski 		}
805*b1cdbd2cSJim Jagielski 
806*b1cdbd2cSJim Jagielski 		if ( m_pCacheStream )
807*b1cdbd2cSJim Jagielski 			m_pCacheStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
808*b1cdbd2cSJim Jagielski 
809*b1cdbd2cSJim Jagielski 		return NULL != m_pCacheStream;
810*b1cdbd2cSJim Jagielski 	}
811*b1cdbd2cSJim Jagielski 
812*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
needsUpdate(sal_Bool _bForceCheck)813*b1cdbd2cSJim Jagielski 	sal_Bool TemplateFolderCacheImpl::needsUpdate( sal_Bool _bForceCheck )
814*b1cdbd2cSJim Jagielski 	{
815*b1cdbd2cSJim Jagielski 		if ( m_bKnowState && !_bForceCheck )
816*b1cdbd2cSJim Jagielski 			return m_bNeedsUpdate;
817*b1cdbd2cSJim Jagielski 
818*b1cdbd2cSJim Jagielski 		m_bNeedsUpdate = sal_True;
819*b1cdbd2cSJim Jagielski 		m_bKnowState = sal_True;
820*b1cdbd2cSJim Jagielski 
821*b1cdbd2cSJim Jagielski 		if ( readCurrentState() )
822*b1cdbd2cSJim Jagielski 		{
823*b1cdbd2cSJim Jagielski 			// open the stream which contains the cached state of the directories
824*b1cdbd2cSJim Jagielski 			if ( openCacheStream( sal_True ) )
825*b1cdbd2cSJim Jagielski 			{	// opening the stream succeeded
826*b1cdbd2cSJim Jagielski 				if ( readPreviousState() )
827*b1cdbd2cSJim Jagielski 				{
828*b1cdbd2cSJim Jagielski 					m_bNeedsUpdate = !equalStates( m_aPreviousState, m_aCurrentState );
829*b1cdbd2cSJim Jagielski 				}
830*b1cdbd2cSJim Jagielski 				else
831*b1cdbd2cSJim Jagielski 				{
832*b1cdbd2cSJim Jagielski 					closeCacheStream();
833*b1cdbd2cSJim Jagielski 				}
834*b1cdbd2cSJim Jagielski 			}
835*b1cdbd2cSJim Jagielski 		}
836*b1cdbd2cSJim Jagielski 		return m_bNeedsUpdate;
837*b1cdbd2cSJim Jagielski 	}
838*b1cdbd2cSJim Jagielski 
839*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
initTemplDirs(::std::vector<String> &)840*b1cdbd2cSJim Jagielski 	void TemplateFolderCacheImpl::initTemplDirs( ::std::vector< String >& )
841*b1cdbd2cSJim Jagielski 	{
842*b1cdbd2cSJim Jagielski 	}
843*b1cdbd2cSJim Jagielski 
844*b1cdbd2cSJim Jagielski     //---------------------------------------------------------------------
845*b1cdbd2cSJim Jagielski     uno::Reference< util::XOfficeInstallationDirectories >
getOfficeInstDirs()846*b1cdbd2cSJim Jagielski     TemplateFolderCacheImpl::getOfficeInstDirs()
847*b1cdbd2cSJim Jagielski     {
848*b1cdbd2cSJim Jagielski         if ( !m_xOfficeInstDirs.is() )
849*b1cdbd2cSJim Jagielski         {
850*b1cdbd2cSJim Jagielski             osl::MutexGuard aGuard( m_aMutex );
851*b1cdbd2cSJim Jagielski             if ( !m_xOfficeInstDirs.is() )
852*b1cdbd2cSJim Jagielski             {
853*b1cdbd2cSJim Jagielski                 // @@@ This is bad!
854*b1cdbd2cSJim Jagielski                 uno::Reference< lang::XMultiServiceFactory > xSMgr
855*b1cdbd2cSJim Jagielski                     = comphelper::getProcessServiceFactory();
856*b1cdbd2cSJim Jagielski                 OSL_ENSURE( xSMgr.is(), "No service manager!" );
857*b1cdbd2cSJim Jagielski 
858*b1cdbd2cSJim Jagielski                 uno::Reference< beans::XPropertySet > xPropSet(
859*b1cdbd2cSJim Jagielski                     xSMgr, uno::UNO_QUERY );
860*b1cdbd2cSJim Jagielski                 if ( xPropSet.is() )
861*b1cdbd2cSJim Jagielski                 {
862*b1cdbd2cSJim Jagielski                     uno::Reference< uno::XComponentContext > xCtx;
863*b1cdbd2cSJim Jagielski                     xPropSet->getPropertyValue(
864*b1cdbd2cSJim Jagielski                         rtl::OUString(
865*b1cdbd2cSJim Jagielski                             RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
866*b1cdbd2cSJim Jagielski                     >>= xCtx;
867*b1cdbd2cSJim Jagielski 
868*b1cdbd2cSJim Jagielski                     OSL_ENSURE( xCtx.is(),
869*b1cdbd2cSJim Jagielski                                 "Unable to obtain component context from service manager!" );
870*b1cdbd2cSJim Jagielski 
871*b1cdbd2cSJim Jagielski                     if ( xCtx.is() )
872*b1cdbd2cSJim Jagielski                     {
873*b1cdbd2cSJim Jagielski                         xCtx->getValueByName(
874*b1cdbd2cSJim Jagielski                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
875*b1cdbd2cSJim Jagielski                                 "/singletons/com.sun.star.util.theOfficeInstallationDirectories" ) ) )
876*b1cdbd2cSJim Jagielski                         >>= m_xOfficeInstDirs;
877*b1cdbd2cSJim Jagielski                     }
878*b1cdbd2cSJim Jagielski 
879*b1cdbd2cSJim Jagielski                     OSL_ENSURE( m_xOfficeInstDirs.is(),
880*b1cdbd2cSJim Jagielski                                 "Unable to obtain office directories singleton!" );
881*b1cdbd2cSJim Jagielski 
882*b1cdbd2cSJim Jagielski                 }
883*b1cdbd2cSJim Jagielski             }
884*b1cdbd2cSJim Jagielski         }
885*b1cdbd2cSJim Jagielski         return m_xOfficeInstDirs;
886*b1cdbd2cSJim Jagielski     }
887*b1cdbd2cSJim Jagielski 
888*b1cdbd2cSJim Jagielski 	//=====================================================================
889*b1cdbd2cSJim Jagielski 	//= TemplateFolderCache
890*b1cdbd2cSJim Jagielski 	//=====================================================================
891*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
TemplateFolderCache(sal_Bool _bAutoStoreState)892*b1cdbd2cSJim Jagielski 	TemplateFolderCache::TemplateFolderCache( sal_Bool _bAutoStoreState )
893*b1cdbd2cSJim Jagielski 		:m_pImpl( new TemplateFolderCacheImpl( _bAutoStoreState ) )
894*b1cdbd2cSJim Jagielski 	{
895*b1cdbd2cSJim Jagielski 	}
896*b1cdbd2cSJim Jagielski 
897*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
~TemplateFolderCache()898*b1cdbd2cSJim Jagielski 	TemplateFolderCache::~TemplateFolderCache( )
899*b1cdbd2cSJim Jagielski 	{
900*b1cdbd2cSJim Jagielski 		DELETEZ( m_pImpl );
901*b1cdbd2cSJim Jagielski 	}
902*b1cdbd2cSJim Jagielski 
903*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
needsUpdate(sal_Bool _bForceCheck)904*b1cdbd2cSJim Jagielski 	sal_Bool TemplateFolderCache::needsUpdate( sal_Bool _bForceCheck )
905*b1cdbd2cSJim Jagielski 	{
906*b1cdbd2cSJim Jagielski 		return m_pImpl->needsUpdate( _bForceCheck );
907*b1cdbd2cSJim Jagielski 	}
908*b1cdbd2cSJim Jagielski 
909*b1cdbd2cSJim Jagielski 	//---------------------------------------------------------------------
storeState(sal_Bool _bForceRetrieval)910*b1cdbd2cSJim Jagielski 	void TemplateFolderCache::storeState( sal_Bool _bForceRetrieval )
911*b1cdbd2cSJim Jagielski 	{
912*b1cdbd2cSJim Jagielski 		m_pImpl->storeState( _bForceRetrieval );
913*b1cdbd2cSJim Jagielski 	}
914*b1cdbd2cSJim Jagielski 
915*b1cdbd2cSJim Jagielski //.........................................................................
916*b1cdbd2cSJim Jagielski }	// namespace sfx2
917*b1cdbd2cSJim Jagielski //.........................................................................
918*b1cdbd2cSJim Jagielski 
919