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