bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / ucp / file / shell.cxx
blob63c0f74d63438f80deaf05929f26299ea54d215e
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 <sys/stat.h>
24 #include <stack>
25 #include "osl/diagnose.h"
26 #include <rtl/uri.hxx>
27 #include <rtl/ustrbuf.hxx>
28 #include <osl/time.h>
29 #include <osl/file.hxx>
30 #include <com/sun/star/lang/IllegalAccessException.hpp>
31 #include <com/sun/star/beans/IllegalTypeException.hpp>
32 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
33 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
34 #include <com/sun/star/ucb/NameClash.hpp>
35 #include <com/sun/star/ucb/Store.hpp>
36 #include <com/sun/star/ucb/XContentIdentifier.hpp>
37 #include <com/sun/star/lang/XComponent.hpp>
38 #include <com/sun/star/ucb/XContentAccess.hpp>
39 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <com/sun/star/io/XSeekable.hpp>
41 #include <com/sun/star/io/XTruncate.hpp>
42 #include <com/sun/star/ucb/OpenCommandArgument.hpp>
43 #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp>
44 #include <com/sun/star/ucb/TransferInfo.hpp>
45 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
46 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
47 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
48 #include <rtl/string.hxx>
49 #include "filerror.hxx"
50 #include "filglob.hxx"
51 #include "filcmd.hxx"
52 #include "filinpstr.hxx"
53 #include "filstr.hxx"
54 #include "filrset.hxx"
55 #include "filrow.hxx"
56 #include "filprp.hxx"
57 #include "filid.hxx"
58 #include "shell.hxx"
59 #include "prov.hxx"
60 #include "bc.hxx"
62 using namespace fileaccess;
63 using namespace com::sun::star;
64 using namespace com::sun::star::ucb;
66 #if OSL_DEBUG_LEVEL > 0
67 #define THROW_WHERE SAL_WHERE
68 #else
69 #define THROW_WHERE ""
70 #endif
72 shell::UnqPathData::UnqPathData()
73 : properties( 0 ),
74 notifier( 0 ),
75 xS( 0 ),
76 xC( 0 ),
77 xA( 0 )
79 // empty
83 shell::UnqPathData::UnqPathData( const UnqPathData& a )
84 : properties( a.properties ),
85 notifier( a.notifier ),
86 xS( a.xS ),
87 xC( a.xC ),
88 xA( a.xA )
93 shell::UnqPathData& shell::UnqPathData::operator=( UnqPathData& a )
95 properties = a.properties;
96 notifier = a.notifier;
97 xS = a.xS;
98 xC = a.xC;
99 xA = a.xA;
100 a.properties = 0;
101 a.notifier = 0;
102 a.xS = 0;
103 a.xC = 0;
104 a.xA = 0;
105 return *this;
108 shell::UnqPathData::~UnqPathData()
110 delete properties;
111 delete notifier;
114 shell::MyProperty::MyProperty( const OUString& __PropertyName )
115 : PropertyName( __PropertyName )
116 , Handle(-1)
117 , isNative(false)
118 , State(beans::PropertyState_AMBIGUOUS_VALUE)
119 , Attributes(0)
121 // empty
124 shell::MyProperty::MyProperty( const bool& __isNative,
125 const OUString& __PropertyName,
126 const sal_Int32& __Handle,
127 const com::sun::star::uno::Type& __Typ,
128 const com::sun::star::uno::Any& __Value,
129 const com::sun::star::beans::PropertyState& __State,
130 const sal_Int16& __Attributes )
131 : PropertyName( __PropertyName ),
132 Handle( __Handle ),
133 isNative( __isNative ),
134 Typ( __Typ ),
135 Value( __Value ),
136 State( __State ),
137 Attributes( __Attributes )
139 // empty
142 shell::MyProperty::~MyProperty()
144 // empty for now
148 #include "filinl.hxx"
151 shell::shell( const uno::Reference< uno::XComponentContext >& rxContext,
152 FileProvider* pProvider, bool bWithConfig )
153 : TaskManager(),
154 m_bWithConfig( bWithConfig ),
155 m_pProvider( pProvider ),
156 m_xContext( rxContext ),
157 Title( "Title" ),
158 CasePreservingURL( "CasePreservingURL" ),
159 IsDocument( "IsDocument" ),
160 IsFolder( "IsFolder" ),
161 DateModified( "DateModified" ),
162 Size( "Size" ),
163 IsVolume( "IsVolume" ),
164 IsRemoveable( "IsRemoveable" ),
165 IsRemote( "IsRemote" ),
166 IsCompactDisc( "IsCompactDisc" ),
167 IsFloppy( "IsFloppy" ),
168 IsHidden( "IsHidden" ),
169 ContentType( "ContentType" ),
170 IsReadOnly( "IsReadOnly" ),
171 CreatableContentsInfo( "CreatableContentsInfo" ),
172 FolderContentType( "application/vnd.sun.staroffice.fsys-folder" ),
173 FileContentType( "application/vnd.sun.staroffice.fsys-file" ),
174 m_sCommandInfo( 9 )
176 // Title
177 m_aDefaultProperties.insert( MyProperty( true,
178 Title,
179 -1 ,
180 cppu::UnoType<OUString>::get(),
181 uno::Any(),
182 beans::PropertyState_DEFAULT_VALUE,
183 beans::PropertyAttribute::MAYBEVOID
184 | beans::PropertyAttribute::BOUND ) );
186 // CasePreservingURL
187 m_aDefaultProperties.insert(
188 MyProperty( true,
189 CasePreservingURL,
190 -1 ,
191 cppu::UnoType<OUString>::get(),
192 uno::Any(),
193 beans::PropertyState_DEFAULT_VALUE,
194 beans::PropertyAttribute::MAYBEVOID
195 | beans::PropertyAttribute::BOUND
196 | beans::PropertyAttribute::READONLY ) );
199 // IsFolder
200 m_aDefaultProperties.insert( MyProperty( true,
201 IsFolder,
202 -1 ,
203 cppu::UnoType<sal_Bool>::get(),
204 uno::Any(),
205 beans::PropertyState_DEFAULT_VALUE,
206 beans::PropertyAttribute::MAYBEVOID
207 | beans::PropertyAttribute::BOUND
208 | beans::PropertyAttribute::READONLY ) );
211 // IsDocument
212 m_aDefaultProperties.insert( MyProperty( true,
213 IsDocument,
214 -1 ,
215 cppu::UnoType<sal_Bool>::get(),
216 uno::Any(),
217 beans::PropertyState_DEFAULT_VALUE,
218 beans::PropertyAttribute::MAYBEVOID
219 | beans::PropertyAttribute::BOUND
220 | beans::PropertyAttribute::READONLY ) );
222 // Removable
223 m_aDefaultProperties.insert( MyProperty( true,
224 IsVolume,
225 -1 ,
226 cppu::UnoType<sal_Bool>::get(),
227 uno::Any(),
228 beans::PropertyState_DEFAULT_VALUE,
229 beans::PropertyAttribute::MAYBEVOID
230 | beans::PropertyAttribute::BOUND
231 | beans::PropertyAttribute::READONLY ) );
234 // Removable
235 m_aDefaultProperties.insert( MyProperty( true,
236 IsRemoveable,
237 -1 ,
238 cppu::UnoType<sal_Bool>::get(),
239 uno::Any(),
240 beans::PropertyState_DEFAULT_VALUE,
241 beans::PropertyAttribute::MAYBEVOID
242 | beans::PropertyAttribute::BOUND
243 | beans::PropertyAttribute::READONLY ) );
245 // Remote
246 m_aDefaultProperties.insert( MyProperty( true,
247 IsRemote,
248 -1 ,
249 cppu::UnoType<sal_Bool>::get(),
250 uno::Any(),
251 beans::PropertyState_DEFAULT_VALUE,
252 beans::PropertyAttribute::MAYBEVOID
253 | beans::PropertyAttribute::BOUND
254 | beans::PropertyAttribute::READONLY ) );
256 // CompactDisc
257 m_aDefaultProperties.insert( MyProperty( true,
258 IsCompactDisc,
259 -1 ,
260 cppu::UnoType<sal_Bool>::get(),
261 uno::Any(),
262 beans::PropertyState_DEFAULT_VALUE,
263 beans::PropertyAttribute::MAYBEVOID
264 | beans::PropertyAttribute::BOUND
265 | beans::PropertyAttribute::READONLY ) );
267 // Floppy
268 m_aDefaultProperties.insert( MyProperty( true,
269 IsFloppy,
270 -1 ,
271 cppu::UnoType<sal_Bool>::get(),
272 uno::Any(),
273 beans::PropertyState_DEFAULT_VALUE,
274 beans::PropertyAttribute::MAYBEVOID
275 | beans::PropertyAttribute::BOUND
276 | beans::PropertyAttribute::READONLY ) );
278 // Hidden
279 m_aDefaultProperties.insert(
280 MyProperty(
281 true,
282 IsHidden,
283 -1 ,
284 cppu::UnoType<sal_Bool>::get(),
285 uno::Any(),
286 beans::PropertyState_DEFAULT_VALUE,
287 beans::PropertyAttribute::MAYBEVOID
288 | beans::PropertyAttribute::BOUND
289 #if defined( WNT )
291 #else
292 | beans::PropertyAttribute::READONLY)); // under unix/linux only readable
293 #endif
296 // ContentType
297 uno::Any aAny;
298 aAny <<= OUString();
299 m_aDefaultProperties.insert( MyProperty( false,
300 ContentType,
301 -1 ,
302 cppu::UnoType<OUString>::get(),
303 aAny,
304 beans::PropertyState_DEFAULT_VALUE,
305 beans::PropertyAttribute::MAYBEVOID
306 | beans::PropertyAttribute::BOUND
307 | beans::PropertyAttribute::READONLY ) );
310 // DateModified
311 m_aDefaultProperties.insert( MyProperty( true,
312 DateModified,
313 -1 ,
314 cppu::UnoType<util::DateTime>::get(),
315 uno::Any(),
316 beans::PropertyState_DEFAULT_VALUE,
317 beans::PropertyAttribute::MAYBEVOID
318 | beans::PropertyAttribute::BOUND ) );
320 // Size
321 m_aDefaultProperties.insert( MyProperty( true,
322 Size,
324 cppu::UnoType<sal_Int64>::get(),
325 uno::Any(),
326 beans::PropertyState_DEFAULT_VALUE,
327 beans::PropertyAttribute::MAYBEVOID
328 | beans::PropertyAttribute::BOUND ) );
330 // IsReadOnly
331 m_aDefaultProperties.insert( MyProperty( true,
332 IsReadOnly,
333 -1 ,
334 cppu::UnoType<sal_Bool>::get(),
335 uno::Any(),
336 beans::PropertyState_DEFAULT_VALUE,
337 beans::PropertyAttribute::MAYBEVOID
338 | beans::PropertyAttribute::BOUND ) );
341 // CreatableContentsInfo
342 m_aDefaultProperties.insert( MyProperty( true,
343 CreatableContentsInfo,
344 -1 ,
345 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
346 uno::Any(),
347 beans::PropertyState_DEFAULT_VALUE,
348 beans::PropertyAttribute::MAYBEVOID
349 | beans::PropertyAttribute::BOUND
350 | beans::PropertyAttribute::READONLY ) );
352 // Commands
353 m_sCommandInfo[0].Name = "getCommandInfo";
354 m_sCommandInfo[0].Handle = -1;
355 m_sCommandInfo[0].ArgType = cppu::UnoType<void>::get();
357 m_sCommandInfo[1].Name = "getPropertySetInfo";
358 m_sCommandInfo[1].Handle = -1;
359 m_sCommandInfo[1].ArgType = cppu::UnoType<void>::get();
361 m_sCommandInfo[2].Name = "getPropertyValues";
362 m_sCommandInfo[2].Handle = -1;
363 m_sCommandInfo[2].ArgType = cppu::UnoType<uno::Sequence< beans::Property >>::get();
365 m_sCommandInfo[3].Name = "setPropertyValues";
366 m_sCommandInfo[3].Handle = -1;
367 m_sCommandInfo[3].ArgType = cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get();
369 m_sCommandInfo[4].Name = "open";
370 m_sCommandInfo[4].Handle = -1;
371 m_sCommandInfo[4].ArgType = cppu::UnoType<OpenCommandArgument>::get();
373 m_sCommandInfo[5].Name = "transfer";
374 m_sCommandInfo[5].Handle = -1;
375 m_sCommandInfo[5].ArgType = cppu::UnoType<TransferInfo>::get();
377 m_sCommandInfo[6].Name = "delete";
378 m_sCommandInfo[6].Handle = -1;
379 m_sCommandInfo[6].ArgType = cppu::UnoType<sal_Bool>::get();
381 m_sCommandInfo[7].Name = "insert";
382 m_sCommandInfo[7].Handle = -1;
383 m_sCommandInfo[7].ArgType = cppu::UnoType<InsertCommandArgument>::get();
385 m_sCommandInfo[7].Name = "createNewContent";
386 m_sCommandInfo[7].Handle = -1;
387 m_sCommandInfo[7].ArgType = cppu::UnoType<ucb::ContentInfo>::get();
389 if(m_bWithConfig)
391 uno::Reference< XPropertySetRegistryFactory > xRegFac = ucb::Store::create( m_xContext );
392 // Open/create a registry
393 m_xFileRegistry = xRegFac->createPropertySetRegistry( OUString() );
398 shell::~shell()
403 /*********************************************************************************/
404 /* */
405 /* de/registerNotifier-Implementation */
406 /* */
407 /*********************************************************************************/
410 // This two methods register and deregister a change listener for the content belonging
411 // to URL aUnqPath
414 void SAL_CALL
415 shell::registerNotifier( const OUString& aUnqPath, Notifier* pNotifier )
417 osl::MutexGuard aGuard( m_aMutex );
419 ContentMap::iterator it =
420 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
422 if( ! it->second.notifier )
423 it->second.notifier = new NotifierList();
425 std::list< Notifier* >& nlist = *( it->second.notifier );
427 std::list<Notifier*>::iterator it1 = nlist.begin();
428 while( it1 != nlist.end() ) // Every "Notifier" only once
430 if( *it1 == pNotifier ) return;
431 ++it1;
433 nlist.push_back( pNotifier );
438 void SAL_CALL
439 shell::deregisterNotifier( const OUString& aUnqPath,Notifier* pNotifier )
441 osl::MutexGuard aGuard( m_aMutex );
443 ContentMap::iterator it = m_aContent.find( aUnqPath );
444 if( it == m_aContent.end() )
445 return;
447 it->second.notifier->remove( pNotifier );
449 if( ! it->second.notifier->size() )
450 m_aContent.erase( it );
455 /*********************************************************************************/
456 /* */
457 /* de/associate-Implementation */
458 /* */
459 /*********************************************************************************/
461 // Used to associate and deassociate a new property with
462 // the content belonging to URL UnqPath.
463 // The default value and the attributes are input
466 void SAL_CALL
467 shell::associate( const OUString& aUnqPath,
468 const OUString& PropertyName,
469 const uno::Any& DefaultValue,
470 const sal_Int16 Attributes )
471 throw( beans::PropertyExistException,
472 beans::IllegalTypeException,
473 uno::RuntimeException )
475 MyProperty newProperty( false,
476 PropertyName,
478 DefaultValue.getValueType(),
479 DefaultValue,
480 beans::PropertyState_DEFAULT_VALUE,
481 Attributes );
483 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty );
484 if( it1 != m_aDefaultProperties.end() )
485 throw beans::PropertyExistException( THROW_WHERE );
488 osl::MutexGuard aGuard( m_aMutex );
490 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
492 // Load the XPersistentPropertySetInfo and create it, if it does not exist
493 load( it,true );
495 PropertySet& properties = *(it->second.properties);
496 it1 = properties.find( newProperty );
497 if( it1 != properties.end() )
498 throw beans::PropertyExistException(THROW_WHERE );
500 // Property does not exist
501 properties.insert( newProperty );
502 it->second.xC->addProperty( PropertyName,Attributes,DefaultValue );
504 notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName );
510 void SAL_CALL
511 shell::deassociate( const OUString& aUnqPath,
512 const OUString& PropertyName )
513 throw( beans::UnknownPropertyException,
514 beans::NotRemoveableException,
515 uno::RuntimeException )
517 MyProperty oldProperty( PropertyName );
519 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty );
520 if( it1 != m_aDefaultProperties.end() )
521 throw beans::NotRemoveableException( THROW_WHERE );
523 osl::MutexGuard aGuard( m_aMutex );
525 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
527 load( it,false );
529 PropertySet& properties = *(it->second.properties);
531 it1 = properties.find( oldProperty );
532 if( it1 == properties.end() )
533 throw beans::UnknownPropertyException( THROW_WHERE );
535 properties.erase( it1 );
537 if( it->second.xC.is() )
538 it->second.xC->removeProperty( PropertyName );
540 if( properties.size() == 9 )
542 MyProperty ContentTProperty( ContentType );
544 if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE )
546 it->second.xS = 0;
547 it->second.xC = 0;
548 it->second.xA = 0;
549 if(m_xFileRegistry.is())
550 m_xFileRegistry->removePropertySet( aUnqPath );
553 notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName );
559 /*********************************************************************************/
560 /* */
561 /* page-Implementation */
562 /* */
563 /*********************************************************************************/
565 // Given an xOutputStream, this method writes the content of the file belonging to
566 // URL aUnqPath into the XOutputStream
570 void SAL_CALL shell::page( sal_Int32 CommandId,
571 const OUString& aUnqPath,
572 const uno::Reference< io::XOutputStream >& xOutputStream )
573 throw()
575 uno::Reference< XContentProvider > xProvider( m_pProvider );
576 osl::File aFile( aUnqPath );
577 osl::FileBase::RC err = aFile.open( osl_File_OpenFlag_Read );
579 if( err != osl::FileBase::E_None )
581 aFile.close();
582 installError( CommandId,
583 TASKHANDLING_OPEN_FILE_FOR_PAGING,
584 err );
585 return;
588 const sal_uInt64 bfz = 4*1024;
589 sal_Int8 BFF[bfz];
590 sal_uInt64 nrc; // Retrieved number of Bytes;
594 err = aFile.read( (void*) BFF,bfz,nrc );
595 if( err == osl::FileBase::E_None )
597 uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc );
600 xOutputStream->writeBytes( seq );
602 catch (const io::NotConnectedException&)
604 installError( CommandId,
605 TASKHANDLING_NOTCONNECTED_FOR_PAGING );
606 break;
608 catch (const io::BufferSizeExceededException&)
610 installError( CommandId,
611 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING );
612 break;
614 catch (const io::IOException&)
616 installError( CommandId,
617 TASKHANDLING_IOEXCEPTION_FOR_PAGING );
618 break;
621 else
623 installError( CommandId,
624 TASKHANDLING_READING_FILE_FOR_PAGING,
625 err );
626 break;
628 } while( nrc == bfz );
631 aFile.close();
636 xOutputStream->closeOutput();
638 catch (const io::NotConnectedException&)
641 catch (const io::BufferSizeExceededException&)
644 catch (const io::IOException&)
650 /*********************************************************************************/
651 /* */
652 /* open-Implementation */
653 /* */
654 /*********************************************************************************/
656 // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
660 uno::Reference< io::XInputStream > SAL_CALL
661 shell::open( sal_Int32 CommandId,
662 const OUString& aUnqPath,
663 bool bLock )
664 throw()
666 XInputStream_impl* xInputStream = new XInputStream_impl( this, aUnqPath, bLock ); // from filinpstr.hxx
668 sal_Int32 ErrorCode = xInputStream->CtorSuccess();
670 if( ErrorCode != TASKHANDLER_NO_ERROR )
672 installError( CommandId,
673 ErrorCode,
674 xInputStream->getMinorError() );
676 delete xInputStream;
677 xInputStream = 0;
680 return uno::Reference< io::XInputStream >( xInputStream );
686 /*********************************************************************************/
687 /* */
688 /* open for read/write access-Implementation */
689 /* */
690 /*********************************************************************************/
692 // Given a file URL aUnqPath, this methods returns a XStream which can be used
693 // to read and write from/to the file.
697 uno::Reference< io::XStream > SAL_CALL
698 shell::open_rw( sal_Int32 CommandId,
699 const OUString& aUnqPath,
700 bool bLock )
701 throw()
703 XStream_impl* xStream = new XStream_impl( this, aUnqPath, bLock ); // from filstr.hxx
705 sal_Int32 ErrorCode = xStream->CtorSuccess();
707 if( ErrorCode != TASKHANDLER_NO_ERROR )
709 installError( CommandId,
710 ErrorCode,
711 xStream->getMinorError() );
713 delete xStream;
714 xStream = 0;
716 return uno::Reference< io::XStream >( xStream );
721 /*********************************************************************************/
722 /* */
723 /* ls-Implementation */
724 /* */
725 /*********************************************************************************/
727 // This method returns the result set containing the children of the directory belonging
728 // to file URL aUnqPath
732 uno::Reference< XDynamicResultSet > SAL_CALL
733 shell::ls( sal_Int32 CommandId,
734 const OUString& aUnqPath,
735 const sal_Int32 OpenMode,
736 const uno::Sequence< beans::Property >& seq,
737 const uno::Sequence< NumberedSortingInfo >& seqSort )
738 throw()
740 XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort );
742 sal_Int32 ErrorCode = p->CtorSuccess();
744 if( ErrorCode != TASKHANDLER_NO_ERROR )
746 installError( CommandId,
747 ErrorCode,
748 p->getMinorError() );
750 delete p;
751 p = 0;
754 return uno::Reference< XDynamicResultSet > ( p );
760 /*********************************************************************************/
761 /* */
762 /* info_c implementation */
763 /* */
764 /*********************************************************************************/
765 // Info for commands
767 uno::Reference< XCommandInfo > SAL_CALL
768 shell::info_c()
769 throw()
771 XCommandInfo_impl* p = new XCommandInfo_impl( this );
772 return uno::Reference< XCommandInfo >( p );
778 /*********************************************************************************/
779 /* */
780 /* info_p-Implementation */
781 /* */
782 /*********************************************************************************/
783 // Info for the properties
785 uno::Reference< beans::XPropertySetInfo > SAL_CALL
786 shell::info_p( const OUString& aUnqPath )
787 throw()
789 osl::MutexGuard aGuard( m_aMutex );
790 XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath );
791 return uno::Reference< beans::XPropertySetInfo >( p );
797 /*********************************************************************************/
798 /* */
799 /* setv-Implementation */
800 /* */
801 /*********************************************************************************/
803 // Sets the values of the properties belonging to fileURL aUnqPath
807 uno::Sequence< uno::Any > SAL_CALL
808 shell::setv( const OUString& aUnqPath,
809 const uno::Sequence< beans::PropertyValue >& values )
810 throw()
812 osl::MutexGuard aGuard( m_aMutex );
814 sal_Int32 propChanged = 0;
815 uno::Sequence< uno::Any > ret( values.getLength() );
816 uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() );
818 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
819 PropertySet& properties = *( it->second.properties );
820 shell::PropertySet::iterator it1;
821 uno::Any aAny;
823 for( sal_Int32 i = 0; i < values.getLength(); ++i )
825 MyProperty toset( values[i].Name );
826 it1 = properties.find( toset );
827 if( it1 == properties.end() )
829 ret[i] <<= beans::UnknownPropertyException( THROW_WHERE );
830 continue;
833 aAny = it1->getValue();
834 if( aAny == values[i].Value )
835 continue; // nothing needs to be changed
837 if( it1->getAttributes() & beans::PropertyAttribute::READONLY )
839 ret[i] <<= lang::IllegalAccessException( THROW_WHERE );
840 continue;
843 seqChanged[ propChanged ].PropertyName = values[i].Name;
844 seqChanged[ propChanged ].PropertyHandle = -1;
845 seqChanged[ propChanged ].Further = false;
846 seqChanged[ propChanged ].OldValue <<= aAny;
847 seqChanged[ propChanged++ ].NewValue = values[i].Value;
849 it1->setValue( values[i].Value ); // Put the new value into the local cash
851 if( ! it1->IsNative() )
853 // Also put logical properties into storage
854 if( !it->second.xS.is() )
855 load( it,true );
857 if( ( values[i].Name == ContentType ) &&
858 it1->getState() == beans::PropertyState_DEFAULT_VALUE )
859 { // Special logic for ContentType
860 // 09.07.01: Not reached anymore, because ContentType is readonly
861 it1->setState( beans::PropertyState_DIRECT_VALUE );
862 it->second.xC->addProperty( values[i].Name,
863 beans::PropertyAttribute::MAYBEVOID,
864 values[i].Value );
869 it->second.xS->setPropertyValue( values[i].Name,values[i].Value );
871 catch (const uno::Exception&e)
873 --propChanged; // unsuccessful setting
874 ret[i] <<= e;
877 else
879 // native properties
880 // Setting of physical file properties
881 if( values[i].Name == Size )
883 sal_Int64 newSize = 0;
884 if( values[i].Value >>= newSize )
885 { // valid value for the size
886 osl::File aFile(aUnqPath);
887 bool err =
888 aFile.open(osl_File_OpenFlag_Write) != osl::FileBase::E_None ||
889 aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None ||
890 aFile.close() != osl::FileBase::E_None;
892 if( err )
894 --propChanged; // unsuccessful setting
895 uno::Sequence< uno::Any > names( 1 );
896 ret[0] <<= beans::PropertyValue(
897 OUString("Uri"), -1,
898 uno::makeAny(aUnqPath),
899 beans::PropertyState_DIRECT_VALUE);
900 IOErrorCode ioError(IOErrorCode_GENERAL);
901 ret[i] <<= InteractiveAugmentedIOException(
902 OUString(),
904 task::InteractionClassification_ERROR,
905 ioError,
906 names );
909 else
910 ret[i] <<= beans::IllegalTypeException( THROW_WHERE );
912 else if(values[i].Name == IsReadOnly ||
913 values[i].Name == IsHidden)
915 bool value = false;
916 if( values[i].Value >>= value )
918 osl::DirectoryItem aDirItem;
919 osl::FileBase::RC err =
920 osl::DirectoryItem::get(aUnqPath,aDirItem);
921 sal_uInt64 nAttributes(0);
922 if(err == osl::FileBase::E_None)
924 osl::FileStatus aFileStatus(osl_FileStatus_Mask_Attributes);
925 err = aDirItem.getFileStatus(aFileStatus);
926 if(err == osl::FileBase::E_None &&
927 aFileStatus.isValid(osl_FileStatus_Mask_Attributes))
928 nAttributes = aFileStatus.getAttributes();
930 // now we have the attributes provided all went well.
931 if(err == osl::FileBase::E_None) {
932 if(values[i].Name == IsReadOnly)
934 nAttributes &= ~(osl_File_Attribute_OwnWrite |
935 osl_File_Attribute_GrpWrite |
936 osl_File_Attribute_OthWrite |
937 osl_File_Attribute_ReadOnly);
938 if(value)
939 nAttributes |= osl_File_Attribute_ReadOnly;
940 else
941 nAttributes |= (
942 osl_File_Attribute_OwnWrite |
943 osl_File_Attribute_GrpWrite |
944 osl_File_Attribute_OthWrite);
946 else if(values[i].Name == IsHidden)
948 nAttributes &= ~(osl_File_Attribute_Hidden);
949 if(value)
950 nAttributes |= osl_File_Attribute_Hidden;
952 err = osl::File::setAttributes(
953 aUnqPath,nAttributes);
956 if( err != osl::FileBase::E_None )
958 --propChanged; // unsuccessful setting
959 uno::Sequence< uno::Any > names( 1 );
960 names[0] <<= beans::PropertyValue(
961 OUString("Uri"), -1,
962 uno::makeAny(aUnqPath),
963 beans::PropertyState_DIRECT_VALUE);
964 IOErrorCode ioError;
965 switch( err )
967 case osl::FileBase::E_NOMEM:
968 // not enough memory for allocating structures <br>
969 ioError = IOErrorCode_OUT_OF_MEMORY;
970 break;
971 case osl::FileBase::E_INVAL:
972 // the format of the parameters was not valid<p>
973 ioError = IOErrorCode_INVALID_PARAMETER;
974 break;
975 case osl::FileBase::E_NAMETOOLONG:
976 // File name too long<br>
977 ioError = IOErrorCode_NAME_TOO_LONG;
978 break;
979 case osl::FileBase::E_NOENT:
980 // No such file or directory<br>
981 case osl::FileBase::E_NOLINK:
982 // Link has been severed<br>
983 ioError = IOErrorCode_NOT_EXISTING;
984 break;
985 case osl::FileBase::E_ROFS:
986 // #i4735# handle ROFS transparently
987 // as ACCESS_DENIED
988 case osl::FileBase::E_PERM:
989 case osl::FileBase::E_ACCES:
990 // permission denied<br>
991 ioError = IOErrorCode_ACCESS_DENIED;
992 break;
993 case osl::FileBase::E_LOOP:
994 // Too many symbolic links encountered<br>
995 case osl::FileBase::E_FAULT:
996 // Bad address<br>
997 case osl::FileBase::E_IO:
998 // I/O error<br>
999 case osl::FileBase::E_NOSYS:
1000 // Function not implemented<br>
1001 case osl::FileBase::E_MULTIHOP:
1002 // Multihop attempted<br>
1003 case osl::FileBase::E_INTR:
1004 // function call was interrupted<p>
1005 default:
1006 ioError = IOErrorCode_GENERAL;
1007 break;
1009 ret[i] <<= InteractiveAugmentedIOException(
1010 OUString(),
1012 task::InteractionClassification_ERROR,
1013 ioError,
1014 names );
1017 else
1018 ret[i] <<= beans::IllegalTypeException( THROW_WHERE );
1021 } // end for
1023 if( propChanged )
1025 seqChanged.realloc( propChanged );
1026 notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged );
1029 return ret;
1032 /*********************************************************************************/
1033 /* */
1034 /* getv-Implementation */
1035 /* */
1036 /*********************************************************************************/
1038 // Reads the values of the properties belonging to fileURL aUnqPath;
1039 // Returns an XRow object containing the values in the requested order.
1043 uno::Reference< sdbc::XRow > SAL_CALL
1044 shell::getv( sal_Int32 CommandId,
1045 const OUString& aUnqPath,
1046 const uno::Sequence< beans::Property >& properties )
1047 throw()
1049 uno::Sequence< uno::Any > seq( properties.getLength() );
1051 sal_Int32 n_Mask;
1052 getMaskFromProperties( n_Mask,properties );
1053 osl::FileStatus aFileStatus( n_Mask );
1055 osl::DirectoryItem aDirItem;
1056 osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem );
1057 if( nError1 != osl::FileBase::E_None )
1058 installError(CommandId,
1059 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1060 nError1);
1062 osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus );
1063 if( nError1 == osl::FileBase::E_None &&
1064 nError2 != osl::FileBase::E_None )
1065 installError(CommandId,
1066 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1067 nError2);
1070 osl::MutexGuard aGuard( m_aMutex );
1072 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
1073 commit( it,aFileStatus );
1075 shell::PropertySet::iterator it1;
1076 PropertySet& propset = *(it->second.properties);
1078 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
1080 MyProperty readProp( properties[i].Name );
1081 it1 = propset.find( readProp );
1082 if( it1 == propset.end() )
1083 seq[i] = uno::Any();
1084 else
1085 seq[i] = it1->getValue();
1089 XRow_impl* p = new XRow_impl( this,seq );
1090 return uno::Reference< sdbc::XRow >( p );
1094 /********************************************************************************/
1095 /* */
1096 /* transfer-commandos */
1097 /* */
1098 /********************************************************************************/
1101 /********************************************************************************/
1102 /* */
1103 /* move-implementation */
1104 /* */
1105 /********************************************************************************/
1107 // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath.
1110 void SAL_CALL
1111 shell::move( sal_Int32 CommandId,
1112 const OUString& srcUnqPath,
1113 const OUString& dstUnqPathIn,
1114 const sal_Int32 NameClash )
1115 throw()
1117 // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if
1118 // srcUnqPath and dstUnqPathIn are equal
1119 if( srcUnqPath == dstUnqPathIn )
1120 return;
1122 osl::FileBase::RC nError;
1123 OUString dstUnqPath( dstUnqPathIn );
1125 switch( NameClash )
1127 case NameClash::KEEP:
1129 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1130 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1132 installError( CommandId,
1133 TASKHANDLING_KEEPERROR_FOR_MOVE,
1134 nError );
1135 return;
1137 break;
1139 case NameClash::OVERWRITE:
1141 // stat to determine whether we have a symlink
1142 OUString targetPath(dstUnqPath);
1144 osl::FileStatus aStatus(osl_FileStatus_Mask_Type|osl_FileStatus_Mask_LinkTargetURL);
1145 osl::DirectoryItem aItem;
1146 osl::DirectoryItem::get(dstUnqPath,aItem);
1147 aItem.getFileStatus(aStatus);
1149 if( aStatus.isValid(osl_FileStatus_Mask_Type) &&
1150 aStatus.isValid(osl_FileStatus_Mask_LinkTargetURL) &&
1151 aStatus.getFileType() == osl::FileStatus::Link )
1152 targetPath = aStatus.getLinkTargetURL();
1154 // Will do nothing if file does not exist.
1155 osl::File::remove( targetPath );
1157 nError = osl_File_move( srcUnqPath,targetPath );
1158 if( nError != osl::FileBase::E_None )
1160 installError( CommandId,
1161 TASKHANDLING_OVERWRITE_FOR_MOVE,
1162 nError );
1163 return;
1165 break;
1167 case NameClash::RENAME:
1169 OUString newDstUnqPath;
1170 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1171 if( nError == osl::FileBase::E_EXIST )
1173 // "invent" a new valid title.
1175 sal_Int32 nPos = -1;
1176 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1177 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1178 if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1179 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1180 nPos = nLastDot;
1181 else
1182 nPos = dstUnqPath.getLength();
1184 sal_Int32 nTry = 0;
1188 newDstUnqPath = dstUnqPath;
1190 OUString aPostfix = "_" + OUString::number( ++nTry );
1192 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix );
1194 nError = osl_File_move( srcUnqPath,newDstUnqPath,true );
1196 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1199 if( nError == osl::FileBase::E_EXIST )
1201 installError( CommandId,
1202 TASKHANDLING_RENAME_FOR_MOVE );
1203 return;
1205 else if( nError != osl::FileBase::E_None )
1207 installError( CommandId,
1208 TASKHANDLING_RENAMEMOVE_FOR_MOVE,
1209 nError );
1210 return;
1212 else
1213 dstUnqPath = newDstUnqPath;
1215 break;
1217 case NameClash::ERROR:
1219 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1220 if( nError == osl::FileBase::E_EXIST )
1222 installError( CommandId,
1223 TASKHANDLING_NAMECLASH_FOR_MOVE );
1224 return;
1226 else if( nError != osl::FileBase::E_None )
1228 installError( CommandId,
1229 TASKHANDLING_NAMECLASHMOVE_FOR_MOVE,
1230 nError );
1231 return;
1233 break;
1235 case NameClash::ASK:
1236 default:
1238 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1239 if( nError == osl::FileBase::E_EXIST )
1241 installError( CommandId,
1242 TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE,
1243 NameClash::ASK);
1244 return;
1247 break;
1250 // Determine, whether we have moved a file or a folder
1251 osl::DirectoryItem aItem;
1252 nError = osl::DirectoryItem::get( dstUnqPath,aItem );
1253 if( nError != osl::FileBase::E_None )
1255 installError( CommandId,
1256 TASKHANDLING_TRANSFER_BY_MOVE_SOURCE,
1257 nError );
1258 return;
1260 osl::FileStatus aStatus( osl_FileStatus_Mask_Type );
1261 nError = aItem.getFileStatus( aStatus );
1262 if( nError != osl::FileBase::E_None || ! aStatus.isValid( osl_FileStatus_Mask_Type ) )
1264 installError( CommandId,
1265 TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT,
1266 nError );
1267 return;
1269 bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular );
1272 copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument );
1274 OUString aDstParent = getParentName( dstUnqPath );
1275 OUString aSrcParent = getParentName( srcUnqPath );
1277 notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath );
1278 if( aDstParent != aSrcParent )
1279 notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath );
1281 notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) );
1282 erasePersistentSet( srcUnqPath,!isDocument );
1287 /********************************************************************************/
1288 /* */
1289 /* copy-implementation */
1290 /* */
1291 /********************************************************************************/
1293 // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
1296 namespace {
1298 bool getType(
1299 TaskManager & task, sal_Int32 id, OUString const & fileUrl,
1300 osl::DirectoryItem * item, osl::FileStatus::Type * type)
1302 OSL_ASSERT(item != 0 && type != 0);
1303 osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item);
1304 if (err != osl::FileBase::E_None) {
1305 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err);
1306 return false;
1308 osl::FileStatus stat(osl_FileStatus_Mask_Type);
1309 err = item->getFileStatus(stat);
1310 if (err != osl::FileBase::E_None) {
1311 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err);
1312 return false;
1314 *type = stat.getFileType();
1315 return true;
1320 void SAL_CALL
1321 shell::copy(
1322 sal_Int32 CommandId,
1323 const OUString& srcUnqPath,
1324 const OUString& dstUnqPathIn,
1325 sal_Int32 NameClash )
1326 throw()
1328 osl::FileBase::RC nError;
1329 OUString dstUnqPath( dstUnqPathIn );
1331 // Resolve symbolic links within the source path. If srcUnqPath denotes a
1332 // symbolic link (targeting either a file or a folder), the contents of the
1333 // target is copied (recursively, in the case of a folder). However, if
1334 // recursively copying the contents of a folder causes a symbolic link to be
1335 // copied, the symbolic link itself is copied.
1336 osl::DirectoryItem item;
1337 osl::FileStatus::Type type;
1338 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1339 return;
1341 OUString rslvdSrcUnqPath;
1342 if (type == osl::FileStatus::Link) {
1343 osl::FileStatus stat(osl_FileStatus_Mask_LinkTargetURL);
1344 nError = item.getFileStatus(stat);
1345 if (nError != osl::FileBase::E_None) {
1346 installError(
1347 CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError);
1348 return;
1350 rslvdSrcUnqPath = stat.getLinkTargetURL();
1351 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1352 return;
1354 } else {
1355 rslvdSrcUnqPath = srcUnqPath;
1358 bool isDocument
1359 = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume;
1360 sal_Int32 IsWhat = isDocument ? -1 : 1;
1362 switch( NameClash )
1364 case NameClash::KEEP:
1366 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1367 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1369 installError( CommandId,
1370 TASKHANDLING_KEEPERROR_FOR_COPY,
1371 nError );
1372 return;
1374 break;
1376 case NameClash::OVERWRITE:
1378 // remove (..., MustExist = sal_False).
1379 remove( CommandId, dstUnqPath, IsWhat, false );
1381 // copy.
1382 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false );
1383 if( nError != osl::FileBase::E_None )
1385 installError( CommandId,
1386 TASKHANDLING_OVERWRITE_FOR_COPY,
1387 nError );
1388 return;
1390 break;
1392 case NameClash::RENAME:
1394 OUString newDstUnqPath;
1395 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1397 if( nError == osl::FileBase::E_EXIST )
1399 // "invent" a new valid title.
1401 sal_Int32 nPos = -1;
1402 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1403 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1404 if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1405 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1406 nPos = nLastDot;
1407 else
1408 nPos = dstUnqPath.getLength();
1410 sal_Int32 nTry = 0;
1414 newDstUnqPath = dstUnqPath;
1416 OUString aPostfix = "_" + OUString::number( ++nTry );
1418 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix );
1420 nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true );
1422 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1425 if( nError == osl::FileBase::E_EXIST )
1427 installError( CommandId,
1428 TASKHANDLING_RENAME_FOR_COPY );
1429 return;
1431 else if( nError != osl::FileBase::E_None )
1433 installError( CommandId,
1434 TASKHANDLING_RENAMEMOVE_FOR_COPY,
1435 nError );
1436 return;
1438 else
1439 dstUnqPath = newDstUnqPath;
1441 break;
1443 case NameClash::ERROR:
1445 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1447 if( nError == osl::FileBase::E_EXIST )
1449 installError( CommandId,
1450 TASKHANDLING_NAMECLASH_FOR_COPY );
1451 return;
1453 else if( nError != osl::FileBase::E_None )
1455 installError( CommandId,
1456 TASKHANDLING_NAMECLASHMOVE_FOR_COPY,
1457 nError );
1458 return;
1460 break;
1462 case NameClash::ASK:
1463 default:
1465 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1467 if( nError == osl::FileBase::E_EXIST )
1469 installError( CommandId,
1470 TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY,
1471 NameClash);
1472 return;
1474 break;
1478 copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument );
1479 notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath );
1484 /********************************************************************************/
1485 /* */
1486 /* remove-implementation */
1487 /* */
1488 /********************************************************************************/
1490 // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
1491 // Return: success of operation
1495 bool SAL_CALL
1496 shell::remove( sal_Int32 CommandId,
1497 const OUString& aUnqPath,
1498 sal_Int32 IsWhat,
1499 bool MustExist )
1500 throw()
1502 sal_Int32 nMask = osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL;
1504 osl::DirectoryItem aItem;
1505 osl::FileStatus aStatus( nMask );
1506 osl::FileBase::RC nError;
1508 if( IsWhat == 0 ) // Determine whether we are removing a directory or a file
1510 nError = osl::DirectoryItem::get( aUnqPath, aItem );
1511 if( nError != osl::FileBase::E_None )
1513 if (MustExist)
1515 installError( CommandId,
1516 TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE,
1517 nError );
1519 return (!MustExist);
1522 nError = aItem.getFileStatus( aStatus );
1523 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1525 installError( CommandId,
1526 TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE,
1527 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1528 return false;
1531 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1532 aStatus.getFileType() == osl::FileStatus::Link )
1533 IsWhat = -1; // RemoveFile
1534 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1535 aStatus.getFileType() == osl::FileStatus::Volume )
1536 IsWhat = +1; // RemoveDirectory
1540 if( IsWhat == -1 ) // Removing a file
1542 nError = osl::File::remove( aUnqPath );
1543 if( nError != osl::FileBase::E_None )
1545 if (MustExist)
1547 installError( CommandId,
1548 TASKHANDLING_DELETEFILE_FOR_REMOVE,
1549 nError );
1551 return (!MustExist);
1553 else
1555 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1556 erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet
1559 else if( IsWhat == +1 ) // Removing a directory
1561 osl::Directory aDirectory( aUnqPath );
1563 nError = aDirectory.open();
1564 if( nError != osl::FileBase::E_None )
1566 if (MustExist)
1568 installError( CommandId,
1569 TASKHANDLING_OPENDIRECTORY_FOR_REMOVE,
1570 nError );
1572 return (!MustExist);
1575 bool whileSuccess = true;
1576 sal_Int32 recurse = 0;
1577 OUString name;
1579 nError = aDirectory.getNextItem( aItem );
1580 while( nError == osl::FileBase::E_None )
1582 nError = aItem.getFileStatus( aStatus );
1583 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1585 installError( CommandId,
1586 TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE,
1587 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1588 whileSuccess = false;
1589 break;
1592 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1593 aStatus.getFileType() == osl::FileStatus::Link )
1594 recurse = -1;
1595 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1596 aStatus.getFileType() == osl::FileStatus::Volume )
1597 recurse = +1;
1599 name = aStatus.getFileURL();
1600 whileSuccess = remove(
1601 CommandId, name, recurse, MustExist );
1602 if( !whileSuccess )
1603 break;
1605 nError = aDirectory.getNextItem( aItem );
1608 aDirectory.close();
1610 if( ! whileSuccess )
1611 return false; // error code is installed
1613 if( nError != osl::FileBase::E_NOENT )
1615 installError( CommandId,
1616 TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE,
1617 nError );
1618 return false;
1621 nError = osl::Directory::remove( aUnqPath );
1622 if( nError != osl::FileBase::E_None )
1624 if (MustExist)
1626 installError( CommandId,
1627 TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE,
1628 nError );
1630 return (!MustExist);
1632 else
1634 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1635 erasePersistentSet( aUnqPath );
1638 else // Don't know what to remove
1640 installError( CommandId,
1641 TASKHANDLING_FILETYPE_FOR_REMOVE );
1642 return false;
1645 return true;
1649 /********************************************************************************/
1650 /* */
1651 /* mkdir-implementation */
1652 /* */
1653 /********************************************************************************/
1655 // Creates new directory with given URL, recursively if necessary
1656 // Return:: success of operation
1659 bool SAL_CALL
1660 shell::mkdir( sal_Int32 CommandId,
1661 const OUString& rUnqPath,
1662 bool OverWrite )
1663 throw()
1665 OUString aUnqPath;
1667 // remove trailing slash
1668 if ( rUnqPath.endsWith("/") )
1669 aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
1670 else
1671 aUnqPath = rUnqPath;
1673 osl::FileBase::RC nError = osl::Directory::create( aUnqPath );
1675 switch ( nError )
1677 case osl::FileBase::E_EXIST: // Directory cannot be overwritten
1679 if( !OverWrite )
1681 installError( CommandId,
1682 TASKHANDLING_FOLDER_EXISTS_MKDIR );
1683 return false;
1685 else
1686 return true;
1688 case osl::FileBase::E_INVAL:
1690 installError(CommandId,
1691 TASKHANDLING_INVALID_NAME_MKDIR);
1692 return false;
1694 case osl::FileBase::E_None:
1696 OUString aPrtPath = getParentName( aUnqPath );
1697 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1698 return true;
1700 default:
1701 return ensuredir(
1702 CommandId,
1703 aUnqPath,
1704 TASKHANDLING_CREATEDIRECTORY_MKDIR );
1709 /********************************************************************************/
1710 /* */
1711 /* mkfil-implementation */
1712 /* */
1713 /********************************************************************************/
1715 // Creates new file with given URL.
1716 // The content of aInputStream becomes the content of the file
1717 // Return:: success of operation
1720 bool SAL_CALL
1721 shell::mkfil( sal_Int32 CommandId,
1722 const OUString& aUnqPath,
1723 bool Overwrite,
1724 const uno::Reference< io::XInputStream >& aInputStream )
1725 throw()
1727 // return value unimportant
1728 bool bSuccess = write( CommandId,
1729 aUnqPath,
1730 Overwrite,
1731 aInputStream );
1732 if ( bSuccess )
1734 OUString aPrtPath = getParentName( aUnqPath );
1735 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1737 return bSuccess;
1741 /********************************************************************************/
1742 /* */
1743 /* write-implementation */
1744 /* */
1745 /********************************************************************************/
1747 // writes to the file with given URL.
1748 // The content of aInputStream becomes the content of the file
1749 // Return:: success of operation
1752 bool SAL_CALL
1753 shell::write( sal_Int32 CommandId,
1754 const OUString& aUnqPath,
1755 bool OverWrite,
1756 const uno::Reference< io::XInputStream >& aInputStream )
1757 throw()
1759 if( ! aInputStream.is() )
1761 installError( CommandId,
1762 TASKHANDLING_INPUTSTREAM_FOR_WRITE );
1763 return false;
1766 // Create parent path, if necessary.
1767 if ( ! ensuredir( CommandId,
1768 getParentName( aUnqPath ),
1769 TASKHANDLING_ENSUREDIR_FOR_WRITE ) )
1770 return false;
1772 osl::FileBase::RC err;
1773 osl::File aFile( aUnqPath );
1775 if( OverWrite )
1777 err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
1779 if( err != osl::FileBase::E_None )
1781 aFile.close();
1782 err = aFile.open( osl_File_OpenFlag_Write );
1784 if( err != osl::FileBase::E_None )
1786 installError( CommandId,
1787 TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE,
1788 err );
1789 return false;
1792 // the existing file was just opened and should be overwritten now,
1793 // truncate it first
1795 err = aFile.setSize( 0 );
1796 if( err != osl::FileBase::E_None )
1798 installError( CommandId,
1799 TASKHANDLING_FILESIZE_FOR_WRITE,
1800 err );
1801 return false;
1805 else
1807 err = aFile.open( osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock );
1808 if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten
1810 installError( CommandId,
1811 TASKHANDLING_NOREPLACE_FOR_WRITE, // Now an exception
1812 err );
1814 aFile.close();
1815 return false;
1818 // as a temporary solution the creation does not lock the file at all
1819 // in future it should be possible to create the file without lock explicitly
1820 err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock );
1822 if( err != osl::FileBase::E_None )
1824 aFile.close();
1825 installError( CommandId,
1826 TASKHANDLING_NO_OPEN_FILE_FOR_WRITE,
1827 err );
1828 return false;
1832 bool bSuccess = true;
1834 sal_uInt64 nWrittenBytes;
1835 sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/;
1836 uno::Sequence< sal_Int8 > seq( nRequestedBytes );
1842 nReadBytes = aInputStream->readBytes( seq,
1843 nRequestedBytes );
1845 catch( const io::NotConnectedException& )
1847 installError( CommandId,
1848 TASKHANDLING_NOTCONNECTED_FOR_WRITE );
1849 bSuccess = false;
1850 break;
1852 catch( const io::BufferSizeExceededException& )
1854 installError( CommandId,
1855 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE );
1856 bSuccess = false;
1857 break;
1859 catch( const io::IOException& )
1861 installError( CommandId,
1862 TASKHANDLING_IOEXCEPTION_FOR_WRITE );
1863 bSuccess = false;
1864 break;
1867 if( nReadBytes )
1869 const sal_Int8* p = seq.getConstArray();
1871 err = aFile.write( ((void*)(p)),
1872 sal_uInt64( nReadBytes ),
1873 nWrittenBytes );
1875 if( err != osl::FileBase::E_None )
1877 installError( CommandId,
1878 TASKHANDLING_FILEIOERROR_FOR_WRITE,
1879 err );
1880 bSuccess = false;
1881 break;
1883 else if( nWrittenBytes != sal_uInt64( nReadBytes ) )
1885 installError( CommandId,
1886 TASKHANDLING_FILEIOERROR_FOR_NO_SPACE );
1887 bSuccess = false;
1888 break;
1891 } while( nReadBytes == nRequestedBytes );
1893 err = aFile.close();
1894 if( err != osl::FileBase::E_None )
1896 installError( CommandId,
1897 TASKHANDLING_FILEIOERROR_FOR_WRITE,
1898 err );
1899 bSuccess = false;
1902 return bSuccess;
1907 /*********************************************************************************/
1908 /* */
1909 /* insertDefaultProperties-Implementation */
1910 /* */
1911 /*********************************************************************************/
1914 void SAL_CALL shell::insertDefaultProperties( const OUString& aUnqPath )
1916 osl::MutexGuard aGuard( m_aMutex );
1918 ContentMap::iterator it =
1919 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
1921 load( it,false );
1923 MyProperty ContentTProperty( ContentType );
1925 PropertySet& properties = *(it->second.properties);
1926 bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end();
1928 shell::PropertySet::iterator it1 = m_aDefaultProperties.begin();
1929 while( it1 != m_aDefaultProperties.end() )
1931 if( ContentNotDefau && it1->getPropertyName() == ContentType )
1933 // No insertion
1935 else
1936 properties.insert( *it1 );
1937 ++it1;
1944 /******************************************************************************/
1945 /* */
1946 /* mapping of file urls */
1947 /* to uncpath and vice versa */
1948 /* */
1949 /******************************************************************************/
1952 bool SAL_CALL shell::getUnqFromUrl( const OUString& Url, OUString& Unq )
1954 if ( Url == "file:///" || Url == "file://localhost/" || Url == "file://127.0.0.1/" )
1956 Unq = "file:///";
1957 return false;
1960 bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq );
1962 Unq = Url;
1964 sal_Int32 l = Unq.getLength()-1;
1965 if( ! err && Unq.endsWith("/") &&
1966 Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) != -1 )
1967 Unq = Unq.copy(0, l);
1969 return err;
1974 bool SAL_CALL shell::getUrlFromUnq( const OUString& Unq,OUString& Url )
1976 bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url );
1978 Url = Unq;
1980 return err;
1985 // Helper function for public copy
1987 osl::FileBase::RC SAL_CALL
1988 shell::copy_recursive( const OUString& srcUnqPath,
1989 const OUString& dstUnqPath,
1990 sal_Int32 TypeToCopy,
1991 bool testExistBeforeCopy )
1992 throw()
1994 osl::FileBase::RC err = osl::FileBase::E_None;
1996 if( TypeToCopy == -1 ) // Document
1998 err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy );
2000 else if( TypeToCopy == +1 ) // Folder
2002 osl::Directory aDir( srcUnqPath );
2003 aDir.open();
2005 err = osl::Directory::create( dstUnqPath );
2006 osl::FileBase::RC next = err;
2007 if( err == osl::FileBase::E_None )
2009 sal_Int32 n_Mask = osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Type;
2011 osl::DirectoryItem aDirItem;
2013 while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None )
2015 bool IsDoc = false;
2016 osl::FileStatus aFileStatus( n_Mask );
2017 aDirItem.getFileStatus( aFileStatus );
2018 if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2019 IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
2021 // Getting the information for the next recursive copy
2022 sal_Int32 newTypeToCopy = IsDoc ? -1 : +1;
2024 OUString newSrcUnqPath;
2025 if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2026 newSrcUnqPath = aFileStatus.getFileURL();
2028 OUString newDstUnqPath = dstUnqPath;
2029 OUString tit;
2030 if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2031 tit = rtl::Uri::encode( aFileStatus.getFileName(),
2032 rtl_UriCharClassPchar,
2033 rtl_UriEncodeIgnoreEscapes,
2034 RTL_TEXTENCODING_UTF8 );
2036 if( !newDstUnqPath.endsWith( "/" ) )
2037 newDstUnqPath += "/";
2039 newDstUnqPath += tit;
2041 if ( newSrcUnqPath != dstUnqPath )
2042 err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false );
2045 if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
2046 err = next;
2048 aDir.close();
2051 return err;
2056 // Helper function for mkfil,mkdir and write
2057 // Creates whole path
2058 // returns success of the operation
2061 bool SAL_CALL shell::ensuredir( sal_Int32 CommandId,
2062 const OUString& rUnqPath,
2063 sal_Int32 errorCode )
2064 throw()
2066 OUString aPath;
2068 if ( rUnqPath.isEmpty() )
2069 return false;
2071 if ( rUnqPath.endsWith("/") )
2072 aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
2073 else
2074 aPath = rUnqPath;
2076 #if HAVE_FEATURE_MACOSX_SANDBOX
2078 // Avoid annoying sandbox messages in the system.log from the
2079 // below aDirectory.open(), which ends up calling opendir().
2080 // Surely it is easier to just call stat()? Calling stat() on an
2081 // arbitrary (?) directory does not seem to cause any sandbox
2082 // violation, while opendir() does. (Sorry I could not be bothered
2083 // to use some complex cross-platform abstraction over stat() here
2084 // in this OS X specific code block.)
2086 OUString aDirName;
2087 struct stat s;
2088 if( osl::FileBase::getSystemPathFromFileURL( aPath, aDirName ) == osl::FileBase::E_None &&
2089 stat(OUStringToOString( aDirName, RTL_TEXTENCODING_UTF8).getStr(), &s ) == 0 &&
2090 S_ISDIR( s.st_mode ) )
2091 return sal_True;
2092 #endif
2094 // HACK: create directory on a mount point with nobrowse option
2095 // returns ENOSYS in any case !!
2096 osl::Directory aDirectory( aPath );
2097 osl::FileBase::RC nError = aDirectory.open();
2098 aDirectory.close();
2100 if( nError == osl::File::E_None )
2101 return true;
2103 nError = osl::Directory::create( aPath );
2105 if( nError == osl::File::E_None )
2106 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2108 bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2110 if( ! bSuccess )
2112 OUString aParentDir = getParentName( aPath );
2114 if ( aParentDir != aPath )
2115 { // Create first the parent directory
2116 bSuccess = ensuredir( CommandId,
2117 getParentName( aPath ),
2118 errorCode );
2120 // After parent directory structure exists try it one's more
2122 if ( bSuccess )
2123 { // Parent directory exists, retry creation of directory
2124 nError = osl::Directory::create( aPath );
2126 if( nError == osl::File::E_None )
2127 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2129 bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2134 if( ! bSuccess )
2135 installError( CommandId,
2136 errorCode,
2137 nError );
2139 return bSuccess;
2146 // Given a sequence of properties seq, this method determines the mask
2147 // used to instantiate a osl::FileStatus, so that a call to
2148 // osl::DirectoryItem::getFileStatus fills the required fields.
2152 void SAL_CALL
2153 shell::getMaskFromProperties(
2154 sal_Int32& n_Mask,
2155 const uno::Sequence< beans::Property >& seq )
2157 n_Mask = 0;
2158 for(sal_Int32 j = 0; j < seq.getLength(); ++j) {
2159 if(seq[j].Name == Title)
2160 n_Mask |= osl_FileStatus_Mask_FileName;
2161 else if(seq[j].Name == CasePreservingURL)
2162 n_Mask |= osl_FileStatus_Mask_FileURL;
2163 else if(seq[j].Name == IsDocument ||
2164 seq[j].Name == IsFolder ||
2165 seq[j].Name == IsVolume ||
2166 seq[j].Name == IsRemoveable ||
2167 seq[j].Name == IsRemote ||
2168 seq[j].Name == IsCompactDisc ||
2169 seq[j].Name == IsFloppy ||
2170 seq[j].Name == ContentType)
2171 n_Mask |= (osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL);
2172 else if(seq[j].Name == Size)
2173 n_Mask |= (osl_FileStatus_Mask_FileSize |
2174 osl_FileStatus_Mask_Type |
2175 osl_FileStatus_Mask_LinkTargetURL);
2176 else if(seq[j].Name == IsHidden ||
2177 seq[j].Name == IsReadOnly)
2178 n_Mask |= osl_FileStatus_Mask_Attributes;
2179 else if(seq[j].Name == DateModified)
2180 n_Mask |= osl_FileStatus_Mask_ModifyTime;
2186 /*********************************************************************************/
2187 /* */
2188 /* load-Implementation */
2189 /* */
2190 /*********************************************************************************/
2192 // Load the properties from configuration, if create == true create them.
2193 // The Properties are stored under the url belonging to it->first.
2196 void SAL_CALL
2197 shell::load( const ContentMap::iterator& it, bool create )
2199 if( ! it->second.properties )
2200 it->second.properties = new PropertySet;
2202 if( ( ! it->second.xS.is() ||
2203 ! it->second.xC.is() ||
2204 ! it->second.xA.is() )
2205 && m_xFileRegistry.is() )
2208 uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create );
2209 if( xS.is() )
2211 uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY );
2212 uno::Reference< beans::XPropertyAccess > xA( xS,uno::UNO_QUERY );
2214 it->second.xS = xS;
2215 it->second.xC = xC;
2216 it->second.xA = xA;
2218 // Now put in all values in the storage in the local hash;
2220 PropertySet& properties = *(it->second.properties);
2221 uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties();
2223 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2225 MyProperty readProp( false,
2226 seq[i].Name,
2227 seq[i].Handle,
2228 seq[i].Type,
2229 xS->getPropertyValue( seq[i].Name ),
2230 beans::PropertyState_DIRECT_VALUE,
2231 seq[i].Attributes );
2232 if( properties.find( readProp ) == properties.end() )
2233 properties.insert( readProp );
2236 else if( create )
2238 // Catastrophic error
2246 /*********************************************************************************/
2247 /* */
2248 /* commit-Implementation */
2249 /* */
2250 /*********************************************************************************/
2251 // Commit inserts the determined properties in the filestatus object into
2252 // the internal map, so that is possible to determine on a subsequent
2253 // setting of file properties which properties have changed without filestat
2256 void SAL_CALL
2257 shell::commit( const shell::ContentMap::iterator& it,
2258 const osl::FileStatus& aFileStatus )
2260 uno::Any aAny;
2261 shell::PropertySet::iterator it1;
2263 if( it->second.properties == 0 )
2265 OUString aPath = it->first;
2266 insertDefaultProperties( aPath );
2269 PropertySet& properties = *( it->second.properties );
2271 it1 = properties.find( MyProperty( Title ) );
2272 if( it1 != properties.end() )
2274 if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2276 aAny <<= aFileStatus.getFileName();
2277 it1->setValue( aAny );
2281 it1 = properties.find( MyProperty( CasePreservingURL ) );
2282 if( it1 != properties.end() )
2284 if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2286 aAny <<= aFileStatus.getFileURL();
2287 it1->setValue( aAny );
2292 bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc;
2294 sal_Int64 dirSize = 0;
2296 if( aFileStatus.isValid( osl_FileStatus_Mask_FileSize ) )
2297 dirSize = aFileStatus.getFileSize();
2299 if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2301 if( osl::FileStatus::Link == aFileStatus.getFileType() &&
2302 aFileStatus.isValid( osl_FileStatus_Mask_LinkTargetURL ) )
2304 osl::DirectoryItem aDirItem;
2305 osl::FileStatus aFileStatus2( osl_FileStatus_Mask_Type );
2306 if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) &&
2307 osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) &&
2308 aFileStatus2.isValid( osl_FileStatus_Mask_Type ) )
2310 isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType();
2311 isDirectory =
2312 osl::FileStatus::Volume == aFileStatus2.getFileType() ||
2313 osl::FileStatus::Directory == aFileStatus2.getFileType();
2314 isFile =
2315 osl::FileStatus::Regular == aFileStatus2.getFileType();
2317 if( aFileStatus2.isValid( osl_FileStatus_Mask_FileSize ) )
2318 dirSize = aFileStatus2.getFileSize();
2320 else
2322 // extremely ugly, but otherwise default construction
2323 // of aDirItem and aFileStatus2
2324 // before the preciding if
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 else
2335 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2336 isDirectory =
2337 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2338 osl::FileStatus::Directory == aFileStatus.getFileType();
2339 isFile =
2340 osl::FileStatus::Regular == aFileStatus.getFileType();
2343 it1 = properties.find( MyProperty( IsVolume ) );
2344 if( it1 != properties.end() )
2345 it1->setValue( uno::makeAny( isVolume ) );
2347 it1 = properties.find( MyProperty( IsFolder ) );
2348 if( it1 != properties.end() )
2349 it1->setValue( uno::makeAny( isDirectory ) );
2351 it1 = properties.find( MyProperty( IsDocument ) );
2352 if( it1 != properties.end() )
2353 it1->setValue( uno::makeAny( isFile ) );
2355 osl::VolumeInfo aVolumeInfo( osl_VolumeInfo_Mask_Attributes );
2356 if( isVolume &&
2357 osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) &&
2358 aVolumeInfo.isValid( osl_VolumeInfo_Mask_Attributes ) )
2360 // Retrieve the flags;
2361 isRemote = aVolumeInfo.getRemoteFlag();
2362 isRemoveable = aVolumeInfo.getRemoveableFlag();
2363 isCompactDisc = aVolumeInfo.getCompactDiscFlag();
2364 isFloppy = aVolumeInfo.getFloppyDiskFlag();
2366 it1 = properties.find( MyProperty( IsRemote ) );
2367 if( it1 != properties.end() )
2368 it1->setValue( uno::makeAny( isRemote ) );
2370 it1 = properties.find( MyProperty( IsRemoveable ) );
2371 if( it1 != properties.end() )
2372 it1->setValue( uno::makeAny( isRemoveable ) );
2374 it1 = properties.find( MyProperty( IsCompactDisc ) );
2375 if( it1 != properties.end() )
2376 it1->setValue( uno::makeAny( isCompactDisc ) );
2378 it1 = properties.find( MyProperty( IsFloppy ) );
2379 if( it1 != properties.end() )
2380 it1->setValue( uno::makeAny( isFloppy ) );
2382 else
2384 bool dummy = false;
2385 aAny <<= dummy;
2386 it1 = properties.find( MyProperty( IsRemote ) );
2387 if( it1 != properties.end() )
2388 it1->setValue( aAny );
2390 it1 = properties.find( MyProperty( IsRemoveable ) );
2391 if( it1 != properties.end() )
2392 it1->setValue( aAny );
2394 it1 = properties.find( MyProperty( IsCompactDisc ) );
2395 if( it1 != properties.end() )
2396 it1->setValue( aAny );
2398 it1 = properties.find( MyProperty( IsFloppy ) );
2399 if( it1 != properties.end() )
2400 it1->setValue( aAny );
2403 else
2405 isDirectory = false;
2408 it1 = properties.find( MyProperty( Size ) );
2409 if( it1 != properties.end() )
2410 it1->setValue( uno::makeAny( dirSize ) );
2412 it1 = properties.find( MyProperty( IsReadOnly ) );
2413 if( it1 != properties.end() )
2415 if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2417 sal_uInt64 Attr = aFileStatus.getAttributes();
2418 bool readonly = ( Attr & osl_File_Attribute_ReadOnly ) != 0;
2419 it1->setValue( uno::makeAny( readonly ) );
2423 it1 = properties.find( MyProperty( IsHidden ) );
2424 if( it1 != properties.end() )
2426 if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2428 sal_uInt64 Attr = aFileStatus.getAttributes();
2429 bool ishidden = ( Attr & osl_File_Attribute_Hidden ) != 0;
2430 it1->setValue( uno::makeAny( ishidden ) );
2434 it1 = properties.find( MyProperty( DateModified ) );
2435 if( it1 != properties.end() )
2437 if( aFileStatus.isValid( osl_FileStatus_Mask_ModifyTime ) )
2439 TimeValue temp = aFileStatus.getModifyTime();
2441 // Convert system time to local time (for EA)
2442 TimeValue myLocalTime;
2443 if (!osl_getLocalTimeFromSystemTime( &temp, &myLocalTime ))
2445 SAL_WARN(
2446 "ucb.ucp.file",
2447 "cannot convert (" << temp.Seconds << ", " << temp.Nanosec
2448 << ") to local time");
2449 myLocalTime = temp;
2452 oslDateTime myDateTime;
2453 osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime );
2454 util::DateTime aDateTime;
2456 aDateTime.NanoSeconds = myDateTime.NanoSeconds;
2457 aDateTime.Seconds = myDateTime.Seconds;
2458 aDateTime.Minutes = myDateTime.Minutes;
2459 aDateTime.Hours = myDateTime.Hours;
2460 aDateTime.Day = myDateTime.Day;
2461 aDateTime.Month = myDateTime.Month;
2462 aDateTime.Year = myDateTime.Year;
2463 it1->setValue( uno::makeAny( aDateTime ) );
2467 it1 = properties.find( MyProperty( CreatableContentsInfo ) );
2468 if( it1 != properties.end() )
2469 it1->setValue( uno::makeAny(
2470 isDirectory || !aFileStatus.isValid( osl_FileStatus_Mask_Type )
2471 ? queryCreatableContentsInfo()
2472 : uno::Sequence< ucb::ContentInfo >() ) );
2476 // Special optimized method for getting the properties of a
2477 // directoryitem, which is returned by osl::DirectoryItem::getNextItem()
2480 uno::Reference< sdbc::XRow > SAL_CALL
2481 shell::getv(
2482 Notifier* pNotifier,
2483 const uno::Sequence< beans::Property >& properties,
2484 osl::DirectoryItem& aDirItem,
2485 OUString& aUnqPath,
2486 bool& aIsRegular )
2488 uno::Sequence< uno::Any > seq( properties.getLength() );
2490 sal_Int32 n_Mask;
2491 getMaskFromProperties( n_Mask,properties );
2493 // Always retrieve the type and the target URL because item might be a link
2494 osl::FileStatus aFileStatus( n_Mask |
2495 osl_FileStatus_Mask_FileURL |
2496 osl_FileStatus_Mask_Type |
2497 osl_FileStatus_Mask_LinkTargetURL );
2499 osl::FileBase::RC aRes = aDirItem.getFileStatus( aFileStatus );
2500 if ( aRes == osl::FileBase::E_None )
2502 aUnqPath = aFileStatus.getFileURL();
2504 // If the directory item type is a link retrieve the type of the target
2506 if ( aFileStatus.getFileType() == osl::FileStatus::Link )
2508 // Assume failure
2509 aIsRegular = false;
2510 osl::FileBase::RC result = osl::FileBase::E_INVAL;
2511 osl::DirectoryItem aTargetItem;
2512 osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem );
2513 if ( aTargetItem.is() )
2515 osl::FileStatus aTargetStatus( osl_FileStatus_Mask_Type );
2517 if ( osl::FileBase::E_None ==
2518 ( result = aTargetItem.getFileStatus( aTargetStatus ) ) )
2519 aIsRegular =
2520 aTargetStatus.getFileType() == osl::FileStatus::Regular;
2523 else
2524 aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular;
2526 registerNotifier( aUnqPath,pNotifier );
2527 insertDefaultProperties( aUnqPath );
2529 osl::MutexGuard aGuard( m_aMutex );
2531 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
2532 commit( it,aFileStatus );
2534 shell::PropertySet::iterator it1;
2535 PropertySet& propset = *(it->second.properties);
2537 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2539 MyProperty readProp( properties[i].Name );
2540 it1 = propset.find( readProp );
2541 if( it1 == propset.end() )
2542 seq[i] = uno::Any();
2543 else
2544 seq[i] = it1->getValue();
2547 deregisterNotifier( aUnqPath,pNotifier );
2549 XRow_impl* p = new XRow_impl( this,seq );
2550 return uno::Reference< sdbc::XRow >( p );
2558 // EventListener
2561 std::list< ContentEventNotifier* >* SAL_CALL
2562 shell::getContentEventListeners( const OUString& aName )
2564 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2565 std::list< ContentEventNotifier* >& listeners = *p;
2567 osl::MutexGuard aGuard( m_aMutex );
2568 shell::ContentMap::iterator it = m_aContent.find( aName );
2569 if( it != m_aContent.end() && it->second.notifier )
2571 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2572 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2573 while( it1 != listOfNotifiers.end() )
2575 Notifier* pointer = *it1;
2576 ContentEventNotifier* notifier = pointer->cCEL();
2577 if( notifier )
2578 listeners.push_back( notifier );
2579 ++it1;
2583 return p;
2588 std::list< ContentEventNotifier* >* SAL_CALL
2589 shell::getContentDeletedEventListeners( const OUString& aName )
2591 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2592 std::list< ContentEventNotifier* >& listeners = *p;
2594 osl::MutexGuard aGuard( m_aMutex );
2595 shell::ContentMap::iterator it = m_aContent.find( aName );
2596 if( it != m_aContent.end() && it->second.notifier )
2598 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2599 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2600 while( it1 != listOfNotifiers.end() )
2602 Notifier* pointer = *it1;
2603 ContentEventNotifier* notifier = pointer->cDEL();
2604 if( notifier )
2605 listeners.push_back( notifier );
2606 ++it1;
2610 return p;
2614 void SAL_CALL
2615 shell::notifyInsert( std::list< ContentEventNotifier* >* listeners,const OUString& aChildName )
2617 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2618 while( it != listeners->end() )
2620 (*it)->notifyChildInserted( aChildName );
2621 delete (*it);
2622 ++it;
2624 delete listeners;
2628 void SAL_CALL
2629 shell::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners )
2631 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2632 while( it != listeners->end() )
2634 (*it)->notifyDeleted();
2635 delete (*it);
2636 ++it;
2638 delete listeners;
2642 void SAL_CALL
2643 shell::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners,
2644 const OUString& aChildName )
2646 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2647 while( it != listeners->end() )
2649 (*it)->notifyRemoved( aChildName );
2650 delete (*it);
2651 ++it;
2653 delete listeners;
2659 std::list< PropertySetInfoChangeNotifier* >* SAL_CALL
2660 shell::getPropertySetListeners( const OUString& aName )
2662 std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >;
2663 std::list< PropertySetInfoChangeNotifier* >& listeners = *p;
2665 osl::MutexGuard aGuard( m_aMutex );
2666 shell::ContentMap::iterator it = m_aContent.find( aName );
2667 if( it != m_aContent.end() && it->second.notifier )
2669 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2670 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2671 while( it1 != listOfNotifiers.end() )
2673 Notifier* pointer = *it1;
2674 PropertySetInfoChangeNotifier* notifier = pointer->cPSL();
2675 if( notifier )
2676 listeners.push_back( notifier );
2677 ++it1;
2681 return p;
2685 void SAL_CALL
2686 shell::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners,
2687 const OUString& aPropertyName )
2689 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2690 while( it != listeners->end() )
2692 (*it)->notifyPropertyAdded( aPropertyName );
2693 delete (*it);
2694 ++it;
2696 delete listeners;
2700 void SAL_CALL
2701 shell::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners,
2702 const OUString& aPropertyName )
2704 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2705 while( it != listeners->end() )
2707 (*it)->notifyPropertyRemoved( aPropertyName );
2708 delete (*it);
2709 ++it;
2711 delete listeners;
2716 std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL
2717 shell::getContentExchangedEventListeners( const OUString& aOldPrefix,
2718 const OUString& aNewPrefix,
2719 bool withChildren )
2722 std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap =
2723 new std::vector< std::list< ContentEventNotifier* >* >;
2724 std::vector< std::list< ContentEventNotifier* >* >& aVector = *aVectorOnHeap;
2726 sal_Int32 count;
2727 OUString aOldName;
2728 OUString aNewName;
2729 std::vector< OUString > oldChildList;
2732 osl::MutexGuard aGuard( m_aMutex );
2734 if( ! withChildren )
2736 aOldName = aOldPrefix;
2737 aNewName = aNewPrefix;
2738 count = 1;
2740 else
2742 ContentMap::iterator itnames = m_aContent.begin();
2743 while( itnames != m_aContent.end() )
2745 if( isChild( aOldPrefix,itnames->first ) )
2747 oldChildList.push_back( itnames->first );
2749 ++itnames;
2751 count = oldChildList.size();
2755 for( sal_Int32 j = 0; j < count; ++j )
2757 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2758 std::list< ContentEventNotifier* >& listeners = *p;
2760 if( withChildren )
2762 aOldName = oldChildList[j];
2763 aNewName = newName( aNewPrefix,aOldPrefix,aOldName );
2766 shell::ContentMap::iterator itold = m_aContent.find( aOldName );
2767 if( itold != m_aContent.end() )
2769 shell::ContentMap::iterator itnew = m_aContent.insert(
2770 ContentMap::value_type( aNewName,UnqPathData() ) ).first;
2772 // copy Ownership also
2773 delete itnew->second.properties;
2774 itnew->second.properties = itold->second.properties;
2775 itold->second.properties = 0;
2777 // copy existing list
2778 std::list< Notifier* >* copyList = itnew->second.notifier;
2779 itnew->second.notifier = itold->second.notifier;
2780 itold->second.notifier = 0;
2782 m_aContent.erase( itold );
2784 if( itnew != m_aContent.end() && itnew->second.notifier )
2786 std::list<Notifier*>& listOfNotifiers = *( itnew->second.notifier );
2787 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2788 while( it1 != listOfNotifiers.end() )
2790 Notifier* pointer = *it1;
2791 ContentEventNotifier* notifier = pointer->cEXC( aNewName );
2792 if( notifier )
2793 listeners.push_back( notifier );
2794 ++it1;
2798 // Merge with preexisting notifiers
2799 // However, these may be in status BaseContent::Deleted
2800 if( copyList != 0 )
2802 std::list< Notifier* >::iterator copyIt = copyList->begin();
2803 while( copyIt != copyList->end() )
2805 itnew->second.notifier->push_back( *copyIt );
2806 ++copyIt;
2809 delete copyList;
2811 aVector.push_back( p );
2815 return aVectorOnHeap;
2820 void SAL_CALL
2821 shell::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec )
2823 std::list< ContentEventNotifier* >* listeners;
2824 for( sal_uInt32 i = 0; i < listeners_vec->size(); ++i )
2826 listeners = (*listeners_vec)[i];
2827 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2828 while( it != listeners->end() )
2830 (*it)->notifyExchanged();
2831 delete (*it);
2832 ++it;
2834 delete listeners;
2836 delete listeners_vec;
2841 std::list< PropertyChangeNotifier* >* SAL_CALL
2842 shell::getPropertyChangeNotifier( const OUString& aName )
2844 std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >;
2845 std::list< PropertyChangeNotifier* >& listeners = *p;
2847 osl::MutexGuard aGuard( m_aMutex );
2848 shell::ContentMap::iterator it = m_aContent.find( aName );
2849 if( it != m_aContent.end() && it->second.notifier )
2851 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2852 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2853 while( it1 != listOfNotifiers.end() )
2855 Notifier* pointer = *it1;
2856 PropertyChangeNotifier* notifier = pointer->cPCL();
2857 if( notifier )
2858 listeners.push_back( notifier );
2859 ++it1;
2863 return p;
2867 void SAL_CALL shell::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners,
2868 const uno::Sequence< beans::PropertyChangeEvent >& seqChanged )
2870 std::list< PropertyChangeNotifier* >::iterator it = listeners->begin();
2871 while( it != listeners->end() )
2873 (*it)->notifyPropertyChanged( seqChanged );
2874 delete (*it);
2875 ++it;
2877 delete listeners;
2883 /********************************************************************************/
2884 /* remove persistent propertyset */
2885 /********************************************************************************/
2887 void SAL_CALL
2888 shell::erasePersistentSet( const OUString& aUnqPath,
2889 bool withChildren )
2891 if( ! m_xFileRegistry.is() )
2893 OSL_ASSERT( m_xFileRegistry.is() );
2894 return;
2897 uno::Sequence< OUString > seqNames;
2899 if( withChildren )
2901 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2902 seqNames = xName->getElementNames();
2905 sal_Int32 count = withChildren ? seqNames.getLength() : 1;
2907 OUString
2908 old_Name = aUnqPath;
2910 for( sal_Int32 j = 0; j < count; ++j )
2912 if( withChildren && ! ( isChild( old_Name,seqNames[j] ) ) )
2913 continue;
2915 if( withChildren )
2917 old_Name = seqNames[j];
2921 // Release possible references
2922 osl::MutexGuard aGuard( m_aMutex );
2923 ContentMap::iterator it = m_aContent.find( old_Name );
2924 if( it != m_aContent.end() )
2926 it->second.xS = 0;
2927 it->second.xC = 0;
2928 it->second.xA = 0;
2930 delete it->second.properties;
2931 it->second.properties = 0;
2935 if( m_xFileRegistry.is() )
2936 m_xFileRegistry->removePropertySet( old_Name );
2943 /********************************************************************************/
2944 /* copy persistent propertyset */
2945 /* from srcUnqPath to dstUnqPath */
2946 /********************************************************************************/
2949 void SAL_CALL
2950 shell::copyPersistentSet( const OUString& srcUnqPath,
2951 const OUString& dstUnqPath,
2952 bool withChildren )
2954 if( ! m_xFileRegistry.is() )
2956 OSL_ASSERT( m_xFileRegistry.is() );
2957 return;
2960 uno::Sequence< OUString > seqNames;
2962 if( withChildren )
2964 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2965 seqNames = xName->getElementNames();
2968 sal_Int32 count = withChildren ? seqNames.getLength() : 1;
2970 OUString
2971 old_Name = srcUnqPath,
2972 new_Name = dstUnqPath;
2974 for( sal_Int32 j = 0; j < count; ++j )
2976 if( withChildren && ! ( isChild( srcUnqPath,seqNames[j] ) ) )
2977 continue;
2979 if( withChildren )
2981 old_Name = seqNames[j];
2982 new_Name = newName( dstUnqPath,srcUnqPath,old_Name );
2985 uno::Reference< XPersistentPropertySet > x_src;
2987 if( m_xFileRegistry.is() )
2989 x_src = m_xFileRegistry->openPropertySet( old_Name,false );
2990 m_xFileRegistry->removePropertySet( new_Name );
2993 if( x_src.is() )
2995 uno::Sequence< beans::Property > seqProperty =
2996 x_src->getPropertySetInfo()->getProperties();
2998 if( seqProperty.getLength() )
3000 uno::Reference< XPersistentPropertySet >
3001 x_dstS = m_xFileRegistry->openPropertySet( new_Name,true );
3002 uno::Reference< beans::XPropertyContainer >
3003 x_dstC( x_dstS,uno::UNO_QUERY );
3005 for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i )
3007 x_dstC->addProperty( seqProperty[i].Name,
3008 seqProperty[i].Attributes,
3009 x_src->getPropertyValue( seqProperty[i].Name ) );
3013 } // end for( sal_Int...
3016 uno::Sequence< ucb::ContentInfo > shell::queryCreatableContentsInfo()
3018 uno::Sequence< ucb::ContentInfo > seq(2);
3020 // file
3021 seq[0].Type = FileContentType;
3022 seq[0].Attributes = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
3023 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
3025 uno::Sequence< beans::Property > props( 1 );
3026 props[0] = beans::Property(
3027 OUString("Title"),
3029 cppu::UnoType<OUString>::get(),
3030 beans::PropertyAttribute::MAYBEVOID
3031 | beans::PropertyAttribute::BOUND );
3032 seq[0].Properties = props;
3034 // folder
3035 seq[1].Type = FolderContentType;
3036 seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
3037 seq[1].Properties = props;
3038 return seq;
3041 /*******************************************************************************/
3042 /* */
3043 /* some miscellaneous static functions */
3044 /* */
3045 /*******************************************************************************/
3047 void SAL_CALL
3048 shell::getScheme( OUString& Scheme )
3050 Scheme = "file";
3053 OUString SAL_CALL
3054 shell::getImplementationName_static()
3056 return OUString("com.sun.star.comp.ucb.FileProvider");
3060 uno::Sequence< OUString > SAL_CALL
3061 shell::getSupportedServiceNames_static()
3063 OUString Supported("com.sun.star.ucb.FileContentProvider");
3064 com::sun::star::uno::Sequence< OUString > Seq( &Supported,1 );
3065 return Seq;
3068 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */