tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / ucb / source / ucp / file / filtask.cxx
bloba088e9b63017a8092932abfb1835274ba11faba4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
26 #include <sys/stat.h>
27 #endif
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 <osl/diagnose.h>
49 #include <rtl/ref.hxx>
50 #include <rtl/uri.hxx>
52 #include "filtask.hxx"
53 #include "filcmd.hxx"
54 #include "filglob.hxx"
55 #include "filinpstr.hxx"
56 #include "filprp.hxx"
57 #include "filrset.hxx"
58 #include "filstr.hxx"
59 #include "prov.hxx"
61 /******************************************************************************/
62 /* */
63 /* TaskHandling */
64 /* */
65 /******************************************************************************/
68 using namespace fileaccess;
69 using namespace com::sun::star;
70 using namespace com::sun::star::uno;
71 using namespace com::sun::star::ucb;
73 #if OSL_DEBUG_LEVEL > 0
74 #define THROW_WHERE SAL_WHERE
75 #else
76 #define THROW_WHERE ""
77 #endif
79 TaskManager::UnqPathData::UnqPathData() = default;
81 TaskManager::UnqPathData::UnqPathData(TaskManager::UnqPathData&&) = default;
84 TaskManager::UnqPathData::~UnqPathData()
88 TaskManager::MyProperty::MyProperty( const OUString& thePropertyName )
89 : PropertyName( thePropertyName )
90 , Handle(-1)
91 , isNative(false)
92 , State(beans::PropertyState_AMBIGUOUS_VALUE)
93 , Attributes(0)
95 // empty
98 TaskManager::MyProperty::MyProperty( bool theisNative,
99 const OUString& thePropertyName,
100 sal_Int32 theHandle,
101 const css::uno::Type& theTyp,
102 const css::uno::Any& theValue,
103 const css::beans::PropertyState& theState,
104 sal_Int16 theAttributes )
105 : PropertyName( thePropertyName ),
106 Handle( theHandle ),
107 isNative( theisNative ),
108 Typ( theTyp ),
109 Value( theValue ),
110 State( theState ),
111 Attributes( theAttributes )
113 // empty
116 #include "filinl.hxx"
118 // Default properties
120 constexpr OUString Title( u"Title"_ustr );
121 constexpr OUString CasePreservingURL( u"CasePreservingURL"_ustr );
122 constexpr OUString IsDocument( u"IsDocument"_ustr );
123 constexpr OUString IsFolder( u"IsFolder"_ustr );
124 constexpr OUString DateModified( u"DateModified"_ustr );
125 constexpr OUString Size( u"Size"_ustr );
126 constexpr OUString IsVolume( u"IsVolume"_ustr );
127 constexpr OUString IsRemoveable( u"IsRemoveable"_ustr );
128 constexpr OUString IsRemote( u"IsRemote"_ustr );
129 constexpr OUString IsCompactDisc( u"IsCompactDisc"_ustr );
130 constexpr OUString IsFloppy( u"IsFloppy"_ustr );
131 constexpr OUString IsHidden( u"IsHidden"_ustr );
132 constexpr OUString ContentType( u"ContentType"_ustr );
133 constexpr OUString IsReadOnly( u"IsReadOnly"_ustr );
134 constexpr OUString CreatableContentsInfo( u"CreatableContentsInfo"_ustr );
136 TaskManager::TaskManager( const uno::Reference< uno::XComponentContext >& rxContext,
137 FileProvider* pProvider, bool bWithConfig )
138 : m_nCommandId( 0 ),
139 m_pProvider( pProvider ),
140 m_xContext( rxContext ),
141 // Commands
142 m_sCommandInfo{
143 { /* Name */ u"getCommandInfo"_ustr,
144 /* Handle */ -1,
145 /* ArgType */ cppu::UnoType<void>::get() },
147 { /* Name */ u"getPropertySetInfo"_ustr,
148 /* Handle */ -1,
149 /* ArgType */ cppu::UnoType<void>::get() },
151 { /* Name */ u"getPropertyValues"_ustr,
152 /* Handle */ -1,
153 /* ArgType */ cppu::UnoType<uno::Sequence< beans::Property >>::get() },
155 { /* Name */ u"setPropertyValues"_ustr,
156 /* Handle */ -1,
157 /* ArgType */ cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get() },
159 { /* Name */ u"open"_ustr,
160 /* Handle */ -1,
161 /* ArgType */ cppu::UnoType<OpenCommandArgument>::get() },
163 { /* Name */ u"transfer"_ustr,
164 /* Handle */ -1,
165 /* ArgType */ cppu::UnoType<TransferInfo>::get() },
167 { /* Name */ u"delete"_ustr,
168 /* Handle */ -1,
169 /* ArgType */ cppu::UnoType<sal_Bool>::get() },
171 { /* Name */ u"insert"_ustr,
172 /* Handle */ -1,
173 /* ArgType */ cppu::UnoType<InsertCommandArgument>::get() },
175 { /* Name */ u"createNewContent"_ustr,
176 /* Handle */ -1,
177 /* ArgType */ cppu::UnoType<ucb::ContentInfo>::get() } }
179 // Title
180 m_aDefaultProperties.insert( MyProperty( true,
181 Title,
182 -1 ,
183 cppu::UnoType<OUString>::get(),
184 uno::Any(),
185 beans::PropertyState_DEFAULT_VALUE,
186 beans::PropertyAttribute::MAYBEVOID
187 | beans::PropertyAttribute::BOUND ) );
189 // CasePreservingURL
190 m_aDefaultProperties.insert(
191 MyProperty( true,
192 CasePreservingURL,
193 -1 ,
194 cppu::UnoType<OUString>::get(),
195 uno::Any(),
196 beans::PropertyState_DEFAULT_VALUE,
197 beans::PropertyAttribute::MAYBEVOID
198 | beans::PropertyAttribute::BOUND
199 | beans::PropertyAttribute::READONLY ) );
202 // IsFolder
203 m_aDefaultProperties.insert( MyProperty( true,
204 IsFolder,
205 -1 ,
206 cppu::UnoType<sal_Bool>::get(),
207 uno::Any(),
208 beans::PropertyState_DEFAULT_VALUE,
209 beans::PropertyAttribute::MAYBEVOID
210 | beans::PropertyAttribute::BOUND
211 | beans::PropertyAttribute::READONLY ) );
214 // IsDocument
215 m_aDefaultProperties.insert( MyProperty( true,
216 IsDocument,
217 -1 ,
218 cppu::UnoType<sal_Bool>::get(),
219 uno::Any(),
220 beans::PropertyState_DEFAULT_VALUE,
221 beans::PropertyAttribute::MAYBEVOID
222 | beans::PropertyAttribute::BOUND
223 | beans::PropertyAttribute::READONLY ) );
225 // Removable
226 m_aDefaultProperties.insert( MyProperty( true,
227 IsVolume,
228 -1 ,
229 cppu::UnoType<sal_Bool>::get(),
230 uno::Any(),
231 beans::PropertyState_DEFAULT_VALUE,
232 beans::PropertyAttribute::MAYBEVOID
233 | beans::PropertyAttribute::BOUND
234 | beans::PropertyAttribute::READONLY ) );
237 // Removable
238 m_aDefaultProperties.insert( MyProperty( true,
239 IsRemoveable,
240 -1 ,
241 cppu::UnoType<sal_Bool>::get(),
242 uno::Any(),
243 beans::PropertyState_DEFAULT_VALUE,
244 beans::PropertyAttribute::MAYBEVOID
245 | beans::PropertyAttribute::BOUND
246 | beans::PropertyAttribute::READONLY ) );
248 // Remote
249 m_aDefaultProperties.insert( MyProperty( true,
250 IsRemote,
251 -1 ,
252 cppu::UnoType<sal_Bool>::get(),
253 uno::Any(),
254 beans::PropertyState_DEFAULT_VALUE,
255 beans::PropertyAttribute::MAYBEVOID
256 | beans::PropertyAttribute::BOUND
257 | beans::PropertyAttribute::READONLY ) );
259 // CompactDisc
260 m_aDefaultProperties.insert( MyProperty( true,
261 IsCompactDisc,
262 -1 ,
263 cppu::UnoType<sal_Bool>::get(),
264 uno::Any(),
265 beans::PropertyState_DEFAULT_VALUE,
266 beans::PropertyAttribute::MAYBEVOID
267 | beans::PropertyAttribute::BOUND
268 | beans::PropertyAttribute::READONLY ) );
270 // Floppy
271 m_aDefaultProperties.insert( MyProperty( true,
272 IsFloppy,
273 -1 ,
274 cppu::UnoType<sal_Bool>::get(),
275 uno::Any(),
276 beans::PropertyState_DEFAULT_VALUE,
277 beans::PropertyAttribute::MAYBEVOID
278 | beans::PropertyAttribute::BOUND
279 | beans::PropertyAttribute::READONLY ) );
281 // Hidden
282 m_aDefaultProperties.insert(
283 MyProperty(
284 true,
285 IsHidden,
286 -1 ,
287 cppu::UnoType<sal_Bool>::get(),
288 uno::Any(),
289 beans::PropertyState_DEFAULT_VALUE,
290 beans::PropertyAttribute::MAYBEVOID
291 | beans::PropertyAttribute::BOUND
292 #if defined(_WIN32)
294 #else
295 | beans::PropertyAttribute::READONLY)); // under unix/linux only readable
296 #endif
299 // ContentType
300 m_aDefaultProperties.insert( MyProperty( false,
301 ContentType,
302 -1 ,
303 cppu::UnoType<OUString>::get(),
304 uno::Any(OUString()),
305 beans::PropertyState_DEFAULT_VALUE,
306 beans::PropertyAttribute::MAYBEVOID
307 | beans::PropertyAttribute::BOUND
308 | beans::PropertyAttribute::READONLY ) );
311 // DateModified
312 m_aDefaultProperties.insert( MyProperty( true,
313 DateModified,
314 -1 ,
315 cppu::UnoType<util::DateTime>::get(),
316 uno::Any(),
317 beans::PropertyState_DEFAULT_VALUE,
318 beans::PropertyAttribute::MAYBEVOID
319 | beans::PropertyAttribute::BOUND ) );
321 // Size
322 m_aDefaultProperties.insert( MyProperty( true,
323 Size,
325 cppu::UnoType<sal_Int64>::get(),
326 uno::Any(),
327 beans::PropertyState_DEFAULT_VALUE,
328 beans::PropertyAttribute::MAYBEVOID
329 | beans::PropertyAttribute::BOUND ) );
331 // IsReadOnly
332 m_aDefaultProperties.insert( MyProperty( true,
333 IsReadOnly,
334 -1 ,
335 cppu::UnoType<sal_Bool>::get(),
336 uno::Any(),
337 beans::PropertyState_DEFAULT_VALUE,
338 beans::PropertyAttribute::MAYBEVOID
339 | beans::PropertyAttribute::BOUND ) );
342 // CreatableContentsInfo
343 m_aDefaultProperties.insert( MyProperty( true,
344 CreatableContentsInfo,
345 -1 ,
346 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
347 uno::Any(),
348 beans::PropertyState_DEFAULT_VALUE,
349 beans::PropertyAttribute::MAYBEVOID
350 | beans::PropertyAttribute::BOUND
351 | beans::PropertyAttribute::READONLY ) );
353 if(bWithConfig)
355 uno::Reference< XPropertySetRegistryFactory > xRegFac = ucb::Store::create( m_xContext );
356 // Open/create a registry
357 m_xFileRegistry = xRegFac->createPropertySetRegistry( OUString() );
362 TaskManager::~TaskManager()
367 void
368 TaskManager::startTask(
369 sal_Int32 CommandId,
370 const uno::Reference< XCommandEnvironment >& xCommandEnv )
372 std::unique_lock aGuard( m_aMutex );
373 TaskMap::iterator it = m_aTaskMap.find( CommandId );
374 if( it != m_aTaskMap.end() )
376 throw DuplicateCommandIdentifierException( OSL_LOG_PREFIX );
378 m_aTaskMap.emplace( CommandId, TaskHandling( xCommandEnv ));
382 void
383 TaskManager::endTask( sal_Int32 CommandId,
384 const OUString& aUncPath,
385 BaseContent* pContent)
387 std::unique_lock aGuard( m_aMutex );
388 TaskMap::iterator it = m_aTaskMap.find( CommandId );
389 if( it == m_aTaskMap.end() )
390 return;
392 TaskHandlerErr ErrorCode = it->second.getInstalledError();
393 sal_Int32 MinorCode = it->second.getMinorErrorCode();
394 bool isHandled = it->second.isHandled();
396 Reference< XCommandEnvironment > xComEnv
397 = it->second.getCommandEnvironment();
399 m_aTaskMap.erase( it );
401 aGuard.unlock();
403 if( ErrorCode != TaskHandlerErr::NO_ERROR )
404 throw_handler(
405 ErrorCode,
406 MinorCode,
407 xComEnv,
408 aUncPath,
409 pContent,
410 isHandled);
414 void TaskManager::clearError( sal_Int32 CommandId )
416 std::unique_lock aGuard( m_aMutex );
417 TaskMap::iterator it = m_aTaskMap.find( CommandId );
418 if( it != m_aTaskMap.end() )
419 it->second.clearError();
423 void TaskManager::retrieveError( sal_Int32 CommandId,
424 TaskHandlerErr &ErrorCode,
425 sal_Int32 &minorCode)
427 std::unique_lock aGuard( m_aMutex );
428 TaskMap::iterator it = m_aTaskMap.find( CommandId );
429 if( it != m_aTaskMap.end() )
431 ErrorCode = it->second.getInstalledError();
432 minorCode = it->second. getMinorErrorCode();
437 void TaskManager::installError( sal_Int32 CommandId,
438 TaskHandlerErr ErrorCode,
439 sal_Int32 MinorCode )
441 std::unique_lock aGuard( m_aMutex );
442 TaskMap::iterator it = m_aTaskMap.find( CommandId );
443 if( it != m_aTaskMap.end() )
444 it->second.installError( ErrorCode,MinorCode );
448 sal_Int32
449 TaskManager::getCommandId()
451 std::unique_lock aGuard( m_aMutex );
452 return ++m_nCommandId;
456 void TaskManager::handleTask(
457 sal_Int32 CommandId,
458 const uno::Reference< task::XInteractionRequest >& request )
460 std::unique_lock aGuard( m_aMutex );
461 TaskMap::iterator it = m_aTaskMap.find( CommandId );
462 uno::Reference< task::XInteractionHandler > xInt;
463 if( it != m_aTaskMap.end() )
465 xInt = it->second.getInteractionHandler();
466 if( xInt.is() )
467 xInt->handle( request );
468 it->second.setHandled();
472 /*********************************************************************************/
473 /* */
474 /* de/registerNotifier-Implementation */
475 /* */
476 /*********************************************************************************/
479 // This two methods register and deregister a change listener for the content belonging
480 // to URL aUnqPath
483 void
484 TaskManager::registerNotifier( const OUString& aUnqPath, Notifier* pNotifier )
486 std::unique_lock aGuard( m_aMutex );
488 ContentMap::iterator it =
489 m_aContent.emplace( aUnqPath, UnqPathData() ).first;
491 std::vector< Notifier* >& nlist = it->second.notifier;
493 std::vector<Notifier*>::iterator it1 = std::find(nlist.begin(), nlist.end(), pNotifier);
494 if( it1 != nlist.end() ) // Every "Notifier" only once
496 return;
498 nlist.push_back( pNotifier );
502 void
503 TaskManager::deregisterNotifier( const OUString& aUnqPath,Notifier* pNotifier )
505 std::unique_lock aGuard( m_aMutex );
507 ContentMap::iterator it = m_aContent.find( aUnqPath );
508 if( it == m_aContent.end() )
509 return;
511 std::erase(it->second.notifier, pNotifier);
513 if( it->second.notifier.empty() )
514 m_aContent.erase( it );
518 /*********************************************************************************/
519 /* */
520 /* de/associate-Implementation */
521 /* */
522 /*********************************************************************************/
524 // Used to associate and deassociate a new property with
525 // the content belonging to URL UnqPath.
526 // The default value and the attributes are input
529 void
530 TaskManager::associate( const OUString& aUnqPath,
531 const OUString& PropertyName,
532 const uno::Any& DefaultValue,
533 const sal_Int16 Attributes )
535 MyProperty newProperty( false,
536 PropertyName,
538 DefaultValue.getValueType(),
539 DefaultValue,
540 beans::PropertyState_DEFAULT_VALUE,
541 Attributes );
543 auto it1 = m_aDefaultProperties.find( newProperty );
544 if( it1 != m_aDefaultProperties.end() )
545 throw beans::PropertyExistException( THROW_WHERE );
548 std::unique_lock aGuard( m_aMutex );
550 ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first;
552 // Load the XPersistentPropertySetInfo and create it, if it does not exist
553 load( it,true );
555 PropertySet& properties = it->second.properties;
556 it1 = properties.find( newProperty );
557 if( it1 != properties.end() )
558 throw beans::PropertyExistException(THROW_WHERE );
560 // Property does not exist
561 properties.insert( newProperty );
562 it->second.xC->addProperty( PropertyName,Attributes,DefaultValue );
564 notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName );
568 void
569 TaskManager::deassociate( const OUString& aUnqPath,
570 const OUString& PropertyName )
572 MyProperty oldProperty( PropertyName );
574 auto it1 = m_aDefaultProperties.find( oldProperty );
575 if( it1 != m_aDefaultProperties.end() )
576 throw beans::NotRemoveableException( THROW_WHERE );
578 std::unique_lock aGuard( m_aMutex );
580 ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first;
582 load( it, false );
584 PropertySet& properties = it->second.properties;
586 it1 = properties.find( oldProperty );
587 if( it1 == properties.end() )
588 throw beans::UnknownPropertyException( PropertyName );
590 properties.erase( it1 );
592 if( it->second.xC.is() )
593 it->second.xC->removeProperty( PropertyName );
595 if( properties.size() == 9 )
597 MyProperty ContentTProperty( ContentType );
599 if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE )
601 it->second.xS = nullptr;
602 it->second.xC = nullptr;
603 it->second.xA = nullptr;
604 if(m_xFileRegistry.is())
605 m_xFileRegistry->removePropertySet( aUnqPath );
608 aGuard.unlock();
609 notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName );
613 /*********************************************************************************/
614 /* */
615 /* page-Implementation */
616 /* */
617 /*********************************************************************************/
619 // Given an xOutputStream, this method writes the content of the file belonging to
620 // URL aUnqPath into the XOutputStream
623 void TaskManager::page( sal_Int32 CommandId,
624 const OUString& aUnqPath,
625 const uno::Reference< io::XOutputStream >& xOutputStream )
627 osl::File aFile( aUnqPath );
628 osl::FileBase::RC err = aFile.open( osl_File_OpenFlag_Read );
630 if( err != osl::FileBase::E_None )
632 aFile.close();
633 installError( CommandId,
634 TaskHandlerErr::OPEN_FILE_FOR_PAGING,
635 err );
636 return;
639 const sal_uInt64 bfz = 4*1024;
640 sal_Int8 BFF[bfz];
641 sal_uInt64 nrc; // Retrieved number of Bytes;
645 err = aFile.read( static_cast<void*>(BFF),bfz,nrc );
646 if( err == osl::FileBase::E_None )
648 // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
649 uno::Sequence< sal_Int8 > seq( BFF, static_cast<sal_uInt32>(nrc) );
652 xOutputStream->writeBytes( seq );
654 catch (const io::NotConnectedException&)
656 installError( CommandId,
657 TaskHandlerErr::NOTCONNECTED_FOR_PAGING );
658 break;
660 catch (const io::BufferSizeExceededException&)
662 installError( CommandId,
663 TaskHandlerErr::BUFFERSIZEEXCEEDED_FOR_PAGING );
664 break;
666 catch (const io::IOException&)
668 installError( CommandId,
669 TaskHandlerErr::IOEXCEPTION_FOR_PAGING );
670 break;
673 else
675 installError( CommandId,
676 TaskHandlerErr::READING_FILE_FOR_PAGING,
677 err );
678 break;
680 } while( nrc == bfz );
683 aFile.close();
688 xOutputStream->closeOutput();
690 catch (const io::NotConnectedException&)
693 catch (const io::BufferSizeExceededException&)
696 catch (const io::IOException&)
702 /*********************************************************************************/
703 /* */
704 /* open-Implementation */
705 /* */
706 /*********************************************************************************/
708 // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
711 uno::Reference< io::XInputStream >
712 TaskManager::open( sal_Int32 CommandId,
713 const OUString& aUnqPath,
714 bool bLock )
716 rtl::Reference<XInputStream_impl> pInputStream(new XInputStream_impl( aUnqPath, bLock )); // from filinpstr.hxx
718 TaskHandlerErr ErrorCode = pInputStream->CtorSuccess();
720 if( ErrorCode != TaskHandlerErr::NO_ERROR )
722 installError( CommandId,
723 ErrorCode,
724 pInputStream->getMinorError() );
726 pInputStream.clear();
729 return pInputStream;
733 /*********************************************************************************/
734 /* */
735 /* open for read/write access-Implementation */
736 /* */
737 /*********************************************************************************/
739 // Given a file URL aUnqPath, this methods returns a XStream which can be used
740 // to read and write from/to the file.
743 uno::Reference< io::XStream >
744 TaskManager::open_rw( sal_Int32 CommandId,
745 const OUString& aUnqPath,
746 bool bLock )
748 rtl::Reference<XStream_impl> pStream(new XStream_impl( aUnqPath, bLock )); // from filstr.hxx
750 TaskHandlerErr ErrorCode = pStream->CtorSuccess();
752 if( ErrorCode != TaskHandlerErr::NO_ERROR )
754 installError( CommandId,
755 ErrorCode,
756 pStream->getMinorError() );
758 pStream.clear();
760 return pStream;
764 /*********************************************************************************/
765 /* */
766 /* ls-Implementation */
767 /* */
768 /*********************************************************************************/
770 // This method returns the result set containing the children of the directory belonging
771 // to file URL aUnqPath
774 uno::Reference< XDynamicResultSet >
775 TaskManager::ls( sal_Int32 CommandId,
776 const OUString& aUnqPath,
777 const sal_Int32 OpenMode,
778 const uno::Sequence< beans::Property >& seq,
779 const uno::Sequence< NumberedSortingInfo >& seqSort )
781 rtl::Reference<XResultSet_impl> p(new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort ));
783 TaskHandlerErr ErrorCode = p->CtorSuccess();
785 if( ErrorCode != TaskHandlerErr::NO_ERROR )
787 installError( CommandId,
788 ErrorCode,
789 p->getMinorError() );
791 p.clear();
794 return p;
798 /*********************************************************************************/
799 /* */
800 /* info_c implementation */
801 /* */
802 /*********************************************************************************/
803 // Info for commands
805 uno::Reference< XCommandInfo >
806 TaskManager::info_c()
808 return new XCommandInfo_impl( this );
812 /*********************************************************************************/
813 /* */
814 /* info_p-Implementation */
815 /* */
816 /*********************************************************************************/
817 // Info for the properties
819 uno::Reference< beans::XPropertySetInfo >
820 TaskManager::info_p( const OUString& aUnqPath )
822 std::unique_lock aGuard( m_aMutex );
823 return new XPropertySetInfo_impl( this,aUnqPath );
827 /*********************************************************************************/
828 /* */
829 /* setv-Implementation */
830 /* */
831 /*********************************************************************************/
833 // Sets the values of the properties belonging to fileURL aUnqPath
836 uno::Sequence< uno::Any >
837 TaskManager::setv( const OUString& aUnqPath,
838 const uno::Sequence< beans::PropertyValue >& values )
840 std::unique_lock aGuard( m_aMutex );
842 sal_Int32 propChanged = 0;
843 uno::Sequence< uno::Any > ret( values.getLength() );
844 auto retRange = asNonConstRange(ret);
845 uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() );
846 auto seqChangedRange = asNonConstRange(seqChanged);
848 TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath );
849 PropertySet& properties = it->second.properties;
850 TaskManager::PropertySet::const_iterator it1;
851 uno::Any aAny;
853 for( sal_Int32 i = 0; i < values.getLength(); ++i )
855 MyProperty toset( values[i].Name );
856 it1 = properties.find( toset );
857 if( it1 == properties.end() )
859 retRange[i] <<= beans::UnknownPropertyException( THROW_WHERE );
860 continue;
863 aAny = it1->getValue();
864 if( aAny == values[i].Value )
865 continue; // nothing needs to be changed
867 if( it1->getAttributes() & beans::PropertyAttribute::READONLY )
869 retRange[i] <<= lang::IllegalAccessException( THROW_WHERE );
870 continue;
873 seqChangedRange[ propChanged ].PropertyName = values[i].Name;
874 seqChangedRange[ propChanged ].PropertyHandle = -1;
875 seqChangedRange[ propChanged ].Further = false;
876 seqChangedRange[ propChanged ].OldValue = aAny;
877 seqChangedRange[ propChanged++ ].NewValue = values[i].Value;
879 it1->setValue( values[i].Value ); // Put the new value into the local cash
881 if( ! it1->IsNative() )
883 // Also put logical properties into storage
884 if( !it->second.xS.is() )
885 load( it, true );
887 if( ( values[i].Name == ContentType ) &&
888 it1->getState() == beans::PropertyState_DEFAULT_VALUE )
889 { // Special logic for ContentType
890 // 09.07.01: Not reached anymore, because ContentType is readonly
891 it1->setState( beans::PropertyState_DIRECT_VALUE );
892 it->second.xC->addProperty( values[i].Name,
893 beans::PropertyAttribute::MAYBEVOID,
894 values[i].Value );
899 it->second.xS->setPropertyValue( values[i].Name,values[i].Value );
901 catch (const uno::Exception&e)
903 --propChanged; // unsuccessful setting
904 retRange[i] <<= e;
907 else
909 // native properties
910 // Setting of physical file properties
911 if( values[i].Name == Size )
913 sal_Int64 newSize = 0;
914 if( values[i].Value >>= newSize )
915 { // valid value for the size
916 osl::File aFile(aUnqPath);
917 bool err =
918 aFile.open(osl_File_OpenFlag_Write) != osl::FileBase::E_None ||
919 aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None ||
920 aFile.close() != osl::FileBase::E_None;
922 if( err )
924 --propChanged; // unsuccessful setting
925 uno::Sequence<uno::Any> names(comphelper::InitAnyPropertySequence(
927 {"Uri", uno::Any(aUnqPath)}
928 }));
929 retRange[i] <<= InteractiveAugmentedIOException(
930 OUString(),
931 nullptr,
932 task::InteractionClassification_ERROR,
933 IOErrorCode_GENERAL,
934 names );
937 else
938 retRange[i] <<= beans::IllegalTypeException( THROW_WHERE );
940 else if(values[i].Name == IsReadOnly ||
941 values[i].Name == IsHidden)
943 bool value = false;
944 if( values[i].Value >>= value )
946 osl::DirectoryItem aDirItem;
947 osl::FileBase::RC err =
948 osl::DirectoryItem::get(aUnqPath,aDirItem);
949 sal_uInt64 nAttributes(0);
950 if(err == osl::FileBase::E_None)
952 osl::FileStatus aFileStatus(osl_FileStatus_Mask_Attributes);
953 err = aDirItem.getFileStatus(aFileStatus);
954 if(err == osl::FileBase::E_None &&
955 aFileStatus.isValid(osl_FileStatus_Mask_Attributes))
956 nAttributes = aFileStatus.getAttributes();
958 // now we have the attributes provided all went well.
959 if(err == osl::FileBase::E_None) {
960 if(values[i].Name == IsReadOnly)
962 nAttributes &= ~(osl_File_Attribute_OwnWrite |
963 osl_File_Attribute_GrpWrite |
964 osl_File_Attribute_OthWrite |
965 osl_File_Attribute_ReadOnly);
966 if(value)
967 nAttributes |= osl_File_Attribute_ReadOnly;
968 else
969 nAttributes |= (
970 osl_File_Attribute_OwnWrite |
971 osl_File_Attribute_GrpWrite |
972 osl_File_Attribute_OthWrite);
974 else if(values[i].Name == IsHidden)
976 nAttributes &= ~(osl_File_Attribute_Hidden);
977 if(value)
978 nAttributes |= osl_File_Attribute_Hidden;
980 err = osl::File::setAttributes(
981 aUnqPath,nAttributes);
984 if( err != osl::FileBase::E_None )
986 --propChanged; // unsuccessful setting
987 uno::Sequence<uno::Any> names(comphelper::InitAnyPropertySequence(
989 {"Uri", uno::Any(aUnqPath)}
990 }));
991 IOErrorCode ioError;
992 switch( err )
994 case osl::FileBase::E_NOMEM:
995 // not enough memory for allocating structures <br>
996 ioError = IOErrorCode_OUT_OF_MEMORY;
997 break;
998 case osl::FileBase::E_INVAL:
999 // the format of the parameters was not valid<p>
1000 ioError = IOErrorCode_INVALID_PARAMETER;
1001 break;
1002 case osl::FileBase::E_NAMETOOLONG:
1003 // File name too long<br>
1004 ioError = IOErrorCode_NAME_TOO_LONG;
1005 break;
1006 case osl::FileBase::E_NOENT:
1007 // No such file or directory<br>
1008 case osl::FileBase::E_NOLINK:
1009 // Link has been severed<br>
1010 ioError = IOErrorCode_NOT_EXISTING;
1011 break;
1012 case osl::FileBase::E_ROFS:
1013 // #i4735# handle ROFS transparently
1014 // as ACCESS_DENIED
1015 case osl::FileBase::E_PERM:
1016 case osl::FileBase::E_ACCES:
1017 // permission denied<br>
1018 ioError = IOErrorCode_ACCESS_DENIED;
1019 break;
1020 case osl::FileBase::E_LOOP:
1021 // Too many symbolic links encountered<br>
1022 case osl::FileBase::E_FAULT:
1023 // Bad address<br>
1024 case osl::FileBase::E_IO:
1025 // I/O error<br>
1026 case osl::FileBase::E_NOSYS:
1027 // Function not implemented<br>
1028 case osl::FileBase::E_MULTIHOP:
1029 // Multihop attempted<br>
1030 case osl::FileBase::E_INTR:
1031 // function call was interrupted<p>
1032 default:
1033 ioError = IOErrorCode_GENERAL;
1034 break;
1036 retRange[i] <<= InteractiveAugmentedIOException(
1037 OUString(),
1038 nullptr,
1039 task::InteractionClassification_ERROR,
1040 ioError,
1041 names );
1044 else
1045 retRange[i] <<= beans::IllegalTypeException( THROW_WHERE );
1048 } // end for
1050 aGuard.unlock();
1051 if( propChanged )
1053 seqChanged.realloc( propChanged );
1054 notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ), seqChanged );
1057 return ret;
1060 /*********************************************************************************/
1061 /* */
1062 /* getv-Implementation */
1063 /* */
1064 /*********************************************************************************/
1066 // Reads the values of the properties belonging to fileURL aUnqPath;
1067 // Returns an XRow object containing the values in the requested order.
1070 uno::Reference< sdbc::XRow >
1071 TaskManager::getv( sal_Int32 CommandId,
1072 const OUString& aUnqPath,
1073 const uno::Sequence< beans::Property >& properties )
1075 uno::Sequence< uno::Any > seq( properties.getLength() );
1077 sal_Int32 n_Mask;
1078 getMaskFromProperties( n_Mask,properties );
1079 osl::FileStatus aFileStatus( n_Mask );
1081 osl::DirectoryItem aDirItem;
1082 osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem );
1083 if( nError1 != osl::FileBase::E_None )
1084 installError(CommandId,
1085 TaskHandlerErr::OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1086 nError1);
1088 osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus );
1089 if( nError1 == osl::FileBase::E_None &&
1090 nError2 != osl::FileBase::E_None )
1091 installError(CommandId,
1092 TaskHandlerErr::OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1093 nError2);
1096 std::unique_lock aGuard( m_aMutex );
1098 TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath );
1099 commit( aGuard, it, aFileStatus );
1101 PropertySet& propset = it->second.properties;
1103 std::transform(properties.begin(), properties.end(), seq.getArray(),
1104 [&propset](const beans::Property& rProp) -> uno::Any {
1105 MyProperty readProp( rProp.Name );
1106 auto it1 = propset.find( readProp );
1107 if( it1 == propset.end() )
1108 return uno::Any();
1109 return it1->getValue();
1113 return new XRow_impl( this,seq );
1117 /********************************************************************************/
1118 /* */
1119 /* transfer-commandos */
1120 /* */
1121 /********************************************************************************/
1124 /********************************************************************************/
1125 /* */
1126 /* move-implementation */
1127 /* */
1128 /********************************************************************************/
1130 // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath.
1133 void
1134 TaskManager::move( sal_Int32 CommandId,
1135 const OUString& srcUnqPath,
1136 const OUString& dstUnqPathIn,
1137 const sal_Int32 NameClash )
1139 // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if
1140 // srcUnqPath and dstUnqPathIn are equal
1141 if( srcUnqPath == dstUnqPathIn )
1142 return;
1144 osl::FileBase::RC nError;
1145 OUString dstUnqPath( dstUnqPathIn );
1147 switch( NameClash )
1149 case NameClash::KEEP:
1151 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1152 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1154 installError( CommandId,
1155 TaskHandlerErr::KEEPERROR_FOR_MOVE,
1156 nError );
1157 return;
1159 break;
1161 case NameClash::OVERWRITE:
1163 // stat to determine whether we have a symlink
1164 OUString targetPath(dstUnqPath);
1166 osl::FileStatus aStatus(osl_FileStatus_Mask_Type|osl_FileStatus_Mask_LinkTargetURL);
1167 osl::DirectoryItem aItem;
1168 (void)osl::DirectoryItem::get(dstUnqPath,aItem);
1169 (void)aItem.getFileStatus(aStatus);
1171 if( aStatus.isValid(osl_FileStatus_Mask_Type) &&
1172 aStatus.isValid(osl_FileStatus_Mask_LinkTargetURL) &&
1173 aStatus.getFileType() == osl::FileStatus::Link )
1174 targetPath = aStatus.getLinkTargetURL();
1176 // Will do nothing if file does not exist.
1177 osl::File::remove( targetPath );
1179 nError = osl_File_move( srcUnqPath,targetPath );
1180 if( nError != osl::FileBase::E_None )
1182 installError( CommandId,
1183 TaskHandlerErr::OVERWRITE_FOR_MOVE,
1184 nError );
1185 return;
1187 break;
1189 case NameClash::RENAME:
1191 OUString newDstUnqPath;
1192 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1193 if( nError == osl::FileBase::E_EXIST )
1195 // "invent" a new valid title.
1197 sal_Int32 nPos = -1;
1198 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1199 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1200 if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1201 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1202 nPos = nLastDot;
1203 else
1204 nPos = dstUnqPath.getLength();
1206 sal_Int32 nTry = 0;
1210 newDstUnqPath = dstUnqPath;
1212 OUString aPostfix = "_" + OUString::number( ++nTry );
1214 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix );
1216 nError = osl_File_move( srcUnqPath,newDstUnqPath,true );
1218 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1221 if( nError == osl::FileBase::E_EXIST )
1223 installError( CommandId,
1224 TaskHandlerErr::RENAME_FOR_MOVE );
1225 return;
1227 else if( nError != osl::FileBase::E_None )
1229 installError( CommandId,
1230 TaskHandlerErr::RENAMEMOVE_FOR_MOVE,
1231 nError );
1232 return;
1234 else
1235 dstUnqPath = newDstUnqPath;
1237 break;
1239 case NameClash::ERROR:
1241 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1242 if( nError == osl::FileBase::E_EXIST )
1244 installError( CommandId,
1245 TaskHandlerErr::NAMECLASH_FOR_MOVE );
1246 return;
1248 else if( nError != osl::FileBase::E_None )
1250 installError( CommandId,
1251 TaskHandlerErr::NAMECLASHMOVE_FOR_MOVE,
1252 nError );
1253 return;
1255 break;
1257 case NameClash::ASK:
1258 default:
1260 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1261 if( nError == osl::FileBase::E_EXIST )
1263 installError( CommandId,
1264 TaskHandlerErr::NAMECLASHSUPPORT_FOR_MOVE,
1265 NameClash::ASK);
1266 return;
1269 break;
1272 // Determine, whether we have moved a file or a folder
1273 osl::DirectoryItem aItem;
1274 nError = osl::DirectoryItem::get( dstUnqPath,aItem );
1275 if( nError != osl::FileBase::E_None )
1277 installError( CommandId,
1278 TaskHandlerErr::TRANSFER_BY_MOVE_SOURCE,
1279 nError );
1280 return;
1282 osl::FileStatus aStatus( osl_FileStatus_Mask_Type );
1283 nError = aItem.getFileStatus( aStatus );
1284 if( nError != osl::FileBase::E_None || ! aStatus.isValid( osl_FileStatus_Mask_Type ) )
1286 installError( CommandId,
1287 TaskHandlerErr::TRANSFER_BY_MOVE_SOURCESTAT,
1288 nError );
1289 return;
1291 bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular );
1294 copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument );
1296 OUString aDstParent = getParentName( dstUnqPath );
1297 OUString aSrcParent = getParentName( srcUnqPath );
1299 notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath );
1300 if( aDstParent != aSrcParent )
1301 notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath );
1303 notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) );
1304 erasePersistentSet( srcUnqPath,!isDocument );
1308 /********************************************************************************/
1309 /* */
1310 /* copy-implementation */
1311 /* */
1312 /********************************************************************************/
1314 // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
1317 namespace {
1319 bool getType(
1320 TaskManager & task, sal_Int32 id, OUString const & fileUrl,
1321 osl::DirectoryItem * item, osl::FileStatus::Type * type)
1323 assert(item != nullptr && type != nullptr);
1324 osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item);
1325 if (err != osl::FileBase::E_None) {
1326 task.installError(id, TaskHandlerErr::TRANSFER_BY_COPY_SOURCE, err);
1327 return false;
1329 osl::FileStatus stat(osl_FileStatus_Mask_Type);
1330 err = item->getFileStatus(stat);
1331 if (err != osl::FileBase::E_None) {
1332 task.installError(id, TaskHandlerErr::TRANSFER_BY_COPY_SOURCESTAT, err);
1333 return false;
1335 *type = stat.getFileType();
1336 return true;
1341 void
1342 TaskManager::copy(
1343 sal_Int32 CommandId,
1344 const OUString& srcUnqPath,
1345 const OUString& dstUnqPathIn,
1346 sal_Int32 NameClash )
1348 osl::FileBase::RC nError;
1349 OUString dstUnqPath( dstUnqPathIn );
1351 // Resolve symbolic links within the source path. If srcUnqPath denotes a
1352 // symbolic link (targeting either a file or a folder), the contents of the
1353 // target is copied (recursively, in the case of a folder). However, if
1354 // recursively copying the contents of a folder causes a symbolic link to be
1355 // copied, the symbolic link itself is copied.
1356 osl::DirectoryItem item;
1357 osl::FileStatus::Type type;
1358 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1359 return;
1361 OUString rslvdSrcUnqPath;
1362 if (type == osl::FileStatus::Link) {
1363 osl::FileStatus stat(osl_FileStatus_Mask_LinkTargetURL);
1364 nError = item.getFileStatus(stat);
1365 if (nError != osl::FileBase::E_None) {
1366 installError(
1367 CommandId, TaskHandlerErr::TRANSFER_BY_COPY_SOURCESTAT, nError);
1368 return;
1370 rslvdSrcUnqPath = stat.getLinkTargetURL();
1371 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1372 return;
1374 } else {
1375 rslvdSrcUnqPath = srcUnqPath;
1378 bool isDocument
1379 = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume;
1380 FileUrlType IsWhat = isDocument ? FileUrlType::File : FileUrlType::Folder;
1382 switch( NameClash )
1384 case NameClash::KEEP:
1386 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1387 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1389 installError( CommandId,
1390 TaskHandlerErr::KEEPERROR_FOR_COPY,
1391 nError );
1392 return;
1394 break;
1396 case NameClash::OVERWRITE:
1398 // remove (..., MustExist = sal_False).
1399 remove( CommandId, dstUnqPath, IsWhat, false );
1401 // copy.
1402 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false );
1403 if( nError != osl::FileBase::E_None )
1405 installError( CommandId,
1406 TaskHandlerErr::OVERWRITE_FOR_COPY,
1407 nError );
1408 return;
1410 break;
1412 case NameClash::RENAME:
1414 OUString newDstUnqPath = dstUnqPath;
1415 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1417 if( nError == osl::FileBase::E_EXIST )
1419 // "invent" a new valid title.
1421 sal_Int32 nPos = -1;
1422 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1423 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1424 if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1425 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1426 nPos = nLastDot;
1427 else
1428 nPos = dstUnqPath.getLength();
1430 sal_Int32 nTry = 0;
1434 newDstUnqPath = dstUnqPath;
1436 OUString aPostfix = "_" + OUString::number( ++nTry );
1438 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix );
1440 nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true );
1442 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1445 if( nError == osl::FileBase::E_EXIST )
1447 installError( CommandId,
1448 TaskHandlerErr::RENAME_FOR_COPY );
1449 return;
1451 else if( nError != osl::FileBase::E_None )
1453 installError( CommandId,
1454 TaskHandlerErr::RENAMEMOVE_FOR_COPY,
1455 nError );
1456 return;
1458 else
1459 dstUnqPath = newDstUnqPath;
1461 break;
1463 case NameClash::ERROR:
1465 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1467 if( nError == osl::FileBase::E_EXIST )
1469 installError( CommandId,
1470 TaskHandlerErr::NAMECLASH_FOR_COPY );
1471 return;
1473 else if( nError != osl::FileBase::E_None )
1475 installError( CommandId,
1476 TaskHandlerErr::NAMECLASHMOVE_FOR_COPY,
1477 nError );
1478 return;
1480 break;
1482 case NameClash::ASK:
1483 default:
1485 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1487 if( nError == osl::FileBase::E_EXIST )
1489 installError( CommandId,
1490 TaskHandlerErr::NAMECLASHSUPPORT_FOR_COPY,
1491 NameClash);
1492 return;
1494 break;
1498 copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument );
1499 notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath );
1503 /********************************************************************************/
1504 /* */
1505 /* remove-implementation */
1506 /* */
1507 /********************************************************************************/
1509 // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
1510 // Return: success of operation
1513 bool
1514 TaskManager::remove( sal_Int32 CommandId,
1515 const OUString& aUnqPath,
1516 FileUrlType IsWhat,
1517 bool MustExist )
1519 sal_Int32 nMask = osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL;
1521 osl::DirectoryItem aItem;
1522 osl::FileStatus aStatus( nMask );
1523 osl::FileBase::RC nError;
1525 if( IsWhat == FileUrlType::Unknown ) // Determine whether we are removing a directory or a file
1527 nError = osl::DirectoryItem::get( aUnqPath, aItem );
1528 if( nError != osl::FileBase::E_None )
1530 if (MustExist)
1532 installError( CommandId,
1533 TaskHandlerErr::NOSUCHFILEORDIR_FOR_REMOVE,
1534 nError );
1536 return (!MustExist);
1539 nError = aItem.getFileStatus( aStatus );
1540 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1542 installError( CommandId,
1543 TaskHandlerErr::VALIDFILESTATUS_FOR_REMOVE,
1544 nError != osl::FileBase::E_None ? nError : 0 );
1545 return false;
1548 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1549 aStatus.getFileType() == osl::FileStatus::Link )
1550 IsWhat = FileUrlType::File;
1551 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1552 aStatus.getFileType() == osl::FileStatus::Volume )
1553 IsWhat = FileUrlType::Folder;
1557 if( IsWhat == FileUrlType::File )
1559 nError = osl::File::remove( aUnqPath );
1560 if( nError != osl::FileBase::E_None )
1562 if (MustExist)
1564 installError( CommandId,
1565 TaskHandlerErr::DELETEFILE_FOR_REMOVE,
1566 nError );
1568 return (!MustExist);
1570 else
1572 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1573 erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet
1576 else if( IsWhat == FileUrlType::Folder )
1578 osl::Directory aDirectory( aUnqPath );
1580 nError = aDirectory.open();
1581 if( nError != osl::FileBase::E_None )
1583 if (MustExist)
1585 installError( CommandId,
1586 TaskHandlerErr::OPENDIRECTORY_FOR_REMOVE,
1587 nError );
1589 return (!MustExist);
1592 bool whileSuccess = true;
1593 FileUrlType recurse = FileUrlType::Unknown;
1594 OUString name;
1596 nError = aDirectory.getNextItem( aItem );
1597 while( nError == osl::FileBase::E_None )
1599 nError = aItem.getFileStatus( aStatus );
1600 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1602 installError( CommandId,
1603 TaskHandlerErr::VALIDFILESTATUSWHILE_FOR_REMOVE,
1604 nError != osl::FileBase::E_None ? nError : 0 );
1605 whileSuccess = false;
1606 break;
1609 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1610 aStatus.getFileType() == osl::FileStatus::Link )
1611 recurse = FileUrlType::File;
1612 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1613 aStatus.getFileType() == osl::FileStatus::Volume )
1614 recurse = FileUrlType::Folder;
1616 name = aStatus.getFileURL();
1617 whileSuccess = remove( CommandId, name, recurse, MustExist );
1618 if( !whileSuccess )
1619 break;
1621 nError = aDirectory.getNextItem( aItem );
1624 aDirectory.close();
1626 if( ! whileSuccess )
1627 return false; // error code is installed
1629 if( nError != osl::FileBase::E_NOENT )
1631 installError( CommandId,
1632 TaskHandlerErr::DIRECTORYEXHAUSTED_FOR_REMOVE,
1633 nError );
1634 return false;
1637 nError = osl::Directory::remove( aUnqPath );
1638 if( nError != osl::FileBase::E_None )
1640 if (MustExist)
1642 installError( CommandId,
1643 TaskHandlerErr::DELETEDIRECTORY_FOR_REMOVE,
1644 nError );
1646 return (!MustExist);
1648 else
1650 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1651 erasePersistentSet( aUnqPath );
1654 else // Don't know what to remove
1656 installError( CommandId,
1657 TaskHandlerErr::FILETYPE_FOR_REMOVE );
1658 return false;
1661 return true;
1665 /********************************************************************************/
1666 /* */
1667 /* mkdir-implementation */
1668 /* */
1669 /********************************************************************************/
1671 // Creates new directory with given URL, recursively if necessary
1672 // Return:: success of operation
1675 bool
1676 TaskManager::mkdir( sal_Int32 CommandId,
1677 const OUString& rUnqPath,
1678 bool OverWrite )
1680 OUString aUnqPath;
1682 // remove trailing slash
1683 if ( rUnqPath.endsWith("/") )
1684 aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
1685 else
1686 aUnqPath = rUnqPath;
1688 osl::FileBase::RC nError = osl::Directory::create( aUnqPath );
1690 switch ( nError )
1692 case osl::FileBase::E_EXIST: // Directory cannot be overwritten
1694 if( !OverWrite )
1696 installError( CommandId,
1697 TaskHandlerErr::FOLDER_EXISTS_MKDIR );
1698 return false;
1700 else
1701 return true;
1703 case osl::FileBase::E_INVAL:
1705 installError(CommandId,
1706 TaskHandlerErr::INVALID_NAME_MKDIR);
1707 return false;
1709 case osl::FileBase::E_None:
1711 OUString aPrtPath = getParentName( aUnqPath );
1712 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1713 return true;
1715 default:
1716 return ensuredir(
1717 CommandId,
1718 aUnqPath,
1719 TaskHandlerErr::CREATEDIRECTORY_MKDIR );
1724 /********************************************************************************/
1725 /* */
1726 /* mkfil-implementation */
1727 /* */
1728 /********************************************************************************/
1730 // Creates new file with given URL.
1731 // The content of aInputStream becomes the content of the file
1732 // Return:: success of operation
1735 bool
1736 TaskManager::mkfil( sal_Int32 CommandId,
1737 const OUString& aUnqPath,
1738 bool Overwrite,
1739 const uno::Reference< io::XInputStream >& aInputStream )
1741 // return value unimportant
1742 bool bSuccess = write( CommandId,
1743 aUnqPath,
1744 Overwrite,
1745 aInputStream );
1746 if ( bSuccess )
1748 OUString aPrtPath = getParentName( aUnqPath );
1749 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1751 return bSuccess;
1755 /********************************************************************************/
1756 /* */
1757 /* write-implementation */
1758 /* */
1759 /********************************************************************************/
1761 // writes to the file with given URL.
1762 // The content of aInputStream becomes the content of the file
1763 // Return:: success of operation
1766 bool
1767 TaskManager::write( sal_Int32 CommandId,
1768 const OUString& aUnqPath,
1769 bool OverWrite,
1770 const uno::Reference< io::XInputStream >& aInputStream )
1772 if( ! aInputStream.is() )
1774 installError( CommandId,
1775 TaskHandlerErr::INPUTSTREAM_FOR_WRITE );
1776 return false;
1779 // Create parent path, if necessary.
1780 if ( ! ensuredir( CommandId,
1781 getParentName( aUnqPath ),
1782 TaskHandlerErr::ENSUREDIR_FOR_WRITE ) )
1783 return false;
1785 osl::FileBase::RC err;
1786 osl::File aFile( aUnqPath );
1788 if( OverWrite )
1790 err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
1792 if( err != osl::FileBase::E_None )
1794 aFile.close();
1795 err = aFile.open( osl_File_OpenFlag_Write );
1797 if( err != osl::FileBase::E_None )
1799 installError( CommandId,
1800 TaskHandlerErr::NO_OPEN_FILE_FOR_OVERWRITE,
1801 err );
1802 return false;
1805 // the existing file was just opened and should be overwritten now,
1806 // truncate it first
1808 err = aFile.setSize( 0 );
1809 if( err != osl::FileBase::E_None )
1811 installError( CommandId,
1812 TaskHandlerErr::FILESIZE_FOR_WRITE,
1813 err );
1814 return false;
1818 else
1820 err = aFile.open( osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock );
1821 if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten
1823 installError( CommandId,
1824 TaskHandlerErr::NOREPLACE_FOR_WRITE, // Now an exception
1825 err );
1827 aFile.close();
1828 return false;
1831 // as a temporary solution the creation does not lock the file at all
1832 // in future it should be possible to create the file without lock explicitly
1833 err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock );
1835 if( err != osl::FileBase::E_None )
1837 aFile.close();
1838 installError( CommandId,
1839 TaskHandlerErr::NO_OPEN_FILE_FOR_WRITE,
1840 err );
1841 return false;
1845 bool bSuccess = true;
1847 sal_uInt64 nWrittenBytes;
1848 sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/;
1849 uno::Sequence< sal_Int8 > seq( nRequestedBytes );
1855 nReadBytes = aInputStream->readBytes( seq,
1856 nRequestedBytes );
1858 catch( const io::NotConnectedException& )
1860 installError( CommandId,
1861 TaskHandlerErr::NOTCONNECTED_FOR_WRITE );
1862 bSuccess = false;
1863 break;
1865 catch( const io::BufferSizeExceededException& )
1867 installError( CommandId,
1868 TaskHandlerErr::BUFFERSIZEEXCEEDED_FOR_WRITE );
1869 bSuccess = false;
1870 break;
1872 catch( const io::IOException& )
1874 installError( CommandId,
1875 TaskHandlerErr::IOEXCEPTION_FOR_WRITE );
1876 bSuccess = false;
1877 break;
1880 if( nReadBytes )
1882 const sal_Int8* p = seq.getConstArray();
1884 err = aFile.write( static_cast<void const *>(p),
1885 sal_uInt64( nReadBytes ),
1886 nWrittenBytes );
1888 if( err != osl::FileBase::E_None )
1890 installError( CommandId,
1891 TaskHandlerErr::FILEIOERROR_FOR_WRITE,
1892 err );
1893 bSuccess = false;
1894 break;
1896 else if( nWrittenBytes != sal_uInt64( nReadBytes ) )
1898 installError( CommandId,
1899 TaskHandlerErr::FILEIOERROR_FOR_NO_SPACE );
1900 bSuccess = false;
1901 break;
1904 } while( nReadBytes == nRequestedBytes );
1906 err = aFile.close();
1907 if( err != osl::FileBase::E_None )
1909 installError( CommandId,
1910 TaskHandlerErr::FILEIOERROR_FOR_WRITE,
1911 err );
1912 bSuccess = false;
1915 return bSuccess;
1919 /*********************************************************************************/
1920 /* */
1921 /* insertDefaultProperties-Implementation */
1922 /* */
1923 /*********************************************************************************/
1926 void TaskManager::insertDefaultProperties( const OUString& aUnqPath )
1928 std::unique_lock aGuard(m_aMutex);
1929 insertDefaultProperties(aGuard, aUnqPath);
1932 void TaskManager::insertDefaultProperties( std::unique_lock<std::mutex>& /*rGuard*/, const OUString& aUnqPath )
1934 ContentMap::iterator it =
1935 m_aContent.emplace( aUnqPath,UnqPathData() ).first;
1937 load( it, false );
1939 MyProperty ContentTProperty( ContentType );
1941 PropertySet& properties = it->second.properties;
1942 bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end();
1944 properties.reserve(properties.size() + m_aDefaultProperties.size());
1945 for (auto const& defaultprop : m_aDefaultProperties)
1947 if( !ContentNotDefau || defaultprop.getPropertyName() != ContentType )
1948 properties.insert( defaultprop );
1953 /******************************************************************************/
1954 /* */
1955 /* mapping of file urls */
1956 /* to uncpath and vice versa */
1957 /* */
1958 /******************************************************************************/
1961 bool TaskManager::getUnqFromUrl( const OUString& Url, OUString& Unq )
1963 if ( Url == "file:///" || Url == "file://localhost/" || Url == "file://127.0.0.1/" )
1965 Unq = "file:///";
1966 return false;
1969 bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq );
1971 Unq = Url;
1973 sal_Int32 l = Unq.getLength()-1;
1974 if( ! err && Unq.endsWith("/") &&
1975 Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) != -1 )
1976 Unq = Unq.copy(0, l);
1978 return err;
1982 bool TaskManager::getUrlFromUnq( const OUString& Unq,OUString& Url )
1984 bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url );
1986 Url = Unq;
1988 return err;
1992 // Helper function for public copy
1994 osl::FileBase::RC
1995 TaskManager::copy_recursive( const OUString& srcUnqPath,
1996 const OUString& dstUnqPath,
1997 FileUrlType TypeToCopy,
1998 bool testExistBeforeCopy )
2000 osl::FileBase::RC err = osl::FileBase::E_None;
2002 if( TypeToCopy == FileUrlType::File ) // Document
2004 err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy );
2006 else if( TypeToCopy == FileUrlType::Folder )
2008 osl::Directory aDir( srcUnqPath );
2009 (void)aDir.open();
2011 err = osl::Directory::create( dstUnqPath );
2012 osl::FileBase::RC next = err;
2013 if( err == osl::FileBase::E_None )
2015 sal_Int32 const n_Mask = osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Type;
2017 osl::DirectoryItem aDirItem;
2019 while( err == osl::FileBase::E_None )
2021 next = aDir.getNextItem( aDirItem );
2022 if (next != osl::FileBase::E_None )
2023 break;
2024 bool IsDoc = false;
2025 osl::FileStatus aFileStatus( n_Mask );
2026 aDirItem.getFileStatus( aFileStatus );
2027 if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2028 IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
2030 // Getting the information for the next recursive copy
2031 FileUrlType newTypeToCopy = IsDoc ? FileUrlType::File : FileUrlType::Folder;
2033 OUString newSrcUnqPath;
2034 if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2035 newSrcUnqPath = aFileStatus.getFileURL();
2037 OUString newDstUnqPath = dstUnqPath;
2038 OUString tit;
2039 if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2040 tit = rtl::Uri::encode( aFileStatus.getFileName(),
2041 rtl_UriCharClassPchar,
2042 rtl_UriEncodeIgnoreEscapes,
2043 RTL_TEXTENCODING_UTF8 );
2045 if( !newDstUnqPath.endsWith( "/" ) )
2046 newDstUnqPath += "/";
2048 newDstUnqPath += tit;
2050 if ( newSrcUnqPath != dstUnqPath )
2051 err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false );
2054 if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
2055 err = next;
2057 aDir.close();
2060 return err;
2064 // Helper function for mkfil,mkdir and write
2065 // Creates whole path
2066 // returns success of the operation
2069 bool TaskManager::ensuredir( sal_Int32 CommandId,
2070 const OUString& rUnqPath,
2071 TaskHandlerErr errorCode )
2073 OUString aPath;
2075 if ( rUnqPath.isEmpty() )
2076 return false;
2078 if ( rUnqPath.endsWith("/") )
2079 aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
2080 else
2081 aPath = rUnqPath;
2083 #if HAVE_FEATURE_MACOSX_SANDBOX
2085 // Avoid annoying sandbox messages in the system.log from the
2086 // below aDirectory.open(), which ends up calling opendir().
2087 // Surely it is easier to just call stat()? Calling stat() on an
2088 // arbitrary (?) directory does not seem to cause any sandbox
2089 // violation, while opendir() does. (Sorry I could not be bothered
2090 // to use some complex cross-platform abstraction over stat() here
2091 // in this macOS specific code block.)
2093 OUString aDirName;
2094 struct stat s;
2095 if( osl::FileBase::getSystemPathFromFileURL( aPath, aDirName ) == osl::FileBase::E_None &&
2096 stat(OUStringToOString( aDirName, RTL_TEXTENCODING_UTF8).getStr(), &s ) == 0 &&
2097 S_ISDIR( s.st_mode ) )
2098 return sal_True;
2099 #endif
2101 // HACK: create directory on a mount point with nobrowse option
2102 // returns ENOSYS in any case !!
2103 osl::Directory aDirectory( aPath );
2104 osl::FileBase::RC nError = aDirectory.open();
2105 aDirectory.close();
2107 if( nError == osl::File::E_None )
2108 return true;
2110 nError = osl::Directory::create( aPath );
2112 if( nError == osl::File::E_None )
2113 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2115 bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2117 if( ! bSuccess )
2119 OUString aParentDir = getParentName( aPath );
2121 if ( aParentDir != aPath )
2122 { // Create first the parent directory
2123 bSuccess = ensuredir( CommandId,
2124 getParentName( aPath ),
2125 errorCode );
2127 // After parent directory structure exists try it one's more
2129 if ( bSuccess )
2130 { // Parent directory exists, retry creation of directory
2131 nError = osl::Directory::create( aPath );
2133 if( nError == osl::File::E_None )
2134 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2136 bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2141 if( ! bSuccess )
2142 installError( CommandId,
2143 errorCode,
2144 nError );
2146 return bSuccess;
2150 // Given a sequence of properties seq, this method determines the mask
2151 // used to instantiate an osl::FileStatus, so that a call to
2152 // osl::DirectoryItem::getFileStatus fills the required fields.
2155 void
2156 TaskManager::getMaskFromProperties(
2157 sal_Int32& n_Mask,
2158 const uno::Sequence< beans::Property >& seq )
2160 n_Mask = 0;
2161 for(const auto& rProp : seq) {
2162 if(rProp.Name == Title)
2163 n_Mask |= osl_FileStatus_Mask_FileName;
2164 else if(rProp.Name == CasePreservingURL)
2165 n_Mask |= osl_FileStatus_Mask_FileURL;
2166 else if(rProp.Name == IsDocument ||
2167 rProp.Name == IsFolder ||
2168 rProp.Name == IsVolume ||
2169 rProp.Name == IsRemoveable ||
2170 rProp.Name == IsRemote ||
2171 rProp.Name == IsCompactDisc ||
2172 rProp.Name == IsFloppy ||
2173 rProp.Name == ContentType)
2174 n_Mask |= (osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL);
2175 else if(rProp.Name == Size)
2176 n_Mask |= (osl_FileStatus_Mask_FileSize |
2177 osl_FileStatus_Mask_Type |
2178 osl_FileStatus_Mask_LinkTargetURL);
2179 else if(rProp.Name == IsHidden ||
2180 rProp.Name == IsReadOnly)
2181 n_Mask |= osl_FileStatus_Mask_Attributes;
2182 else if(rProp.Name == DateModified)
2183 n_Mask |= osl_FileStatus_Mask_ModifyTime;
2188 /*********************************************************************************/
2189 /* */
2190 /* load-Implementation */
2191 /* */
2192 /*********************************************************************************/
2194 // Load the properties from configuration, if create == true create them.
2195 // The Properties are stored under the url belonging to it->first.
2198 void
2199 TaskManager::load( const ContentMap::iterator& it, bool create )
2201 if( ( it->second.xS.is() && it->second.xC.is() && it->second.xA.is() )
2202 || !m_xFileRegistry.is() )
2203 return;
2206 uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create );
2207 if( xS.is() )
2209 it->second.xS = xS;
2210 it->second.xC.set(xS, uno::UNO_QUERY);
2211 it->second.xA.set(xS, uno::UNO_QUERY);
2213 // Now put in all values in the storage in the local hash;
2215 PropertySet& properties = it->second.properties;
2216 const uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties();
2218 for( const auto& rProp : seq )
2220 MyProperty readProp( false,
2221 rProp.Name,
2222 rProp.Handle,
2223 rProp.Type,
2224 xS->getPropertyValue( rProp.Name ),
2225 beans::PropertyState_DIRECT_VALUE,
2226 rProp.Attributes );
2227 properties.insert( readProp );
2230 else if( create )
2232 // Catastrophic error
2237 /*********************************************************************************/
2238 /* */
2239 /* commit-Implementation */
2240 /* */
2241 /*********************************************************************************/
2242 // Commit inserts the determined properties in the filestatus object into
2243 // the internal map, so that is possible to determine on a subsequent
2244 // setting of file properties which properties have changed without filestat
2247 void
2248 TaskManager::commit( std::unique_lock<std::mutex>& rGuard,
2249 const TaskManager::ContentMap::iterator& it,
2250 const osl::FileStatus& aFileStatus )
2252 TaskManager::PropertySet::const_iterator it1;
2254 if( it->second.properties.empty() )
2256 OUString aPath = it->first;
2257 insertDefaultProperties( rGuard, aPath );
2260 PropertySet& properties = it->second.properties;
2262 it1 = properties.find( MyProperty( Title ) );
2263 if( it1 != properties.end() )
2265 if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2267 it1->setValue( uno::Any(aFileStatus.getFileName()) );
2271 it1 = properties.find( MyProperty( CasePreservingURL ) );
2272 if( it1 != properties.end() )
2274 if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2276 it1->setValue( uno::Any(aFileStatus.getFileURL()) );
2281 bool isDirectory;
2283 sal_Int64 dirSize = 0;
2285 if( aFileStatus.isValid( osl_FileStatus_Mask_FileSize ) )
2286 dirSize = aFileStatus.getFileSize();
2288 if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2290 bool isFile,isVolume;
2291 if( osl::FileStatus::Link == aFileStatus.getFileType() &&
2292 aFileStatus.isValid( osl_FileStatus_Mask_LinkTargetURL ) )
2294 osl::DirectoryItem aDirItem;
2295 osl::FileStatus aFileStatus2( osl_FileStatus_Mask_Type );
2296 if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) &&
2297 osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) &&
2298 aFileStatus2.isValid( osl_FileStatus_Mask_Type ) )
2300 isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType();
2301 isDirectory =
2302 osl::FileStatus::Volume == aFileStatus2.getFileType() ||
2303 osl::FileStatus::Directory == aFileStatus2.getFileType();
2304 isFile =
2305 osl::FileStatus::Regular == aFileStatus2.getFileType();
2307 if( aFileStatus2.isValid( osl_FileStatus_Mask_FileSize ) )
2308 dirSize = aFileStatus2.getFileSize();
2310 else
2312 // extremely ugly, but otherwise default construction
2313 // of aDirItem and aFileStatus2
2314 // before the preceding if
2315 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2316 isDirectory =
2317 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2318 osl::FileStatus::Directory == aFileStatus.getFileType();
2319 isFile =
2320 osl::FileStatus::Regular == aFileStatus.getFileType();
2323 else
2325 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2326 isDirectory =
2327 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2328 osl::FileStatus::Directory == aFileStatus.getFileType();
2329 isFile =
2330 osl::FileStatus::Regular == aFileStatus.getFileType();
2333 it1 = properties.find( MyProperty( IsVolume ) );
2334 if( it1 != properties.end() )
2335 it1->setValue( uno::Any( isVolume ) );
2337 it1 = properties.find( MyProperty( IsFolder ) );
2338 if( it1 != properties.end() )
2339 it1->setValue( uno::Any( isDirectory ) );
2341 it1 = properties.find( MyProperty( IsDocument ) );
2342 if( it1 != properties.end() )
2343 it1->setValue( uno::Any( isFile ) );
2345 osl::VolumeInfo aVolumeInfo( osl_VolumeInfo_Mask_Attributes );
2346 if( isVolume &&
2347 osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) &&
2348 aVolumeInfo.isValid( osl_VolumeInfo_Mask_Attributes ) )
2350 // Retrieve the flags;
2351 bool isRemote = aVolumeInfo.getRemoteFlag();
2352 bool isRemoveable = aVolumeInfo.getRemoveableFlag();
2353 bool isCompactDisc = aVolumeInfo.getCompactDiscFlag();
2354 bool isFloppy = aVolumeInfo.getFloppyDiskFlag();
2356 it1 = properties.find( MyProperty( IsRemote ) );
2357 if( it1 != properties.end() )
2358 it1->setValue( uno::Any( isRemote ) );
2360 it1 = properties.find( MyProperty( IsRemoveable ) );
2361 if( it1 != properties.end() )
2362 it1->setValue( uno::Any( isRemoveable ) );
2364 it1 = properties.find( MyProperty( IsCompactDisc ) );
2365 if( it1 != properties.end() )
2366 it1->setValue( uno::Any( isCompactDisc ) );
2368 it1 = properties.find( MyProperty( IsFloppy ) );
2369 if( it1 != properties.end() )
2370 it1->setValue( uno::Any( isFloppy ) );
2372 else
2374 uno::Any aAny(false);
2375 it1 = properties.find( MyProperty( IsRemote ) );
2376 if( it1 != properties.end() )
2377 it1->setValue( aAny );
2379 it1 = properties.find( MyProperty( IsRemoveable ) );
2380 if( it1 != properties.end() )
2381 it1->setValue( aAny );
2383 it1 = properties.find( MyProperty( IsCompactDisc ) );
2384 if( it1 != properties.end() )
2385 it1->setValue( aAny );
2387 it1 = properties.find( MyProperty( IsFloppy ) );
2388 if( it1 != properties.end() )
2389 it1->setValue( aAny );
2392 else
2394 isDirectory = false;
2397 it1 = properties.find( MyProperty( Size ) );
2398 if( it1 != properties.end() )
2399 it1->setValue( uno::Any( dirSize ) );
2401 it1 = properties.find( MyProperty( IsReadOnly ) );
2402 if( it1 != properties.end() )
2404 if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2406 sal_uInt64 Attr = aFileStatus.getAttributes();
2407 bool readonly = ( Attr & osl_File_Attribute_ReadOnly ) != 0;
2408 it1->setValue( uno::Any( readonly ) );
2412 it1 = properties.find( MyProperty( IsHidden ) );
2413 if( it1 != properties.end() )
2415 if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2417 sal_uInt64 Attr = aFileStatus.getAttributes();
2418 bool ishidden = ( Attr & osl_File_Attribute_Hidden ) != 0;
2419 it1->setValue( uno::Any( ishidden ) );
2423 it1 = properties.find( MyProperty( DateModified ) );
2424 if( it1 != properties.end() )
2426 if( aFileStatus.isValid( osl_FileStatus_Mask_ModifyTime ) )
2428 TimeValue temp = aFileStatus.getModifyTime();
2430 // Convert system time to local time (for EA)
2431 TimeValue myLocalTime;
2432 if (!osl_getLocalTimeFromSystemTime( &temp, &myLocalTime ))
2434 SAL_WARN(
2435 "ucb.ucp.file",
2436 "cannot convert (" << temp.Seconds << ", " << temp.Nanosec
2437 << ") to local time");
2438 myLocalTime = temp;
2441 oslDateTime myDateTime;
2442 osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime );
2443 util::DateTime aDateTime;
2445 aDateTime.NanoSeconds = myDateTime.NanoSeconds;
2446 aDateTime.Seconds = myDateTime.Seconds;
2447 aDateTime.Minutes = myDateTime.Minutes;
2448 aDateTime.Hours = myDateTime.Hours;
2449 aDateTime.Day = myDateTime.Day;
2450 aDateTime.Month = myDateTime.Month;
2451 aDateTime.Year = myDateTime.Year;
2452 it1->setValue( uno::Any( aDateTime ) );
2456 it1 = properties.find( MyProperty( CreatableContentsInfo ) );
2457 if( it1 != properties.end() )
2458 it1->setValue( uno::Any(
2459 isDirectory || !aFileStatus.isValid( osl_FileStatus_Mask_Type )
2460 ? queryCreatableContentsInfo()
2461 : uno::Sequence< ucb::ContentInfo >() ) );
2465 // Special optimized method for getting the properties of a
2466 // directoryitem, which is returned by osl::DirectoryItem::getNextItem()
2469 bool
2470 TaskManager::getv(
2471 const uno::Sequence< beans::Property >& properties,
2472 osl::DirectoryItem& aDirItem,
2473 OUString& aUnqPath,
2474 bool& aIsRegular,
2475 uno::Reference< sdbc::XRow > & row )
2477 uno::Sequence< uno::Any > seq( properties.getLength() );
2479 sal_Int32 n_Mask;
2480 getMaskFromProperties( n_Mask,properties );
2482 // Always retrieve the type and the target URL because item might be a link
2483 osl::FileStatus aFileStatus( n_Mask |
2484 osl_FileStatus_Mask_FileURL |
2485 osl_FileStatus_Mask_Type |
2486 osl_FileStatus_Mask_LinkTargetURL );
2488 osl::FileBase::RC aRes = aDirItem.getFileStatus( aFileStatus );
2489 if ( aRes != osl::FileBase::E_None )
2491 SAL_WARN(
2492 "ucb.ucp.file",
2493 "osl::DirectoryItem::getFileStatus failed with " << +aRes);
2494 return false;
2497 aUnqPath = aFileStatus.getFileURL();
2499 // If the directory item type is a link retrieve the type of the target
2501 if ( aFileStatus.getFileType() == osl::FileStatus::Link )
2503 // Assume failure
2504 aIsRegular = false;
2505 osl::DirectoryItem aTargetItem;
2506 (void)osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem );
2507 if ( aTargetItem.is() )
2509 osl::FileStatus aTargetStatus( osl_FileStatus_Mask_Type );
2511 if ( osl::FileBase::E_None == aTargetItem.getFileStatus( aTargetStatus ) )
2512 aIsRegular =
2513 aTargetStatus.getFileType() == osl::FileStatus::Regular;
2516 else
2517 aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular;
2520 std::unique_lock aGuard( m_aMutex );
2522 insertDefaultProperties( aGuard, aUnqPath );
2524 TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath );
2525 commit( aGuard, it, aFileStatus );
2527 PropertySet& propset = it->second.properties;
2529 std::transform(properties.begin(), properties.end(), seq.getArray(),
2530 [&propset](const beans::Property& rProp) -> uno::Any {
2531 MyProperty readProp( rProp.Name );
2532 auto it1 = propset.find( readProp );
2533 if( it1 == propset.end() )
2534 return uno::Any();
2535 return it1->getValue();
2539 row = new XRow_impl( this,seq );
2540 return true;
2544 // EventListener
2547 std::vector< ContentEventNotifier >
2548 TaskManager::getContentEventListeners( const OUString& aName )
2550 std::vector< ContentEventNotifier > listeners;
2552 std::unique_lock aGuard( m_aMutex );
2553 TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2554 if( it != m_aContent.end() && !it->second.notifier.empty() )
2556 std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2557 for (auto const& pointer : listOfNotifiers)
2559 std::optional<ContentEventNotifier> notifier = pointer->cCEL();
2560 if( notifier )
2561 listeners.push_back( std::move(*notifier) );
2565 return listeners;
2569 std::vector< ContentEventNotifier >
2570 TaskManager::getContentDeletedEventListeners( const OUString& aName )
2572 std::vector< ContentEventNotifier > listeners;
2574 std::unique_lock aGuard( m_aMutex );
2575 TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2576 if( it != m_aContent.end() && !it->second.notifier.empty() )
2578 std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2579 for (auto const& pointer : listOfNotifiers)
2581 std::optional<ContentEventNotifier> notifier = pointer->cDEL();
2582 if( notifier )
2583 listeners.push_back( std::move(*notifier) );
2587 return listeners;
2590 void TaskManager::notifyInsert(const std::vector<ContentEventNotifier>& listeners,
2591 const OUString& aChildName)
2593 for (const auto & l : listeners )
2595 l.notifyChildInserted( aChildName );
2599 void TaskManager::notifyContentDeleted(
2600 const std::vector<ContentEventNotifier>& listeners)
2602 for( auto const & l : listeners )
2604 l.notifyDeleted();
2608 void TaskManager::notifyContentRemoved(
2609 const std::vector<ContentEventNotifier>& listeners, const OUString& aChildName)
2611 for( auto const & l : listeners )
2613 l.notifyRemoved( aChildName );
2618 std::vector< PropertySetInfoChangeNotifier >
2619 TaskManager::getPropertySetListeners( const OUString& aName )
2621 std::vector< PropertySetInfoChangeNotifier > listeners;
2623 std::unique_lock aGuard( m_aMutex );
2624 TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2625 if( it != m_aContent.end() && !it->second.notifier.empty() )
2627 std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2628 for (auto const& pointer : listOfNotifiers)
2630 std::optional<PropertySetInfoChangeNotifier> notifier = pointer->cPSL();
2631 if( notifier )
2632 listeners.push_back( std::move(*notifier) );
2636 return listeners;
2639 void TaskManager::notifyPropertyAdded(
2640 const std::vector<PropertySetInfoChangeNotifier>& listeners,
2641 const OUString& aPropertyName)
2643 for( auto const & l : listeners )
2645 l.notifyPropertyAdded( aPropertyName );
2649 void TaskManager::notifyPropertyRemoved(
2650 const std::vector<PropertySetInfoChangeNotifier>& listeners,
2651 const OUString& aPropertyName)
2653 for( auto const & l : listeners )
2655 l.notifyPropertyRemoved( aPropertyName );
2660 std::vector< ContentEventNotifier >
2661 TaskManager::getContentExchangedEventListeners( const OUString& aOldPrefix,
2662 const OUString& aNewPrefix,
2663 bool withChildren )
2665 std::vector< ContentEventNotifier > aVector;
2667 sal_Int32 count;
2668 OUString aOldName;
2669 OUString aNewName;
2670 std::vector< OUString > oldChildList;
2673 std::unique_lock aGuard( m_aMutex );
2675 if( ! withChildren )
2677 aOldName = aOldPrefix;
2678 aNewName = aNewPrefix;
2679 count = 1;
2681 else
2683 for (auto const& content : m_aContent)
2685 if( isChild( aOldPrefix, content.first ) )
2687 oldChildList.push_back( content.first );
2690 count = oldChildList.size();
2694 for( sal_Int32 j = 0; j < count; ++j )
2696 if( withChildren )
2698 aOldName = oldChildList[j];
2699 aNewName = newName( aNewPrefix,aOldPrefix,aOldName );
2702 TaskManager::ContentMap::iterator itold = m_aContent.find( aOldName );
2703 if( itold != m_aContent.end() )
2705 TaskManager::ContentMap::iterator itnew = m_aContent.emplace(
2706 aNewName,UnqPathData() ).first;
2708 // copy Ownership also
2709 itnew->second.properties = std::move(itold->second.properties);
2711 // copy existing list
2712 std::vector< Notifier* > copyList;
2713 std::swap(copyList, itnew->second.notifier);
2714 itnew->second.notifier = std::move(itold->second.notifier);
2716 m_aContent.erase( itold );
2718 if (itnew != m_aContent.end())
2720 if (!itnew->second.notifier.empty())
2722 std::vector<Notifier*>& listOfNotifiers = itnew->second.notifier;
2723 for (auto const& pointer : listOfNotifiers)
2725 std::optional<ContentEventNotifier> notifier = pointer->cEXC( aNewName );
2726 if( notifier )
2727 aVector.push_back( std::move(*notifier) );
2731 // Merge with preexisting notifiers
2732 // However, these may be in status BaseContent::Deleted
2733 itnew->second.notifier.insert(itnew->second.notifier.end(),
2734 copyList.begin(), copyList.end() );
2740 return aVector;
2743 void TaskManager::notifyContentExchanged(
2744 const std::vector<ContentEventNotifier>& listeners_vec)
2746 for( auto & l : listeners_vec)
2748 l.notifyExchanged();
2753 std::vector< PropertyChangeNotifier >
2754 TaskManager::getPropertyChangeNotifier( const OUString& aName )
2756 std::vector< PropertyChangeNotifier > listeners;
2758 std::unique_lock aGuard( m_aMutex );
2759 TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2760 if( it != m_aContent.end() && !it->second.notifier.empty() )
2762 std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2763 for (auto const& pointer : listOfNotifiers)
2765 std::optional<PropertyChangeNotifier> notifier = pointer->cPCL();
2766 if( notifier )
2767 listeners.push_back( std::move(*notifier) );
2771 return listeners;
2774 void TaskManager::notifyPropertyChanges(
2775 const std::vector<PropertyChangeNotifier>& listeners,
2776 const uno::Sequence<beans::PropertyChangeEvent>& seqChanged)
2778 for( auto const & l : listeners )
2780 l.notifyPropertyChanged( seqChanged );
2785 /********************************************************************************/
2786 /* remove persistent propertyset */
2787 /********************************************************************************/
2789 void
2790 TaskManager::erasePersistentSetWithoutChildren( const OUString& aUnqPath )
2793 // Release possible references
2794 std::unique_lock aGuard( m_aMutex );
2795 ContentMap::iterator it = m_aContent.find( aUnqPath );
2796 if( it != m_aContent.end() )
2798 it->second.xS = nullptr;
2799 it->second.xC = nullptr;
2800 it->second.xA = nullptr;
2802 it->second.properties.clear();
2806 m_xFileRegistry->removePropertySet( aUnqPath );
2809 void
2810 TaskManager::erasePersistentSet( const OUString& aUnqPath,
2811 bool withChildren )
2813 if( ! m_xFileRegistry.is() )
2815 OSL_ASSERT( m_xFileRegistry.is() );
2816 return;
2819 if( ! withChildren )
2821 erasePersistentSetWithoutChildren(aUnqPath);
2822 return;
2825 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2826 const uno::Sequence< OUString > seqNames = xName->getElementNames();
2828 OUString old_Name = aUnqPath;
2830 for( const auto& rName : seqNames )
2832 if( ! ( isChild( old_Name,rName ) ) )
2833 continue;
2835 old_Name = rName;
2837 erasePersistentSetWithoutChildren(old_Name);
2842 /********************************************************************************/
2843 /* copy persistent propertyset */
2844 /* from srcUnqPath to dstUnqPath */
2845 /********************************************************************************/
2847 void
2848 TaskManager::copyPersistentSetWithoutChildren( const OUString& srcUnqPath,
2849 const OUString& dstUnqPath )
2851 uno::Reference< XPersistentPropertySet > x_src =
2852 m_xFileRegistry->openPropertySet( srcUnqPath,false );
2853 m_xFileRegistry->removePropertySet( dstUnqPath );
2855 if( ! x_src.is() )
2856 return;
2858 const uno::Sequence< beans::Property > seqProperty =
2859 x_src->getPropertySetInfo()->getProperties();
2861 if( ! seqProperty.hasElements() )
2862 return;
2864 uno::Reference< XPersistentPropertySet >
2865 x_dstS = m_xFileRegistry->openPropertySet( dstUnqPath,true );
2866 uno::Reference< beans::XPropertyContainer >
2867 x_dstC( x_dstS,uno::UNO_QUERY );
2869 for( const auto& rProperty : seqProperty )
2871 x_dstC->addProperty( rProperty.Name,
2872 rProperty.Attributes,
2873 x_src->getPropertyValue( rProperty.Name ) );
2877 void
2878 TaskManager::copyPersistentSet( const OUString& srcUnqPath,
2879 const OUString& dstUnqPath,
2880 bool withChildren )
2882 if( ! m_xFileRegistry.is() )
2884 OSL_ASSERT( m_xFileRegistry.is() );
2885 return;
2888 if( ! withChildren )
2890 copyPersistentSetWithoutChildren(srcUnqPath, dstUnqPath);
2891 return;
2894 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2895 const uno::Sequence< OUString > seqNames = xName->getElementNames();
2897 OUString new_Name;
2899 for( const auto& rName : seqNames )
2901 if( ! ( isChild( srcUnqPath,rName ) ) )
2902 continue;
2904 new_Name = newName( dstUnqPath,srcUnqPath,rName );
2906 copyPersistentSetWithoutChildren(rName, new_Name);
2910 uno::Sequence< ucb::ContentInfo > TaskManager::queryCreatableContentsInfo()
2914 uno::Sequence< beans::Property > props
2916 { u"Title"_ustr, -1, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND }
2918 return
2920 { FileContentType, ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | ucb::ContentInfoAttribute::KIND_DOCUMENT, props },
2921 { FolderContentType, ucb::ContentInfoAttribute::KIND_FOLDER, props }
2925 /*******************************************************************************/
2926 /* */
2927 /* some miscellaneous static functions */
2928 /* */
2929 /*******************************************************************************/
2931 void
2932 TaskManager::getScheme( OUString& Scheme )
2934 Scheme = "file";
2937 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */