2937 lines
102 KiB
C++
2937 lines
102 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice 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;
|
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
#define THROW_WHERE SAL_WHERE
|
|
#else
|
|
#define THROW_WHERE ""
|
|
#endif
|
|
|
|
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( THROW_WHERE );
|
|
|
|
{
|
|
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(THROW_WHERE );
|
|
|
|
// 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( THROW_WHERE );
|
|
|
|
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 )
|
|
{
|
|
// coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
|
|
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( THROW_WHERE );
|
|
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( THROW_WHERE );
|
|
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( THROW_WHERE );
|
|
}
|
|
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( THROW_WHERE );
|
|
}
|
|
}
|
|
} // 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: */
|