| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| #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 <vos/ref.hxx> |
| #include <vos/refernce.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< ::vos::ORef< 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 ::vos::OReference |
| { |
| 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(); |
| TemplateContent( const INetURLObject& _rURL ); |
| TemplateContent( const INetURLObject& _rURL, const util::DateTime& _rLastModified ); |
| |
| // 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 ::vos::ORef< TemplateContent >& _rxNewElement ) |
| { m_aSubContents.push_back( _rxNewElement ); } |
| }; |
| |
| //--------------------------------------------------------------------- |
| DBG_NAME( TemplateContent ) |
| |
| //--------------------------------------------------------------------- |
| TemplateContent::TemplateContent() |
| { |
| DBG_CTOR( TemplateContent, NULL ); |
| implResetDate(); |
| } |
| |
| //--------------------------------------------------------------------- |
| 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( const INetURLObject& _rURL, const util::DateTime& _rLastModified ) |
| :m_aURL( _rURL ) |
| ,m_aLastModified( _rLastModified ) |
| { |
| DBG_CTOR( TemplateContent, NULL ); |
| DBG_ASSERT( INET_PROT_NOT_VALID != m_aURL.GetProtocol(), "TemplateContent::TemplateContent: invalid URL!" ); |
| m_sLocalName = m_aURL.getName(); |
| } |
| |
| //--------------------------------------------------------------------- |
| TemplateContent::~TemplateContent() |
| { |
| DBG_DTOR( TemplateContent, NULL ); |
| } |
| |
| //===================================================================== |
| //= stl helpers |
| //===================================================================== |
| //--------------------------------------------------------------------- |
| /// compares two TemplateContent by URL |
| struct TemplateContentURLLess |
| :public ::std::binary_function < ::vos::ORef< TemplateContent > |
| , ::vos::ORef< TemplateContent > |
| , bool |
| > |
| { |
| bool operator() ( const ::vos::ORef< TemplateContent >& _rxLHS, const ::vos::ORef< TemplateContent >& _rxRHS ) const |
| { |
| return _rxLHS->getURL() < _rxRHS->getURL() |
| ? true |
| : false; |
| } |
| }; |
| |
| //--------------------------------------------------------------------- |
| /// sorts the sib contents of a TemplateFolderContent |
| struct SubContentSort : public ::std::unary_function< ::vos::ORef< 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 ::vos::ORef< TemplateContent >& _rxContent ) const |
| { |
| if ( _rxContent.isValid() && _rxContent->size() ) |
| { |
| operator()( _rxContent->getSubContents() ); |
| } |
| } |
| }; |
| //--------------------------------------------------------------------- |
| /** does a deep compare of two template contents |
| */ |
| struct TemplateContentEqual |
| :public ::std::binary_function < ::vos::ORef< TemplateContent > |
| , ::vos::ORef< TemplateContent > |
| , bool |
| > |
| { |
| //................................................................. |
| bool operator() (const ::vos::ORef< TemplateContent >& _rLHS, const ::vos::ORef< TemplateContent >& _rRHS ) |
| { |
| if ( !_rLHS.isValid() || !_rRHS.isValid() ) |
| { |
| DBG_ERROR( "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.WriteByteString( _rString ); |
| } |
| }; |
| |
| //--------------------------------------------------------------------- |
| /// functor which stores the local name of a TemplateContent |
| struct StoreLocalContentName |
| :public ::std::unary_function< ::vos::ORef< TemplateContent >, void > |
| ,public StoreString |
| { |
| StoreLocalContentName( SvStream& _rStorage ) : StoreString( _rStorage ) { } |
| |
| void operator() ( const ::vos::ORef< TemplateContent >& _rxContent ) const |
| { |
| DBG_ERRORFILE( "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< ::vos::ORef< 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 ::vos::ORef< 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< ::vos::ORef< 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 ::vos::ORef< TemplateContent >& _rxContent ) const |
| { |
| if ( _rxContent.isValid() ) |
| { |
| operator()( *_rxContent ); |
| } |
| } |
| }; |
| |
| //--------------------------------------------------------------------- |
| /// functor which reads a complete TemplateContent instance |
| struct ReadFolderContent |
| :public ::std::unary_function< ::vos::ORef< 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.ReadByteString( sURL ); |
| 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 ::vos::ORef< TemplateContent >& _rxContent ) const |
| { |
| if ( _rxContent.isValid() ) |
| { |
| 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: |
| void initTemplDirs( ::std::vector< String >& _rRootDirs ); |
| 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 ::vos::ORef< TemplateContent >& _rxRoot ); |
| |
| static String 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; |
| } |
| |
| //--------------------------------------------------------------------- |
| String TemplateFolderCacheImpl::getCacheFileName() |
| { |
| return String::CreateFromAscii( ".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() ) |
| { |
| String 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 ::vos::ORef< TemplateContent >& _rxRoot ) |
| { |
| try |
| { |
| // create a content for the current folder root |
| Reference< XResultSet > xResultSet; |
| Sequence< ::rtl::OUString > aContentProperties( 4); |
| aContentProperties[0] = ::rtl::OUString::createFromAscii( "Title" ); |
| aContentProperties[1] = ::rtl::OUString::createFromAscii( "DateModified" ); |
| aContentProperties[2] = ::rtl::OUString::createFromAscii( "DateCreated" ); |
| aContentProperties[3] = ::rtl::OUString::createFromAscii( "IsFolder" ); |
| |
| // get the set of sub contents in the folder |
| try |
| { |
| Reference< XDynamicResultSet > xDynResultSet; |
| |
| ::ucbhelper::Content aTemplateRoot( _rxRoot->getURL(), Reference< XCommandEnvironment >() ); |
| xDynResultSet = aTemplateRoot.createDynamicCursor( aContentProperties, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ); |
| if ( xDynResultSet.is() ) |
| xResultSet = xDynResultSet->getStaticResultSet(); |
| } |
| catch( CommandAbortedException& ) |
| { |
| DBG_ERRORFILE( "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 |
| ::vos::ORef< 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& ) |
| { |
| DBG_ERROR( "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; |
| String aDirs = aPathOptions.GetTemplatePath(); |
| sal_uInt16 nDirs = aDirs.GetTokenCount( ';' ); |
| |
| m_aCurrentState.reserve( nDirs ); |
| // loop through all the root-level template folders |
| for ( sal_uInt16 i=0; i<nDirs; ++i) |
| { |
| String sTemplatePath( aDirs.GetToken( i, ';' ) ); |
| sTemplatePath = aPathOptions.ExpandMacros( 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; |
| } |
| |
| // 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->ReadByteString( sURL ); |
| // #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() ) |
| { |
| DBG_ERROR( "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; |
| } |
| |
| //--------------------------------------------------------------------- |
| void TemplateFolderCacheImpl::initTemplDirs( ::std::vector< String >& ) |
| { |
| } |
| |
| //--------------------------------------------------------------------- |
| 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 |
| //......................................................................... |
| |