| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| /* |
| * This file is part of the Collabora Office project. |
| * |
| * This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| * |
| * This file incorporates work covered by the following license notice: |
| * |
| * 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 . |
| */ |
| |
| #include <config_features.h> |
| |
| #include <sal/config.h> |
| #include <sal/log.hxx> |
| |
| #if HAVE_FEATURE_MACOSX_SANDBOX |
| #include <sys/stat.h> |
| #endif |
| |
| #include <com/sun/star/beans/IllegalTypeException.hpp> |
| #include <com/sun/star/beans/NotRemoveableException.hpp> |
| #include <com/sun/star/beans/PropertyAttribute.hpp> |
| #include <com/sun/star/beans/PropertyExistException.hpp> |
| #include <com/sun/star/io/BufferSizeExceededException.hpp> |
| #include <com/sun/star/io/NotConnectedException.hpp> |
| #include <com/sun/star/io/IOException.hpp> |
| #include <com/sun/star/lang/IllegalAccessException.hpp> |
| #include <com/sun/star/task/InteractionClassification.hpp> |
| #include <com/sun/star/ucb/ContentInfoAttribute.hpp> |
| #include <com/sun/star/ucb/DuplicateCommandIdentifierException.hpp> |
| #include <com/sun/star/ucb/IOErrorCode.hpp> |
| #include <com/sun/star/ucb/InsertCommandArgument.hpp> |
| #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> |
| #include <com/sun/star/ucb/NameClash.hpp> |
| #include <com/sun/star/ucb/OpenCommandArgument.hpp> |
| #include <com/sun/star/ucb/Store.hpp> |
| #include <com/sun/star/ucb/TransferInfo.hpp> |
| #include <comphelper/propertysequence.hxx> |
| #include <osl/diagnose.h> |
| #include <rtl/ref.hxx> |
| #include <rtl/uri.hxx> |
| |
| #include "filtask.hxx" |
| #include "filcmd.hxx" |
| #include "filglob.hxx" |
| #include "filinpstr.hxx" |
| #include "filprp.hxx" |
| #include "filrset.hxx" |
| #include "filstr.hxx" |
| #include "prov.hxx" |
| |
| /******************************************************************************/ |
| /* */ |
| /* TaskHandling */ |
| /* */ |
| /******************************************************************************/ |
| |
| |
| using namespace fileaccess; |
| using namespace com::sun::star; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::ucb; |
| |
| TaskManager::UnqPathData::UnqPathData() = default; |
| |
| TaskManager::UnqPathData::UnqPathData(TaskManager::UnqPathData&&) = default; |
| |
| |
| TaskManager::UnqPathData::~UnqPathData() |
| { |
| } |
| |
| TaskManager::MyProperty::MyProperty( const OUString& thePropertyName ) |
| : PropertyName( thePropertyName ) |
| , Handle(-1) |
| , isNative(false) |
| , State(beans::PropertyState_AMBIGUOUS_VALUE) |
| , Attributes(0) |
| { |
| // empty |
| } |
| |
| TaskManager::MyProperty::MyProperty( bool theisNative, |
| const OUString& thePropertyName, |
| sal_Int32 theHandle, |
| const css::uno::Type& theTyp, |
| const css::uno::Any& theValue, |
| const css::beans::PropertyState& theState, |
| sal_Int16 theAttributes ) |
| : PropertyName( thePropertyName ), |
| Handle( theHandle ), |
| isNative( theisNative ), |
| Typ( theTyp ), |
| Value( theValue ), |
| State( theState ), |
| Attributes( theAttributes ) |
| { |
| // empty |
| } |
| |
| #include "filinl.hxx" |
| |
| // Default properties |
| |
| constexpr OUString Title( u"Title"_ustr ); |
| constexpr OUString CasePreservingURL( u"CasePreservingURL"_ustr ); |
| constexpr OUString IsDocument( u"IsDocument"_ustr ); |
| constexpr OUString IsFolder( u"IsFolder"_ustr ); |
| constexpr OUString DateModified( u"DateModified"_ustr ); |
| constexpr OUString Size( u"Size"_ustr ); |
| constexpr OUString IsVolume( u"IsVolume"_ustr ); |
| constexpr OUString IsRemoveable( u"IsRemoveable"_ustr ); |
| constexpr OUString IsRemote( u"IsRemote"_ustr ); |
| constexpr OUString IsCompactDisc( u"IsCompactDisc"_ustr ); |
| constexpr OUString IsFloppy( u"IsFloppy"_ustr ); |
| constexpr OUString IsHidden( u"IsHidden"_ustr ); |
| constexpr OUString ContentType( u"ContentType"_ustr ); |
| constexpr OUString IsReadOnly( u"IsReadOnly"_ustr ); |
| constexpr OUString CreatableContentsInfo( u"CreatableContentsInfo"_ustr ); |
| |
| TaskManager::TaskManager( const uno::Reference< uno::XComponentContext >& rxContext, |
| FileProvider* pProvider, bool bWithConfig ) |
| : m_nCommandId( 0 ), |
| m_pProvider( pProvider ), |
| m_xContext( rxContext ), |
| // Commands |
| m_sCommandInfo{ |
| { /* Name */ u"getCommandInfo"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<void>::get() }, |
| |
| { /* Name */ u"getPropertySetInfo"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<void>::get() }, |
| |
| { /* Name */ u"getPropertyValues"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<uno::Sequence< beans::Property >>::get() }, |
| |
| { /* Name */ u"setPropertyValues"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get() }, |
| |
| { /* Name */ u"open"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<OpenCommandArgument>::get() }, |
| |
| { /* Name */ u"transfer"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<TransferInfo>::get() }, |
| |
| { /* Name */ u"delete"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<sal_Bool>::get() }, |
| |
| { /* Name */ u"insert"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<InsertCommandArgument>::get() }, |
| |
| { /* Name */ u"createNewContent"_ustr, |
| /* Handle */ -1, |
| /* ArgType */ cppu::UnoType<ucb::ContentInfo>::get() } } |
| { |
| // Title |
| m_aDefaultProperties.insert( MyProperty( true, |
| Title, |
| -1 , |
| cppu::UnoType<OUString>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND ) ); |
| |
| // CasePreservingURL |
| m_aDefaultProperties.insert( |
| MyProperty( true, |
| CasePreservingURL, |
| -1 , |
| cppu::UnoType<OUString>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| |
| // IsFolder |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsFolder, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| |
| // IsDocument |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsDocument, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| // Removable |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsVolume, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| |
| // Removable |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsRemoveable, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| // Remote |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsRemote, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| // CompactDisc |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsCompactDisc, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| // Floppy |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsFloppy, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| // Hidden |
| m_aDefaultProperties.insert( |
| MyProperty( |
| true, |
| IsHidden, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| #if defined(_WIN32) |
| )); |
| #else |
| | beans::PropertyAttribute::READONLY)); // under unix/linux only readable |
| #endif |
| |
| |
| // ContentType |
| m_aDefaultProperties.insert( MyProperty( false, |
| ContentType, |
| -1 , |
| cppu::UnoType<OUString>::get(), |
| uno::Any(OUString()), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| |
| // DateModified |
| m_aDefaultProperties.insert( MyProperty( true, |
| DateModified, |
| -1 , |
| cppu::UnoType<util::DateTime>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND ) ); |
| |
| // Size |
| m_aDefaultProperties.insert( MyProperty( true, |
| Size, |
| -1, |
| cppu::UnoType<sal_Int64>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND ) ); |
| |
| // IsReadOnly |
| m_aDefaultProperties.insert( MyProperty( true, |
| IsReadOnly, |
| -1 , |
| cppu::UnoType<sal_Bool>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND ) ); |
| |
| |
| // CreatableContentsInfo |
| m_aDefaultProperties.insert( MyProperty( true, |
| CreatableContentsInfo, |
| -1 , |
| cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(), |
| uno::Any(), |
| beans::PropertyState_DEFAULT_VALUE, |
| beans::PropertyAttribute::MAYBEVOID |
| | beans::PropertyAttribute::BOUND |
| | beans::PropertyAttribute::READONLY ) ); |
| |
| if(bWithConfig) |
| { |
| uno::Reference< XPropertySetRegistryFactory > xRegFac = ucb::Store::create( m_xContext ); |
| // Open/create a registry |
| m_xFileRegistry = xRegFac->createPropertySetRegistry( OUString() ); |
| } |
| } |
| |
| |
| TaskManager::~TaskManager() |
| { |
| } |
| |
| |
| void |
| TaskManager::startTask( |
| sal_Int32 CommandId, |
| const uno::Reference< XCommandEnvironment >& xCommandEnv ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskMap::iterator it = m_aTaskMap.find( CommandId ); |
| if( it != m_aTaskMap.end() ) |
| { |
| throw DuplicateCommandIdentifierException( OSL_LOG_PREFIX ); |
| } |
| m_aTaskMap.emplace( CommandId, TaskHandling( xCommandEnv )); |
| } |
| |
| |
| void |
| TaskManager::endTask( sal_Int32 CommandId, |
| const OUString& aUncPath, |
| BaseContent* pContent) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskMap::iterator it = m_aTaskMap.find( CommandId ); |
| if( it == m_aTaskMap.end() ) |
| return; |
| |
| TaskHandlerErr ErrorCode = it->second.getInstalledError(); |
| sal_Int32 MinorCode = it->second.getMinorErrorCode(); |
| bool isHandled = it->second.isHandled(); |
| |
| Reference< XCommandEnvironment > xComEnv |
| = it->second.getCommandEnvironment(); |
| |
| m_aTaskMap.erase( it ); |
| |
| aGuard.unlock(); |
| |
| if( ErrorCode != TaskHandlerErr::NO_ERROR ) |
| throw_handler( |
| ErrorCode, |
| MinorCode, |
| xComEnv, |
| aUncPath, |
| pContent, |
| isHandled); |
| } |
| |
| |
| void TaskManager::clearError( sal_Int32 CommandId ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskMap::iterator it = m_aTaskMap.find( CommandId ); |
| if( it != m_aTaskMap.end() ) |
| it->second.clearError(); |
| } |
| |
| |
| void TaskManager::retrieveError( sal_Int32 CommandId, |
| TaskHandlerErr &ErrorCode, |
| sal_Int32 &minorCode) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskMap::iterator it = m_aTaskMap.find( CommandId ); |
| if( it != m_aTaskMap.end() ) |
| { |
| ErrorCode = it->second.getInstalledError(); |
| minorCode = it->second. getMinorErrorCode(); |
| } |
| } |
| |
| |
| void TaskManager::installError( sal_Int32 CommandId, |
| TaskHandlerErr ErrorCode, |
| sal_Int32 MinorCode ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskMap::iterator it = m_aTaskMap.find( CommandId ); |
| if( it != m_aTaskMap.end() ) |
| it->second.installError( ErrorCode,MinorCode ); |
| } |
| |
| |
| sal_Int32 |
| TaskManager::getCommandId() |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| return ++m_nCommandId; |
| } |
| |
| |
| void TaskManager::handleTask( |
| sal_Int32 CommandId, |
| const uno::Reference< task::XInteractionRequest >& request ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskMap::iterator it = m_aTaskMap.find( CommandId ); |
| uno::Reference< task::XInteractionHandler > xInt; |
| if( it != m_aTaskMap.end() ) |
| { |
| xInt = it->second.getInteractionHandler(); |
| if( xInt.is() ) |
| xInt->handle( request ); |
| it->second.setHandled(); |
| } |
| } |
| |
| /*********************************************************************************/ |
| /* */ |
| /* de/registerNotifier-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| |
| // This two methods register and deregister a change listener for the content belonging |
| // to URL aUnqPath |
| |
| |
| void |
| TaskManager::registerNotifier( const OUString& aUnqPath, Notifier* pNotifier ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| |
| ContentMap::iterator it = |
| m_aContent.emplace( aUnqPath, UnqPathData() ).first; |
| |
| std::vector< Notifier* >& nlist = it->second.notifier; |
| |
| std::vector<Notifier*>::iterator it1 = std::find(nlist.begin(), nlist.end(), pNotifier); |
| if( it1 != nlist.end() ) // Every "Notifier" only once |
| { |
| return; |
| } |
| nlist.push_back( pNotifier ); |
| } |
| |
| |
| void |
| TaskManager::deregisterNotifier( const OUString& aUnqPath,Notifier* pNotifier ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| |
| ContentMap::iterator it = m_aContent.find( aUnqPath ); |
| if( it == m_aContent.end() ) |
| return; |
| |
| std::erase(it->second.notifier, pNotifier); |
| |
| if( it->second.notifier.empty() ) |
| m_aContent.erase( it ); |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* de/associate-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // Used to associate and deassociate a new property with |
| // the content belonging to URL UnqPath. |
| // The default value and the attributes are input |
| |
| |
| void |
| TaskManager::associate( const OUString& aUnqPath, |
| const OUString& PropertyName, |
| const uno::Any& DefaultValue, |
| const sal_Int16 Attributes ) |
| { |
| MyProperty newProperty( false, |
| PropertyName, |
| -1, |
| DefaultValue.getValueType(), |
| DefaultValue, |
| beans::PropertyState_DEFAULT_VALUE, |
| Attributes ); |
| |
| auto it1 = m_aDefaultProperties.find( newProperty ); |
| if( it1 != m_aDefaultProperties.end() ) |
| throw beans::PropertyExistException(); |
| |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| |
| ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first; |
| |
| // Load the XPersistentPropertySetInfo and create it, if it does not exist |
| load( it,true ); |
| |
| PropertySet& properties = it->second.properties; |
| it1 = properties.find( newProperty ); |
| if( it1 != properties.end() ) |
| throw beans::PropertyExistException(); |
| |
| // Property does not exist |
| properties.insert( newProperty ); |
| it->second.xC->addProperty( PropertyName,Attributes,DefaultValue ); |
| } |
| notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName ); |
| } |
| |
| |
| void |
| TaskManager::deassociate( const OUString& aUnqPath, |
| const OUString& PropertyName ) |
| { |
| MyProperty oldProperty( PropertyName ); |
| |
| auto it1 = m_aDefaultProperties.find( oldProperty ); |
| if( it1 != m_aDefaultProperties.end() ) |
| throw beans::NotRemoveableException(); |
| |
| std::unique_lock aGuard( m_aMutex ); |
| |
| ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first; |
| |
| load( it, false ); |
| |
| PropertySet& properties = it->second.properties; |
| |
| it1 = properties.find( oldProperty ); |
| if( it1 == properties.end() ) |
| throw beans::UnknownPropertyException( PropertyName ); |
| |
| properties.erase( it1 ); |
| |
| if( it->second.xC.is() ) |
| it->second.xC->removeProperty( PropertyName ); |
| |
| if( properties.size() == 9 ) |
| { |
| MyProperty ContentTProperty( ContentType ); |
| |
| if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE ) |
| { |
| it->second.xS = nullptr; |
| it->second.xC = nullptr; |
| it->second.xA = nullptr; |
| if(m_xFileRegistry.is()) |
| m_xFileRegistry->removePropertySet( aUnqPath ); |
| } |
| } |
| aGuard.unlock(); |
| notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName ); |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* page-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // Given an xOutputStream, this method writes the content of the file belonging to |
| // URL aUnqPath into the XOutputStream |
| |
| |
| void TaskManager::page( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| const uno::Reference< io::XOutputStream >& xOutputStream ) |
| { |
| osl::File aFile( aUnqPath ); |
| osl::FileBase::RC err = aFile.open( osl_File_OpenFlag_Read ); |
| |
| if( err != osl::FileBase::E_None ) |
| { |
| aFile.close(); |
| installError( CommandId, |
| TaskHandlerErr::OPEN_FILE_FOR_PAGING, |
| err ); |
| return; |
| } |
| |
| const sal_uInt64 bfz = 4*1024; |
| sal_Int8 BFF[bfz]; |
| sal_uInt64 nrc; // Retrieved number of Bytes; |
| |
| do |
| { |
| err = aFile.read( static_cast<void*>(BFF),bfz,nrc ); |
| if( err == osl::FileBase::E_None ) |
| { |
| uno::Sequence< sal_Int8 > seq( BFF, static_cast<sal_uInt32>(nrc) ); |
| try |
| { |
| xOutputStream->writeBytes( seq ); |
| } |
| catch (const io::NotConnectedException&) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NOTCONNECTED_FOR_PAGING ); |
| break; |
| } |
| catch (const io::BufferSizeExceededException&) |
| { |
| installError( CommandId, |
| TaskHandlerErr::BUFFERSIZEEXCEEDED_FOR_PAGING ); |
| break; |
| } |
| catch (const io::IOException&) |
| { |
| installError( CommandId, |
| TaskHandlerErr::IOEXCEPTION_FOR_PAGING ); |
| break; |
| } |
| } |
| else |
| { |
| installError( CommandId, |
| TaskHandlerErr::READING_FILE_FOR_PAGING, |
| err ); |
| break; |
| } |
| } while( nrc == bfz ); |
| |
| |
| aFile.close(); |
| |
| |
| try |
| { |
| xOutputStream->closeOutput(); |
| } |
| catch (const io::NotConnectedException&) |
| { |
| } |
| catch (const io::BufferSizeExceededException&) |
| { |
| } |
| catch (const io::IOException&) |
| { |
| } |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* open-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file. |
| |
| |
| uno::Reference< io::XInputStream > |
| TaskManager::open( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| bool bLock ) |
| { |
| rtl::Reference<XInputStream_impl> pInputStream(new XInputStream_impl( aUnqPath, bLock )); // from filinpstr.hxx |
| |
| TaskHandlerErr ErrorCode = pInputStream->CtorSuccess(); |
| |
| if( ErrorCode != TaskHandlerErr::NO_ERROR ) |
| { |
| installError( CommandId, |
| ErrorCode, |
| pInputStream->getMinorError() ); |
| |
| pInputStream.clear(); |
| } |
| |
| return pInputStream; |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* open for read/write access-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // Given a file URL aUnqPath, this methods returns a XStream which can be used |
| // to read and write from/to the file. |
| |
| |
| uno::Reference< io::XStream > |
| TaskManager::open_rw( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| bool bLock ) |
| { |
| rtl::Reference<XStream_impl> pStream(new XStream_impl( aUnqPath, bLock )); // from filstr.hxx |
| |
| TaskHandlerErr ErrorCode = pStream->CtorSuccess(); |
| |
| if( ErrorCode != TaskHandlerErr::NO_ERROR ) |
| { |
| installError( CommandId, |
| ErrorCode, |
| pStream->getMinorError() ); |
| |
| pStream.clear(); |
| } |
| return pStream; |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* ls-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // This method returns the result set containing the children of the directory belonging |
| // to file URL aUnqPath |
| |
| |
| uno::Reference< XDynamicResultSet > |
| TaskManager::ls( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| const sal_Int32 OpenMode, |
| const uno::Sequence< beans::Property >& seq, |
| const uno::Sequence< NumberedSortingInfo >& seqSort ) |
| { |
| rtl::Reference<XResultSet_impl> p(new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort )); |
| |
| TaskHandlerErr ErrorCode = p->CtorSuccess(); |
| |
| if( ErrorCode != TaskHandlerErr::NO_ERROR ) |
| { |
| installError( CommandId, |
| ErrorCode, |
| p->getMinorError() ); |
| |
| p.clear(); |
| } |
| |
| return p; |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* info_c implementation */ |
| /* */ |
| /*********************************************************************************/ |
| // Info for commands |
| |
| uno::Reference< XCommandInfo > |
| TaskManager::info_c() |
| { |
| return new XCommandInfo_impl( this ); |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* info_p-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| // Info for the properties |
| |
| uno::Reference< beans::XPropertySetInfo > |
| TaskManager::info_p( const OUString& aUnqPath ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| return new XPropertySetInfo_impl( this,aUnqPath ); |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* setv-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // Sets the values of the properties belonging to fileURL aUnqPath |
| |
| |
| uno::Sequence< uno::Any > |
| TaskManager::setv( const OUString& aUnqPath, |
| const uno::Sequence< beans::PropertyValue >& values ) |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| |
| sal_Int32 propChanged = 0; |
| uno::Sequence< uno::Any > ret( values.getLength() ); |
| auto retRange = asNonConstRange(ret); |
| uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() ); |
| auto seqChangedRange = asNonConstRange(seqChanged); |
| |
| TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath ); |
| PropertySet& properties = it->second.properties; |
| TaskManager::PropertySet::const_iterator it1; |
| uno::Any aAny; |
| |
| for( sal_Int32 i = 0; i < values.getLength(); ++i ) |
| { |
| MyProperty toset( values[i].Name ); |
| it1 = properties.find( toset ); |
| if( it1 == properties.end() ) |
| { |
| retRange[i] <<= beans::UnknownPropertyException(); |
| continue; |
| } |
| |
| aAny = it1->getValue(); |
| if( aAny == values[i].Value ) |
| continue; // nothing needs to be changed |
| |
| if( it1->getAttributes() & beans::PropertyAttribute::READONLY ) |
| { |
| retRange[i] <<= lang::IllegalAccessException(); |
| continue; |
| } |
| |
| seqChangedRange[ propChanged ].PropertyName = values[i].Name; |
| seqChangedRange[ propChanged ].PropertyHandle = -1; |
| seqChangedRange[ propChanged ].Further = false; |
| seqChangedRange[ propChanged ].OldValue = aAny; |
| seqChangedRange[ propChanged++ ].NewValue = values[i].Value; |
| |
| it1->setValue( values[i].Value ); // Put the new value into the local cash |
| |
| if( ! it1->IsNative() ) |
| { |
| // Also put logical properties into storage |
| if( !it->second.xS.is() ) |
| load( it, true ); |
| |
| if( ( values[i].Name == ContentType ) && |
| it1->getState() == beans::PropertyState_DEFAULT_VALUE ) |
| { // Special logic for ContentType |
| // 09.07.01: Not reached anymore, because ContentType is readonly |
| it1->setState( beans::PropertyState_DIRECT_VALUE ); |
| it->second.xC->addProperty( values[i].Name, |
| beans::PropertyAttribute::MAYBEVOID, |
| values[i].Value ); |
| } |
| |
| try |
| { |
| it->second.xS->setPropertyValue( values[i].Name,values[i].Value ); |
| } |
| catch (const uno::Exception&e) |
| { |
| --propChanged; // unsuccessful setting |
| retRange[i] <<= e; |
| } |
| } |
| else |
| { |
| // native properties |
| // Setting of physical file properties |
| if( values[i].Name == Size ) |
| { |
| sal_Int64 newSize = 0; |
| if( values[i].Value >>= newSize ) |
| { // valid value for the size |
| osl::File aFile(aUnqPath); |
| bool err = |
| aFile.open(osl_File_OpenFlag_Write) != osl::FileBase::E_None || |
| aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None || |
| aFile.close() != osl::FileBase::E_None; |
| |
| if( err ) |
| { |
| --propChanged; // unsuccessful setting |
| uno::Sequence<uno::Any> names(comphelper::InitAnyPropertySequence( |
| { |
| {"Uri", uno::Any(aUnqPath)} |
| })); |
| retRange[i] <<= InteractiveAugmentedIOException( |
| OUString(), |
| nullptr, |
| task::InteractionClassification_ERROR, |
| IOErrorCode_GENERAL, |
| names ); |
| } |
| } |
| else |
| retRange[i] <<= beans::IllegalTypeException(); |
| } |
| else if(values[i].Name == IsReadOnly || |
| values[i].Name == IsHidden) |
| { |
| bool value = false; |
| if( values[i].Value >>= value ) |
| { |
| osl::DirectoryItem aDirItem; |
| osl::FileBase::RC err = |
| osl::DirectoryItem::get(aUnqPath,aDirItem); |
| sal_uInt64 nAttributes(0); |
| if(err == osl::FileBase::E_None) |
| { |
| osl::FileStatus aFileStatus(osl_FileStatus_Mask_Attributes); |
| err = aDirItem.getFileStatus(aFileStatus); |
| if(err == osl::FileBase::E_None && |
| aFileStatus.isValid(osl_FileStatus_Mask_Attributes)) |
| nAttributes = aFileStatus.getAttributes(); |
| } |
| // now we have the attributes provided all went well. |
| if(err == osl::FileBase::E_None) { |
| if(values[i].Name == IsReadOnly) |
| { |
| nAttributes &= ~(osl_File_Attribute_OwnWrite | |
| osl_File_Attribute_GrpWrite | |
| osl_File_Attribute_OthWrite | |
| osl_File_Attribute_ReadOnly); |
| if(value) |
| nAttributes |= osl_File_Attribute_ReadOnly; |
| else |
| nAttributes |= ( |
| osl_File_Attribute_OwnWrite | |
| osl_File_Attribute_GrpWrite | |
| osl_File_Attribute_OthWrite); |
| } |
| else if(values[i].Name == IsHidden) |
| { |
| nAttributes &= ~(osl_File_Attribute_Hidden); |
| if(value) |
| nAttributes |= osl_File_Attribute_Hidden; |
| } |
| err = osl::File::setAttributes( |
| aUnqPath,nAttributes); |
| } |
| |
| if( err != osl::FileBase::E_None ) |
| { |
| --propChanged; // unsuccessful setting |
| uno::Sequence<uno::Any> names(comphelper::InitAnyPropertySequence( |
| { |
| {"Uri", uno::Any(aUnqPath)} |
| })); |
| IOErrorCode ioError; |
| switch( err ) |
| { |
| case osl::FileBase::E_NOMEM: |
| // not enough memory for allocating structures <br> |
| ioError = IOErrorCode_OUT_OF_MEMORY; |
| break; |
| case osl::FileBase::E_INVAL: |
| // the format of the parameters was not valid<p> |
| ioError = IOErrorCode_INVALID_PARAMETER; |
| break; |
| case osl::FileBase::E_NAMETOOLONG: |
| // File name too long<br> |
| ioError = IOErrorCode_NAME_TOO_LONG; |
| break; |
| case osl::FileBase::E_NOENT: |
| // No such file or directory<br> |
| case osl::FileBase::E_NOLINK: |
| // Link has been severed<br> |
| ioError = IOErrorCode_NOT_EXISTING; |
| break; |
| case osl::FileBase::E_ROFS: |
| // #i4735# handle ROFS transparently |
| // as ACCESS_DENIED |
| case osl::FileBase::E_PERM: |
| case osl::FileBase::E_ACCES: |
| // permission denied<br> |
| ioError = IOErrorCode_ACCESS_DENIED; |
| break; |
| case osl::FileBase::E_LOOP: |
| // Too many symbolic links encountered<br> |
| case osl::FileBase::E_FAULT: |
| // Bad address<br> |
| case osl::FileBase::E_IO: |
| // I/O error<br> |
| case osl::FileBase::E_NOSYS: |
| // Function not implemented<br> |
| case osl::FileBase::E_MULTIHOP: |
| // Multihop attempted<br> |
| case osl::FileBase::E_INTR: |
| // function call was interrupted<p> |
| default: |
| ioError = IOErrorCode_GENERAL; |
| break; |
| } |
| retRange[i] <<= InteractiveAugmentedIOException( |
| OUString(), |
| nullptr, |
| task::InteractionClassification_ERROR, |
| ioError, |
| names ); |
| } |
| } |
| else |
| retRange[i] <<= beans::IllegalTypeException(); |
| } |
| } |
| } // end for |
| |
| aGuard.unlock(); |
| if( propChanged ) |
| { |
| seqChanged.realloc( propChanged ); |
| notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ), seqChanged ); |
| } |
| |
| return ret; |
| } |
| |
| /*********************************************************************************/ |
| /* */ |
| /* getv-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // Reads the values of the properties belonging to fileURL aUnqPath; |
| // Returns an XRow object containing the values in the requested order. |
| |
| |
| uno::Reference< sdbc::XRow > |
| TaskManager::getv( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| const uno::Sequence< beans::Property >& properties ) |
| { |
| uno::Sequence< uno::Any > seq( properties.getLength() ); |
| |
| sal_Int32 n_Mask; |
| getMaskFromProperties( n_Mask,properties ); |
| osl::FileStatus aFileStatus( n_Mask ); |
| |
| osl::DirectoryItem aDirItem; |
| osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem ); |
| if( nError1 != osl::FileBase::E_None ) |
| installError(CommandId, |
| TaskHandlerErr::OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED |
| nError1); |
| |
| osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus ); |
| if( nError1 == osl::FileBase::E_None && |
| nError2 != osl::FileBase::E_None ) |
| installError(CommandId, |
| TaskHandlerErr::OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED |
| nError2); |
| |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| |
| TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath ); |
| commit( aGuard, it, aFileStatus ); |
| |
| PropertySet& propset = it->second.properties; |
| |
| std::transform(properties.begin(), properties.end(), seq.getArray(), |
| [&propset](const beans::Property& rProp) -> uno::Any { |
| MyProperty readProp( rProp.Name ); |
| auto it1 = propset.find( readProp ); |
| if( it1 == propset.end() ) |
| return uno::Any(); |
| return it1->getValue(); |
| }); |
| } |
| |
| return new XRow_impl( this,seq ); |
| } |
| |
| |
| /********************************************************************************/ |
| /* */ |
| /* transfer-commandos */ |
| /* */ |
| /********************************************************************************/ |
| |
| |
| /********************************************************************************/ |
| /* */ |
| /* move-implementation */ |
| /* */ |
| /********************************************************************************/ |
| |
| // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath. |
| |
| |
| void |
| TaskManager::move( sal_Int32 CommandId, |
| const OUString& srcUnqPath, |
| const OUString& dstUnqPathIn, |
| const sal_Int32 NameClash ) |
| { |
| // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if |
| // srcUnqPath and dstUnqPathIn are equal |
| if( srcUnqPath == dstUnqPathIn ) |
| return; |
| |
| osl::FileBase::RC nError; |
| OUString dstUnqPath( dstUnqPathIn ); |
| |
| switch( NameClash ) |
| { |
| case NameClash::KEEP: |
| { |
| nError = osl_File_move( srcUnqPath,dstUnqPath,true ); |
| if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::KEEPERROR_FOR_MOVE, |
| nError ); |
| return; |
| } |
| break; |
| } |
| case NameClash::OVERWRITE: |
| { |
| // stat to determine whether we have a symlink |
| OUString targetPath(dstUnqPath); |
| |
| osl::FileStatus aStatus(osl_FileStatus_Mask_Type|osl_FileStatus_Mask_LinkTargetURL); |
| osl::DirectoryItem aItem; |
| (void)osl::DirectoryItem::get(dstUnqPath,aItem); |
| (void)aItem.getFileStatus(aStatus); |
| |
| if( aStatus.isValid(osl_FileStatus_Mask_Type) && |
| aStatus.isValid(osl_FileStatus_Mask_LinkTargetURL) && |
| aStatus.getFileType() == osl::FileStatus::Link ) |
| targetPath = aStatus.getLinkTargetURL(); |
| |
| // Will do nothing if file does not exist. |
| osl::File::remove( targetPath ); |
| |
| nError = osl_File_move( srcUnqPath,targetPath ); |
| if( nError != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::OVERWRITE_FOR_MOVE, |
| nError ); |
| return; |
| } |
| break; |
| } |
| case NameClash::RENAME: |
| { |
| OUString newDstUnqPath; |
| nError = osl_File_move( srcUnqPath,dstUnqPath,true ); |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| // "invent" a new valid title. |
| |
| sal_Int32 nPos = -1; |
| sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); |
| sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); |
| if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment |
| && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot |
| nPos = nLastDot; |
| else |
| nPos = dstUnqPath.getLength(); |
| |
| sal_Int32 nTry = 0; |
| |
| do |
| { |
| newDstUnqPath = dstUnqPath; |
| |
| OUString aPostfix = "_" + OUString::number( ++nTry ); |
| |
| newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix ); |
| |
| nError = osl_File_move( srcUnqPath,newDstUnqPath,true ); |
| } |
| while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); |
| } |
| |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::RENAME_FOR_MOVE ); |
| return; |
| } |
| else if( nError != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::RENAMEMOVE_FOR_MOVE, |
| nError ); |
| return; |
| } |
| else |
| dstUnqPath = newDstUnqPath; |
| |
| break; |
| } |
| case NameClash::ERROR: |
| { |
| nError = osl_File_move( srcUnqPath,dstUnqPath,true ); |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NAMECLASH_FOR_MOVE ); |
| return; |
| } |
| else if( nError != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NAMECLASHMOVE_FOR_MOVE, |
| nError ); |
| return; |
| } |
| break; |
| } |
| case NameClash::ASK: |
| default: |
| { |
| nError = osl_File_move( srcUnqPath,dstUnqPath,true ); |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NAMECLASHSUPPORT_FOR_MOVE, |
| NameClash::ASK); |
| return; |
| } |
| } |
| break; |
| } |
| |
| // Determine, whether we have moved a file or a folder |
| osl::DirectoryItem aItem; |
| nError = osl::DirectoryItem::get( dstUnqPath,aItem ); |
| if( nError != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::TRANSFER_BY_MOVE_SOURCE, |
| nError ); |
| return; |
| } |
| osl::FileStatus aStatus( osl_FileStatus_Mask_Type ); |
| nError = aItem.getFileStatus( aStatus ); |
| if( nError != osl::FileBase::E_None || ! aStatus.isValid( osl_FileStatus_Mask_Type ) ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::TRANSFER_BY_MOVE_SOURCESTAT, |
| nError ); |
| return; |
| } |
| bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular ); |
| |
| |
| copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument ); |
| |
| OUString aDstParent = getParentName( dstUnqPath ); |
| OUString aSrcParent = getParentName( srcUnqPath ); |
| |
| notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath ); |
| if( aDstParent != aSrcParent ) |
| notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath ); |
| |
| notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); |
| erasePersistentSet( srcUnqPath,!isDocument ); |
| } |
| |
| |
| /********************************************************************************/ |
| /* */ |
| /* copy-implementation */ |
| /* */ |
| /********************************************************************************/ |
| |
| // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories ) |
| |
| |
| namespace { |
| |
| bool getType( |
| TaskManager & task, sal_Int32 id, OUString const & fileUrl, |
| osl::DirectoryItem * item, osl::FileStatus::Type * type) |
| { |
| assert(item != nullptr && type != nullptr); |
| osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item); |
| if (err != osl::FileBase::E_None) { |
| task.installError(id, TaskHandlerErr::TRANSFER_BY_COPY_SOURCE, err); |
| return false; |
| } |
| osl::FileStatus stat(osl_FileStatus_Mask_Type); |
| err = item->getFileStatus(stat); |
| if (err != osl::FileBase::E_None) { |
| task.installError(id, TaskHandlerErr::TRANSFER_BY_COPY_SOURCESTAT, err); |
| return false; |
| } |
| *type = stat.getFileType(); |
| return true; |
| } |
| |
| } |
| |
| void |
| TaskManager::copy( |
| sal_Int32 CommandId, |
| const OUString& srcUnqPath, |
| const OUString& dstUnqPathIn, |
| sal_Int32 NameClash ) |
| { |
| osl::FileBase::RC nError; |
| OUString dstUnqPath( dstUnqPathIn ); |
| |
| // Resolve symbolic links within the source path. If srcUnqPath denotes a |
| // symbolic link (targeting either a file or a folder), the contents of the |
| // target is copied (recursively, in the case of a folder). However, if |
| // recursively copying the contents of a folder causes a symbolic link to be |
| // copied, the symbolic link itself is copied. |
| osl::DirectoryItem item; |
| osl::FileStatus::Type type; |
| if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { |
| return; |
| } |
| OUString rslvdSrcUnqPath; |
| if (type == osl::FileStatus::Link) { |
| osl::FileStatus stat(osl_FileStatus_Mask_LinkTargetURL); |
| nError = item.getFileStatus(stat); |
| if (nError != osl::FileBase::E_None) { |
| installError( |
| CommandId, TaskHandlerErr::TRANSFER_BY_COPY_SOURCESTAT, nError); |
| return; |
| } |
| rslvdSrcUnqPath = stat.getLinkTargetURL(); |
| if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { |
| return; |
| } |
| } else { |
| rslvdSrcUnqPath = srcUnqPath; |
| } |
| |
| bool isDocument |
| = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume; |
| FileUrlType IsWhat = isDocument ? FileUrlType::File : FileUrlType::Folder; |
| |
| switch( NameClash ) |
| { |
| case NameClash::KEEP: |
| { |
| nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); |
| if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::KEEPERROR_FOR_COPY, |
| nError ); |
| return; |
| } |
| break; |
| } |
| case NameClash::OVERWRITE: |
| { |
| // remove (..., MustExist = sal_False). |
| remove( CommandId, dstUnqPath, IsWhat, false ); |
| |
| // copy. |
| nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false ); |
| if( nError != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::OVERWRITE_FOR_COPY, |
| nError ); |
| return; |
| } |
| break; |
| } |
| case NameClash::RENAME: |
| { |
| OUString newDstUnqPath = dstUnqPath; |
| nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); |
| |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| // "invent" a new valid title. |
| |
| sal_Int32 nPos = -1; |
| sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); |
| sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); |
| if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment |
| && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot |
| nPos = nLastDot; |
| else |
| nPos = dstUnqPath.getLength(); |
| |
| sal_Int32 nTry = 0; |
| |
| do |
| { |
| newDstUnqPath = dstUnqPath; |
| |
| OUString aPostfix = "_" + OUString::number( ++nTry ); |
| |
| newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix ); |
| |
| nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true ); |
| } |
| while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); |
| } |
| |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::RENAME_FOR_COPY ); |
| return; |
| } |
| else if( nError != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::RENAMEMOVE_FOR_COPY, |
| nError ); |
| return; |
| } |
| else |
| dstUnqPath = newDstUnqPath; |
| |
| break; |
| } |
| case NameClash::ERROR: |
| { |
| nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); |
| |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NAMECLASH_FOR_COPY ); |
| return; |
| } |
| else if( nError != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NAMECLASHMOVE_FOR_COPY, |
| nError ); |
| return; |
| } |
| break; |
| } |
| case NameClash::ASK: |
| default: |
| { |
| nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); |
| |
| if( nError == osl::FileBase::E_EXIST ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NAMECLASHSUPPORT_FOR_COPY, |
| NameClash); |
| return; |
| } |
| break; |
| } |
| } |
| |
| copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument ); |
| notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath ); |
| } |
| |
| |
| /********************************************************************************/ |
| /* */ |
| /* remove-implementation */ |
| /* */ |
| /********************************************************************************/ |
| |
| // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory ) |
| // Return: success of operation |
| |
| |
| bool |
| TaskManager::remove( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| FileUrlType IsWhat, |
| bool MustExist ) |
| { |
| sal_Int32 nMask = osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL; |
| |
| osl::DirectoryItem aItem; |
| osl::FileStatus aStatus( nMask ); |
| osl::FileBase::RC nError; |
| |
| if( IsWhat == FileUrlType::Unknown ) // Determine whether we are removing a directory or a file |
| { |
| nError = osl::DirectoryItem::get( aUnqPath, aItem ); |
| if( nError != osl::FileBase::E_None ) |
| { |
| if (MustExist) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NOSUCHFILEORDIR_FOR_REMOVE, |
| nError ); |
| } |
| return (!MustExist); |
| } |
| |
| nError = aItem.getFileStatus( aStatus ); |
| if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::VALIDFILESTATUS_FOR_REMOVE, |
| nError != osl::FileBase::E_None ? nError : 0 ); |
| return false; |
| } |
| |
| if( aStatus.getFileType() == osl::FileStatus::Regular || |
| aStatus.getFileType() == osl::FileStatus::Link ) |
| IsWhat = FileUrlType::File; |
| else if( aStatus.getFileType() == osl::FileStatus::Directory || |
| aStatus.getFileType() == osl::FileStatus::Volume ) |
| IsWhat = FileUrlType::Folder; |
| } |
| |
| |
| if( IsWhat == FileUrlType::File ) |
| { |
| nError = osl::File::remove( aUnqPath ); |
| if( nError != osl::FileBase::E_None ) |
| { |
| if (MustExist) |
| { |
| installError( CommandId, |
| TaskHandlerErr::DELETEFILE_FOR_REMOVE, |
| nError ); |
| } |
| return (!MustExist); |
| } |
| else |
| { |
| notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); |
| erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet |
| } |
| } |
| else if( IsWhat == FileUrlType::Folder ) |
| { |
| osl::Directory aDirectory( aUnqPath ); |
| |
| nError = aDirectory.open(); |
| if( nError != osl::FileBase::E_None ) |
| { |
| if (MustExist) |
| { |
| installError( CommandId, |
| TaskHandlerErr::OPENDIRECTORY_FOR_REMOVE, |
| nError ); |
| } |
| return (!MustExist); |
| } |
| |
| bool whileSuccess = true; |
| FileUrlType recurse = FileUrlType::Unknown; |
| OUString name; |
| |
| nError = aDirectory.getNextItem( aItem ); |
| while( nError == osl::FileBase::E_None ) |
| { |
| nError = aItem.getFileStatus( aStatus ); |
| if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::VALIDFILESTATUSWHILE_FOR_REMOVE, |
| nError != osl::FileBase::E_None ? nError : 0 ); |
| whileSuccess = false; |
| break; |
| } |
| |
| if( aStatus.getFileType() == osl::FileStatus::Regular || |
| aStatus.getFileType() == osl::FileStatus::Link ) |
| recurse = FileUrlType::File; |
| else if( aStatus.getFileType() == osl::FileStatus::Directory || |
| aStatus.getFileType() == osl::FileStatus::Volume ) |
| recurse = FileUrlType::Folder; |
| |
| name = aStatus.getFileURL(); |
| whileSuccess = remove( CommandId, name, recurse, MustExist ); |
| if( !whileSuccess ) |
| break; |
| |
| nError = aDirectory.getNextItem( aItem ); |
| } |
| |
| aDirectory.close(); |
| |
| if( ! whileSuccess ) |
| return false; // error code is installed |
| |
| if( nError != osl::FileBase::E_NOENT ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::DIRECTORYEXHAUSTED_FOR_REMOVE, |
| nError ); |
| return false; |
| } |
| |
| nError = osl::Directory::remove( aUnqPath ); |
| if( nError != osl::FileBase::E_None ) |
| { |
| if (MustExist) |
| { |
| installError( CommandId, |
| TaskHandlerErr::DELETEDIRECTORY_FOR_REMOVE, |
| nError ); |
| } |
| return (!MustExist); |
| } |
| else |
| { |
| notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); |
| erasePersistentSet( aUnqPath ); |
| } |
| } |
| else // Don't know what to remove |
| { |
| installError( CommandId, |
| TaskHandlerErr::FILETYPE_FOR_REMOVE ); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| |
| /********************************************************************************/ |
| /* */ |
| /* mkdir-implementation */ |
| /* */ |
| /********************************************************************************/ |
| |
| // Creates new directory with given URL, recursively if necessary |
| // Return:: success of operation |
| |
| |
| bool |
| TaskManager::mkdir( sal_Int32 CommandId, |
| const OUString& rUnqPath, |
| bool OverWrite ) |
| { |
| OUString aUnqPath; |
| |
| // remove trailing slash |
| if ( rUnqPath.endsWith("/") ) |
| aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); |
| else |
| aUnqPath = rUnqPath; |
| |
| osl::FileBase::RC nError = osl::Directory::create( aUnqPath ); |
| |
| switch ( nError ) |
| { |
| case osl::FileBase::E_EXIST: // Directory cannot be overwritten |
| { |
| if( !OverWrite ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::FOLDER_EXISTS_MKDIR ); |
| return false; |
| } |
| else |
| return true; |
| } |
| case osl::FileBase::E_INVAL: |
| { |
| installError(CommandId, |
| TaskHandlerErr::INVALID_NAME_MKDIR); |
| return false; |
| } |
| case osl::FileBase::E_None: |
| { |
| OUString aPrtPath = getParentName( aUnqPath ); |
| notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); |
| return true; |
| } |
| default: |
| return ensuredir( |
| CommandId, |
| aUnqPath, |
| TaskHandlerErr::CREATEDIRECTORY_MKDIR ); |
| } |
| } |
| |
| |
| /********************************************************************************/ |
| /* */ |
| /* mkfil-implementation */ |
| /* */ |
| /********************************************************************************/ |
| |
| // Creates new file with given URL. |
| // The content of aInputStream becomes the content of the file |
| // Return:: success of operation |
| |
| |
| bool |
| TaskManager::mkfil( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| bool Overwrite, |
| const uno::Reference< io::XInputStream >& aInputStream ) |
| { |
| // return value unimportant |
| bool bSuccess = write( CommandId, |
| aUnqPath, |
| Overwrite, |
| aInputStream ); |
| if ( bSuccess ) |
| { |
| OUString aPrtPath = getParentName( aUnqPath ); |
| notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); |
| } |
| return bSuccess; |
| } |
| |
| |
| /********************************************************************************/ |
| /* */ |
| /* write-implementation */ |
| /* */ |
| /********************************************************************************/ |
| |
| // writes to the file with given URL. |
| // The content of aInputStream becomes the content of the file |
| // Return:: success of operation |
| |
| |
| bool |
| TaskManager::write( sal_Int32 CommandId, |
| const OUString& aUnqPath, |
| bool OverWrite, |
| const uno::Reference< io::XInputStream >& aInputStream ) |
| { |
| if( ! aInputStream.is() ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::INPUTSTREAM_FOR_WRITE ); |
| return false; |
| } |
| |
| // Create parent path, if necessary. |
| if ( ! ensuredir( CommandId, |
| getParentName( aUnqPath ), |
| TaskHandlerErr::ENSUREDIR_FOR_WRITE ) ) |
| return false; |
| |
| osl::FileBase::RC err; |
| osl::File aFile( aUnqPath ); |
| |
| if( OverWrite ) |
| { |
| err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ); |
| |
| if( err != osl::FileBase::E_None ) |
| { |
| aFile.close(); |
| err = aFile.open( osl_File_OpenFlag_Write ); |
| |
| if( err != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NO_OPEN_FILE_FOR_OVERWRITE, |
| err ); |
| return false; |
| } |
| |
| // the existing file was just opened and should be overwritten now, |
| // truncate it first |
| |
| err = aFile.setSize( 0 ); |
| if( err != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::FILESIZE_FOR_WRITE, |
| err ); |
| return false; |
| } |
| } |
| } |
| else |
| { |
| err = aFile.open( osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock ); |
| if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten |
| { |
| installError( CommandId, |
| TaskHandlerErr::NOREPLACE_FOR_WRITE, // Now an exception |
| err ); |
| |
| aFile.close(); |
| return false; |
| } |
| |
| // as a temporary solution the creation does not lock the file at all |
| // in future it should be possible to create the file without lock explicitly |
| err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock ); |
| |
| if( err != osl::FileBase::E_None ) |
| { |
| aFile.close(); |
| installError( CommandId, |
| TaskHandlerErr::NO_OPEN_FILE_FOR_WRITE, |
| err ); |
| return false; |
| } |
| } |
| |
| bool bSuccess = true; |
| |
| sal_uInt64 nWrittenBytes; |
| sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/; |
| uno::Sequence< sal_Int8 > seq( nRequestedBytes ); |
| |
| do |
| { |
| try |
| { |
| nReadBytes = aInputStream->readBytes( seq, |
| nRequestedBytes ); |
| } |
| catch( const io::NotConnectedException& ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::NOTCONNECTED_FOR_WRITE ); |
| bSuccess = false; |
| break; |
| } |
| catch( const io::BufferSizeExceededException& ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::BUFFERSIZEEXCEEDED_FOR_WRITE ); |
| bSuccess = false; |
| break; |
| } |
| catch( const io::IOException& ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::IOEXCEPTION_FOR_WRITE ); |
| bSuccess = false; |
| break; |
| } |
| |
| if( nReadBytes ) |
| { |
| const sal_Int8* p = seq.getConstArray(); |
| |
| err = aFile.write( static_cast<void const *>(p), |
| sal_uInt64( nReadBytes ), |
| nWrittenBytes ); |
| |
| if( err != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::FILEIOERROR_FOR_WRITE, |
| err ); |
| bSuccess = false; |
| break; |
| } |
| else if( nWrittenBytes != sal_uInt64( nReadBytes ) ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::FILEIOERROR_FOR_NO_SPACE ); |
| bSuccess = false; |
| break; |
| } |
| } |
| } while( nReadBytes == nRequestedBytes ); |
| |
| err = aFile.close(); |
| if( err != osl::FileBase::E_None ) |
| { |
| installError( CommandId, |
| TaskHandlerErr::FILEIOERROR_FOR_WRITE, |
| err ); |
| bSuccess = false; |
| } |
| |
| return bSuccess; |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* insertDefaultProperties-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| |
| void TaskManager::insertDefaultProperties( const OUString& aUnqPath ) |
| { |
| std::unique_lock aGuard(m_aMutex); |
| insertDefaultProperties(aGuard, aUnqPath); |
| } |
| |
| void TaskManager::insertDefaultProperties( std::unique_lock<std::mutex>& /*rGuard*/, const OUString& aUnqPath ) |
| { |
| ContentMap::iterator it = |
| m_aContent.emplace( aUnqPath,UnqPathData() ).first; |
| |
| load( it, false ); |
| |
| MyProperty ContentTProperty( ContentType ); |
| |
| PropertySet& properties = it->second.properties; |
| bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end(); |
| |
| properties.reserve(properties.size() + m_aDefaultProperties.size()); |
| for (auto const& defaultprop : m_aDefaultProperties) |
| { |
| if( !ContentNotDefau || defaultprop.getPropertyName() != ContentType ) |
| properties.insert( defaultprop ); |
| } |
| } |
| |
| |
| /******************************************************************************/ |
| /* */ |
| /* mapping of file urls */ |
| /* to uncpath and vice versa */ |
| /* */ |
| /******************************************************************************/ |
| |
| |
| bool TaskManager::getUnqFromUrl( const OUString& Url, OUString& Unq ) |
| { |
| if ( Url == "file:///" || Url == "file://localhost/" || Url == "file://127.0.0.1/" ) |
| { |
| Unq = "file:///"; |
| return false; |
| } |
| |
| bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq ); |
| |
| Unq = Url; |
| |
| sal_Int32 l = Unq.getLength()-1; |
| if( ! err && Unq.endsWith("/") && |
| Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) != -1 ) |
| Unq = Unq.copy(0, l); |
| |
| return err; |
| } |
| |
| |
| bool TaskManager::getUrlFromUnq( const OUString& Unq,OUString& Url ) |
| { |
| bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url ); |
| |
| Url = Unq; |
| |
| return err; |
| } |
| |
| |
| // Helper function for public copy |
| |
| osl::FileBase::RC |
| TaskManager::copy_recursive( const OUString& srcUnqPath, |
| const OUString& dstUnqPath, |
| FileUrlType TypeToCopy, |
| bool testExistBeforeCopy ) |
| { |
| osl::FileBase::RC err = osl::FileBase::E_None; |
| |
| if( TypeToCopy == FileUrlType::File ) // Document |
| { |
| err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy ); |
| } |
| else if( TypeToCopy == FileUrlType::Folder ) |
| { |
| osl::Directory aDir( srcUnqPath ); |
| (void)aDir.open(); |
| |
| err = osl::Directory::create( dstUnqPath ); |
| osl::FileBase::RC next = err; |
| if( err == osl::FileBase::E_None ) |
| { |
| sal_Int32 const n_Mask = osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Type; |
| |
| osl::DirectoryItem aDirItem; |
| |
| while( err == osl::FileBase::E_None ) |
| { |
| next = aDir.getNextItem( aDirItem ); |
| if (next != osl::FileBase::E_None ) |
| break; |
| bool IsDoc = false; |
| osl::FileStatus aFileStatus( n_Mask ); |
| aDirItem.getFileStatus( aFileStatus ); |
| if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) ) |
| IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; |
| |
| // Getting the information for the next recursive copy |
| FileUrlType newTypeToCopy = IsDoc ? FileUrlType::File : FileUrlType::Folder; |
| |
| OUString newSrcUnqPath; |
| if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) ) |
| newSrcUnqPath = aFileStatus.getFileURL(); |
| |
| OUString newDstUnqPath = dstUnqPath; |
| OUString tit; |
| if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) ) |
| tit = rtl::Uri::encode( aFileStatus.getFileName(), |
| rtl_UriCharClassPchar, |
| rtl_UriEncodeIgnoreEscapes, |
| RTL_TEXTENCODING_UTF8 ); |
| |
| if( !newDstUnqPath.endsWith( "/" ) ) |
| newDstUnqPath += "/"; |
| |
| newDstUnqPath += tit; |
| |
| if ( newSrcUnqPath != dstUnqPath ) |
| err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false ); |
| } |
| |
| if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) |
| err = next; |
| } |
| aDir.close(); |
| } |
| |
| return err; |
| } |
| |
| |
| // Helper function for mkfil,mkdir and write |
| // Creates whole path |
| // returns success of the operation |
| |
| |
| bool TaskManager::ensuredir( sal_Int32 CommandId, |
| const OUString& rUnqPath, |
| TaskHandlerErr errorCode ) |
| { |
| OUString aPath; |
| |
| if ( rUnqPath.isEmpty() ) |
| return false; |
| |
| if ( rUnqPath.endsWith("/") ) |
| aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); |
| else |
| aPath = rUnqPath; |
| |
| #if HAVE_FEATURE_MACOSX_SANDBOX |
| |
| // Avoid annoying sandbox messages in the system.log from the |
| // below aDirectory.open(), which ends up calling opendir(). |
| // Surely it is easier to just call stat()? Calling stat() on an |
| // arbitrary (?) directory does not seem to cause any sandbox |
| // violation, while opendir() does. (Sorry I could not be bothered |
| // to use some complex cross-platform abstraction over stat() here |
| // in this macOS specific code block.) |
| |
| OUString aDirName; |
| struct stat s; |
| if( osl::FileBase::getSystemPathFromFileURL( aPath, aDirName ) == osl::FileBase::E_None && |
| stat(OUStringToOString( aDirName, RTL_TEXTENCODING_UTF8).getStr(), &s ) == 0 && |
| S_ISDIR( s.st_mode ) ) |
| return sal_True; |
| #endif |
| |
| // HACK: create directory on a mount point with nobrowse option |
| // returns ENOSYS in any case !! |
| osl::Directory aDirectory( aPath ); |
| osl::FileBase::RC nError = aDirectory.open(); |
| aDirectory.close(); |
| |
| if( nError == osl::File::E_None ) |
| return true; |
| |
| nError = osl::Directory::create( aPath ); |
| |
| if( nError == osl::File::E_None ) |
| notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); |
| |
| bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); |
| |
| if( ! bSuccess ) |
| { |
| OUString aParentDir = getParentName( aPath ); |
| |
| if ( aParentDir != aPath ) |
| { // Create first the parent directory |
| bSuccess = ensuredir( CommandId, |
| getParentName( aPath ), |
| errorCode ); |
| |
| // After parent directory structure exists try it one's more |
| |
| if ( bSuccess ) |
| { // Parent directory exists, retry creation of directory |
| nError = osl::Directory::create( aPath ); |
| |
| if( nError == osl::File::E_None ) |
| notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); |
| |
| bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); |
| } |
| } |
| } |
| |
| if( ! bSuccess ) |
| installError( CommandId, |
| errorCode, |
| nError ); |
| |
| return bSuccess; |
| } |
| |
| |
| // Given a sequence of properties seq, this method determines the mask |
| // used to instantiate an osl::FileStatus, so that a call to |
| // osl::DirectoryItem::getFileStatus fills the required fields. |
| |
| |
| void |
| TaskManager::getMaskFromProperties( |
| sal_Int32& n_Mask, |
| const uno::Sequence< beans::Property >& seq ) |
| { |
| n_Mask = 0; |
| for(const auto& rProp : seq) { |
| if(rProp.Name == Title) |
| n_Mask |= osl_FileStatus_Mask_FileName; |
| else if(rProp.Name == CasePreservingURL) |
| n_Mask |= osl_FileStatus_Mask_FileURL; |
| else if(rProp.Name == IsDocument || |
| rProp.Name == IsFolder || |
| rProp.Name == IsVolume || |
| rProp.Name == IsRemoveable || |
| rProp.Name == IsRemote || |
| rProp.Name == IsCompactDisc || |
| rProp.Name == IsFloppy || |
| rProp.Name == ContentType) |
| n_Mask |= (osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL); |
| else if(rProp.Name == Size) |
| n_Mask |= (osl_FileStatus_Mask_FileSize | |
| osl_FileStatus_Mask_Type | |
| osl_FileStatus_Mask_LinkTargetURL); |
| else if(rProp.Name == IsHidden || |
| rProp.Name == IsReadOnly) |
| n_Mask |= osl_FileStatus_Mask_Attributes; |
| else if(rProp.Name == DateModified) |
| n_Mask |= osl_FileStatus_Mask_ModifyTime; |
| } |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* load-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| |
| // Load the properties from configuration, if create == true create them. |
| // The Properties are stored under the url belonging to it->first. |
| |
| |
| void |
| TaskManager::load( const ContentMap::iterator& it, bool create ) |
| { |
| if( ( it->second.xS.is() && it->second.xC.is() && it->second.xA.is() ) |
| || !m_xFileRegistry.is() ) |
| return; |
| |
| |
| uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create ); |
| if( xS.is() ) |
| { |
| it->second.xS = xS; |
| it->second.xC.set(xS, uno::UNO_QUERY); |
| it->second.xA.set(xS, uno::UNO_QUERY); |
| |
| // Now put in all values in the storage in the local hash; |
| |
| PropertySet& properties = it->second.properties; |
| const uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties(); |
| |
| for( const auto& rProp : seq ) |
| { |
| MyProperty readProp( false, |
| rProp.Name, |
| rProp.Handle, |
| rProp.Type, |
| xS->getPropertyValue( rProp.Name ), |
| beans::PropertyState_DIRECT_VALUE, |
| rProp.Attributes ); |
| properties.insert( readProp ); |
| } |
| } |
| else if( create ) |
| { |
| // Catastrophic error |
| } |
| } |
| |
| |
| /*********************************************************************************/ |
| /* */ |
| /* commit-Implementation */ |
| /* */ |
| /*********************************************************************************/ |
| // Commit inserts the determined properties in the filestatus object into |
| // the internal map, so that is possible to determine on a subsequent |
| // setting of file properties which properties have changed without filestat |
| |
| |
| void |
| TaskManager::commit( std::unique_lock<std::mutex>& rGuard, |
| const TaskManager::ContentMap::iterator& it, |
| const osl::FileStatus& aFileStatus ) |
| { |
| TaskManager::PropertySet::const_iterator it1; |
| |
| if( it->second.properties.empty() ) |
| { |
| OUString aPath = it->first; |
| insertDefaultProperties( rGuard, aPath ); |
| } |
| |
| PropertySet& properties = it->second.properties; |
| |
| it1 = properties.find( MyProperty( Title ) ); |
| if( it1 != properties.end() ) |
| { |
| if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) ) |
| { |
| it1->setValue( uno::Any(aFileStatus.getFileName()) ); |
| } |
| } |
| |
| it1 = properties.find( MyProperty( CasePreservingURL ) ); |
| if( it1 != properties.end() ) |
| { |
| if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) ) |
| { |
| it1->setValue( uno::Any(aFileStatus.getFileURL()) ); |
| } |
| } |
| |
| |
| bool isDirectory; |
| |
| sal_Int64 dirSize = 0; |
| |
| if( aFileStatus.isValid( osl_FileStatus_Mask_FileSize ) ) |
| dirSize = aFileStatus.getFileSize(); |
| |
| if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) ) |
| { |
| bool isFile,isVolume; |
| if( osl::FileStatus::Link == aFileStatus.getFileType() && |
| aFileStatus.isValid( osl_FileStatus_Mask_LinkTargetURL ) ) |
| { |
| osl::DirectoryItem aDirItem; |
| osl::FileStatus aFileStatus2( osl_FileStatus_Mask_Type ); |
| if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) && |
| osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) && |
| aFileStatus2.isValid( osl_FileStatus_Mask_Type ) ) |
| { |
| isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType(); |
| isDirectory = |
| osl::FileStatus::Volume == aFileStatus2.getFileType() || |
| osl::FileStatus::Directory == aFileStatus2.getFileType(); |
| isFile = |
| osl::FileStatus::Regular == aFileStatus2.getFileType(); |
| |
| if( aFileStatus2.isValid( osl_FileStatus_Mask_FileSize ) ) |
| dirSize = aFileStatus2.getFileSize(); |
| } |
| else |
| { |
| // extremely ugly, but otherwise default construction |
| // of aDirItem and aFileStatus2 |
| // before the preceding if |
| isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); |
| isDirectory = |
| osl::FileStatus::Volume == aFileStatus.getFileType() || |
| osl::FileStatus::Directory == aFileStatus.getFileType(); |
| isFile = |
| osl::FileStatus::Regular == aFileStatus.getFileType(); |
| } |
| } |
| else |
| { |
| isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); |
| isDirectory = |
| osl::FileStatus::Volume == aFileStatus.getFileType() || |
| osl::FileStatus::Directory == aFileStatus.getFileType(); |
| isFile = |
| osl::FileStatus::Regular == aFileStatus.getFileType(); |
| } |
| |
| it1 = properties.find( MyProperty( IsVolume ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( isVolume ) ); |
| |
| it1 = properties.find( MyProperty( IsFolder ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( isDirectory ) ); |
| |
| it1 = properties.find( MyProperty( IsDocument ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( isFile ) ); |
| |
| osl::VolumeInfo aVolumeInfo( osl_VolumeInfo_Mask_Attributes ); |
| if( isVolume && |
| osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) && |
| aVolumeInfo.isValid( osl_VolumeInfo_Mask_Attributes ) ) |
| { |
| // Retrieve the flags; |
| bool isRemote = aVolumeInfo.getRemoteFlag(); |
| bool isRemoveable = aVolumeInfo.getRemoveableFlag(); |
| bool isCompactDisc = aVolumeInfo.getCompactDiscFlag(); |
| bool isFloppy = aVolumeInfo.getFloppyDiskFlag(); |
| |
| it1 = properties.find( MyProperty( IsRemote ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( isRemote ) ); |
| |
| it1 = properties.find( MyProperty( IsRemoveable ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( isRemoveable ) ); |
| |
| it1 = properties.find( MyProperty( IsCompactDisc ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( isCompactDisc ) ); |
| |
| it1 = properties.find( MyProperty( IsFloppy ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( isFloppy ) ); |
| } |
| else |
| { |
| uno::Any aAny(false); |
| it1 = properties.find( MyProperty( IsRemote ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( aAny ); |
| |
| it1 = properties.find( MyProperty( IsRemoveable ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( aAny ); |
| |
| it1 = properties.find( MyProperty( IsCompactDisc ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( aAny ); |
| |
| it1 = properties.find( MyProperty( IsFloppy ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( aAny ); |
| } |
| } |
| else |
| { |
| isDirectory = false; |
| } |
| |
| it1 = properties.find( MyProperty( Size ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( dirSize ) ); |
| |
| it1 = properties.find( MyProperty( IsReadOnly ) ); |
| if( it1 != properties.end() ) |
| { |
| if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) ) |
| { |
| sal_uInt64 Attr = aFileStatus.getAttributes(); |
| bool readonly = ( Attr & osl_File_Attribute_ReadOnly ) != 0; |
| it1->setValue( uno::Any( readonly ) ); |
| } |
| } |
| |
| it1 = properties.find( MyProperty( IsHidden ) ); |
| if( it1 != properties.end() ) |
| { |
| if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) ) |
| { |
| sal_uInt64 Attr = aFileStatus.getAttributes(); |
| bool ishidden = ( Attr & osl_File_Attribute_Hidden ) != 0; |
| it1->setValue( uno::Any( ishidden ) ); |
| } |
| } |
| |
| it1 = properties.find( MyProperty( DateModified ) ); |
| if( it1 != properties.end() ) |
| { |
| if( aFileStatus.isValid( osl_FileStatus_Mask_ModifyTime ) ) |
| { |
| TimeValue temp = aFileStatus.getModifyTime(); |
| |
| // Convert system time to local time (for EA) |
| TimeValue myLocalTime; |
| if (!osl_getLocalTimeFromSystemTime( &temp, &myLocalTime )) |
| { |
| SAL_WARN( |
| "ucb.ucp.file", |
| "cannot convert (" << temp.Seconds << ", " << temp.Nanosec |
| << ") to local time"); |
| myLocalTime = temp; |
| } |
| |
| oslDateTime myDateTime; |
| osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime ); |
| util::DateTime aDateTime; |
| |
| aDateTime.NanoSeconds = myDateTime.NanoSeconds; |
| aDateTime.Seconds = myDateTime.Seconds; |
| aDateTime.Minutes = myDateTime.Minutes; |
| aDateTime.Hours = myDateTime.Hours; |
| aDateTime.Day = myDateTime.Day; |
| aDateTime.Month = myDateTime.Month; |
| aDateTime.Year = myDateTime.Year; |
| it1->setValue( uno::Any( aDateTime ) ); |
| } |
| } |
| |
| it1 = properties.find( MyProperty( CreatableContentsInfo ) ); |
| if( it1 != properties.end() ) |
| it1->setValue( uno::Any( |
| isDirectory || !aFileStatus.isValid( osl_FileStatus_Mask_Type ) |
| ? queryCreatableContentsInfo() |
| : uno::Sequence< ucb::ContentInfo >() ) ); |
| } |
| |
| |
| // Special optimized method for getting the properties of a |
| // directoryitem, which is returned by osl::DirectoryItem::getNextItem() |
| |
| |
| bool |
| TaskManager::getv( |
| const uno::Sequence< beans::Property >& properties, |
| osl::DirectoryItem& aDirItem, |
| OUString& aUnqPath, |
| bool& aIsRegular, |
| uno::Reference< sdbc::XRow > & row ) |
| { |
| uno::Sequence< uno::Any > seq( properties.getLength() ); |
| |
| sal_Int32 n_Mask; |
| getMaskFromProperties( n_Mask,properties ); |
| |
| // Always retrieve the type and the target URL because item might be a link |
| osl::FileStatus aFileStatus( n_Mask | |
| osl_FileStatus_Mask_FileURL | |
| osl_FileStatus_Mask_Type | |
| osl_FileStatus_Mask_LinkTargetURL ); |
| |
| osl::FileBase::RC aRes = aDirItem.getFileStatus( aFileStatus ); |
| if ( aRes != osl::FileBase::E_None ) |
| { |
| SAL_WARN( |
| "ucb.ucp.file", |
| "osl::DirectoryItem::getFileStatus failed with " << +aRes); |
| return false; |
| } |
| |
| aUnqPath = aFileStatus.getFileURL(); |
| |
| // If the directory item type is a link retrieve the type of the target |
| |
| if ( aFileStatus.getFileType() == osl::FileStatus::Link ) |
| { |
| // Assume failure |
| aIsRegular = false; |
| osl::DirectoryItem aTargetItem; |
| (void)osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem ); |
| if ( aTargetItem.is() ) |
| { |
| osl::FileStatus aTargetStatus( osl_FileStatus_Mask_Type ); |
| |
| if ( osl::FileBase::E_None == aTargetItem.getFileStatus( aTargetStatus ) ) |
| aIsRegular = |
| aTargetStatus.getFileType() == osl::FileStatus::Regular; |
| } |
| } |
| else |
| aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular; |
| |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| |
| insertDefaultProperties( aGuard, aUnqPath ); |
| |
| TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath ); |
| commit( aGuard, it, aFileStatus ); |
| |
| PropertySet& propset = it->second.properties; |
| |
| std::transform(properties.begin(), properties.end(), seq.getArray(), |
| [&propset](const beans::Property& rProp) -> uno::Any { |
| MyProperty readProp( rProp.Name ); |
| auto it1 = propset.find( readProp ); |
| if( it1 == propset.end() ) |
| return uno::Any(); |
| return it1->getValue(); |
| }); |
| } |
| |
| row = new XRow_impl( this,seq ); |
| return true; |
| } |
| |
| |
| // EventListener |
| |
| |
| std::vector< ContentEventNotifier > |
| TaskManager::getContentEventListeners( const OUString& aName ) |
| { |
| std::vector< ContentEventNotifier > listeners; |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskManager::ContentMap::iterator it = m_aContent.find( aName ); |
| if( it != m_aContent.end() && !it->second.notifier.empty() ) |
| { |
| std::vector<Notifier*>& listOfNotifiers = it->second.notifier; |
| for (auto const& pointer : listOfNotifiers) |
| { |
| std::optional<ContentEventNotifier> notifier = pointer->cCEL(); |
| if( notifier ) |
| listeners.push_back( std::move(*notifier) ); |
| } |
| } |
| } |
| return listeners; |
| } |
| |
| |
| std::vector< ContentEventNotifier > |
| TaskManager::getContentDeletedEventListeners( const OUString& aName ) |
| { |
| std::vector< ContentEventNotifier > listeners; |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskManager::ContentMap::iterator it = m_aContent.find( aName ); |
| if( it != m_aContent.end() && !it->second.notifier.empty() ) |
| { |
| std::vector<Notifier*>& listOfNotifiers = it->second.notifier; |
| for (auto const& pointer : listOfNotifiers) |
| { |
| std::optional<ContentEventNotifier> notifier = pointer->cDEL(); |
| if( notifier ) |
| listeners.push_back( std::move(*notifier) ); |
| } |
| } |
| } |
| return listeners; |
| } |
| |
| void TaskManager::notifyInsert(const std::vector<ContentEventNotifier>& listeners, |
| const OUString& aChildName) |
| { |
| for (const auto & l : listeners ) |
| { |
| l.notifyChildInserted( aChildName ); |
| } |
| } |
| |
| void TaskManager::notifyContentDeleted( |
| const std::vector<ContentEventNotifier>& listeners) |
| { |
| for( auto const & l : listeners ) |
| { |
| l.notifyDeleted(); |
| } |
| } |
| |
| void TaskManager::notifyContentRemoved( |
| const std::vector<ContentEventNotifier>& listeners, const OUString& aChildName) |
| { |
| for( auto const & l : listeners ) |
| { |
| l.notifyRemoved( aChildName ); |
| } |
| } |
| |
| |
| std::vector< PropertySetInfoChangeNotifier > |
| TaskManager::getPropertySetListeners( const OUString& aName ) |
| { |
| std::vector< PropertySetInfoChangeNotifier > listeners; |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskManager::ContentMap::iterator it = m_aContent.find( aName ); |
| if( it != m_aContent.end() && !it->second.notifier.empty() ) |
| { |
| std::vector<Notifier*>& listOfNotifiers = it->second.notifier; |
| for (auto const& pointer : listOfNotifiers) |
| { |
| std::optional<PropertySetInfoChangeNotifier> notifier = pointer->cPSL(); |
| if( notifier ) |
| listeners.push_back( std::move(*notifier) ); |
| } |
| } |
| } |
| return listeners; |
| } |
| |
| void TaskManager::notifyPropertyAdded( |
| const std::vector<PropertySetInfoChangeNotifier>& listeners, |
| const OUString& aPropertyName) |
| { |
| for( auto const & l : listeners ) |
| { |
| l.notifyPropertyAdded( aPropertyName ); |
| } |
| } |
| |
| void TaskManager::notifyPropertyRemoved( |
| const std::vector<PropertySetInfoChangeNotifier>& listeners, |
| const OUString& aPropertyName) |
| { |
| for( auto const & l : listeners ) |
| { |
| l.notifyPropertyRemoved( aPropertyName ); |
| } |
| } |
| |
| |
| std::vector< ContentEventNotifier > |
| TaskManager::getContentExchangedEventListeners( const OUString& aOldPrefix, |
| const OUString& aNewPrefix, |
| bool withChildren ) |
| { |
| std::vector< ContentEventNotifier > aVector; |
| |
| sal_Int32 count; |
| OUString aOldName; |
| OUString aNewName; |
| std::vector< OUString > oldChildList; |
| |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| |
| if( ! withChildren ) |
| { |
| aOldName = aOldPrefix; |
| aNewName = aNewPrefix; |
| count = 1; |
| } |
| else |
| { |
| for (auto const& content : m_aContent) |
| { |
| if( isChild( aOldPrefix, content.first ) ) |
| { |
| oldChildList.push_back( content.first ); |
| } |
| } |
| count = oldChildList.size(); |
| } |
| |
| |
| for( sal_Int32 j = 0; j < count; ++j ) |
| { |
| if( withChildren ) |
| { |
| aOldName = oldChildList[j]; |
| aNewName = newName( aNewPrefix,aOldPrefix,aOldName ); |
| } |
| |
| TaskManager::ContentMap::iterator itold = m_aContent.find( aOldName ); |
| if( itold != m_aContent.end() ) |
| { |
| TaskManager::ContentMap::iterator itnew = m_aContent.emplace( |
| aNewName,UnqPathData() ).first; |
| |
| // copy Ownership also |
| itnew->second.properties = std::move(itold->second.properties); |
| |
| // copy existing list |
| std::vector< Notifier* > copyList; |
| std::swap(copyList, itnew->second.notifier); |
| itnew->second.notifier = std::move(itold->second.notifier); |
| |
| m_aContent.erase( itold ); |
| |
| if (itnew != m_aContent.end()) |
| { |
| if (!itnew->second.notifier.empty()) |
| { |
| std::vector<Notifier*>& listOfNotifiers = itnew->second.notifier; |
| for (auto const& pointer : listOfNotifiers) |
| { |
| std::optional<ContentEventNotifier> notifier = pointer->cEXC( aNewName ); |
| if( notifier ) |
| aVector.push_back( std::move(*notifier) ); |
| } |
| } |
| |
| // Merge with preexisting notifiers |
| // However, these may be in status BaseContent::Deleted |
| itnew->second.notifier.insert(itnew->second.notifier.end(), |
| copyList.begin(), copyList.end() ); |
| } |
| } |
| } |
| } |
| |
| return aVector; |
| } |
| |
| void TaskManager::notifyContentExchanged( |
| const std::vector<ContentEventNotifier>& listeners_vec) |
| { |
| for( auto & l : listeners_vec) |
| { |
| l.notifyExchanged(); |
| } |
| } |
| |
| |
| std::vector< PropertyChangeNotifier > |
| TaskManager::getPropertyChangeNotifier( const OUString& aName ) |
| { |
| std::vector< PropertyChangeNotifier > listeners; |
| { |
| std::unique_lock aGuard( m_aMutex ); |
| TaskManager::ContentMap::iterator it = m_aContent.find( aName ); |
| if( it != m_aContent.end() && !it->second.notifier.empty() ) |
| { |
| std::vector<Notifier*>& listOfNotifiers = it->second.notifier; |
| for (auto const& pointer : listOfNotifiers) |
| { |
| std::optional<PropertyChangeNotifier> notifier = pointer->cPCL(); |
| if( notifier ) |
| listeners.push_back( std::move(*notifier) ); |
| } |
| } |
| } |
| return listeners; |
| } |
| |
| void TaskManager::notifyPropertyChanges( |
| const std::vector<PropertyChangeNotifier>& listeners, |
| const uno::Sequence<beans::PropertyChangeEvent>& seqChanged) |
| { |
| for( auto const & l : listeners ) |
| { |
| l.notifyPropertyChanged( seqChanged ); |
| } |
| } |
| |
| |
| /********************************************************************************/ |
| /* remove persistent propertyset */ |
| /********************************************************************************/ |
| |
| void |
| TaskManager::erasePersistentSetWithoutChildren( const OUString& aUnqPath ) |
| { |
| { |
| // Release possible references |
| std::unique_lock aGuard( m_aMutex ); |
| ContentMap::iterator it = m_aContent.find( aUnqPath ); |
| if( it != m_aContent.end() ) |
| { |
| it->second.xS = nullptr; |
| it->second.xC = nullptr; |
| it->second.xA = nullptr; |
| |
| it->second.properties.clear(); |
| } |
| } |
| |
| m_xFileRegistry->removePropertySet( aUnqPath ); |
| } |
| |
| void |
| TaskManager::erasePersistentSet( const OUString& aUnqPath, |
| bool withChildren ) |
| { |
| if( ! m_xFileRegistry.is() ) |
| { |
| OSL_ASSERT( m_xFileRegistry.is() ); |
| return; |
| } |
| |
| if( ! withChildren ) |
| { |
| erasePersistentSetWithoutChildren(aUnqPath); |
| return; |
| } |
| |
| uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); |
| const uno::Sequence< OUString > seqNames = xName->getElementNames(); |
| |
| OUString old_Name = aUnqPath; |
| |
| for( const auto& rName : seqNames ) |
| { |
| if( ! ( isChild( old_Name,rName ) ) ) |
| continue; |
| |
| old_Name = rName; |
| |
| erasePersistentSetWithoutChildren(old_Name); |
| } |
| } |
| |
| |
| /********************************************************************************/ |
| /* copy persistent propertyset */ |
| /* from srcUnqPath to dstUnqPath */ |
| /********************************************************************************/ |
| |
| void |
| TaskManager::copyPersistentSetWithoutChildren( const OUString& srcUnqPath, |
| const OUString& dstUnqPath ) |
| { |
| uno::Reference< XPersistentPropertySet > x_src = |
| m_xFileRegistry->openPropertySet( srcUnqPath,false ); |
| m_xFileRegistry->removePropertySet( dstUnqPath ); |
| |
| if( ! x_src.is() ) |
| return; |
| |
| const uno::Sequence< beans::Property > seqProperty = |
| x_src->getPropertySetInfo()->getProperties(); |
| |
| if( ! seqProperty.hasElements() ) |
| return; |
| |
| uno::Reference< XPersistentPropertySet > |
| x_dstS = m_xFileRegistry->openPropertySet( dstUnqPath,true ); |
| uno::Reference< beans::XPropertyContainer > |
| x_dstC( x_dstS,uno::UNO_QUERY ); |
| |
| for( const auto& rProperty : seqProperty ) |
| { |
| x_dstC->addProperty( rProperty.Name, |
| rProperty.Attributes, |
| x_src->getPropertyValue( rProperty.Name ) ); |
| } |
| } |
| |
| void |
| TaskManager::copyPersistentSet( const OUString& srcUnqPath, |
| const OUString& dstUnqPath, |
| bool withChildren ) |
| { |
| if( ! m_xFileRegistry.is() ) |
| { |
| OSL_ASSERT( m_xFileRegistry.is() ); |
| return; |
| } |
| |
| if( ! withChildren ) |
| { |
| copyPersistentSetWithoutChildren(srcUnqPath, dstUnqPath); |
| return; |
| } |
| |
| uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); |
| const uno::Sequence< OUString > seqNames = xName->getElementNames(); |
| |
| OUString new_Name; |
| |
| for( const auto& rName : seqNames ) |
| { |
| if( ! ( isChild( srcUnqPath,rName ) ) ) |
| continue; |
| |
| new_Name = newName( dstUnqPath,srcUnqPath,rName ); |
| |
| copyPersistentSetWithoutChildren(rName, new_Name); |
| } |
| } |
| |
| uno::Sequence< ucb::ContentInfo > TaskManager::queryCreatableContentsInfo() |
| { |
| |
| |
| uno::Sequence< beans::Property > props |
| { |
| { u"Title"_ustr, -1, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND } |
| }; |
| return |
| { |
| { FileContentType, ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | ucb::ContentInfoAttribute::KIND_DOCUMENT, props }, |
| { FolderContentType, ucb::ContentInfoAttribute::KIND_FOLDER, props } |
| }; |
| } |
| |
| /*******************************************************************************/ |
| /* */ |
| /* some miscellaneous static functions */ |
| /* */ |
| /*******************************************************************************/ |
| |
| void |
| TaskManager::getScheme( OUString& Scheme ) |
| { |
| Scheme = "file"; |
| } |
| |
| /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |