1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <sal/config.h>
23 #include <sal/log.hxx>
25 #if HAVE_FEATURE_MACOSX_SANDBOX
29 #include <com/sun/star/beans/IllegalTypeException.hpp>
30 #include <com/sun/star/beans/NotRemoveableException.hpp>
31 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/beans/PropertyExistException.hpp>
33 #include <com/sun/star/io/BufferSizeExceededException.hpp>
34 #include <com/sun/star/io/NotConnectedException.hpp>
35 #include <com/sun/star/io/IOException.hpp>
36 #include <com/sun/star/lang/IllegalAccessException.hpp>
37 #include <com/sun/star/task/InteractionClassification.hpp>
38 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
39 #include <com/sun/star/ucb/DuplicateCommandIdentifierException.hpp>
40 #include <com/sun/star/ucb/IOErrorCode.hpp>
41 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
42 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
43 #include <com/sun/star/ucb/NameClash.hpp>
44 #include <com/sun/star/ucb/OpenCommandArgument.hpp>
45 #include <com/sun/star/ucb/Store.hpp>
46 #include <com/sun/star/ucb/TransferInfo.hpp>
47 #include <comphelper/propertysequence.hxx>
48 #include <rtl/ref.hxx>
49 #include <rtl/uri.hxx>
51 #include "filtask.hxx"
53 #include "filglob.hxx"
54 #include "filinpstr.hxx"
56 #include "filrset.hxx"
60 /******************************************************************************/
64 /******************************************************************************/
67 using namespace fileaccess
;
68 using namespace com::sun::star
;
69 using namespace com::sun::star::uno
;
70 using namespace com::sun::star::ucb
;
72 #if OSL_DEBUG_LEVEL > 0
73 #define THROW_WHERE SAL_WHERE
75 #define THROW_WHERE ""
78 TaskManager::UnqPathData::UnqPathData() = default;
80 TaskManager::UnqPathData::UnqPathData(TaskManager::UnqPathData
&&) = default;
83 TaskManager::UnqPathData::~UnqPathData()
87 TaskManager::MyProperty::MyProperty( const OUString
& thePropertyName
)
88 : PropertyName( thePropertyName
)
91 , State(beans::PropertyState_AMBIGUOUS_VALUE
)
97 TaskManager::MyProperty::MyProperty( bool theisNative
,
98 const OUString
& thePropertyName
,
100 const css::uno::Type
& theTyp
,
101 const css::uno::Any
& theValue
,
102 const css::beans::PropertyState
& theState
,
103 sal_Int16 theAttributes
)
104 : PropertyName( thePropertyName
),
106 isNative( theisNative
),
110 Attributes( theAttributes
)
115 #include "filinl.hxx"
117 // Default properties
119 constexpr OUStringLiteral
Title( u
"Title" );
120 constexpr OUStringLiteral
CasePreservingURL( u
"CasePreservingURL" );
121 constexpr OUStringLiteral
IsDocument( u
"IsDocument" );
122 constexpr OUStringLiteral
IsFolder( u
"IsFolder" );
123 constexpr OUStringLiteral
DateModified( u
"DateModified" );
124 constexpr OUStringLiteral
Size( u
"Size" );
125 constexpr OUStringLiteral
IsVolume( u
"IsVolume" );
126 constexpr OUStringLiteral
IsRemoveable( u
"IsRemoveable" );
127 constexpr OUStringLiteral
IsRemote( u
"IsRemote" );
128 constexpr OUStringLiteral
IsCompactDisc( u
"IsCompactDisc" );
129 constexpr OUStringLiteral
IsFloppy( u
"IsFloppy" );
130 constexpr OUStringLiteral
IsHidden( u
"IsHidden" );
131 constexpr OUStringLiteral
ContentType( u
"ContentType" );
132 constexpr OUStringLiteral
IsReadOnly( u
"IsReadOnly" );
133 constexpr OUStringLiteral
CreatableContentsInfo( u
"CreatableContentsInfo" );
135 TaskManager::TaskManager( const uno::Reference
< uno::XComponentContext
>& rxContext
,
136 FileProvider
* pProvider
, bool bWithConfig
)
138 m_pProvider( pProvider
),
139 m_xContext( rxContext
),
142 { /* Name */ "getCommandInfo",
144 /* ArgType */ cppu::UnoType
<void>::get() },
146 { /* Name */ "getPropertySetInfo",
148 /* ArgType */ cppu::UnoType
<void>::get() },
150 { /* Name */ "getPropertyValues",
152 /* ArgType */ cppu::UnoType
<uno::Sequence
< beans::Property
>>::get() },
154 { /* Name */ "setPropertyValues",
156 /* ArgType */ cppu::UnoType
<uno::Sequence
< beans::PropertyValue
>>::get() },
160 /* ArgType */ cppu::UnoType
<OpenCommandArgument
>::get() },
162 { /* Name */ "transfer",
164 /* ArgType */ cppu::UnoType
<TransferInfo
>::get() },
166 { /* Name */ "delete",
168 /* ArgType */ cppu::UnoType
<sal_Bool
>::get() },
170 { /* Name */ "insert",
172 /* ArgType */ cppu::UnoType
<InsertCommandArgument
>::get() },
174 { /* Name */ "createNewContent",
176 /* ArgType */ cppu::UnoType
<ucb::ContentInfo
>::get() } }
179 m_aDefaultProperties
.insert( MyProperty( true,
182 cppu::UnoType
<OUString
>::get(),
184 beans::PropertyState_DEFAULT_VALUE
,
185 beans::PropertyAttribute::MAYBEVOID
186 | beans::PropertyAttribute::BOUND
) );
189 m_aDefaultProperties
.insert(
193 cppu::UnoType
<OUString
>::get(),
195 beans::PropertyState_DEFAULT_VALUE
,
196 beans::PropertyAttribute::MAYBEVOID
197 | beans::PropertyAttribute::BOUND
198 | beans::PropertyAttribute::READONLY
) );
202 m_aDefaultProperties
.insert( MyProperty( true,
205 cppu::UnoType
<sal_Bool
>::get(),
207 beans::PropertyState_DEFAULT_VALUE
,
208 beans::PropertyAttribute::MAYBEVOID
209 | beans::PropertyAttribute::BOUND
210 | beans::PropertyAttribute::READONLY
) );
214 m_aDefaultProperties
.insert( MyProperty( true,
217 cppu::UnoType
<sal_Bool
>::get(),
219 beans::PropertyState_DEFAULT_VALUE
,
220 beans::PropertyAttribute::MAYBEVOID
221 | beans::PropertyAttribute::BOUND
222 | beans::PropertyAttribute::READONLY
) );
225 m_aDefaultProperties
.insert( MyProperty( true,
228 cppu::UnoType
<sal_Bool
>::get(),
230 beans::PropertyState_DEFAULT_VALUE
,
231 beans::PropertyAttribute::MAYBEVOID
232 | beans::PropertyAttribute::BOUND
233 | beans::PropertyAttribute::READONLY
) );
237 m_aDefaultProperties
.insert( MyProperty( true,
240 cppu::UnoType
<sal_Bool
>::get(),
242 beans::PropertyState_DEFAULT_VALUE
,
243 beans::PropertyAttribute::MAYBEVOID
244 | beans::PropertyAttribute::BOUND
245 | beans::PropertyAttribute::READONLY
) );
248 m_aDefaultProperties
.insert( MyProperty( true,
251 cppu::UnoType
<sal_Bool
>::get(),
253 beans::PropertyState_DEFAULT_VALUE
,
254 beans::PropertyAttribute::MAYBEVOID
255 | beans::PropertyAttribute::BOUND
256 | beans::PropertyAttribute::READONLY
) );
259 m_aDefaultProperties
.insert( MyProperty( true,
262 cppu::UnoType
<sal_Bool
>::get(),
264 beans::PropertyState_DEFAULT_VALUE
,
265 beans::PropertyAttribute::MAYBEVOID
266 | beans::PropertyAttribute::BOUND
267 | beans::PropertyAttribute::READONLY
) );
270 m_aDefaultProperties
.insert( MyProperty( true,
273 cppu::UnoType
<sal_Bool
>::get(),
275 beans::PropertyState_DEFAULT_VALUE
,
276 beans::PropertyAttribute::MAYBEVOID
277 | beans::PropertyAttribute::BOUND
278 | beans::PropertyAttribute::READONLY
) );
281 m_aDefaultProperties
.insert(
286 cppu::UnoType
<sal_Bool
>::get(),
288 beans::PropertyState_DEFAULT_VALUE
,
289 beans::PropertyAttribute::MAYBEVOID
290 | beans::PropertyAttribute::BOUND
294 | beans::PropertyAttribute::READONLY
)); // under unix/linux only readable
299 m_aDefaultProperties
.insert( MyProperty( false,
302 cppu::UnoType
<OUString
>::get(),
303 uno::Any(OUString()),
304 beans::PropertyState_DEFAULT_VALUE
,
305 beans::PropertyAttribute::MAYBEVOID
306 | beans::PropertyAttribute::BOUND
307 | beans::PropertyAttribute::READONLY
) );
311 m_aDefaultProperties
.insert( MyProperty( true,
314 cppu::UnoType
<util::DateTime
>::get(),
316 beans::PropertyState_DEFAULT_VALUE
,
317 beans::PropertyAttribute::MAYBEVOID
318 | beans::PropertyAttribute::BOUND
) );
321 m_aDefaultProperties
.insert( MyProperty( true,
324 cppu::UnoType
<sal_Int64
>::get(),
326 beans::PropertyState_DEFAULT_VALUE
,
327 beans::PropertyAttribute::MAYBEVOID
328 | beans::PropertyAttribute::BOUND
) );
331 m_aDefaultProperties
.insert( MyProperty( true,
334 cppu::UnoType
<sal_Bool
>::get(),
336 beans::PropertyState_DEFAULT_VALUE
,
337 beans::PropertyAttribute::MAYBEVOID
338 | beans::PropertyAttribute::BOUND
) );
341 // CreatableContentsInfo
342 m_aDefaultProperties
.insert( MyProperty( true,
343 CreatableContentsInfo
,
345 cppu::UnoType
<uno::Sequence
< ucb::ContentInfo
>>::get(),
347 beans::PropertyState_DEFAULT_VALUE
,
348 beans::PropertyAttribute::MAYBEVOID
349 | beans::PropertyAttribute::BOUND
350 | beans::PropertyAttribute::READONLY
) );
354 uno::Reference
< XPropertySetRegistryFactory
> xRegFac
= ucb::Store::create( m_xContext
);
355 // Open/create a registry
356 m_xFileRegistry
= xRegFac
->createPropertySetRegistry( OUString() );
361 TaskManager::~TaskManager()
367 TaskManager::startTask(
369 const uno::Reference
< XCommandEnvironment
>& xCommandEnv
)
371 std::unique_lock
aGuard( m_aMutex
);
372 TaskMap::iterator it
= m_aTaskMap
.find( CommandId
);
373 if( it
!= m_aTaskMap
.end() )
375 throw DuplicateCommandIdentifierException( OSL_LOG_PREFIX
);
377 m_aTaskMap
.emplace( CommandId
, TaskHandling( xCommandEnv
));
382 TaskManager::endTask( sal_Int32 CommandId
,
383 const OUString
& aUncPath
,
384 BaseContent
* pContent
)
386 std::unique_lock
aGuard( m_aMutex
);
387 TaskMap::iterator it
= m_aTaskMap
.find( CommandId
);
388 if( it
== m_aTaskMap
.end() )
391 sal_Int32 ErrorCode
= it
->second
.getInstalledError();
392 sal_Int32 MinorCode
= it
->second
.getMinorErrorCode();
393 bool isHandled
= it
->second
.isHandled();
395 Reference
< XCommandEnvironment
> xComEnv
396 = it
->second
.getCommandEnvironment();
398 m_aTaskMap
.erase( it
);
402 if( ErrorCode
!= TASKHANDLER_NO_ERROR
)
413 void TaskManager::clearError( sal_Int32 CommandId
)
415 std::unique_lock
aGuard( m_aMutex
);
416 TaskMap::iterator it
= m_aTaskMap
.find( CommandId
);
417 if( it
!= m_aTaskMap
.end() )
418 it
->second
.clearError();
422 void TaskManager::retrieveError( sal_Int32 CommandId
,
423 sal_Int32
&ErrorCode
,
424 sal_Int32
&minorCode
)
426 std::unique_lock
aGuard( m_aMutex
);
427 TaskMap::iterator it
= m_aTaskMap
.find( CommandId
);
428 if( it
!= m_aTaskMap
.end() )
430 ErrorCode
= it
->second
.getInstalledError();
431 minorCode
= it
->second
. getMinorErrorCode();
436 void TaskManager::installError( sal_Int32 CommandId
,
438 sal_Int32 MinorCode
)
440 std::unique_lock
aGuard( m_aMutex
);
441 TaskMap::iterator it
= m_aTaskMap
.find( CommandId
);
442 if( it
!= m_aTaskMap
.end() )
443 it
->second
.installError( ErrorCode
,MinorCode
);
448 TaskManager::getCommandId()
450 std::unique_lock
aGuard( m_aMutex
);
451 return ++m_nCommandId
;
455 void TaskManager::handleTask(
457 const uno::Reference
< task::XInteractionRequest
>& request
)
459 std::unique_lock
aGuard( m_aMutex
);
460 TaskMap::iterator it
= m_aTaskMap
.find( CommandId
);
461 uno::Reference
< task::XInteractionHandler
> xInt
;
462 if( it
!= m_aTaskMap
.end() )
464 xInt
= it
->second
.getInteractionHandler();
466 xInt
->handle( request
);
467 it
->second
.setHandled();
471 /*********************************************************************************/
473 /* de/registerNotifier-Implementation */
475 /*********************************************************************************/
478 // This two methods register and deregister a change listener for the content belonging
483 TaskManager::registerNotifier( const OUString
& aUnqPath
, Notifier
* pNotifier
)
485 std::unique_lock
aGuard( m_aMutex
);
487 ContentMap::iterator it
=
488 m_aContent
.emplace( aUnqPath
, UnqPathData() ).first
;
490 std::vector
< Notifier
* >& nlist
= it
->second
.notifier
;
492 std::vector
<Notifier
*>::iterator it1
= std::find(nlist
.begin(), nlist
.end(), pNotifier
);
493 if( it1
!= nlist
.end() ) // Every "Notifier" only once
497 nlist
.push_back( pNotifier
);
502 TaskManager::deregisterNotifier( const OUString
& aUnqPath
,Notifier
* pNotifier
)
504 std::unique_lock
aGuard( m_aMutex
);
506 ContentMap::iterator it
= m_aContent
.find( aUnqPath
);
507 if( it
== m_aContent
.end() )
510 it
->second
.notifier
.erase(std::remove(it
->second
.notifier
.begin(), it
->second
.notifier
.end(), pNotifier
), it
->second
.notifier
.end());
512 if( it
->second
.notifier
.empty() )
513 m_aContent
.erase( it
);
517 /*********************************************************************************/
519 /* de/associate-Implementation */
521 /*********************************************************************************/
523 // Used to associate and deassociate a new property with
524 // the content belonging to URL UnqPath.
525 // The default value and the attributes are input
529 TaskManager::associate( const OUString
& aUnqPath
,
530 const OUString
& PropertyName
,
531 const uno::Any
& DefaultValue
,
532 const sal_Int16 Attributes
)
534 MyProperty
newProperty( false,
537 DefaultValue
.getValueType(),
539 beans::PropertyState_DEFAULT_VALUE
,
542 auto it1
= m_aDefaultProperties
.find( newProperty
);
543 if( it1
!= m_aDefaultProperties
.end() )
544 throw beans::PropertyExistException( THROW_WHERE
);
547 std::unique_lock
aGuard( m_aMutex
);
549 ContentMap::iterator it
= m_aContent
.emplace( aUnqPath
,UnqPathData() ).first
;
551 // Load the XPersistentPropertySetInfo and create it, if it does not exist
554 PropertySet
& properties
= it
->second
.properties
;
555 it1
= properties
.find( newProperty
);
556 if( it1
!= properties
.end() )
557 throw beans::PropertyExistException(THROW_WHERE
);
559 // Property does not exist
560 properties
.insert( newProperty
);
561 it
->second
.xC
->addProperty( PropertyName
,Attributes
,DefaultValue
);
563 notifyPropertyAdded( getPropertySetListeners( aUnqPath
), PropertyName
);
568 TaskManager::deassociate( const OUString
& aUnqPath
,
569 const OUString
& PropertyName
)
571 MyProperty
oldProperty( PropertyName
);
573 auto it1
= m_aDefaultProperties
.find( oldProperty
);
574 if( it1
!= m_aDefaultProperties
.end() )
575 throw beans::NotRemoveableException( THROW_WHERE
);
577 std::unique_lock
aGuard( m_aMutex
);
579 ContentMap::iterator it
= m_aContent
.emplace( aUnqPath
,UnqPathData() ).first
;
583 PropertySet
& properties
= it
->second
.properties
;
585 it1
= properties
.find( oldProperty
);
586 if( it1
== properties
.end() )
587 throw beans::UnknownPropertyException( PropertyName
);
589 properties
.erase( it1
);
591 if( it
->second
.xC
.is() )
592 it
->second
.xC
->removeProperty( PropertyName
);
594 if( properties
.size() == 9 )
596 MyProperty
ContentTProperty( ContentType
);
598 if( properties
.find( ContentTProperty
)->getState() == beans::PropertyState_DEFAULT_VALUE
)
600 it
->second
.xS
= nullptr;
601 it
->second
.xC
= nullptr;
602 it
->second
.xA
= nullptr;
603 if(m_xFileRegistry
.is())
604 m_xFileRegistry
->removePropertySet( aUnqPath
);
608 notifyPropertyRemoved( getPropertySetListeners( aUnqPath
), PropertyName
);
612 /*********************************************************************************/
614 /* page-Implementation */
616 /*********************************************************************************/
618 // Given an xOutputStream, this method writes the content of the file belonging to
619 // URL aUnqPath into the XOutputStream
622 void TaskManager::page( sal_Int32 CommandId
,
623 const OUString
& aUnqPath
,
624 const uno::Reference
< io::XOutputStream
>& xOutputStream
)
626 osl::File
aFile( aUnqPath
);
627 osl::FileBase::RC err
= aFile
.open( osl_File_OpenFlag_Read
);
629 if( err
!= osl::FileBase::E_None
)
632 installError( CommandId
,
633 TASKHANDLING_OPEN_FILE_FOR_PAGING
,
638 const sal_uInt64 bfz
= 4*1024;
640 sal_uInt64 nrc
; // Retrieved number of Bytes;
644 err
= aFile
.read( static_cast<void*>(BFF
),bfz
,nrc
);
645 if( err
== osl::FileBase::E_None
)
647 // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
648 uno::Sequence
< sal_Int8
> seq( BFF
, static_cast<sal_uInt32
>(nrc
) );
651 xOutputStream
->writeBytes( seq
);
653 catch (const io::NotConnectedException
&)
655 installError( CommandId
,
656 TASKHANDLING_NOTCONNECTED_FOR_PAGING
);
659 catch (const io::BufferSizeExceededException
&)
661 installError( CommandId
,
662 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING
);
665 catch (const io::IOException
&)
667 installError( CommandId
,
668 TASKHANDLING_IOEXCEPTION_FOR_PAGING
);
674 installError( CommandId
,
675 TASKHANDLING_READING_FILE_FOR_PAGING
,
679 } while( nrc
== bfz
);
687 xOutputStream
->closeOutput();
689 catch (const io::NotConnectedException
&)
692 catch (const io::BufferSizeExceededException
&)
695 catch (const io::IOException
&)
701 /*********************************************************************************/
703 /* open-Implementation */
705 /*********************************************************************************/
707 // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
710 uno::Reference
< io::XInputStream
>
711 TaskManager::open( sal_Int32 CommandId
,
712 const OUString
& aUnqPath
,
715 rtl::Reference
<XInputStream_impl
> pInputStream(new XInputStream_impl( aUnqPath
, bLock
)); // from filinpstr.hxx
717 sal_Int32 ErrorCode
= pInputStream
->CtorSuccess();
719 if( ErrorCode
!= TASKHANDLER_NO_ERROR
)
721 installError( CommandId
,
723 pInputStream
->getMinorError() );
725 pInputStream
.clear();
732 /*********************************************************************************/
734 /* open for read/write access-Implementation */
736 /*********************************************************************************/
738 // Given a file URL aUnqPath, this methods returns a XStream which can be used
739 // to read and write from/to the file.
742 uno::Reference
< io::XStream
>
743 TaskManager::open_rw( sal_Int32 CommandId
,
744 const OUString
& aUnqPath
,
747 rtl::Reference
<XStream_impl
> pStream(new XStream_impl( aUnqPath
, bLock
)); // from filstr.hxx
749 sal_Int32 ErrorCode
= pStream
->CtorSuccess();
751 if( ErrorCode
!= TASKHANDLER_NO_ERROR
)
753 installError( CommandId
,
755 pStream
->getMinorError() );
763 /*********************************************************************************/
765 /* ls-Implementation */
767 /*********************************************************************************/
769 // This method returns the result set containing the children of the directory belonging
770 // to file URL aUnqPath
773 uno::Reference
< XDynamicResultSet
>
774 TaskManager::ls( sal_Int32 CommandId
,
775 const OUString
& aUnqPath
,
776 const sal_Int32 OpenMode
,
777 const uno::Sequence
< beans::Property
>& seq
,
778 const uno::Sequence
< NumberedSortingInfo
>& seqSort
)
780 rtl::Reference
<XResultSet_impl
> p(new XResultSet_impl( this,aUnqPath
,OpenMode
,seq
,seqSort
));
782 sal_Int32 ErrorCode
= p
->CtorSuccess();
784 if( ErrorCode
!= TASKHANDLER_NO_ERROR
)
786 installError( CommandId
,
788 p
->getMinorError() );
797 /*********************************************************************************/
799 /* info_c implementation */
801 /*********************************************************************************/
804 uno::Reference
< XCommandInfo
>
805 TaskManager::info_c()
807 return new XCommandInfo_impl( this );
811 /*********************************************************************************/
813 /* info_p-Implementation */
815 /*********************************************************************************/
816 // Info for the properties
818 uno::Reference
< beans::XPropertySetInfo
>
819 TaskManager::info_p( const OUString
& aUnqPath
)
821 std::unique_lock
aGuard( m_aMutex
);
822 return new XPropertySetInfo_impl( this,aUnqPath
);
826 /*********************************************************************************/
828 /* setv-Implementation */
830 /*********************************************************************************/
832 // Sets the values of the properties belonging to fileURL aUnqPath
835 uno::Sequence
< uno::Any
>
836 TaskManager::setv( const OUString
& aUnqPath
,
837 const uno::Sequence
< beans::PropertyValue
>& values
)
839 std::unique_lock
aGuard( m_aMutex
);
841 sal_Int32 propChanged
= 0;
842 uno::Sequence
< uno::Any
> ret( values
.getLength() );
843 auto retRange
= asNonConstRange(ret
);
844 uno::Sequence
< beans::PropertyChangeEvent
> seqChanged( values
.getLength() );
845 auto seqChangedRange
= asNonConstRange(seqChanged
);
847 TaskManager::ContentMap::iterator it
= m_aContent
.find( aUnqPath
);
848 PropertySet
& properties
= it
->second
.properties
;
849 TaskManager::PropertySet::const_iterator it1
;
852 for( sal_Int32 i
= 0; i
< values
.getLength(); ++i
)
854 MyProperty
toset( values
[i
].Name
);
855 it1
= properties
.find( toset
);
856 if( it1
== properties
.end() )
858 retRange
[i
] <<= beans::UnknownPropertyException( THROW_WHERE
);
862 aAny
= it1
->getValue();
863 if( aAny
== values
[i
].Value
)
864 continue; // nothing needs to be changed
866 if( it1
->getAttributes() & beans::PropertyAttribute::READONLY
)
868 retRange
[i
] <<= lang::IllegalAccessException( THROW_WHERE
);
872 seqChangedRange
[ propChanged
].PropertyName
= values
[i
].Name
;
873 seqChangedRange
[ propChanged
].PropertyHandle
= -1;
874 seqChangedRange
[ propChanged
].Further
= false;
875 seqChangedRange
[ propChanged
].OldValue
= aAny
;
876 seqChangedRange
[ propChanged
++ ].NewValue
= values
[i
].Value
;
878 it1
->setValue( values
[i
].Value
); // Put the new value into the local cash
880 if( ! it1
->IsNative() )
882 // Also put logical properties into storage
883 if( !it
->second
.xS
.is() )
886 if( ( values
[i
].Name
== ContentType
) &&
887 it1
->getState() == beans::PropertyState_DEFAULT_VALUE
)
888 { // Special logic for ContentType
889 // 09.07.01: Not reached anymore, because ContentType is readonly
890 it1
->setState( beans::PropertyState_DIRECT_VALUE
);
891 it
->second
.xC
->addProperty( values
[i
].Name
,
892 beans::PropertyAttribute::MAYBEVOID
,
898 it
->second
.xS
->setPropertyValue( values
[i
].Name
,values
[i
].Value
);
900 catch (const uno::Exception
&e
)
902 --propChanged
; // unsuccessful setting
909 // Setting of physical file properties
910 if( values
[i
].Name
== Size
)
912 sal_Int64 newSize
= 0;
913 if( values
[i
].Value
>>= newSize
)
914 { // valid value for the size
915 osl::File
aFile(aUnqPath
);
917 aFile
.open(osl_File_OpenFlag_Write
) != osl::FileBase::E_None
||
918 aFile
.setSize(sal_uInt64(newSize
)) != osl::FileBase::E_None
||
919 aFile
.close() != osl::FileBase::E_None
;
923 --propChanged
; // unsuccessful setting
924 uno::Sequence
<uno::Any
> names(comphelper::InitAnyPropertySequence(
926 {"Uri", uno::Any(aUnqPath
)}
928 retRange
[i
] <<= InteractiveAugmentedIOException(
931 task::InteractionClassification_ERROR
,
937 retRange
[i
] <<= beans::IllegalTypeException( THROW_WHERE
);
939 else if(values
[i
].Name
== IsReadOnly
||
940 values
[i
].Name
== IsHidden
)
943 if( values
[i
].Value
>>= value
)
945 osl::DirectoryItem aDirItem
;
946 osl::FileBase::RC err
=
947 osl::DirectoryItem::get(aUnqPath
,aDirItem
);
948 sal_uInt64
nAttributes(0);
949 if(err
== osl::FileBase::E_None
)
951 osl::FileStatus
aFileStatus(osl_FileStatus_Mask_Attributes
);
952 err
= aDirItem
.getFileStatus(aFileStatus
);
953 if(err
== osl::FileBase::E_None
&&
954 aFileStatus
.isValid(osl_FileStatus_Mask_Attributes
))
955 nAttributes
= aFileStatus
.getAttributes();
957 // now we have the attributes provided all went well.
958 if(err
== osl::FileBase::E_None
) {
959 if(values
[i
].Name
== IsReadOnly
)
961 nAttributes
&= ~(osl_File_Attribute_OwnWrite
|
962 osl_File_Attribute_GrpWrite
|
963 osl_File_Attribute_OthWrite
|
964 osl_File_Attribute_ReadOnly
);
966 nAttributes
|= osl_File_Attribute_ReadOnly
;
969 osl_File_Attribute_OwnWrite
|
970 osl_File_Attribute_GrpWrite
|
971 osl_File_Attribute_OthWrite
);
973 else if(values
[i
].Name
== IsHidden
)
975 nAttributes
&= ~(osl_File_Attribute_Hidden
);
977 nAttributes
|= osl_File_Attribute_Hidden
;
979 err
= osl::File::setAttributes(
980 aUnqPath
,nAttributes
);
983 if( err
!= osl::FileBase::E_None
)
985 --propChanged
; // unsuccessful setting
986 uno::Sequence
<uno::Any
> names(comphelper::InitAnyPropertySequence(
988 {"Uri", uno::Any(aUnqPath
)}
993 case osl::FileBase::E_NOMEM
:
994 // not enough memory for allocating structures <br>
995 ioError
= IOErrorCode_OUT_OF_MEMORY
;
997 case osl::FileBase::E_INVAL
:
998 // the format of the parameters was not valid<p>
999 ioError
= IOErrorCode_INVALID_PARAMETER
;
1001 case osl::FileBase::E_NAMETOOLONG
:
1002 // File name too long<br>
1003 ioError
= IOErrorCode_NAME_TOO_LONG
;
1005 case osl::FileBase::E_NOENT
:
1006 // No such file or directory<br>
1007 case osl::FileBase::E_NOLINK
:
1008 // Link has been severed<br>
1009 ioError
= IOErrorCode_NOT_EXISTING
;
1011 case osl::FileBase::E_ROFS
:
1012 // #i4735# handle ROFS transparently
1014 case osl::FileBase::E_PERM
:
1015 case osl::FileBase::E_ACCES
:
1016 // permission denied<br>
1017 ioError
= IOErrorCode_ACCESS_DENIED
;
1019 case osl::FileBase::E_LOOP
:
1020 // Too many symbolic links encountered<br>
1021 case osl::FileBase::E_FAULT
:
1023 case osl::FileBase::E_IO
:
1025 case osl::FileBase::E_NOSYS
:
1026 // Function not implemented<br>
1027 case osl::FileBase::E_MULTIHOP
:
1028 // Multihop attempted<br>
1029 case osl::FileBase::E_INTR
:
1030 // function call was interrupted<p>
1032 ioError
= IOErrorCode_GENERAL
;
1035 retRange
[i
] <<= InteractiveAugmentedIOException(
1038 task::InteractionClassification_ERROR
,
1044 retRange
[i
] <<= beans::IllegalTypeException( THROW_WHERE
);
1052 seqChanged
.realloc( propChanged
);
1053 notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath
), seqChanged
);
1059 /*********************************************************************************/
1061 /* getv-Implementation */
1063 /*********************************************************************************/
1065 // Reads the values of the properties belonging to fileURL aUnqPath;
1066 // Returns an XRow object containing the values in the requested order.
1069 uno::Reference
< sdbc::XRow
>
1070 TaskManager::getv( sal_Int32 CommandId
,
1071 const OUString
& aUnqPath
,
1072 const uno::Sequence
< beans::Property
>& properties
)
1074 uno::Sequence
< uno::Any
> seq( properties
.getLength() );
1077 getMaskFromProperties( n_Mask
,properties
);
1078 osl::FileStatus
aFileStatus( n_Mask
);
1080 osl::DirectoryItem aDirItem
;
1081 osl::FileBase::RC nError1
= osl::DirectoryItem::get( aUnqPath
,aDirItem
);
1082 if( nError1
!= osl::FileBase::E_None
)
1083 installError(CommandId
,
1084 TASKHANDLING_OPEN_FILE_FOR_PAGING
, // BEAWARE, REUSED
1087 osl::FileBase::RC nError2
= aDirItem
.getFileStatus( aFileStatus
);
1088 if( nError1
== osl::FileBase::E_None
&&
1089 nError2
!= osl::FileBase::E_None
)
1090 installError(CommandId
,
1091 TASKHANDLING_OPEN_FILE_FOR_PAGING
, // BEAWARE, REUSED
1095 std::unique_lock
aGuard( m_aMutex
);
1097 TaskManager::ContentMap::iterator it
= m_aContent
.find( aUnqPath
);
1098 commit( aGuard
, it
, aFileStatus
);
1100 PropertySet
& propset
= it
->second
.properties
;
1102 std::transform(properties
.begin(), properties
.end(), seq
.getArray(),
1103 [&propset
](const beans::Property
& rProp
) -> uno::Any
{
1104 MyProperty
readProp( rProp
.Name
);
1105 auto it1
= propset
.find( readProp
);
1106 if( it1
== propset
.end() )
1108 return it1
->getValue();
1112 return new XRow_impl( this,seq
);
1116 /********************************************************************************/
1118 /* transfer-commandos */
1120 /********************************************************************************/
1123 /********************************************************************************/
1125 /* move-implementation */
1127 /********************************************************************************/
1129 // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath.
1133 TaskManager::move( sal_Int32 CommandId
,
1134 const OUString
& srcUnqPath
,
1135 const OUString
& dstUnqPathIn
,
1136 const sal_Int32 NameClash
)
1138 // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if
1139 // srcUnqPath and dstUnqPathIn are equal
1140 if( srcUnqPath
== dstUnqPathIn
)
1143 osl::FileBase::RC nError
;
1144 OUString
dstUnqPath( dstUnqPathIn
);
1148 case NameClash::KEEP
:
1150 nError
= osl_File_move( srcUnqPath
,dstUnqPath
,true );
1151 if( nError
!= osl::FileBase::E_None
&& nError
!= osl::FileBase::E_EXIST
)
1153 installError( CommandId
,
1154 TASKHANDLING_KEEPERROR_FOR_MOVE
,
1160 case NameClash::OVERWRITE
:
1162 // stat to determine whether we have a symlink
1163 OUString
targetPath(dstUnqPath
);
1165 osl::FileStatus
aStatus(osl_FileStatus_Mask_Type
|osl_FileStatus_Mask_LinkTargetURL
);
1166 osl::DirectoryItem aItem
;
1167 (void)osl::DirectoryItem::get(dstUnqPath
,aItem
);
1168 (void)aItem
.getFileStatus(aStatus
);
1170 if( aStatus
.isValid(osl_FileStatus_Mask_Type
) &&
1171 aStatus
.isValid(osl_FileStatus_Mask_LinkTargetURL
) &&
1172 aStatus
.getFileType() == osl::FileStatus::Link
)
1173 targetPath
= aStatus
.getLinkTargetURL();
1175 // Will do nothing if file does not exist.
1176 osl::File::remove( targetPath
);
1178 nError
= osl_File_move( srcUnqPath
,targetPath
);
1179 if( nError
!= osl::FileBase::E_None
)
1181 installError( CommandId
,
1182 TASKHANDLING_OVERWRITE_FOR_MOVE
,
1188 case NameClash::RENAME
:
1190 OUString newDstUnqPath
;
1191 nError
= osl_File_move( srcUnqPath
,dstUnqPath
,true );
1192 if( nError
== osl::FileBase::E_EXIST
)
1194 // "invent" a new valid title.
1196 sal_Int32 nPos
= -1;
1197 sal_Int32 nLastDot
= dstUnqPath
.lastIndexOf( '.' );
1198 sal_Int32 nLastSlash
= dstUnqPath
.lastIndexOf( '/' );
1199 if( ( nLastSlash
< nLastDot
) // dot is part of last(!) path segment
1200 && ( nLastSlash
!= ( nLastDot
- 1 ) ) ) // file name does not start with a dot
1203 nPos
= dstUnqPath
.getLength();
1209 newDstUnqPath
= dstUnqPath
;
1211 OUString aPostfix
= "_" + OUString::number( ++nTry
);
1213 newDstUnqPath
= newDstUnqPath
.replaceAt( nPos
, 0, aPostfix
);
1215 nError
= osl_File_move( srcUnqPath
,newDstUnqPath
,true );
1217 while( ( nError
== osl::FileBase::E_EXIST
) && ( nTry
< 10000 ) );
1220 if( nError
== osl::FileBase::E_EXIST
)
1222 installError( CommandId
,
1223 TASKHANDLING_RENAME_FOR_MOVE
);
1226 else if( nError
!= osl::FileBase::E_None
)
1228 installError( CommandId
,
1229 TASKHANDLING_RENAMEMOVE_FOR_MOVE
,
1234 dstUnqPath
= newDstUnqPath
;
1238 case NameClash::ERROR
:
1240 nError
= osl_File_move( srcUnqPath
,dstUnqPath
,true );
1241 if( nError
== osl::FileBase::E_EXIST
)
1243 installError( CommandId
,
1244 TASKHANDLING_NAMECLASH_FOR_MOVE
);
1247 else if( nError
!= osl::FileBase::E_None
)
1249 installError( CommandId
,
1250 TASKHANDLING_NAMECLASHMOVE_FOR_MOVE
,
1256 case NameClash::ASK
:
1259 nError
= osl_File_move( srcUnqPath
,dstUnqPath
,true );
1260 if( nError
== osl::FileBase::E_EXIST
)
1262 installError( CommandId
,
1263 TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE
,
1271 // Determine, whether we have moved a file or a folder
1272 osl::DirectoryItem aItem
;
1273 nError
= osl::DirectoryItem::get( dstUnqPath
,aItem
);
1274 if( nError
!= osl::FileBase::E_None
)
1276 installError( CommandId
,
1277 TASKHANDLING_TRANSFER_BY_MOVE_SOURCE
,
1281 osl::FileStatus
aStatus( osl_FileStatus_Mask_Type
);
1282 nError
= aItem
.getFileStatus( aStatus
);
1283 if( nError
!= osl::FileBase::E_None
|| ! aStatus
.isValid( osl_FileStatus_Mask_Type
) )
1285 installError( CommandId
,
1286 TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT
,
1290 bool isDocument
= ( aStatus
.getFileType() == osl::FileStatus::Regular
);
1293 copyPersistentSet( srcUnqPath
,dstUnqPath
,!isDocument
);
1295 OUString aDstParent
= getParentName( dstUnqPath
);
1296 OUString aSrcParent
= getParentName( srcUnqPath
);
1298 notifyInsert( getContentEventListeners( aDstParent
),dstUnqPath
);
1299 if( aDstParent
!= aSrcParent
)
1300 notifyContentRemoved( getContentEventListeners( aSrcParent
),srcUnqPath
);
1302 notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath
,dstUnqPath
,!isDocument
) );
1303 erasePersistentSet( srcUnqPath
,!isDocument
);
1307 /********************************************************************************/
1309 /* copy-implementation */
1311 /********************************************************************************/
1313 // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
1319 TaskManager
& task
, sal_Int32 id
, OUString
const & fileUrl
,
1320 osl::DirectoryItem
* item
, osl::FileStatus::Type
* type
)
1322 OSL_ASSERT(item
!= nullptr && type
!= nullptr);
1323 osl::FileBase::RC err
= osl::DirectoryItem::get(fileUrl
, *item
);
1324 if (err
!= osl::FileBase::E_None
) {
1325 task
.installError(id
, TASKHANDLING_TRANSFER_BY_COPY_SOURCE
, err
);
1328 osl::FileStatus
stat(osl_FileStatus_Mask_Type
);
1329 err
= item
->getFileStatus(stat
);
1330 if (err
!= osl::FileBase::E_None
) {
1331 task
.installError(id
, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT
, err
);
1334 *type
= stat
.getFileType();
1342 sal_Int32 CommandId
,
1343 const OUString
& srcUnqPath
,
1344 const OUString
& dstUnqPathIn
,
1345 sal_Int32 NameClash
)
1347 osl::FileBase::RC nError
;
1348 OUString
dstUnqPath( dstUnqPathIn
);
1350 // Resolve symbolic links within the source path. If srcUnqPath denotes a
1351 // symbolic link (targeting either a file or a folder), the contents of the
1352 // target is copied (recursively, in the case of a folder). However, if
1353 // recursively copying the contents of a folder causes a symbolic link to be
1354 // copied, the symbolic link itself is copied.
1355 osl::DirectoryItem item
;
1356 osl::FileStatus::Type type
;
1357 if (!getType(*this, CommandId
, srcUnqPath
, &item
, &type
)) {
1360 OUString rslvdSrcUnqPath
;
1361 if (type
== osl::FileStatus::Link
) {
1362 osl::FileStatus
stat(osl_FileStatus_Mask_LinkTargetURL
);
1363 nError
= item
.getFileStatus(stat
);
1364 if (nError
!= osl::FileBase::E_None
) {
1366 CommandId
, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT
, nError
);
1369 rslvdSrcUnqPath
= stat
.getLinkTargetURL();
1370 if (!getType(*this, CommandId
, srcUnqPath
, &item
, &type
)) {
1374 rslvdSrcUnqPath
= srcUnqPath
;
1378 = type
!= osl::FileStatus::Directory
&& type
!= osl::FileStatus::Volume
;
1379 FileUrlType IsWhat
= isDocument
? FileUrlType::File
: FileUrlType::Folder
;
1383 case NameClash::KEEP
:
1385 nError
= copy_recursive( rslvdSrcUnqPath
,dstUnqPath
,IsWhat
,true );
1386 if( nError
!= osl::FileBase::E_None
&& nError
!= osl::FileBase::E_EXIST
)
1388 installError( CommandId
,
1389 TASKHANDLING_KEEPERROR_FOR_COPY
,
1395 case NameClash::OVERWRITE
:
1397 // remove (..., MustExist = sal_False).
1398 remove( CommandId
, dstUnqPath
, IsWhat
, false );
1401 nError
= copy_recursive( rslvdSrcUnqPath
,dstUnqPath
,IsWhat
,false );
1402 if( nError
!= osl::FileBase::E_None
)
1404 installError( CommandId
,
1405 TASKHANDLING_OVERWRITE_FOR_COPY
,
1411 case NameClash::RENAME
:
1413 OUString newDstUnqPath
= dstUnqPath
;
1414 nError
= copy_recursive( rslvdSrcUnqPath
,dstUnqPath
,IsWhat
,true );
1416 if( nError
== osl::FileBase::E_EXIST
)
1418 // "invent" a new valid title.
1420 sal_Int32 nPos
= -1;
1421 sal_Int32 nLastDot
= dstUnqPath
.lastIndexOf( '.' );
1422 sal_Int32 nLastSlash
= dstUnqPath
.lastIndexOf( '/' );
1423 if ( ( nLastSlash
< nLastDot
) // dot is part of last(!) path segment
1424 && ( nLastSlash
!= ( nLastDot
- 1 ) ) ) // file name does not start with a dot
1427 nPos
= dstUnqPath
.getLength();
1433 newDstUnqPath
= dstUnqPath
;
1435 OUString aPostfix
= "_" + OUString::number( ++nTry
);
1437 newDstUnqPath
= newDstUnqPath
.replaceAt( nPos
, 0, aPostfix
);
1439 nError
= copy_recursive( rslvdSrcUnqPath
,newDstUnqPath
,IsWhat
,true );
1441 while( ( nError
== osl::FileBase::E_EXIST
) && ( nTry
< 10000 ) );
1444 if( nError
== osl::FileBase::E_EXIST
)
1446 installError( CommandId
,
1447 TASKHANDLING_RENAME_FOR_COPY
);
1450 else if( nError
!= osl::FileBase::E_None
)
1452 installError( CommandId
,
1453 TASKHANDLING_RENAMEMOVE_FOR_COPY
,
1458 dstUnqPath
= newDstUnqPath
;
1462 case NameClash::ERROR
:
1464 nError
= copy_recursive( rslvdSrcUnqPath
,dstUnqPath
,IsWhat
,true );
1466 if( nError
== osl::FileBase::E_EXIST
)
1468 installError( CommandId
,
1469 TASKHANDLING_NAMECLASH_FOR_COPY
);
1472 else if( nError
!= osl::FileBase::E_None
)
1474 installError( CommandId
,
1475 TASKHANDLING_NAMECLASHMOVE_FOR_COPY
,
1481 case NameClash::ASK
:
1484 nError
= copy_recursive( rslvdSrcUnqPath
,dstUnqPath
,IsWhat
,true );
1486 if( nError
== osl::FileBase::E_EXIST
)
1488 installError( CommandId
,
1489 TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY
,
1497 copyPersistentSet( srcUnqPath
,dstUnqPath
, !isDocument
);
1498 notifyInsert( getContentEventListeners( getParentName( dstUnqPath
) ),dstUnqPath
);
1502 /********************************************************************************/
1504 /* remove-implementation */
1506 /********************************************************************************/
1508 // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
1509 // Return: success of operation
1513 TaskManager::remove( sal_Int32 CommandId
,
1514 const OUString
& aUnqPath
,
1518 sal_Int32 nMask
= osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileURL
;
1520 osl::DirectoryItem aItem
;
1521 osl::FileStatus
aStatus( nMask
);
1522 osl::FileBase::RC nError
;
1524 if( IsWhat
== FileUrlType::Unknown
) // Determine whether we are removing a directory or a file
1526 nError
= osl::DirectoryItem::get( aUnqPath
, aItem
);
1527 if( nError
!= osl::FileBase::E_None
)
1531 installError( CommandId
,
1532 TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE
,
1535 return (!MustExist
);
1538 nError
= aItem
.getFileStatus( aStatus
);
1539 if( nError
!= osl::FileBase::E_None
|| ! aStatus
.isValid( nMask
) )
1541 installError( CommandId
,
1542 TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE
,
1543 nError
!= osl::FileBase::E_None
? nError
: TASKHANDLER_NO_ERROR
);
1547 if( aStatus
.getFileType() == osl::FileStatus::Regular
||
1548 aStatus
.getFileType() == osl::FileStatus::Link
)
1549 IsWhat
= FileUrlType::File
;
1550 else if( aStatus
.getFileType() == osl::FileStatus::Directory
||
1551 aStatus
.getFileType() == osl::FileStatus::Volume
)
1552 IsWhat
= FileUrlType::Folder
;
1556 if( IsWhat
== FileUrlType::File
)
1558 nError
= osl::File::remove( aUnqPath
);
1559 if( nError
!= osl::FileBase::E_None
)
1563 installError( CommandId
,
1564 TASKHANDLING_DELETEFILE_FOR_REMOVE
,
1567 return (!MustExist
);
1571 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath
) );
1572 erasePersistentSet( aUnqPath
); // Removes from XPersistentPropertySet
1575 else if( IsWhat
== FileUrlType::Folder
)
1577 osl::Directory
aDirectory( aUnqPath
);
1579 nError
= aDirectory
.open();
1580 if( nError
!= osl::FileBase::E_None
)
1584 installError( CommandId
,
1585 TASKHANDLING_OPENDIRECTORY_FOR_REMOVE
,
1588 return (!MustExist
);
1591 bool whileSuccess
= true;
1592 FileUrlType recurse
= FileUrlType::Unknown
;
1595 nError
= aDirectory
.getNextItem( aItem
);
1596 while( nError
== osl::FileBase::E_None
)
1598 nError
= aItem
.getFileStatus( aStatus
);
1599 if( nError
!= osl::FileBase::E_None
|| ! aStatus
.isValid( nMask
) )
1601 installError( CommandId
,
1602 TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE
,
1603 nError
!= osl::FileBase::E_None
? nError
: TASKHANDLER_NO_ERROR
);
1604 whileSuccess
= false;
1608 if( aStatus
.getFileType() == osl::FileStatus::Regular
||
1609 aStatus
.getFileType() == osl::FileStatus::Link
)
1610 recurse
= FileUrlType::File
;
1611 else if( aStatus
.getFileType() == osl::FileStatus::Directory
||
1612 aStatus
.getFileType() == osl::FileStatus::Volume
)
1613 recurse
= FileUrlType::Folder
;
1615 name
= aStatus
.getFileURL();
1616 whileSuccess
= remove( CommandId
, name
, recurse
, MustExist
);
1620 nError
= aDirectory
.getNextItem( aItem
);
1625 if( ! whileSuccess
)
1626 return false; // error code is installed
1628 if( nError
!= osl::FileBase::E_NOENT
)
1630 installError( CommandId
,
1631 TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE
,
1636 nError
= osl::Directory::remove( aUnqPath
);
1637 if( nError
!= osl::FileBase::E_None
)
1641 installError( CommandId
,
1642 TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE
,
1645 return (!MustExist
);
1649 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath
) );
1650 erasePersistentSet( aUnqPath
);
1653 else // Don't know what to remove
1655 installError( CommandId
,
1656 TASKHANDLING_FILETYPE_FOR_REMOVE
);
1664 /********************************************************************************/
1666 /* mkdir-implementation */
1668 /********************************************************************************/
1670 // Creates new directory with given URL, recursively if necessary
1671 // Return:: success of operation
1675 TaskManager::mkdir( sal_Int32 CommandId
,
1676 const OUString
& rUnqPath
,
1681 // remove trailing slash
1682 if ( rUnqPath
.endsWith("/") )
1683 aUnqPath
= rUnqPath
.copy( 0, rUnqPath
.getLength() - 1 );
1685 aUnqPath
= rUnqPath
;
1687 osl::FileBase::RC nError
= osl::Directory::create( aUnqPath
);
1691 case osl::FileBase::E_EXIST
: // Directory cannot be overwritten
1695 installError( CommandId
,
1696 TASKHANDLING_FOLDER_EXISTS_MKDIR
);
1702 case osl::FileBase::E_INVAL
:
1704 installError(CommandId
,
1705 TASKHANDLING_INVALID_NAME_MKDIR
);
1708 case osl::FileBase::E_None
:
1710 OUString aPrtPath
= getParentName( aUnqPath
);
1711 notifyInsert( getContentEventListeners( aPrtPath
),aUnqPath
);
1718 TASKHANDLING_CREATEDIRECTORY_MKDIR
);
1723 /********************************************************************************/
1725 /* mkfil-implementation */
1727 /********************************************************************************/
1729 // Creates new file with given URL.
1730 // The content of aInputStream becomes the content of the file
1731 // Return:: success of operation
1735 TaskManager::mkfil( sal_Int32 CommandId
,
1736 const OUString
& aUnqPath
,
1738 const uno::Reference
< io::XInputStream
>& aInputStream
)
1740 // return value unimportant
1741 bool bSuccess
= write( CommandId
,
1747 OUString aPrtPath
= getParentName( aUnqPath
);
1748 notifyInsert( getContentEventListeners( aPrtPath
),aUnqPath
);
1754 /********************************************************************************/
1756 /* write-implementation */
1758 /********************************************************************************/
1760 // writes to the file with given URL.
1761 // The content of aInputStream becomes the content of the file
1762 // Return:: success of operation
1766 TaskManager::write( sal_Int32 CommandId
,
1767 const OUString
& aUnqPath
,
1769 const uno::Reference
< io::XInputStream
>& aInputStream
)
1771 if( ! aInputStream
.is() )
1773 installError( CommandId
,
1774 TASKHANDLING_INPUTSTREAM_FOR_WRITE
);
1778 // Create parent path, if necessary.
1779 if ( ! ensuredir( CommandId
,
1780 getParentName( aUnqPath
),
1781 TASKHANDLING_ENSUREDIR_FOR_WRITE
) )
1784 osl::FileBase::RC err
;
1785 osl::File
aFile( aUnqPath
);
1789 err
= aFile
.open( osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
1791 if( err
!= osl::FileBase::E_None
)
1794 err
= aFile
.open( osl_File_OpenFlag_Write
);
1796 if( err
!= osl::FileBase::E_None
)
1798 installError( CommandId
,
1799 TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE
,
1804 // the existing file was just opened and should be overwritten now,
1805 // truncate it first
1807 err
= aFile
.setSize( 0 );
1808 if( err
!= osl::FileBase::E_None
)
1810 installError( CommandId
,
1811 TASKHANDLING_FILESIZE_FOR_WRITE
,
1819 err
= aFile
.open( osl_File_OpenFlag_Read
| osl_File_OpenFlag_NoLock
);
1820 if( err
== osl::FileBase::E_None
) // The file exists and shall not be overwritten
1822 installError( CommandId
,
1823 TASKHANDLING_NOREPLACE_FOR_WRITE
, // Now an exception
1830 // as a temporary solution the creation does not lock the file at all
1831 // in future it should be possible to create the file without lock explicitly
1832 err
= aFile
.open( osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
| osl_File_OpenFlag_NoLock
);
1834 if( err
!= osl::FileBase::E_None
)
1837 installError( CommandId
,
1838 TASKHANDLING_NO_OPEN_FILE_FOR_WRITE
,
1844 bool bSuccess
= true;
1846 sal_uInt64 nWrittenBytes
;
1847 sal_Int32 nReadBytes
= 0, nRequestedBytes
= 32768 /*32k*/;
1848 uno::Sequence
< sal_Int8
> seq( nRequestedBytes
);
1854 nReadBytes
= aInputStream
->readBytes( seq
,
1857 catch( const io::NotConnectedException
& )
1859 installError( CommandId
,
1860 TASKHANDLING_NOTCONNECTED_FOR_WRITE
);
1864 catch( const io::BufferSizeExceededException
& )
1866 installError( CommandId
,
1867 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE
);
1871 catch( const io::IOException
& )
1873 installError( CommandId
,
1874 TASKHANDLING_IOEXCEPTION_FOR_WRITE
);
1881 const sal_Int8
* p
= seq
.getConstArray();
1883 err
= aFile
.write( static_cast<void const *>(p
),
1884 sal_uInt64( nReadBytes
),
1887 if( err
!= osl::FileBase::E_None
)
1889 installError( CommandId
,
1890 TASKHANDLING_FILEIOERROR_FOR_WRITE
,
1895 else if( nWrittenBytes
!= sal_uInt64( nReadBytes
) )
1897 installError( CommandId
,
1898 TASKHANDLING_FILEIOERROR_FOR_NO_SPACE
);
1903 } while( nReadBytes
== nRequestedBytes
);
1905 err
= aFile
.close();
1906 if( err
!= osl::FileBase::E_None
)
1908 installError( CommandId
,
1909 TASKHANDLING_FILEIOERROR_FOR_WRITE
,
1918 /*********************************************************************************/
1920 /* insertDefaultProperties-Implementation */
1922 /*********************************************************************************/
1925 void TaskManager::insertDefaultProperties( const OUString
& aUnqPath
)
1927 std::unique_lock
aGuard(m_aMutex
);
1928 insertDefaultProperties(aGuard
, aUnqPath
);
1931 void TaskManager::insertDefaultProperties( std::unique_lock
<std::mutex
>& /*rGuard*/, const OUString
& aUnqPath
)
1933 ContentMap::iterator it
=
1934 m_aContent
.emplace( aUnqPath
,UnqPathData() ).first
;
1938 MyProperty
ContentTProperty( ContentType
);
1940 PropertySet
& properties
= it
->second
.properties
;
1941 bool ContentNotDefau
= properties
.find( ContentTProperty
) != properties
.end();
1943 properties
.reserve(properties
.size() + m_aDefaultProperties
.size());
1944 for (auto const& defaultprop
: m_aDefaultProperties
)
1946 if( !ContentNotDefau
|| defaultprop
.getPropertyName() != ContentType
)
1947 properties
.insert( defaultprop
);
1952 /******************************************************************************/
1954 /* mapping of file urls */
1955 /* to uncpath and vice versa */
1957 /******************************************************************************/
1960 bool TaskManager::getUnqFromUrl( const OUString
& Url
, OUString
& Unq
)
1962 if ( Url
== "file:///" || Url
== "file://localhost/" || Url
== "file://127.0.0.1/" )
1968 bool err
= osl::FileBase::E_None
!= osl::FileBase::getSystemPathFromFileURL( Url
,Unq
);
1972 sal_Int32 l
= Unq
.getLength()-1;
1973 if( ! err
&& Unq
.endsWith("/") &&
1974 Unq
.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) != -1 )
1975 Unq
= Unq
.copy(0, l
);
1981 bool TaskManager::getUrlFromUnq( const OUString
& Unq
,OUString
& Url
)
1983 bool err
= osl::FileBase::E_None
!= osl::FileBase::getSystemPathFromFileURL( Unq
,Url
);
1991 // Helper function for public copy
1994 TaskManager::copy_recursive( const OUString
& srcUnqPath
,
1995 const OUString
& dstUnqPath
,
1996 FileUrlType TypeToCopy
,
1997 bool testExistBeforeCopy
)
1999 osl::FileBase::RC err
= osl::FileBase::E_None
;
2001 if( TypeToCopy
== FileUrlType::File
) // Document
2003 err
= osl_File_copy( srcUnqPath
,dstUnqPath
,testExistBeforeCopy
);
2005 else if( TypeToCopy
== FileUrlType::Folder
)
2007 osl::Directory
aDir( srcUnqPath
);
2010 err
= osl::Directory::create( dstUnqPath
);
2011 osl::FileBase::RC next
= err
;
2012 if( err
== osl::FileBase::E_None
)
2014 sal_Int32
const n_Mask
= osl_FileStatus_Mask_FileURL
| osl_FileStatus_Mask_FileName
| osl_FileStatus_Mask_Type
;
2016 osl::DirectoryItem aDirItem
;
2018 while( err
== osl::FileBase::E_None
)
2020 next
= aDir
.getNextItem( aDirItem
);
2021 if (next
!= osl::FileBase::E_None
)
2024 osl::FileStatus
aFileStatus( n_Mask
);
2025 aDirItem
.getFileStatus( aFileStatus
);
2026 if( aFileStatus
.isValid( osl_FileStatus_Mask_Type
) )
2027 IsDoc
= aFileStatus
.getFileType() == osl::FileStatus::Regular
;
2029 // Getting the information for the next recursive copy
2030 FileUrlType newTypeToCopy
= IsDoc
? FileUrlType::File
: FileUrlType::Folder
;
2032 OUString newSrcUnqPath
;
2033 if( aFileStatus
.isValid( osl_FileStatus_Mask_FileURL
) )
2034 newSrcUnqPath
= aFileStatus
.getFileURL();
2036 OUString newDstUnqPath
= dstUnqPath
;
2038 if( aFileStatus
.isValid( osl_FileStatus_Mask_FileName
) )
2039 tit
= rtl::Uri::encode( aFileStatus
.getFileName(),
2040 rtl_UriCharClassPchar
,
2041 rtl_UriEncodeIgnoreEscapes
,
2042 RTL_TEXTENCODING_UTF8
);
2044 if( !newDstUnqPath
.endsWith( "/" ) )
2045 newDstUnqPath
+= "/";
2047 newDstUnqPath
+= tit
;
2049 if ( newSrcUnqPath
!= dstUnqPath
)
2050 err
= copy_recursive( newSrcUnqPath
,newDstUnqPath
,newTypeToCopy
,false );
2053 if( err
== osl::FileBase::E_None
&& next
!= osl::FileBase::E_NOENT
)
2063 // Helper function for mkfil,mkdir and write
2064 // Creates whole path
2065 // returns success of the operation
2068 bool TaskManager::ensuredir( sal_Int32 CommandId
,
2069 const OUString
& rUnqPath
,
2070 sal_Int32 errorCode
)
2074 if ( rUnqPath
.isEmpty() )
2077 if ( rUnqPath
.endsWith("/") )
2078 aPath
= rUnqPath
.copy( 0, rUnqPath
.getLength() - 1 );
2082 #if HAVE_FEATURE_MACOSX_SANDBOX
2084 // Avoid annoying sandbox messages in the system.log from the
2085 // below aDirectory.open(), which ends up calling opendir().
2086 // Surely it is easier to just call stat()? Calling stat() on an
2087 // arbitrary (?) directory does not seem to cause any sandbox
2088 // violation, while opendir() does. (Sorry I could not be bothered
2089 // to use some complex cross-platform abstraction over stat() here
2090 // in this macOS specific code block.)
2094 if( osl::FileBase::getSystemPathFromFileURL( aPath
, aDirName
) == osl::FileBase::E_None
&&
2095 stat(OUStringToOString( aDirName
, RTL_TEXTENCODING_UTF8
).getStr(), &s
) == 0 &&
2096 S_ISDIR( s
.st_mode
) )
2100 // HACK: create directory on a mount point with nobrowse option
2101 // returns ENOSYS in any case !!
2102 osl::Directory
aDirectory( aPath
);
2103 osl::FileBase::RC nError
= aDirectory
.open();
2106 if( nError
== osl::File::E_None
)
2109 nError
= osl::Directory::create( aPath
);
2111 if( nError
== osl::File::E_None
)
2112 notifyInsert( getContentEventListeners( getParentName( aPath
) ),aPath
);
2114 bool bSuccess
= ( nError
== osl::File::E_None
|| nError
== osl::FileBase::E_EXIST
);
2118 OUString aParentDir
= getParentName( aPath
);
2120 if ( aParentDir
!= aPath
)
2121 { // Create first the parent directory
2122 bSuccess
= ensuredir( CommandId
,
2123 getParentName( aPath
),
2126 // After parent directory structure exists try it one's more
2129 { // Parent directory exists, retry creation of directory
2130 nError
= osl::Directory::create( aPath
);
2132 if( nError
== osl::File::E_None
)
2133 notifyInsert( getContentEventListeners( getParentName( aPath
) ),aPath
);
2135 bSuccess
=( nError
== osl::File::E_None
|| nError
== osl::FileBase::E_EXIST
);
2141 installError( CommandId
,
2149 // Given a sequence of properties seq, this method determines the mask
2150 // used to instantiate an osl::FileStatus, so that a call to
2151 // osl::DirectoryItem::getFileStatus fills the required fields.
2155 TaskManager::getMaskFromProperties(
2157 const uno::Sequence
< beans::Property
>& seq
)
2160 for(const auto& rProp
: seq
) {
2161 if(rProp
.Name
== Title
)
2162 n_Mask
|= osl_FileStatus_Mask_FileName
;
2163 else if(rProp
.Name
== CasePreservingURL
)
2164 n_Mask
|= osl_FileStatus_Mask_FileURL
;
2165 else if(rProp
.Name
== IsDocument
||
2166 rProp
.Name
== IsFolder
||
2167 rProp
.Name
== IsVolume
||
2168 rProp
.Name
== IsRemoveable
||
2169 rProp
.Name
== IsRemote
||
2170 rProp
.Name
== IsCompactDisc
||
2171 rProp
.Name
== IsFloppy
||
2172 rProp
.Name
== ContentType
)
2173 n_Mask
|= (osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_LinkTargetURL
);
2174 else if(rProp
.Name
== Size
)
2175 n_Mask
|= (osl_FileStatus_Mask_FileSize
|
2176 osl_FileStatus_Mask_Type
|
2177 osl_FileStatus_Mask_LinkTargetURL
);
2178 else if(rProp
.Name
== IsHidden
||
2179 rProp
.Name
== IsReadOnly
)
2180 n_Mask
|= osl_FileStatus_Mask_Attributes
;
2181 else if(rProp
.Name
== DateModified
)
2182 n_Mask
|= osl_FileStatus_Mask_ModifyTime
;
2187 /*********************************************************************************/
2189 /* load-Implementation */
2191 /*********************************************************************************/
2193 // Load the properties from configuration, if create == true create them.
2194 // The Properties are stored under the url belonging to it->first.
2198 TaskManager::load( const ContentMap::iterator
& it
, bool create
)
2200 if( ( it
->second
.xS
.is() && it
->second
.xC
.is() && it
->second
.xA
.is() )
2201 || !m_xFileRegistry
.is() )
2205 uno::Reference
< ucb::XPersistentPropertySet
> xS
= m_xFileRegistry
->openPropertySet( it
->first
,create
);
2208 uno::Reference
< beans::XPropertyContainer
> xC( xS
,uno::UNO_QUERY
);
2209 uno::Reference
< beans::XPropertyAccess
> xA( xS
,uno::UNO_QUERY
);
2215 // Now put in all values in the storage in the local hash;
2217 PropertySet
& properties
= it
->second
.properties
;
2218 const uno::Sequence
< beans::Property
> seq
= xS
->getPropertySetInfo()->getProperties();
2220 for( const auto& rProp
: seq
)
2222 MyProperty
readProp( false,
2226 xS
->getPropertyValue( rProp
.Name
),
2227 beans::PropertyState_DIRECT_VALUE
,
2229 properties
.insert( readProp
);
2234 // Catastrophic error
2239 /*********************************************************************************/
2241 /* commit-Implementation */
2243 /*********************************************************************************/
2244 // Commit inserts the determined properties in the filestatus object into
2245 // the internal map, so that is possible to determine on a subsequent
2246 // setting of file properties which properties have changed without filestat
2250 TaskManager::commit( std::unique_lock
<std::mutex
>& rGuard
,
2251 const TaskManager::ContentMap::iterator
& it
,
2252 const osl::FileStatus
& aFileStatus
)
2254 TaskManager::PropertySet::const_iterator it1
;
2256 if( it
->second
.properties
.empty() )
2258 OUString aPath
= it
->first
;
2259 insertDefaultProperties( rGuard
, aPath
);
2262 PropertySet
& properties
= it
->second
.properties
;
2264 it1
= properties
.find( MyProperty( Title
) );
2265 if( it1
!= properties
.end() )
2267 if( aFileStatus
.isValid( osl_FileStatus_Mask_FileName
) )
2269 it1
->setValue( uno::Any(aFileStatus
.getFileName()) );
2273 it1
= properties
.find( MyProperty( CasePreservingURL
) );
2274 if( it1
!= properties
.end() )
2276 if( aFileStatus
.isValid( osl_FileStatus_Mask_FileURL
) )
2278 it1
->setValue( uno::Any(aFileStatus
.getFileURL()) );
2285 sal_Int64 dirSize
= 0;
2287 if( aFileStatus
.isValid( osl_FileStatus_Mask_FileSize
) )
2288 dirSize
= aFileStatus
.getFileSize();
2290 if( aFileStatus
.isValid( osl_FileStatus_Mask_Type
) )
2292 bool isFile
,isVolume
;
2293 if( osl::FileStatus::Link
== aFileStatus
.getFileType() &&
2294 aFileStatus
.isValid( osl_FileStatus_Mask_LinkTargetURL
) )
2296 osl::DirectoryItem aDirItem
;
2297 osl::FileStatus
aFileStatus2( osl_FileStatus_Mask_Type
);
2298 if( osl::FileBase::E_None
== osl::DirectoryItem::get( aFileStatus
.getLinkTargetURL(),aDirItem
) &&
2299 osl::FileBase::E_None
== aDirItem
.getFileStatus( aFileStatus2
) &&
2300 aFileStatus2
.isValid( osl_FileStatus_Mask_Type
) )
2302 isVolume
= osl::FileStatus::Volume
== aFileStatus2
.getFileType();
2304 osl::FileStatus::Volume
== aFileStatus2
.getFileType() ||
2305 osl::FileStatus::Directory
== aFileStatus2
.getFileType();
2307 osl::FileStatus::Regular
== aFileStatus2
.getFileType();
2309 if( aFileStatus2
.isValid( osl_FileStatus_Mask_FileSize
) )
2310 dirSize
= aFileStatus2
.getFileSize();
2314 // extremely ugly, but otherwise default construction
2315 // of aDirItem and aFileStatus2
2316 // before the preceding if
2317 isVolume
= osl::FileStatus::Volume
== aFileStatus
.getFileType();
2319 osl::FileStatus::Volume
== aFileStatus
.getFileType() ||
2320 osl::FileStatus::Directory
== aFileStatus
.getFileType();
2322 osl::FileStatus::Regular
== aFileStatus
.getFileType();
2327 isVolume
= osl::FileStatus::Volume
== aFileStatus
.getFileType();
2329 osl::FileStatus::Volume
== aFileStatus
.getFileType() ||
2330 osl::FileStatus::Directory
== aFileStatus
.getFileType();
2332 osl::FileStatus::Regular
== aFileStatus
.getFileType();
2335 it1
= properties
.find( MyProperty( IsVolume
) );
2336 if( it1
!= properties
.end() )
2337 it1
->setValue( uno::Any( isVolume
) );
2339 it1
= properties
.find( MyProperty( IsFolder
) );
2340 if( it1
!= properties
.end() )
2341 it1
->setValue( uno::Any( isDirectory
) );
2343 it1
= properties
.find( MyProperty( IsDocument
) );
2344 if( it1
!= properties
.end() )
2345 it1
->setValue( uno::Any( isFile
) );
2347 osl::VolumeInfo
aVolumeInfo( osl_VolumeInfo_Mask_Attributes
);
2349 osl::FileBase::E_None
== osl::Directory::getVolumeInfo( it
->first
,aVolumeInfo
) &&
2350 aVolumeInfo
.isValid( osl_VolumeInfo_Mask_Attributes
) )
2352 // Retrieve the flags;
2353 bool isRemote
= aVolumeInfo
.getRemoteFlag();
2354 bool isRemoveable
= aVolumeInfo
.getRemoveableFlag();
2355 bool isCompactDisc
= aVolumeInfo
.getCompactDiscFlag();
2356 bool isFloppy
= aVolumeInfo
.getFloppyDiskFlag();
2358 it1
= properties
.find( MyProperty( IsRemote
) );
2359 if( it1
!= properties
.end() )
2360 it1
->setValue( uno::Any( isRemote
) );
2362 it1
= properties
.find( MyProperty( IsRemoveable
) );
2363 if( it1
!= properties
.end() )
2364 it1
->setValue( uno::Any( isRemoveable
) );
2366 it1
= properties
.find( MyProperty( IsCompactDisc
) );
2367 if( it1
!= properties
.end() )
2368 it1
->setValue( uno::Any( isCompactDisc
) );
2370 it1
= properties
.find( MyProperty( IsFloppy
) );
2371 if( it1
!= properties
.end() )
2372 it1
->setValue( uno::Any( isFloppy
) );
2376 uno::Any
aAny(false);
2377 it1
= properties
.find( MyProperty( IsRemote
) );
2378 if( it1
!= properties
.end() )
2379 it1
->setValue( aAny
);
2381 it1
= properties
.find( MyProperty( IsRemoveable
) );
2382 if( it1
!= properties
.end() )
2383 it1
->setValue( aAny
);
2385 it1
= properties
.find( MyProperty( IsCompactDisc
) );
2386 if( it1
!= properties
.end() )
2387 it1
->setValue( aAny
);
2389 it1
= properties
.find( MyProperty( IsFloppy
) );
2390 if( it1
!= properties
.end() )
2391 it1
->setValue( aAny
);
2396 isDirectory
= false;
2399 it1
= properties
.find( MyProperty( Size
) );
2400 if( it1
!= properties
.end() )
2401 it1
->setValue( uno::Any( dirSize
) );
2403 it1
= properties
.find( MyProperty( IsReadOnly
) );
2404 if( it1
!= properties
.end() )
2406 if( aFileStatus
.isValid( osl_FileStatus_Mask_Attributes
) )
2408 sal_uInt64 Attr
= aFileStatus
.getAttributes();
2409 bool readonly
= ( Attr
& osl_File_Attribute_ReadOnly
) != 0;
2410 it1
->setValue( uno::Any( readonly
) );
2414 it1
= properties
.find( MyProperty( IsHidden
) );
2415 if( it1
!= properties
.end() )
2417 if( aFileStatus
.isValid( osl_FileStatus_Mask_Attributes
) )
2419 sal_uInt64 Attr
= aFileStatus
.getAttributes();
2420 bool ishidden
= ( Attr
& osl_File_Attribute_Hidden
) != 0;
2421 it1
->setValue( uno::Any( ishidden
) );
2425 it1
= properties
.find( MyProperty( DateModified
) );
2426 if( it1
!= properties
.end() )
2428 if( aFileStatus
.isValid( osl_FileStatus_Mask_ModifyTime
) )
2430 TimeValue temp
= aFileStatus
.getModifyTime();
2432 // Convert system time to local time (for EA)
2433 TimeValue myLocalTime
;
2434 if (!osl_getLocalTimeFromSystemTime( &temp
, &myLocalTime
))
2438 "cannot convert (" << temp
.Seconds
<< ", " << temp
.Nanosec
2439 << ") to local time");
2443 oslDateTime myDateTime
;
2444 osl_getDateTimeFromTimeValue( &myLocalTime
, &myDateTime
);
2445 util::DateTime aDateTime
;
2447 aDateTime
.NanoSeconds
= myDateTime
.NanoSeconds
;
2448 aDateTime
.Seconds
= myDateTime
.Seconds
;
2449 aDateTime
.Minutes
= myDateTime
.Minutes
;
2450 aDateTime
.Hours
= myDateTime
.Hours
;
2451 aDateTime
.Day
= myDateTime
.Day
;
2452 aDateTime
.Month
= myDateTime
.Month
;
2453 aDateTime
.Year
= myDateTime
.Year
;
2454 it1
->setValue( uno::Any( aDateTime
) );
2458 it1
= properties
.find( MyProperty( CreatableContentsInfo
) );
2459 if( it1
!= properties
.end() )
2460 it1
->setValue( uno::Any(
2461 isDirectory
|| !aFileStatus
.isValid( osl_FileStatus_Mask_Type
)
2462 ? queryCreatableContentsInfo()
2463 : uno::Sequence
< ucb::ContentInfo
>() ) );
2467 // Special optimized method for getting the properties of a
2468 // directoryitem, which is returned by osl::DirectoryItem::getNextItem()
2473 const uno::Sequence
< beans::Property
>& properties
,
2474 osl::DirectoryItem
& aDirItem
,
2477 uno::Reference
< sdbc::XRow
> & row
)
2479 uno::Sequence
< uno::Any
> seq( properties
.getLength() );
2482 getMaskFromProperties( n_Mask
,properties
);
2484 // Always retrieve the type and the target URL because item might be a link
2485 osl::FileStatus
aFileStatus( n_Mask
|
2486 osl_FileStatus_Mask_FileURL
|
2487 osl_FileStatus_Mask_Type
|
2488 osl_FileStatus_Mask_LinkTargetURL
);
2490 osl::FileBase::RC aRes
= aDirItem
.getFileStatus( aFileStatus
);
2491 if ( aRes
!= osl::FileBase::E_None
)
2495 "osl::DirectoryItem::getFileStatus failed with " << +aRes
);
2499 aUnqPath
= aFileStatus
.getFileURL();
2501 // If the directory item type is a link retrieve the type of the target
2503 if ( aFileStatus
.getFileType() == osl::FileStatus::Link
)
2507 osl::DirectoryItem aTargetItem
;
2508 (void)osl::DirectoryItem::get( aFileStatus
.getLinkTargetURL(), aTargetItem
);
2509 if ( aTargetItem
.is() )
2511 osl::FileStatus
aTargetStatus( osl_FileStatus_Mask_Type
);
2513 if ( osl::FileBase::E_None
== aTargetItem
.getFileStatus( aTargetStatus
) )
2515 aTargetStatus
.getFileType() == osl::FileStatus::Regular
;
2519 aIsRegular
= aFileStatus
.getFileType() == osl::FileStatus::Regular
;
2522 std::unique_lock
aGuard( m_aMutex
);
2524 insertDefaultProperties( aGuard
, aUnqPath
);
2526 TaskManager::ContentMap::iterator it
= m_aContent
.find( aUnqPath
);
2527 commit( aGuard
, it
, aFileStatus
);
2529 PropertySet
& propset
= it
->second
.properties
;
2531 std::transform(properties
.begin(), properties
.end(), seq
.getArray(),
2532 [&propset
](const beans::Property
& rProp
) -> uno::Any
{
2533 MyProperty
readProp( rProp
.Name
);
2534 auto it1
= propset
.find( readProp
);
2535 if( it1
== propset
.end() )
2537 return it1
->getValue();
2541 row
= new XRow_impl( this,seq
);
2549 std::vector
< ContentEventNotifier
>
2550 TaskManager::getContentEventListeners( const OUString
& aName
)
2552 std::vector
< ContentEventNotifier
> listeners
;
2554 std::unique_lock
aGuard( m_aMutex
);
2555 TaskManager::ContentMap::iterator it
= m_aContent
.find( aName
);
2556 if( it
!= m_aContent
.end() && !it
->second
.notifier
.empty() )
2558 std::vector
<Notifier
*>& listOfNotifiers
= it
->second
.notifier
;
2559 for (auto const& pointer
: listOfNotifiers
)
2561 std::optional
<ContentEventNotifier
> notifier
= pointer
->cCEL();
2563 listeners
.push_back( std::move(*notifier
) );
2571 std::vector
< ContentEventNotifier
>
2572 TaskManager::getContentDeletedEventListeners( const OUString
& aName
)
2574 std::vector
< ContentEventNotifier
> listeners
;
2576 std::unique_lock
aGuard( m_aMutex
);
2577 TaskManager::ContentMap::iterator it
= m_aContent
.find( aName
);
2578 if( it
!= m_aContent
.end() && !it
->second
.notifier
.empty() )
2580 std::vector
<Notifier
*>& listOfNotifiers
= it
->second
.notifier
;
2581 for (auto const& pointer
: listOfNotifiers
)
2583 std::optional
<ContentEventNotifier
> notifier
= pointer
->cDEL();
2585 listeners
.push_back( std::move(*notifier
) );
2592 void TaskManager::notifyInsert(const std::vector
<ContentEventNotifier
>& listeners
,
2593 const OUString
& aChildName
)
2595 for (const auto & l
: listeners
)
2597 l
.notifyChildInserted( aChildName
);
2601 void TaskManager::notifyContentDeleted(
2602 const std::vector
<ContentEventNotifier
>& listeners
)
2604 for( auto const & l
: listeners
)
2610 void TaskManager::notifyContentRemoved(
2611 const std::vector
<ContentEventNotifier
>& listeners
, const OUString
& aChildName
)
2613 for( auto const & l
: listeners
)
2615 l
.notifyRemoved( aChildName
);
2620 std::vector
< PropertySetInfoChangeNotifier
>
2621 TaskManager::getPropertySetListeners( const OUString
& aName
)
2623 std::vector
< PropertySetInfoChangeNotifier
> listeners
;
2625 std::unique_lock
aGuard( m_aMutex
);
2626 TaskManager::ContentMap::iterator it
= m_aContent
.find( aName
);
2627 if( it
!= m_aContent
.end() && !it
->second
.notifier
.empty() )
2629 std::vector
<Notifier
*>& listOfNotifiers
= it
->second
.notifier
;
2630 for (auto const& pointer
: listOfNotifiers
)
2632 std::optional
<PropertySetInfoChangeNotifier
> notifier
= pointer
->cPSL();
2634 listeners
.push_back( std::move(*notifier
) );
2641 void TaskManager::notifyPropertyAdded(
2642 const std::vector
<PropertySetInfoChangeNotifier
>& listeners
,
2643 const OUString
& aPropertyName
)
2645 for( auto const & l
: listeners
)
2647 l
.notifyPropertyAdded( aPropertyName
);
2651 void TaskManager::notifyPropertyRemoved(
2652 const std::vector
<PropertySetInfoChangeNotifier
>& listeners
,
2653 const OUString
& aPropertyName
)
2655 for( auto const & l
: listeners
)
2657 l
.notifyPropertyRemoved( aPropertyName
);
2662 std::vector
< ContentEventNotifier
>
2663 TaskManager::getContentExchangedEventListeners( const OUString
& aOldPrefix
,
2664 const OUString
& aNewPrefix
,
2667 std::vector
< ContentEventNotifier
> aVector
;
2672 std::vector
< OUString
> oldChildList
;
2675 std::unique_lock
aGuard( m_aMutex
);
2677 if( ! withChildren
)
2679 aOldName
= aOldPrefix
;
2680 aNewName
= aNewPrefix
;
2685 for (auto const& content
: m_aContent
)
2687 if( isChild( aOldPrefix
, content
.first
) )
2689 oldChildList
.push_back( content
.first
);
2692 count
= oldChildList
.size();
2696 for( sal_Int32 j
= 0; j
< count
; ++j
)
2700 aOldName
= oldChildList
[j
];
2701 aNewName
= newName( aNewPrefix
,aOldPrefix
,aOldName
);
2704 TaskManager::ContentMap::iterator itold
= m_aContent
.find( aOldName
);
2705 if( itold
!= m_aContent
.end() )
2707 TaskManager::ContentMap::iterator itnew
= m_aContent
.emplace(
2708 aNewName
,UnqPathData() ).first
;
2710 // copy Ownership also
2711 itnew
->second
.properties
= std::move(itold
->second
.properties
);
2713 // copy existing list
2714 std::vector
< Notifier
* > copyList
;
2715 std::swap(copyList
, itnew
->second
.notifier
);
2716 itnew
->second
.notifier
= std::move(itold
->second
.notifier
);
2718 m_aContent
.erase( itold
);
2720 if (itnew
!= m_aContent
.end())
2722 if (!itnew
->second
.notifier
.empty())
2724 std::vector
<Notifier
*>& listOfNotifiers
= itnew
->second
.notifier
;
2725 for (auto const& pointer
: listOfNotifiers
)
2727 std::optional
<ContentEventNotifier
> notifier
= pointer
->cEXC( aNewName
);
2729 aVector
.push_back( std::move(*notifier
) );
2733 // Merge with preexisting notifiers
2734 // However, these may be in status BaseContent::Deleted
2735 itnew
->second
.notifier
.insert(itnew
->second
.notifier
.end(),
2736 copyList
.begin(), copyList
.end() );
2745 void TaskManager::notifyContentExchanged(
2746 const std::vector
<ContentEventNotifier
>& listeners_vec
)
2748 for( auto & l
: listeners_vec
)
2750 l
.notifyExchanged();
2755 std::vector
< PropertyChangeNotifier
>
2756 TaskManager::getPropertyChangeNotifier( const OUString
& aName
)
2758 std::vector
< PropertyChangeNotifier
> listeners
;
2760 std::unique_lock
aGuard( m_aMutex
);
2761 TaskManager::ContentMap::iterator it
= m_aContent
.find( aName
);
2762 if( it
!= m_aContent
.end() && !it
->second
.notifier
.empty() )
2764 std::vector
<Notifier
*>& listOfNotifiers
= it
->second
.notifier
;
2765 for (auto const& pointer
: listOfNotifiers
)
2767 std::optional
<PropertyChangeNotifier
> notifier
= pointer
->cPCL();
2769 listeners
.push_back( std::move(*notifier
) );
2776 void TaskManager::notifyPropertyChanges(
2777 const std::vector
<PropertyChangeNotifier
>& listeners
,
2778 const uno::Sequence
<beans::PropertyChangeEvent
>& seqChanged
)
2780 for( auto const & l
: listeners
)
2782 l
.notifyPropertyChanged( seqChanged
);
2787 /********************************************************************************/
2788 /* remove persistent propertyset */
2789 /********************************************************************************/
2792 TaskManager::erasePersistentSetWithoutChildren( const OUString
& aUnqPath
)
2795 // Release possible references
2796 std::unique_lock
aGuard( m_aMutex
);
2797 ContentMap::iterator it
= m_aContent
.find( aUnqPath
);
2798 if( it
!= m_aContent
.end() )
2800 it
->second
.xS
= nullptr;
2801 it
->second
.xC
= nullptr;
2802 it
->second
.xA
= nullptr;
2804 it
->second
.properties
.clear();
2808 m_xFileRegistry
->removePropertySet( aUnqPath
);
2812 TaskManager::erasePersistentSet( const OUString
& aUnqPath
,
2815 if( ! m_xFileRegistry
.is() )
2817 OSL_ASSERT( m_xFileRegistry
.is() );
2821 if( ! withChildren
)
2823 erasePersistentSetWithoutChildren(aUnqPath
);
2827 uno::Reference
< container::XNameAccess
> xName( m_xFileRegistry
,uno::UNO_QUERY
);
2828 const uno::Sequence
< OUString
> seqNames
= xName
->getElementNames();
2830 OUString old_Name
= aUnqPath
;
2832 for( const auto& rName
: seqNames
)
2834 if( ! ( isChild( old_Name
,rName
) ) )
2839 erasePersistentSetWithoutChildren(old_Name
);
2844 /********************************************************************************/
2845 /* copy persistent propertyset */
2846 /* from srcUnqPath to dstUnqPath */
2847 /********************************************************************************/
2850 TaskManager::copyPersistentSetWithoutChildren( const OUString
& srcUnqPath
,
2851 const OUString
& dstUnqPath
)
2853 uno::Reference
< XPersistentPropertySet
> x_src
=
2854 m_xFileRegistry
->openPropertySet( srcUnqPath
,false );
2855 m_xFileRegistry
->removePropertySet( dstUnqPath
);
2860 const uno::Sequence
< beans::Property
> seqProperty
=
2861 x_src
->getPropertySetInfo()->getProperties();
2863 if( ! seqProperty
.hasElements() )
2866 uno::Reference
< XPersistentPropertySet
>
2867 x_dstS
= m_xFileRegistry
->openPropertySet( dstUnqPath
,true );
2868 uno::Reference
< beans::XPropertyContainer
>
2869 x_dstC( x_dstS
,uno::UNO_QUERY
);
2871 for( const auto& rProperty
: seqProperty
)
2873 x_dstC
->addProperty( rProperty
.Name
,
2874 rProperty
.Attributes
,
2875 x_src
->getPropertyValue( rProperty
.Name
) );
2880 TaskManager::copyPersistentSet( const OUString
& srcUnqPath
,
2881 const OUString
& dstUnqPath
,
2884 if( ! m_xFileRegistry
.is() )
2886 OSL_ASSERT( m_xFileRegistry
.is() );
2890 if( ! withChildren
)
2892 copyPersistentSetWithoutChildren(srcUnqPath
, dstUnqPath
);
2896 uno::Reference
< container::XNameAccess
> xName( m_xFileRegistry
,uno::UNO_QUERY
);
2897 const uno::Sequence
< OUString
> seqNames
= xName
->getElementNames();
2901 for( const auto& rName
: seqNames
)
2903 if( ! ( isChild( srcUnqPath
,rName
) ) )
2906 new_Name
= newName( dstUnqPath
,srcUnqPath
,rName
);
2908 copyPersistentSetWithoutChildren(rName
, new_Name
);
2912 uno::Sequence
< ucb::ContentInfo
> TaskManager::queryCreatableContentsInfo()
2916 uno::Sequence
< beans::Property
> props
2918 { "Title", -1, cppu::UnoType
<OUString
>::get(), beans::PropertyAttribute::MAYBEVOID
| beans::PropertyAttribute::BOUND
}
2922 { FileContentType
, ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
| ucb::ContentInfoAttribute::KIND_DOCUMENT
, props
},
2923 { FolderContentType
, ucb::ContentInfoAttribute::KIND_FOLDER
, props
}
2927 /*******************************************************************************/
2929 /* some miscellaneous static functions */
2931 /*******************************************************************************/
2934 TaskManager::getScheme( OUString
& Scheme
)
2939 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */