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