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