xref: /trunk/main/svtools/source/misc/templatefoldercache.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
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
10cdf0e10cSrcweir  *
11*5900e8ecSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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:
131cdf0e10cSrcweir         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
146cdf0e10cSrcweir         inline String                   getName( ) const                            { return m_sLocalName; }
147cdf0e10cSrcweir         inline String                   getURL( ) const                             { return m_aURL.GetMainURL( INetURLObject::DECODE_TO_IURI ); }
148cdf0e10cSrcweir         inline void                     setModDate( const util::DateTime& _rDate )  { m_aLastModified = _rDate; }
149cdf0e10cSrcweir         inline const util::DateTime&    getModDate( ) const                         { return m_aLastModified; }
150cdf0e10cSrcweir 
151cdf0e10cSrcweir         inline TemplateFolderContent&   getSubContents()            { return m_aSubContents; }
152cdf0e10cSrcweir         inline const TemplateFolderContent& getSubContents() const  { return m_aSubContents; }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir                 inline ConstFolderIterator              begin() const   { return m_aSubContents.begin(); }
155cdf0e10cSrcweir                 inline ConstFolderIterator              end() const             { return m_aSubContents.end(); }
156cdf0e10cSrcweir         inline TemplateFolderContent::size_type
157cdf0e10cSrcweir                                         size() const    { return m_aSubContents.size(); }
158cdf0e10cSrcweir 
159cdf0e10cSrcweir         inline void                     push_back( const ::vos::ORef< TemplateContent >& _rxNewElement )
160cdf0e10cSrcweir                                                         { m_aSubContents.push_back( _rxNewElement ); }
161cdf0e10cSrcweir     };
162cdf0e10cSrcweir 
163cdf0e10cSrcweir     //---------------------------------------------------------------------
164cdf0e10cSrcweir     DBG_NAME( TemplateContent )
165cdf0e10cSrcweir 
166cdf0e10cSrcweir     //---------------------------------------------------------------------
167cdf0e10cSrcweir     TemplateContent::TemplateContent()
168cdf0e10cSrcweir     {
169cdf0e10cSrcweir         DBG_CTOR( TemplateContent, NULL );
170cdf0e10cSrcweir         implResetDate();
171cdf0e10cSrcweir     }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     {
210cdf0e10cSrcweir         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     {
222cdf0e10cSrcweir         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 
239cdf0e10cSrcweir         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         //.................................................................
257cdf0e10cSrcweir         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;
298cdf0e10cSrcweir         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     {
307cdf0e10cSrcweir         StoreString( SvStream& _rStorage ) : StorageHelper( _rStorage ) { }
308cdf0e10cSrcweir 
309cdf0e10cSrcweir         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     {
321cdf0e10cSrcweir         StoreLocalContentName( SvStream& _rStorage ) : StoreString( _rStorage ) { }
322cdf0e10cSrcweir 
323cdf0e10cSrcweir         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 
339cdf0e10cSrcweir         StoreContentURL( SvStream& _rStorage,
340cdf0e10cSrcweir                          const uno::Reference<
341cdf0e10cSrcweir                             util::XOfficeInstallationDirectories > &
342cdf0e10cSrcweir                                 xOfficeInstDirs )
343cdf0e10cSrcweir         : StoreString( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
344cdf0e10cSrcweir 
345cdf0e10cSrcweir         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:
365cdf0e10cSrcweir         StoreFolderContent( SvStream& _rStorage,
366cdf0e10cSrcweir                          const uno::Reference<
367cdf0e10cSrcweir                             util::XOfficeInstallationDirectories > &
368cdf0e10cSrcweir                                 xOfficeInstDirs )
369cdf0e10cSrcweir         : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
370cdf0e10cSrcweir 
371cdf0e10cSrcweir         //.................................................................
372cdf0e10cSrcweir         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         //.................................................................
395cdf0e10cSrcweir         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 
412cdf0e10cSrcweir         ReadFolderContent( SvStream& _rStorage,
413cdf0e10cSrcweir                          const uno::Reference<
414cdf0e10cSrcweir                             util::XOfficeInstallationDirectories > &
415cdf0e10cSrcweir                                 xOfficeInstDirs )
416cdf0e10cSrcweir         : StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
417cdf0e10cSrcweir 
418cdf0e10cSrcweir         //.................................................................
419cdf0e10cSrcweir         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         //.................................................................
452cdf0e10cSrcweir         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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
544cdf0e10cSrcweir     String TemplateFolderCacheImpl::getCacheFileName()
545cdf0e10cSrcweir     {
546cdf0e10cSrcweir         return String::CreateFromAscii( ".templdir.cache" );
547cdf0e10cSrcweir     }
548cdf0e10cSrcweir 
549cdf0e10cSrcweir 
550cdf0e10cSrcweir     //---------------------------------------------------------------------
551cdf0e10cSrcweir     void TemplateFolderCacheImpl::normalize( TemplateFolderContent& _rState )
552cdf0e10cSrcweir     {
553cdf0e10cSrcweir         SubContentSort()( _rState );
554cdf0e10cSrcweir     }
555cdf0e10cSrcweir 
556cdf0e10cSrcweir     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
620cdf0e10cSrcweir     void TemplateFolderCacheImpl::closeCacheStream( )
621cdf0e10cSrcweir     {
622cdf0e10cSrcweir         DELETEZ( m_pCacheStream );
623cdf0e10cSrcweir     }
624cdf0e10cSrcweir 
625cdf0e10cSrcweir     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
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     //---------------------------------------------------------------------
840cdf0e10cSrcweir     void TemplateFolderCacheImpl::initTemplDirs( ::std::vector< String >& )
841cdf0e10cSrcweir     {
842cdf0e10cSrcweir     }
843cdf0e10cSrcweir 
844cdf0e10cSrcweir     //---------------------------------------------------------------------
845cdf0e10cSrcweir     uno::Reference< util::XOfficeInstallationDirectories >
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     //---------------------------------------------------------------------
892cdf0e10cSrcweir     TemplateFolderCache::TemplateFolderCache( sal_Bool _bAutoStoreState )
893cdf0e10cSrcweir         :m_pImpl( new TemplateFolderCacheImpl( _bAutoStoreState ) )
894cdf0e10cSrcweir     {
895cdf0e10cSrcweir     }
896cdf0e10cSrcweir 
897cdf0e10cSrcweir     //---------------------------------------------------------------------
898cdf0e10cSrcweir     TemplateFolderCache::~TemplateFolderCache( )
899cdf0e10cSrcweir     {
900cdf0e10cSrcweir         DELETEZ( m_pImpl );
901cdf0e10cSrcweir     }
902cdf0e10cSrcweir 
903cdf0e10cSrcweir     //---------------------------------------------------------------------
904cdf0e10cSrcweir     sal_Bool TemplateFolderCache::needsUpdate( sal_Bool _bForceCheck )
905cdf0e10cSrcweir     {
906cdf0e10cSrcweir         return m_pImpl->needsUpdate( _bForceCheck );
907cdf0e10cSrcweir     }
908cdf0e10cSrcweir 
909cdf0e10cSrcweir     //---------------------------------------------------------------------
910cdf0e10cSrcweir     void TemplateFolderCache::storeState( sal_Bool _bForceRetrieval )
911cdf0e10cSrcweir     {
912cdf0e10cSrcweir         m_pImpl->storeState( _bForceRetrieval );
913cdf0e10cSrcweir     }
914cdf0e10cSrcweir 
915cdf0e10cSrcweir //.........................................................................
916cdf0e10cSrcweir }   // namespace sfx2
917cdf0e10cSrcweir //.........................................................................
918cdf0e10cSrcweir 
919