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