9ac86f484b
* As UCB is only ever initialized with "Local"/"Office", remove this configuration vector completely. The "create" ctor creates an instance internally initialized with those "Local"/"Office" keys. Special (test) code can still instantiate an uninitialized one via plain createInstance. And for backwards compatilibity process startup still ensures to create an initialized instance early, in case there is still code out there (in extensions) that later calls plain createInstance and expects to get the already-initialized (single) instance. * XInitialization is an "implementation detail" of the UniversalContentBroker service, do not expose in XUniversalContentBroker. * ucbhelper/configurationkeys.hxx is no longer needed and is removed. * ucbhelper/contentbroker.hxx is an empty wrapper and is removed; however, that requires ucbhelper::Content constructors to take explicit XComponentContext arguments now. * The only remaining code in ucbhelper/source/client/contentbroker.cxx is Android-only InitUCBHelper. Is that relevant still? Change-Id: I3f7bddd0456bffbcd13590c66d9011915c760f28
906 lines
36 KiB
C++
906 lines
36 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include <svtools/templatefoldercache.hxx>
|
|
#include <unotools/ucbstreamhelper.hxx>
|
|
#include <unotools/localfilehelper.hxx>
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#include <com/sun/star/sdbc/XResultSet.hpp>
|
|
#include <com/sun/star/ucb/XDynamicResultSet.hpp>
|
|
#include <com/sun/star/sdbc/XRow.hpp>
|
|
#include <com/sun/star/ucb/XContentAccess.hpp>
|
|
#include <com/sun/star/uno/XComponentContext.hpp>
|
|
#include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
|
|
#include <ucbhelper/content.hxx>
|
|
#include <rtl/ref.hxx>
|
|
#include <salhelper/simplereferenceobject.hxx>
|
|
#include <tools/urlobj.hxx>
|
|
#include <tools/debug.hxx>
|
|
#include <unotools/pathoptions.hxx>
|
|
|
|
#include "comphelper/processfactory.hxx"
|
|
|
|
#include <vector>
|
|
#include <list>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
|
|
//.........................................................................
|
|
namespace svt
|
|
{
|
|
//.........................................................................
|
|
|
|
using namespace ::utl;
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::sdbc;
|
|
using namespace ::com::sun::star::ucb;
|
|
using namespace ::com::sun::star::uno;
|
|
|
|
//=====================================================================
|
|
//= helpers
|
|
//=====================================================================
|
|
//---------------------------------------------------------------------
|
|
SvStream& operator << ( SvStream& _rStorage, const util::DateTime& _rDate )
|
|
{
|
|
_rStorage << _rDate.HundredthSeconds;
|
|
_rStorage << _rDate.Seconds;
|
|
_rStorage << _rDate.Minutes;
|
|
_rStorage << _rDate.Hours;
|
|
_rStorage << _rDate.Day;
|
|
_rStorage << _rDate.Month;
|
|
_rStorage << _rDate.Year;
|
|
|
|
return _rStorage;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
SvStream& operator >> ( SvStream& _rStorage, util::DateTime& _rDate )
|
|
{
|
|
_rStorage >> _rDate.HundredthSeconds;
|
|
_rStorage >> _rDate.Seconds;
|
|
_rStorage >> _rDate.Minutes;
|
|
_rStorage >> _rDate.Hours;
|
|
_rStorage >> _rDate.Day;
|
|
_rStorage >> _rDate.Month;
|
|
_rStorage >> _rDate.Year;
|
|
|
|
return _rStorage;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool operator == ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
|
|
{
|
|
return _rLHS.HundredthSeconds == _rRHS.HundredthSeconds
|
|
&& _rLHS.Seconds == _rRHS.Seconds
|
|
&& _rLHS.Minutes == _rRHS.Minutes
|
|
&& _rLHS.Hours == _rRHS.Hours
|
|
&& _rLHS.Day == _rRHS.Day
|
|
&& _rLHS.Month == _rRHS.Month
|
|
&& _rLHS.Year == _rRHS.Year;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool operator != ( const util::DateTime& _rLHS, const util::DateTime& _rRHS )
|
|
{
|
|
return !( _rLHS == _rRHS );
|
|
}
|
|
|
|
//=====================================================================
|
|
//= TemplateContent
|
|
//=====================================================================
|
|
struct TemplateContent;
|
|
typedef ::std::vector< ::rtl::Reference< TemplateContent > > TemplateFolderContent;
|
|
typedef TemplateFolderContent::const_iterator ConstFolderIterator;
|
|
typedef TemplateFolderContent::iterator FolderIterator;
|
|
|
|
/** a struct describing one content in one of the template dirs (or at least it's relevant aspects)
|
|
*/
|
|
struct TemplateContent : public ::salhelper::SimpleReferenceObject
|
|
{
|
|
public:
|
|
|
|
private:
|
|
INetURLObject m_aURL;
|
|
String m_sLocalName; // redundant - last segment of m_aURL
|
|
util::DateTime m_aLastModified; // date of last modification as reported by UCP
|
|
TemplateFolderContent m_aSubContents; // sorted (by name) list of the children
|
|
|
|
private:
|
|
inline void implResetDate( )
|
|
{
|
|
m_aLastModified.HundredthSeconds = m_aLastModified.Seconds = m_aLastModified.Minutes = m_aLastModified.Hours = 0;
|
|
m_aLastModified.Day = m_aLastModified.Month = m_aLastModified.Year = 0;
|
|
}
|
|
|
|
private:
|
|
~TemplateContent();
|
|
|
|
public:
|
|
TemplateContent( const INetURLObject& _rURL );
|
|
|
|
// attribute access
|
|
inline String getName( ) const { return m_sLocalName; }
|
|
inline String getURL( ) const { return m_aURL.GetMainURL( INetURLObject::DECODE_TO_IURI ); }
|
|
inline void setModDate( const util::DateTime& _rDate ) { m_aLastModified = _rDate; }
|
|
inline const util::DateTime& getModDate( ) const { return m_aLastModified; }
|
|
|
|
inline TemplateFolderContent& getSubContents() { return m_aSubContents; }
|
|
inline const TemplateFolderContent& getSubContents() const { return m_aSubContents; }
|
|
|
|
inline ConstFolderIterator begin() const { return m_aSubContents.begin(); }
|
|
inline ConstFolderIterator end() const { return m_aSubContents.end(); }
|
|
inline TemplateFolderContent::size_type
|
|
size() const { return m_aSubContents.size(); }
|
|
|
|
inline void push_back( const ::rtl::Reference< TemplateContent >& _rxNewElement )
|
|
{ m_aSubContents.push_back( _rxNewElement ); }
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
DBG_NAME( TemplateContent )
|
|
|
|
//---------------------------------------------------------------------
|
|
TemplateContent::TemplateContent( const INetURLObject& _rURL )
|
|
:m_aURL( _rURL )
|
|
{
|
|
DBG_CTOR( TemplateContent, NULL );
|
|
DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" );
|
|
m_sLocalName = m_aURL.getName();
|
|
implResetDate();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
TemplateContent::~TemplateContent()
|
|
{
|
|
DBG_DTOR( TemplateContent, NULL );
|
|
}
|
|
|
|
//=====================================================================
|
|
//= stl helpers
|
|
//=====================================================================
|
|
//---------------------------------------------------------------------
|
|
/// compares two TemplateContent by URL
|
|
struct TemplateContentURLLess
|
|
:public ::std::binary_function < ::rtl::Reference< TemplateContent >
|
|
, ::rtl::Reference< TemplateContent >
|
|
, bool
|
|
>
|
|
{
|
|
bool operator() ( const ::rtl::Reference< TemplateContent >& _rxLHS, const ::rtl::Reference< TemplateContent >& _rxRHS ) const
|
|
{
|
|
return _rxLHS->getURL() < _rxRHS->getURL()
|
|
? true
|
|
: false;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
/// sorts the sib contents of a TemplateFolderContent
|
|
struct SubContentSort : public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
|
|
{
|
|
void operator() ( TemplateFolderContent& _rFolder ) const
|
|
{
|
|
// sort the directory by name
|
|
::std::sort(
|
|
_rFolder.begin(),
|
|
_rFolder.end(),
|
|
TemplateContentURLLess()
|
|
);
|
|
|
|
// sort the sub directories by name
|
|
::std::for_each(
|
|
_rFolder.begin(),
|
|
_rFolder.end(),
|
|
*this
|
|
);
|
|
}
|
|
|
|
void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
|
|
{
|
|
if ( _rxContent.is() && _rxContent->size() )
|
|
{
|
|
operator()( _rxContent->getSubContents() );
|
|
}
|
|
}
|
|
};
|
|
//---------------------------------------------------------------------
|
|
/** does a deep compare of two template contents
|
|
*/
|
|
struct TemplateContentEqual
|
|
:public ::std::binary_function < ::rtl::Reference< TemplateContent >
|
|
, ::rtl::Reference< TemplateContent >
|
|
, bool
|
|
>
|
|
{
|
|
//.................................................................
|
|
bool operator() (const ::rtl::Reference< TemplateContent >& _rLHS, const ::rtl::Reference< TemplateContent >& _rRHS )
|
|
{
|
|
if ( !_rLHS.is() || !_rRHS.is() )
|
|
{
|
|
OSL_FAIL( "TemplateContentEqual::operator(): invalid contents!" );
|
|
return true;
|
|
// this is not strictly true, in case only one is invalid - but this is a heavy error anyway
|
|
}
|
|
|
|
if ( _rLHS->getURL() != _rRHS->getURL() )
|
|
return false;
|
|
|
|
if ( _rLHS->getModDate() != _rRHS->getModDate() )
|
|
return false;
|
|
|
|
if ( _rLHS->getSubContents().size() != _rRHS->getSubContents().size() )
|
|
return false;
|
|
|
|
if ( _rLHS->getSubContents().size() )
|
|
{ // there are children
|
|
// -> compare them
|
|
::std::pair< FolderIterator, FolderIterator > aFirstDifferent = ::std::mismatch(
|
|
_rLHS->getSubContents().begin(),
|
|
_rLHS->getSubContents().end(),
|
|
_rRHS->getSubContents().begin(),
|
|
*this
|
|
);
|
|
if ( aFirstDifferent.first != _rLHS->getSubContents().end() )
|
|
return false;// the sub contents differ
|
|
}
|
|
|
|
return true;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
/// base class for functors which act an an SvStream
|
|
struct StorageHelper
|
|
{
|
|
protected:
|
|
SvStream& m_rStorage;
|
|
StorageHelper( SvStream& _rStorage ) : m_rStorage( _rStorage ) { }
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
/// functor which allows storing a string
|
|
struct StoreString
|
|
:public ::std::unary_function< String, void >
|
|
,public StorageHelper
|
|
{
|
|
StoreString( SvStream& _rStorage ) : StorageHelper( _rStorage ) { }
|
|
|
|
void operator() ( const String& _rString ) const
|
|
{
|
|
m_rStorage.WriteUniOrByteString( _rString, m_rStorage.GetStreamCharSet() );
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
/// functor which stores the local name of a TemplateContent
|
|
struct StoreLocalContentName
|
|
:public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
|
|
,public StoreString
|
|
{
|
|
StoreLocalContentName( SvStream& _rStorage ) : StoreString( _rStorage ) { }
|
|
|
|
void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
|
|
{
|
|
SAL_WARN( "svtools.misc", "This method must not be used, the whole URL must be stored!" );
|
|
|
|
// use the base class operator with the local name of the content
|
|
StoreString::operator() ( _rxContent->getName() );
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
struct StoreContentURL
|
|
:public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
|
|
,public StoreString
|
|
{
|
|
uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
|
|
|
|
StoreContentURL( SvStream& _rStorage,
|
|
const uno::Reference<
|
|
util::XOfficeInstallationDirectories > &
|
|
xOfficeInstDirs )
|
|
: StoreString( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
|
|
|
|
void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
|
|
{
|
|
// use the base class operator with the local name of the content
|
|
String sURL = _rxContent->getURL();
|
|
// #116281# Keep office installtion relocatable. Never store
|
|
// any direct references to office installation directory.
|
|
sURL = m_xOfficeInstDirs->makeRelocatableURL( sURL );
|
|
StoreString::operator() ( sURL );
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
/// functor which stores the complete content of a TemplateContent
|
|
struct StoreFolderContent
|
|
:public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
|
|
,public StorageHelper
|
|
{
|
|
uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
|
|
|
|
public:
|
|
StoreFolderContent( SvStream& _rStorage,
|
|
const uno::Reference<
|
|
util::XOfficeInstallationDirectories > &
|
|
xOfficeInstDirs )
|
|
: StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
|
|
|
|
//.................................................................
|
|
void operator() ( const TemplateContent& _rContent ) const
|
|
{
|
|
// store the info about this content
|
|
m_rStorage << _rContent.getModDate();
|
|
|
|
// store the info about the children
|
|
// the number
|
|
m_rStorage << (sal_Int32)_rContent.size();
|
|
// their URLs ( the local name is not enough, since URL might be not a hierarchical one, "expand:" for example )
|
|
::std::for_each(
|
|
_rContent.getSubContents().begin(),
|
|
_rContent.getSubContents().end(),
|
|
StoreContentURL( m_rStorage, m_xOfficeInstDirs )
|
|
);
|
|
// their content
|
|
::std::for_each(
|
|
_rContent.getSubContents().begin(),
|
|
_rContent.getSubContents().end(),
|
|
*this
|
|
);
|
|
}
|
|
|
|
//.................................................................
|
|
void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
|
|
{
|
|
if ( _rxContent.is() )
|
|
{
|
|
operator()( *_rxContent );
|
|
}
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
/// functor which reads a complete TemplateContent instance
|
|
struct ReadFolderContent
|
|
:public ::std::unary_function< ::rtl::Reference< TemplateContent >, void >
|
|
,public StorageHelper
|
|
{
|
|
uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
|
|
|
|
ReadFolderContent( SvStream& _rStorage,
|
|
const uno::Reference<
|
|
util::XOfficeInstallationDirectories > &
|
|
xOfficeInstDirs )
|
|
: StorageHelper( _rStorage ), m_xOfficeInstDirs( xOfficeInstDirs ) { }
|
|
|
|
//.................................................................
|
|
void operator() ( TemplateContent& _rContent ) const
|
|
{
|
|
// store the info about this content
|
|
util::DateTime aModDate;
|
|
m_rStorage >> aModDate;
|
|
_rContent.setModDate( aModDate );
|
|
|
|
// store the info about the children
|
|
// the number
|
|
sal_Int32 nChildren = 0;
|
|
m_rStorage >> nChildren;
|
|
TemplateFolderContent& rChildren = _rContent.getSubContents();
|
|
rChildren.resize( 0 );
|
|
rChildren.reserve( nChildren );
|
|
// initialize them with their (local) names
|
|
while ( nChildren-- )
|
|
{
|
|
String sURL = m_rStorage.ReadUniOrByteString(m_rStorage.GetStreamCharSet());
|
|
sURL = m_xOfficeInstDirs->makeAbsoluteURL( sURL );
|
|
INetURLObject aChildURL( sURL );
|
|
rChildren.push_back( new TemplateContent( aChildURL ) );
|
|
}
|
|
|
|
// their content
|
|
::std::for_each(
|
|
_rContent.getSubContents().begin(),
|
|
_rContent.getSubContents().end(),
|
|
*this
|
|
);
|
|
}
|
|
|
|
//.................................................................
|
|
void operator() ( const ::rtl::Reference< TemplateContent >& _rxContent ) const
|
|
{
|
|
if ( _rxContent.is() )
|
|
{
|
|
operator()( *_rxContent );
|
|
}
|
|
}
|
|
};
|
|
|
|
//=====================================================================
|
|
//= TemplateFolderCacheImpl
|
|
//=====================================================================
|
|
class TemplateFolderCacheImpl
|
|
{
|
|
private:
|
|
TemplateFolderContent m_aPreviousState; // the current state of the template dirs (as found on the HD)
|
|
TemplateFolderContent m_aCurrentState; // the previous state of the template dirs (as found in the cache file)
|
|
|
|
osl::Mutex m_aMutex;
|
|
// will be lazy inited; never access directly; use getOfficeInstDirs().
|
|
uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs;
|
|
|
|
SvStream* m_pCacheStream;
|
|
sal_Bool m_bNeedsUpdate : 1;
|
|
sal_Bool m_bKnowState : 1;
|
|
sal_Bool m_bValidCurrentState : 1;
|
|
sal_Bool m_bAutoStoreState : 1;
|
|
|
|
public:
|
|
TemplateFolderCacheImpl( sal_Bool _bAutoStoreState );
|
|
~TemplateFolderCacheImpl( );
|
|
|
|
sal_Bool needsUpdate( sal_Bool _bForceCheck );
|
|
void storeState( sal_Bool _bForceRetrieval );
|
|
|
|
private:
|
|
sal_Bool openCacheStream( sal_Bool _bForRead );
|
|
void closeCacheStream( );
|
|
|
|
/// read the state of the dirs from the cache file
|
|
sal_Bool readPreviousState();
|
|
/// read the current state of the dirs
|
|
sal_Bool readCurrentState();
|
|
|
|
String implParseSmart( const String& _rPath );
|
|
|
|
sal_Bool implReadFolder( const ::rtl::Reference< TemplateContent >& _rxRoot );
|
|
|
|
static rtl::OUString getCacheFileName();
|
|
static sal_Int32 getMagicNumber();
|
|
static void normalize( TemplateFolderContent& _rState );
|
|
|
|
// @return <TRUE/> if the states equal
|
|
static sal_Bool equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS );
|
|
|
|
// late initialize m_xOfficeInstDirs
|
|
uno::Reference< util::XOfficeInstallationDirectories > getOfficeInstDirs();
|
|
};
|
|
|
|
//---------------------------------------------------------------------
|
|
TemplateFolderCacheImpl::TemplateFolderCacheImpl( sal_Bool _bAutoStoreState )
|
|
:m_pCacheStream ( NULL )
|
|
,m_bNeedsUpdate ( sal_True )
|
|
,m_bKnowState ( sal_False )
|
|
,m_bValidCurrentState ( sal_False )
|
|
,m_bAutoStoreState ( _bAutoStoreState )
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
TemplateFolderCacheImpl::~TemplateFolderCacheImpl( )
|
|
{
|
|
// store the current state if possible and required
|
|
if ( m_bValidCurrentState && m_bAutoStoreState )
|
|
storeState( sal_False );
|
|
|
|
closeCacheStream( );
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Int32 TemplateFolderCacheImpl::getMagicNumber()
|
|
{
|
|
sal_Int32 nMagic = 0;
|
|
( nMagic += (sal_Int8)'T' ) <<= 4;
|
|
( nMagic += (sal_Int8)'D' ) <<= 4;
|
|
( nMagic += (sal_Int8)'S' ) <<= 4;
|
|
( nMagic += (sal_Int8)'C' ) <<= 0;
|
|
return nMagic;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
rtl::OUString TemplateFolderCacheImpl::getCacheFileName()
|
|
{
|
|
return rtl::OUString(".templdir.cache");
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
void TemplateFolderCacheImpl::normalize( TemplateFolderContent& _rState )
|
|
{
|
|
SubContentSort()( _rState );
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool TemplateFolderCacheImpl::equalStates( const TemplateFolderContent& _rLHS, const TemplateFolderContent& _rRHS )
|
|
{
|
|
if ( _rLHS.size() != _rRHS.size() )
|
|
return sal_False;
|
|
|
|
// as both arrays are sorted (by definition - this is a precondition of this method)
|
|
// we can simply go from the front to the back and compare the single elements
|
|
|
|
::std::pair< ConstFolderIterator, ConstFolderIterator > aFirstDifferent = ::std::mismatch(
|
|
_rLHS.begin(),
|
|
_rLHS.end(),
|
|
_rRHS.begin(),
|
|
TemplateContentEqual()
|
|
);
|
|
|
|
return aFirstDifferent.first == _rLHS.end();
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
void TemplateFolderCacheImpl::storeState( sal_Bool _bForceRetrieval )
|
|
{
|
|
if ( !m_bValidCurrentState || _bForceRetrieval )
|
|
readCurrentState( );
|
|
|
|
if ( m_bValidCurrentState && openCacheStream( sal_False ) )
|
|
{
|
|
*m_pCacheStream << getMagicNumber();
|
|
|
|
// store the template root folders
|
|
// the size
|
|
*m_pCacheStream << (sal_Int32)m_aCurrentState.size();
|
|
// the complete URLs
|
|
::std::for_each(
|
|
m_aCurrentState.begin(),
|
|
m_aCurrentState.end(),
|
|
StoreContentURL( *m_pCacheStream, getOfficeInstDirs() )
|
|
);
|
|
|
|
// the contents
|
|
::std::for_each(
|
|
m_aCurrentState.begin(),
|
|
m_aCurrentState.end(),
|
|
StoreFolderContent( *m_pCacheStream, getOfficeInstDirs() )
|
|
);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
String TemplateFolderCacheImpl::implParseSmart( const String& _rPath )
|
|
{
|
|
INetURLObject aParser;
|
|
aParser.SetSmartProtocol( INET_PROT_FILE );
|
|
aParser.SetURL( _rPath, INetURLObject::WAS_ENCODED );
|
|
if ( INET_PROT_NOT_VALID == aParser.GetProtocol() )
|
|
{
|
|
rtl::OUString sURL;
|
|
LocalFileHelper::ConvertPhysicalNameToURL( _rPath, sURL );
|
|
aParser.SetURL( sURL, INetURLObject::WAS_ENCODED );
|
|
}
|
|
return aParser.GetMainURL( INetURLObject::DECODE_TO_IURI );
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
void TemplateFolderCacheImpl::closeCacheStream( )
|
|
{
|
|
DELETEZ( m_pCacheStream );
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool TemplateFolderCacheImpl::implReadFolder( const ::rtl::Reference< TemplateContent >& _rxRoot )
|
|
{
|
|
try
|
|
{
|
|
// create a content for the current folder root
|
|
Reference< XResultSet > xResultSet;
|
|
Sequence< ::rtl::OUString > aContentProperties( 4);
|
|
aContentProperties[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ));
|
|
aContentProperties[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ));
|
|
aContentProperties[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ));
|
|
aContentProperties[3] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ));
|
|
|
|
// get the set of sub contents in the folder
|
|
try
|
|
{
|
|
Reference< XDynamicResultSet > xDynResultSet;
|
|
|
|
::ucbhelper::Content aTemplateRoot( _rxRoot->getURL(), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext() );
|
|
xDynResultSet = aTemplateRoot.createDynamicCursor( aContentProperties, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS );
|
|
if ( xDynResultSet.is() )
|
|
xResultSet = xDynResultSet->getStaticResultSet();
|
|
}
|
|
catch( CommandAbortedException& )
|
|
{
|
|
SAL_WARN( "svtools.misc", "TemplateFolderCacheImpl::implReadFolder: caught a CommandAbortedException!" );
|
|
return sal_False;
|
|
}
|
|
catch( ::com::sun::star::uno::Exception& )
|
|
{
|
|
}
|
|
|
|
// collect the infos about the sub contents
|
|
if ( xResultSet.is() )
|
|
{
|
|
Reference< XRow > xRow( xResultSet, UNO_QUERY_THROW );
|
|
Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY_THROW );
|
|
|
|
while ( xResultSet->next() )
|
|
{
|
|
INetURLObject aSubContentURL( xContentAccess->queryContentIdentifierString() );
|
|
|
|
// a new content instance
|
|
::rtl::Reference< TemplateContent > xChild = new TemplateContent( aSubContentURL );
|
|
|
|
// the modified date
|
|
xChild->setModDate( xRow->getTimestamp( 2 ) ); // date modified
|
|
if ( xRow->wasNull() )
|
|
xChild->setModDate( xRow->getTimestamp( 3 ) ); // fallback: date created
|
|
|
|
// push back this content
|
|
_rxRoot->push_back( xChild );
|
|
|
|
// is it a folder?
|
|
if ( xRow->getBoolean( 4 ) && !xRow->wasNull() )
|
|
{ // yes -> step down
|
|
ConstFolderIterator aNextLevelRoot = _rxRoot->end();
|
|
--aNextLevelRoot;
|
|
implReadFolder( *aNextLevelRoot );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
OSL_FAIL( "TemplateFolderCacheImpl::implReadFolder: caught an exception!" );
|
|
return sal_False;
|
|
}
|
|
return sal_True;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool TemplateFolderCacheImpl::readCurrentState()
|
|
{
|
|
// reset
|
|
m_bValidCurrentState = sal_False;
|
|
TemplateFolderContent aTemplateFolderContent;
|
|
m_aCurrentState.swap( aTemplateFolderContent );
|
|
|
|
// the template directories from the config
|
|
const SvtPathOptions aPathOptions;
|
|
rtl::OUString aDirs = aPathOptions.GetTemplatePath();
|
|
|
|
// loop through all the root-level template folders
|
|
sal_Int32 nIndex = 0;
|
|
do
|
|
{
|
|
String sTemplatePath( aDirs.getToken(0, ';', nIndex) );
|
|
sTemplatePath = aPathOptions.ExpandMacros( sTemplatePath );
|
|
|
|
// Make sure excess ".." path segments (from expanding bootstrap
|
|
// variables in paths) are normalized in the same way they are
|
|
// normalized for paths read from the .templdir.cache file (where
|
|
// paths have gone through makeRelocatable URL on writing out and
|
|
// then through makeAbsoluteURL when reading back in), as otherwise
|
|
// equalStates() in needsUpdate() could erroneously consider
|
|
// m_aCurrentState and m_aPreviousState as different:
|
|
sTemplatePath = getOfficeInstDirs()->makeAbsoluteURL(
|
|
getOfficeInstDirs()->makeRelocatableURL(sTemplatePath));
|
|
|
|
// create a new entry
|
|
m_aCurrentState.push_back( new TemplateContent( INetURLObject( sTemplatePath ) ) );
|
|
TemplateFolderContent::iterator aCurrentRoot = m_aCurrentState.end();
|
|
--aCurrentRoot;
|
|
|
|
if ( !implReadFolder( *aCurrentRoot ) )
|
|
return sal_False;
|
|
}
|
|
while ( nIndex >= 0 );
|
|
|
|
// normalize the array (which basically means "sort it")
|
|
normalize( m_aCurrentState );
|
|
|
|
m_bValidCurrentState = sal_True;
|
|
return m_bValidCurrentState;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool TemplateFolderCacheImpl::readPreviousState()
|
|
{
|
|
DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::readPreviousState: not to be called without stream!" );
|
|
|
|
// reset
|
|
TemplateFolderContent aTemplateFolderContent;
|
|
m_aPreviousState.swap( aTemplateFolderContent );
|
|
|
|
// check the magic number
|
|
sal_Int32 nMagic = 0;
|
|
*m_pCacheStream >> nMagic;
|
|
DBG_ASSERT( getMagicNumber() == nMagic, "TemplateFolderCacheImpl::readPreviousState: invalid cache file!" );
|
|
if ( getMagicNumber() != nMagic )
|
|
return sal_False;
|
|
|
|
// the root directories
|
|
// their number
|
|
sal_Int32 nRootDirectories = 0;
|
|
*m_pCacheStream >> nRootDirectories;
|
|
// init empty TemplateContens with the URLs
|
|
m_aPreviousState.reserve( nRootDirectories );
|
|
while ( nRootDirectories-- )
|
|
{
|
|
String sURL = m_pCacheStream->ReadUniOrByteString(m_pCacheStream->GetStreamCharSet());
|
|
// #116281# Keep office installtion relocatable. Never store
|
|
// any direct references to office installation directory.
|
|
sURL = getOfficeInstDirs()->makeAbsoluteURL( sURL );
|
|
m_aPreviousState.push_back(
|
|
new TemplateContent( INetURLObject(sURL) ) );
|
|
}
|
|
|
|
// read the contents of the root folders
|
|
::std::for_each(
|
|
m_aPreviousState.begin(),
|
|
m_aPreviousState.end(),
|
|
ReadFolderContent( *m_pCacheStream, getOfficeInstDirs() )
|
|
);
|
|
|
|
DBG_ASSERT( !m_pCacheStream->GetErrorCode(), "TemplateFolderCacheImpl::readPreviousState: unknown error during reading the state cache!" );
|
|
|
|
// normalize the array (which basically means "sort it")
|
|
normalize( m_aPreviousState );
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool TemplateFolderCacheImpl::openCacheStream( sal_Bool _bForRead )
|
|
{
|
|
// close any old stream instance
|
|
closeCacheStream( );
|
|
|
|
// get the storage directory
|
|
String sStorageURL = implParseSmart( SvtPathOptions().GetStoragePath() );
|
|
INetURLObject aStorageURL( sStorageURL );
|
|
if ( INET_PROT_NOT_VALID == aStorageURL.GetProtocol() )
|
|
{
|
|
OSL_FAIL( "TemplateFolderCacheImpl::openCacheStream: invalid storage path!" );
|
|
return sal_False;
|
|
}
|
|
|
|
// append our name
|
|
aStorageURL.Append( getCacheFileName() );
|
|
|
|
// open the stream
|
|
m_pCacheStream = UcbStreamHelper::CreateStream( aStorageURL.GetMainURL( INetURLObject::DECODE_TO_IURI ),
|
|
_bForRead ? STREAM_READ | STREAM_NOCREATE : STREAM_WRITE | STREAM_TRUNC );
|
|
DBG_ASSERT( m_pCacheStream, "TemplateFolderCacheImpl::openCacheStream: could not open/create the cache stream!" );
|
|
if ( m_pCacheStream && m_pCacheStream->GetErrorCode() )
|
|
{
|
|
DELETEZ( m_pCacheStream );
|
|
}
|
|
|
|
if ( m_pCacheStream )
|
|
m_pCacheStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
|
|
|
|
return NULL != m_pCacheStream;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool TemplateFolderCacheImpl::needsUpdate( sal_Bool _bForceCheck )
|
|
{
|
|
if ( m_bKnowState && !_bForceCheck )
|
|
return m_bNeedsUpdate;
|
|
|
|
m_bNeedsUpdate = sal_True;
|
|
m_bKnowState = sal_True;
|
|
|
|
if ( readCurrentState() )
|
|
{
|
|
// open the stream which contains the cached state of the directories
|
|
if ( openCacheStream( sal_True ) )
|
|
{ // opening the stream succeeded
|
|
if ( readPreviousState() )
|
|
{
|
|
m_bNeedsUpdate = !equalStates( m_aPreviousState, m_aCurrentState );
|
|
}
|
|
else
|
|
{
|
|
closeCacheStream();
|
|
}
|
|
}
|
|
}
|
|
return m_bNeedsUpdate;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
uno::Reference< util::XOfficeInstallationDirectories >
|
|
TemplateFolderCacheImpl::getOfficeInstDirs()
|
|
{
|
|
if ( !m_xOfficeInstDirs.is() )
|
|
{
|
|
osl::MutexGuard aGuard( m_aMutex );
|
|
if ( !m_xOfficeInstDirs.is() )
|
|
{
|
|
// @@@ This is bad!
|
|
uno::Reference< lang::XMultiServiceFactory > xSMgr
|
|
= comphelper::getProcessServiceFactory();
|
|
OSL_ENSURE( xSMgr.is(), "No service manager!" );
|
|
|
|
uno::Reference< beans::XPropertySet > xPropSet(
|
|
xSMgr, uno::UNO_QUERY );
|
|
if ( xPropSet.is() )
|
|
{
|
|
uno::Reference< uno::XComponentContext > xCtx;
|
|
xPropSet->getPropertyValue(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
|
|
>>= xCtx;
|
|
|
|
OSL_ENSURE( xCtx.is(),
|
|
"Unable to obtain component context from service manager!" );
|
|
|
|
if ( xCtx.is() )
|
|
{
|
|
xCtx->getValueByName(
|
|
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
|
|
"/singletons/com.sun.star.util.theOfficeInstallationDirectories" ) ) )
|
|
>>= m_xOfficeInstDirs;
|
|
}
|
|
|
|
OSL_ENSURE( m_xOfficeInstDirs.is(),
|
|
"Unable to obtain office directories singleton!" );
|
|
|
|
}
|
|
}
|
|
}
|
|
return m_xOfficeInstDirs;
|
|
}
|
|
|
|
//=====================================================================
|
|
//= TemplateFolderCache
|
|
//=====================================================================
|
|
//---------------------------------------------------------------------
|
|
TemplateFolderCache::TemplateFolderCache( sal_Bool _bAutoStoreState )
|
|
:m_pImpl( new TemplateFolderCacheImpl( _bAutoStoreState ) )
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
TemplateFolderCache::~TemplateFolderCache( )
|
|
{
|
|
DELETEZ( m_pImpl );
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
sal_Bool TemplateFolderCache::needsUpdate( sal_Bool _bForceCheck )
|
|
{
|
|
return m_pImpl->needsUpdate( _bForceCheck );
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
void TemplateFolderCache::storeState( sal_Bool _bForceRetrieval )
|
|
{
|
|
m_pImpl->storeState( _bForceRetrieval );
|
|
}
|
|
|
|
//.........................................................................
|
|
} // namespace sfx2
|
|
//.........................................................................
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|