Update ooo320-m1
[ooovba.git] / ucb / source / ucp / file / shell.cxx
blob8e3ed6d46bd4940a4c9e3e14ca2b4295125ae200
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shell.cxx,v $
10 * $Revision: 1.98 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
33 #ifndef INCLUDED_STL_STACK
34 #include <stack>
35 #define INCLUDED_STL_STACK
36 #endif
38 #include "osl/diagnose.h"
39 #include <rtl/ustrbuf.hxx>
40 #include <osl/time.h>
41 #include <osl/file.hxx>
42 #include <com/sun/star/lang/IllegalAccessException.hpp>
43 #include <com/sun/star/beans/IllegalTypeException.hpp>
44 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
45 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
46 #include <com/sun/star/ucb/NameClash.hpp>
47 #include <com/sun/star/ucb/XContentIdentifier.hpp>
48 #include <com/sun/star/lang/XComponent.hpp>
49 #ifndef _COM_SUN_STAR_UCB_XCONTENTACCESS_
50 #include <com/sun/star/ucb/XContentAccess.hpp>
51 #endif
52 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_
53 #include <com/sun/star/beans/PropertyAttribute.hpp>
54 #endif
55 #include <com/sun/star/io/XSeekable.hpp>
56 #include <com/sun/star/io/XTruncate.hpp>
57 #include <com/sun/star/ucb/OpenCommandArgument.hpp>
58 #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp>
59 #include <com/sun/star/ucb/TransferInfo.hpp>
60 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
61 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
62 #include <rtl/string.hxx>
63 #ifndef _FILERROR_HXX_
64 #include "filerror.hxx"
65 #endif
66 #include "filglob.hxx"
67 #include "filcmd.hxx"
68 #include "filinpstr.hxx"
69 #include "filstr.hxx"
70 #include "filrset.hxx"
71 #include "filrow.hxx"
72 #include "filprp.hxx"
73 #include "filid.hxx"
74 #include "shell.hxx"
75 #include "prov.hxx"
76 #include "bc.hxx"
79 using namespace fileaccess;
80 using namespace com::sun::star;
81 using namespace com::sun::star::ucb;
84 shell::UnqPathData::UnqPathData()
85 : properties( 0 ),
86 notifier( 0 ),
87 xS( 0 ),
88 xC( 0 ),
89 xA( 0 )
91 // empty
95 shell::UnqPathData::UnqPathData( const UnqPathData& a )
96 : properties( a.properties ),
97 notifier( a.notifier ),
98 xS( a.xS ),
99 xC( a.xC ),
100 xA( a.xA )
105 shell::UnqPathData& shell::UnqPathData::operator=( UnqPathData& a )
107 properties = a.properties;
108 notifier = a.notifier;
109 xS = a.xS;
110 xC = a.xC;
111 xA = a.xA;
112 a.properties = 0;
113 a.notifier = 0;
114 a.xS = 0;
115 a.xC = 0;
116 a.xA = 0;
117 return *this;
120 shell::UnqPathData::~UnqPathData()
122 if( properties )
123 delete properties;
124 if( notifier )
125 delete notifier;
130 ////////////////////////////////////////////////////////////////////////////////////////
136 shell::MyProperty::MyProperty( const rtl::OUString& __PropertyName )
137 : PropertyName( __PropertyName )
139 // empty
143 shell::MyProperty::MyProperty( const sal_Bool& __isNative,
144 const rtl::OUString& __PropertyName,
145 const sal_Int32& __Handle,
146 const com::sun::star::uno::Type& __Typ,
147 const com::sun::star::uno::Any& __Value,
148 const com::sun::star::beans::PropertyState& __State,
149 const sal_Int16& __Attributes )
150 : PropertyName( __PropertyName ),
151 Handle( __Handle ),
152 isNative( __isNative ),
153 Typ( __Typ ),
154 Value( __Value ),
155 State( __State ),
156 Attributes( __Attributes )
158 // empty
161 shell::MyProperty::~MyProperty()
163 // empty for now
167 #include "filinl.hxx"
170 shell::shell( const uno::Reference< lang::XMultiServiceFactory >& xMultiServiceFactory,
171 FileProvider* pProvider, sal_Bool bWithConfig )
172 : TaskManager(),
173 m_bWithConfig( bWithConfig ),
174 m_pProvider( pProvider ),
175 m_xMultiServiceFactory( xMultiServiceFactory ),
176 Title( rtl::OUString::createFromAscii( "Title" ) ),
177 CasePreservingURL(
178 rtl::OUString::createFromAscii( "CasePreservingURL" ) ),
179 IsDocument( rtl::OUString::createFromAscii( "IsDocument" ) ),
180 IsFolder( rtl::OUString::createFromAscii( "IsFolder" ) ),
181 DateModified( rtl::OUString::createFromAscii( "DateModified" ) ),
182 Size( rtl::OUString::createFromAscii( "Size" ) ),
183 IsVolume( rtl::OUString::createFromAscii( "IsVolume" ) ),
184 IsRemoveable( rtl::OUString::createFromAscii( "IsRemoveable" ) ),
185 IsRemote( rtl::OUString::createFromAscii( "IsRemote" ) ),
186 IsCompactDisc( rtl::OUString::createFromAscii( "IsCompactDisc" ) ),
187 IsFloppy( rtl::OUString::createFromAscii( "IsFloppy" ) ),
188 IsHidden( rtl::OUString::createFromAscii( "IsHidden" ) ),
189 ContentType( rtl::OUString::createFromAscii( "ContentType" ) ),
190 IsReadOnly( rtl::OUString::createFromAscii( "IsReadOnly" ) ),
191 FolderContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-folder" ) ),
192 FileContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-file" ) ),
193 m_sCommandInfo( 8 )
195 // Title
196 m_aDefaultProperties.insert( MyProperty( true,
197 Title,
198 -1 ,
199 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
200 uno::Any(),
201 beans::PropertyState_DEFAULT_VALUE,
202 beans::PropertyAttribute::MAYBEVOID
203 | beans::PropertyAttribute::BOUND ) );
205 // CasePreservingURL
206 m_aDefaultProperties.insert(
207 MyProperty( true,
208 CasePreservingURL,
209 -1 ,
210 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
211 uno::Any(),
212 beans::PropertyState_DEFAULT_VALUE,
213 beans::PropertyAttribute::MAYBEVOID
214 | beans::PropertyAttribute::BOUND
215 | beans::PropertyAttribute::READONLY ) );
218 // IsFolder
219 m_aDefaultProperties.insert( MyProperty( true,
220 IsFolder,
221 -1 ,
222 getCppuType( static_cast< sal_Bool* >( 0 ) ),
223 uno::Any(),
224 beans::PropertyState_DEFAULT_VALUE,
225 beans::PropertyAttribute::MAYBEVOID
226 | beans::PropertyAttribute::BOUND
227 | beans::PropertyAttribute::READONLY ) );
230 // IsDocument
231 m_aDefaultProperties.insert( MyProperty( true,
232 IsDocument,
233 -1 ,
234 getCppuType( static_cast< sal_Bool* >( 0 ) ),
235 uno::Any(),
236 beans::PropertyState_DEFAULT_VALUE,
237 beans::PropertyAttribute::MAYBEVOID
238 | beans::PropertyAttribute::BOUND
239 | beans::PropertyAttribute::READONLY ) );
241 // Removable
242 m_aDefaultProperties.insert( MyProperty( true,
243 IsVolume,
244 -1 ,
245 getCppuType( static_cast< sal_Bool* >( 0 ) ),
246 uno::Any(),
247 beans::PropertyState_DEFAULT_VALUE,
248 beans::PropertyAttribute::MAYBEVOID
249 | beans::PropertyAttribute::BOUND
250 | beans::PropertyAttribute::READONLY ) );
253 // Removable
254 m_aDefaultProperties.insert( MyProperty( true,
255 IsRemoveable,
256 -1 ,
257 getCppuType( static_cast< sal_Bool* >( 0 ) ),
258 uno::Any(),
259 beans::PropertyState_DEFAULT_VALUE,
260 beans::PropertyAttribute::MAYBEVOID
261 | beans::PropertyAttribute::BOUND
262 | beans::PropertyAttribute::READONLY ) );
264 // Remote
265 m_aDefaultProperties.insert( MyProperty( true,
266 IsRemote,
267 -1 ,
268 getCppuType( static_cast< sal_Bool* >( 0 ) ),
269 uno::Any(),
270 beans::PropertyState_DEFAULT_VALUE,
271 beans::PropertyAttribute::MAYBEVOID
272 | beans::PropertyAttribute::BOUND
273 | beans::PropertyAttribute::READONLY ) );
275 // CompactDisc
276 m_aDefaultProperties.insert( MyProperty( true,
277 IsCompactDisc,
278 -1 ,
279 getCppuType( static_cast< sal_Bool* >( 0 ) ),
280 uno::Any(),
281 beans::PropertyState_DEFAULT_VALUE,
282 beans::PropertyAttribute::MAYBEVOID
283 | beans::PropertyAttribute::BOUND
284 | beans::PropertyAttribute::READONLY ) );
286 // Floppy
287 m_aDefaultProperties.insert( MyProperty( true,
288 IsFloppy,
289 -1 ,
290 getCppuType( static_cast< sal_Bool* >( 0 ) ),
291 uno::Any(),
292 beans::PropertyState_DEFAULT_VALUE,
293 beans::PropertyAttribute::MAYBEVOID
294 | beans::PropertyAttribute::BOUND
295 | beans::PropertyAttribute::READONLY ) );
297 // Remote
298 m_aDefaultProperties.insert(
299 MyProperty(
300 true,
301 IsHidden,
302 -1 ,
303 getCppuType( static_cast< sal_Bool* >( 0 ) ),
304 uno::Any(),
305 beans::PropertyState_DEFAULT_VALUE,
306 beans::PropertyAttribute::MAYBEVOID
307 | beans::PropertyAttribute::BOUND
308 #if defined( WNT ) || defined( OS2 )
310 #else
311 | beans::PropertyAttribute::READONLY)); // under unix/linux only readable
312 #endif
316 // ContentType
317 uno::Any aAny;
318 aAny <<= rtl::OUString();
319 m_aDefaultProperties.insert( MyProperty( false,
320 ContentType,
321 -1 ,
322 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
323 aAny,
324 beans::PropertyState_DEFAULT_VALUE,
325 beans::PropertyAttribute::MAYBEVOID
326 | beans::PropertyAttribute::BOUND
327 | beans::PropertyAttribute::READONLY ) );
330 // DateModified
331 m_aDefaultProperties.insert( MyProperty( true,
332 DateModified,
333 -1 ,
334 getCppuType( static_cast< util::DateTime* >( 0 ) ),
335 uno::Any(),
336 beans::PropertyState_DEFAULT_VALUE,
337 beans::PropertyAttribute::MAYBEVOID
338 | beans::PropertyAttribute::BOUND ) );
340 // Size
341 m_aDefaultProperties.insert( MyProperty( true,
342 Size,
344 getCppuType( static_cast< sal_Int64* >( 0 ) ),
345 uno::Any(),
346 beans::PropertyState_DEFAULT_VALUE,
347 beans::PropertyAttribute::MAYBEVOID
348 | beans::PropertyAttribute::BOUND ) );
350 // IsReadOnly
351 m_aDefaultProperties.insert( MyProperty( true,
352 IsReadOnly,
353 -1 ,
354 getCppuType( static_cast< sal_Bool* >( 0 ) ),
355 uno::Any(),
356 beans::PropertyState_DEFAULT_VALUE,
357 beans::PropertyAttribute::MAYBEVOID
358 | beans::PropertyAttribute::BOUND ) );
361 // Commands
362 m_sCommandInfo[0].Name = rtl::OUString::createFromAscii( "getCommandInfo" );
363 m_sCommandInfo[0].Handle = -1;
364 m_sCommandInfo[0].ArgType = getCppuVoidType();
366 m_sCommandInfo[1].Name = rtl::OUString::createFromAscii( "getPropertySetInfo" );
367 m_sCommandInfo[1].Handle = -1;
368 m_sCommandInfo[1].ArgType = getCppuVoidType();
370 m_sCommandInfo[2].Name = rtl::OUString::createFromAscii( "getPropertyValues" );
371 m_sCommandInfo[2].Handle = -1;
372 m_sCommandInfo[2].ArgType = getCppuType( static_cast< uno::Sequence< beans::Property >* >( 0 ) );
374 m_sCommandInfo[3].Name = rtl::OUString::createFromAscii( "setPropertyValues" );
375 m_sCommandInfo[3].Handle = -1;
376 m_sCommandInfo[3].ArgType = getCppuType( static_cast< uno::Sequence< beans::PropertyValue >* >( 0 ) );
378 m_sCommandInfo[4].Name = rtl::OUString::createFromAscii( "open" );
379 m_sCommandInfo[4].Handle = -1;
380 m_sCommandInfo[4].ArgType = getCppuType( static_cast< OpenCommandArgument* >( 0 ) );
382 m_sCommandInfo[5].Name = rtl::OUString::createFromAscii( "transfer" );
383 m_sCommandInfo[5].Handle = -1;
384 m_sCommandInfo[5].ArgType = getCppuType( static_cast< TransferInfo* >( 0 ) );
386 m_sCommandInfo[6].Name = rtl::OUString::createFromAscii( "delete" );
387 m_sCommandInfo[6].Handle = -1;
388 m_sCommandInfo[6].ArgType = getCppuType( static_cast< sal_Bool* >( 0 ) );
390 m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "insert" );
391 m_sCommandInfo[7].Handle = -1;
392 m_sCommandInfo[7].ArgType = getCppuType( static_cast< InsertCommandArgument* > ( 0 ) );
395 if(m_bWithConfig)
397 rtl::OUString Store = rtl::OUString::createFromAscii( "com.sun.star.ucb.Store" );
398 uno::Reference< XPropertySetRegistryFactory > xRegFac(
399 m_xMultiServiceFactory->createInstance( Store ),
400 uno::UNO_QUERY );
401 if ( xRegFac.is() )
403 // Open/create a registry
404 m_xFileRegistry = xRegFac->createPropertySetRegistry( rtl::OUString() );
410 shell::~shell()
415 /*********************************************************************************/
416 /* */
417 /* de/registerNotifier-Implementation */
418 /* */
419 /*********************************************************************************/
422 // This two methods register and deregister a change listener for the content belonging
423 // to URL aUnqPath
426 void SAL_CALL
427 shell::registerNotifier( const rtl::OUString& aUnqPath, Notifier* pNotifier )
429 osl::MutexGuard aGuard( m_aMutex );
431 ContentMap::iterator it =
432 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
434 if( ! it->second.notifier )
435 it->second.notifier = new NotifierList();
437 std::list< Notifier* >& nlist = *( it->second.notifier );
439 std::list<Notifier*>::iterator it1 = nlist.begin();
440 while( it1 != nlist.end() ) // Every "Notifier" only once
442 if( *it1 == pNotifier ) return;
443 ++it1;
445 nlist.push_back( pNotifier );
450 void SAL_CALL
451 shell::deregisterNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier )
453 osl::MutexGuard aGuard( m_aMutex );
455 ContentMap::iterator it = m_aContent.find( aUnqPath );
456 if( it == m_aContent.end() )
457 return;
459 it->second.notifier->remove( pNotifier );
461 if( ! it->second.notifier->size() )
462 m_aContent.erase( it );
467 /*********************************************************************************/
468 /* */
469 /* de/associate-Implementation */
470 /* */
471 /*********************************************************************************/
473 // Used to associate and deassociate a new property with
474 // the content belonging to URL UnqPath.
475 // The default value and the the attributes are input
478 void SAL_CALL
479 shell::associate( const rtl::OUString& aUnqPath,
480 const rtl::OUString& PropertyName,
481 const uno::Any& DefaultValue,
482 const sal_Int16 Attributes )
483 throw( beans::PropertyExistException,
484 beans::IllegalTypeException,
485 uno::RuntimeException )
487 MyProperty newProperty( false,
488 PropertyName,
490 DefaultValue.getValueType(),
491 DefaultValue,
492 beans::PropertyState_DEFAULT_VALUE,
493 Attributes );
495 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty );
496 if( it1 != m_aDefaultProperties.end() )
497 throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
500 osl::MutexGuard aGuard( m_aMutex );
502 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
504 // Load the XPersistentPropertySetInfo and create it, if it does not exist
505 load( it,true );
507 PropertySet& properties = *(it->second.properties);
508 it1 = properties.find( newProperty );
509 if( it1 != properties.end() )
510 throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
512 // Property does not exist
513 properties.insert( newProperty );
514 it->second.xC->addProperty( PropertyName,Attributes,DefaultValue );
516 notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName );
522 void SAL_CALL
523 shell::deassociate( const rtl::OUString& aUnqPath,
524 const rtl::OUString& PropertyName )
525 throw( beans::UnknownPropertyException,
526 beans::NotRemoveableException,
527 uno::RuntimeException )
529 MyProperty oldProperty( PropertyName );
531 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty );
532 if( it1 != m_aDefaultProperties.end() )
533 throw beans::NotRemoveableException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
535 osl::MutexGuard aGuard( m_aMutex );
537 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
539 load( it,false );
541 PropertySet& properties = *(it->second.properties);
543 it1 = properties.find( oldProperty );
544 if( it1 == properties.end() )
545 throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
547 properties.erase( it1 );
549 if( it->second.xC.is() )
550 it->second.xC->removeProperty( PropertyName );
552 if( properties.size() == 9 )
554 MyProperty ContentTProperty( ContentType );
556 if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE )
558 it->second.xS = 0;
559 it->second.xC = 0;
560 it->second.xA = 0;
561 if(m_xFileRegistry.is())
562 m_xFileRegistry->removePropertySet( aUnqPath );
565 notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName );
571 /*********************************************************************************/
572 /* */
573 /* page-Implementation */
574 /* */
575 /*********************************************************************************/
577 // Given an xOutputStream, this method writes the content of the file belonging to
578 // URL aUnqPath into the XOutputStream
582 void SAL_CALL shell::page( sal_Int32 CommandId,
583 const rtl::OUString& aUnqPath,
584 const uno::Reference< io::XOutputStream >& xOutputStream )
585 throw()
587 uno::Reference< XContentProvider > xProvider( m_pProvider );
588 osl::File aFile( aUnqPath );
589 osl::FileBase::RC err = aFile.open( OpenFlag_Read );
591 if( err != osl::FileBase::E_None )
593 aFile.close();
594 installError( CommandId,
595 TASKHANDLING_OPEN_FILE_FOR_PAGING,
596 err );
597 return;
600 const sal_uInt64 bfz = 4*1024;
601 sal_Int8 BFF[bfz];
602 sal_uInt64 nrc; // Retrieved number of Bytes;
606 err = aFile.read( (void*) BFF,bfz,nrc );
607 if( err == osl::FileBase::E_None )
609 uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc );
612 xOutputStream->writeBytes( seq );
614 catch( io::NotConnectedException )
616 installError( CommandId,
617 TASKHANDLING_NOTCONNECTED_FOR_PAGING );
618 break;
620 catch( io::BufferSizeExceededException )
622 installError( CommandId,
623 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING );
624 break;
626 catch( io::IOException )
628 installError( CommandId,
629 TASKHANDLING_IOEXCEPTION_FOR_PAGING );
630 break;
633 else
635 installError( CommandId,
636 TASKHANDLING_READING_FILE_FOR_PAGING,
637 err );
638 break;
640 } while( nrc == bfz );
643 aFile.close();
648 xOutputStream->closeOutput();
650 catch( io::NotConnectedException )
653 catch( io::BufferSizeExceededException )
656 catch( io::IOException )
662 /*********************************************************************************/
663 /* */
664 /* open-Implementation */
665 /* */
666 /*********************************************************************************/
668 // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
672 uno::Reference< io::XInputStream > SAL_CALL
673 shell::open( sal_Int32 CommandId,
674 const rtl::OUString& aUnqPath,
675 sal_Bool bLock )
676 throw()
678 XInputStream_impl* xInputStream = new XInputStream_impl( this, aUnqPath, bLock ); // from filinpstr.hxx
680 sal_Int32 ErrorCode = xInputStream->CtorSuccess();
682 if( ErrorCode != TASKHANDLER_NO_ERROR )
684 installError( CommandId,
685 ErrorCode,
686 xInputStream->getMinorError() );
688 delete xInputStream;
689 xInputStream = 0;
692 return uno::Reference< io::XInputStream >( xInputStream );
698 /*********************************************************************************/
699 /* */
700 /* open for read/write access-Implementation */
701 /* */
702 /*********************************************************************************/
704 // Given a file URL aUnqPath, this methods returns a XStream which can be used
705 // to read and write from/to the file.
709 uno::Reference< io::XStream > SAL_CALL
710 shell::open_rw( sal_Int32 CommandId,
711 const rtl::OUString& aUnqPath,
712 sal_Bool bLock )
713 throw()
715 XStream_impl* xStream = new XStream_impl( this, aUnqPath, bLock ); // from filstr.hxx
717 sal_Int32 ErrorCode = xStream->CtorSuccess();
719 if( ErrorCode != TASKHANDLER_NO_ERROR )
721 installError( CommandId,
722 ErrorCode,
723 xStream->getMinorError() );
725 delete xStream;
726 xStream = 0;
728 return uno::Reference< io::XStream >( xStream );
733 /*********************************************************************************/
734 /* */
735 /* ls-Implementation */
736 /* */
737 /*********************************************************************************/
739 // This method returns the result set containing the the children of the directory belonging
740 // to file URL aUnqPath
744 uno::Reference< XDynamicResultSet > SAL_CALL
745 shell::ls( sal_Int32 CommandId,
746 const rtl::OUString& aUnqPath,
747 const sal_Int32 OpenMode,
748 const uno::Sequence< beans::Property >& seq,
749 const uno::Sequence< NumberedSortingInfo >& seqSort )
750 throw()
752 XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort );
754 sal_Int32 ErrorCode = p->CtorSuccess();
756 if( ErrorCode != TASKHANDLER_NO_ERROR )
758 installError( CommandId,
759 ErrorCode,
760 p->getMinorError() );
762 delete p;
763 p = 0;
766 return uno::Reference< XDynamicResultSet > ( p );
772 /*********************************************************************************/
773 /* */
774 /* info_c implementation */
775 /* */
776 /*********************************************************************************/
777 // Info for commands
779 uno::Reference< XCommandInfo > SAL_CALL
780 shell::info_c()
781 throw()
783 XCommandInfo_impl* p = new XCommandInfo_impl( this );
784 return uno::Reference< XCommandInfo >( p );
790 /*********************************************************************************/
791 /* */
792 /* info_p-Implementation */
793 /* */
794 /*********************************************************************************/
795 // Info for the properties
797 uno::Reference< beans::XPropertySetInfo > SAL_CALL
798 shell::info_p( const rtl::OUString& aUnqPath )
799 throw()
801 osl::MutexGuard aGuard( m_aMutex );
802 XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath );
803 return uno::Reference< beans::XPropertySetInfo >( p );
809 /*********************************************************************************/
810 /* */
811 /* setv-Implementation */
812 /* */
813 /*********************************************************************************/
815 // Sets the values of the properties belonging to fileURL aUnqPath
819 uno::Sequence< uno::Any > SAL_CALL
820 shell::setv( const rtl::OUString& aUnqPath,
821 const uno::Sequence< beans::PropertyValue >& values )
822 throw()
824 osl::MutexGuard aGuard( m_aMutex );
826 sal_Int32 propChanged = 0;
827 uno::Sequence< uno::Any > ret( values.getLength() );
828 uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() );
830 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
831 PropertySet& properties = *( it->second.properties );
832 shell::PropertySet::iterator it1;
833 uno::Any aAny;
835 for( sal_Int32 i = 0; i < values.getLength(); ++i )
837 MyProperty toset( values[i].Name );
838 it1 = properties.find( toset );
839 if( it1 == properties.end() )
841 ret[i] <<= beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
842 continue;
845 aAny = it1->getValue();
846 if( aAny == values[i].Value )
847 continue; // nothing needs to be changed
849 if( it1->getAttributes() & beans::PropertyAttribute::READONLY )
851 ret[i] <<= lang::IllegalAccessException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
852 continue;
855 seqChanged[ propChanged ].PropertyName = values[i].Name;
856 seqChanged[ propChanged ].PropertyHandle = -1;
857 seqChanged[ propChanged ].Further = false;
858 seqChanged[ propChanged ].OldValue <<= aAny;
859 seqChanged[ propChanged++ ].NewValue = values[i].Value;
861 it1->setValue( values[i].Value ); // Put the new value into the local cash
863 if( ! it1->IsNative() )
865 // Also put logical properties into storage
866 if( !it->second.xS.is() )
867 load( it,true );
869 if( ( values[i].Name == ContentType ) &&
870 it1->getState() == beans::PropertyState_DEFAULT_VALUE )
871 { // Special logic for ContentType
872 // 09.07.01: Not reached anymore, because ContentType is readonly
873 it1->setState( beans::PropertyState_DIRECT_VALUE );
874 it->second.xC->addProperty( values[i].Name,
875 beans::PropertyAttribute::MAYBEVOID,
876 values[i].Value );
881 it->second.xS->setPropertyValue( values[i].Name,values[i].Value );
883 catch( const uno::Exception& e )
885 --propChanged; // unsuccessful setting
886 ret[i] <<= e;
889 else
891 // native properties
892 // Setting of physical file properties
893 if( values[i].Name == Size )
895 sal_Int64 newSize = 0;
896 if( values[i].Value >>= newSize )
897 { // valid value for the size
898 osl::File aFile(aUnqPath);
899 bool err =
900 aFile.open(OpenFlag_Write) != osl::FileBase::E_None ||
901 aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None ||
902 aFile.close() != osl::FileBase::E_None;
904 if( err )
906 --propChanged; // unsuccessful setting
907 uno::Sequence< uno::Any > names( 1 );
908 ret[0] <<= beans::PropertyValue(
909 rtl::OUString::createFromAscii("Uri"), -1,
910 uno::makeAny(aUnqPath),
911 beans::PropertyState_DIRECT_VALUE);
912 IOErrorCode ioError(IOErrorCode_GENERAL);
913 ret[i] <<= InteractiveAugmentedIOException(
914 rtl::OUString(),
916 task::InteractionClassification_ERROR,
917 ioError,
918 names );
921 else
922 ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
924 else if(values[i].Name == IsReadOnly ||
925 values[i].Name == IsHidden)
927 sal_Bool value = sal_False;
928 if( values[i].Value >>= value )
930 osl::DirectoryItem aDirItem;
931 osl::FileBase::RC err =
932 osl::DirectoryItem::get(aUnqPath,aDirItem);
933 sal_uInt64 nAttributes(0);
934 if(err == osl::FileBase::E_None)
936 osl::FileStatus aFileStatus(FileStatusMask_Attributes);
937 err = aDirItem.getFileStatus(aFileStatus);
938 if(err == osl::FileBase::E_None &&
939 aFileStatus.isValid(FileStatusMask_Attributes))
940 nAttributes = aFileStatus.getAttributes();
942 // now we have the attributes provided all went well.
943 if(err == osl::FileBase::E_None) {
944 if(values[i].Name == IsReadOnly)
946 nAttributes &= ~(Attribute_OwnWrite |
947 Attribute_GrpWrite |
948 Attribute_OthWrite |
949 Attribute_ReadOnly);
950 if(value)
951 nAttributes |= Attribute_ReadOnly;
952 else
953 nAttributes |= (
954 Attribute_OwnWrite |
955 Attribute_GrpWrite |
956 Attribute_OthWrite);
958 else if(values[i].Name == IsHidden)
960 nAttributes &= ~(Attribute_Hidden);
961 if(value)
962 nAttributes |= Attribute_Hidden;
964 err = osl::File::setAttributes(
965 aUnqPath,nAttributes);
968 if( err != osl::FileBase::E_None )
970 --propChanged; // unsuccessful setting
971 uno::Sequence< uno::Any > names( 1 );
972 names[0] <<= beans::PropertyValue(
973 rtl::OUString::createFromAscii("Uri"), -1,
974 uno::makeAny(aUnqPath),
975 beans::PropertyState_DIRECT_VALUE);
976 IOErrorCode ioError;
977 switch( err )
979 case osl::FileBase::E_NOMEM:
980 // not enough memory for allocating structures <br>
981 ioError = IOErrorCode_OUT_OF_MEMORY;
982 break;
983 case osl::FileBase::E_INVAL:
984 // the format of the parameters was not valid<p>
985 ioError = IOErrorCode_INVALID_PARAMETER;
986 break;
987 case osl::FileBase::E_NAMETOOLONG:
988 // File name too long<br>
989 ioError = IOErrorCode_NAME_TOO_LONG;
990 break;
991 case osl::FileBase::E_NOENT:
992 // No such file or directory<br>
993 case osl::FileBase::E_NOLINK:
994 // Link has been severed<br>
995 ioError = IOErrorCode_NOT_EXISTING;
996 break;
997 case osl::FileBase::E_ROFS:
998 // #i4735# handle ROFS transparently
999 // as ACCESS_DENIED
1000 case osl::FileBase::E_PERM:
1001 case osl::FileBase::E_ACCES:
1002 // permission denied<br>
1003 ioError = IOErrorCode_ACCESS_DENIED;
1004 break;
1005 case osl::FileBase::E_LOOP:
1006 // Too many symbolic links encountered<br>
1007 case osl::FileBase::E_FAULT:
1008 // Bad address<br>
1009 case osl::FileBase::E_IO:
1010 // I/O error<br>
1011 case osl::FileBase::E_NOSYS:
1012 // Function not implemented<br>
1013 case osl::FileBase::E_MULTIHOP:
1014 // Multihop attempted<br>
1015 case osl::FileBase::E_INTR:
1016 // function call was interrupted<p>
1017 default:
1018 ioError = IOErrorCode_GENERAL;
1019 break;
1021 ret[i] <<= InteractiveAugmentedIOException(
1022 rtl::OUString(),
1024 task::InteractionClassification_ERROR,
1025 ioError,
1026 names );
1029 else
1030 ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
1033 } // end for
1035 if( propChanged )
1037 seqChanged.realloc( propChanged );
1038 notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged );
1041 return ret;
1044 /*********************************************************************************/
1045 /* */
1046 /* getv-Implementation */
1047 /* */
1048 /*********************************************************************************/
1050 // Reads the values of the properties belonging to fileURL aUnqPath;
1051 // Returns an XRow object containing the values in the requested order.
1055 uno::Reference< sdbc::XRow > SAL_CALL
1056 shell::getv( sal_Int32 CommandId,
1057 const rtl::OUString& aUnqPath,
1058 const uno::Sequence< beans::Property >& properties )
1059 throw()
1061 uno::Sequence< uno::Any > seq( properties.getLength() );
1063 sal_Int32 n_Mask;
1064 getMaskFromProperties( n_Mask,properties );
1065 osl::FileStatus aFileStatus( n_Mask );
1067 osl::DirectoryItem aDirItem;
1068 osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem );
1069 if( nError1 != osl::FileBase::E_None )
1070 installError(CommandId,
1071 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1072 nError1);
1074 osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus );
1075 if( nError1 == osl::FileBase::E_None &&
1076 nError2 != osl::FileBase::E_None )
1077 installError(CommandId,
1078 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1079 nError2);
1082 osl::MutexGuard aGuard( m_aMutex );
1084 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
1085 commit( it,aFileStatus );
1087 shell::PropertySet::iterator it1;
1088 PropertySet& propset = *(it->second.properties);
1090 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
1092 MyProperty readProp( properties[i].Name );
1093 it1 = propset.find( readProp );
1094 if( it1 == propset.end() )
1095 seq[i] = uno::Any();
1096 else
1097 seq[i] = it1->getValue();
1101 XRow_impl* p = new XRow_impl( this,seq );
1102 return uno::Reference< sdbc::XRow >( p );
1106 /********************************************************************************/
1107 /* */
1108 /* transfer-commandos */
1109 /* */
1110 /********************************************************************************/
1113 /********************************************************************************/
1114 /* */
1115 /* move-implementation */
1116 /* */
1117 /********************************************************************************/
1119 // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath.
1122 void SAL_CALL
1123 shell::move( sal_Int32 CommandId,
1124 const rtl::OUString srcUnqPath,
1125 const rtl::OUString dstUnqPathIn,
1126 const sal_Int32 NameClash )
1127 throw()
1129 // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if
1130 // srcUnqPath and dstUnqPathIn are equal
1131 if( srcUnqPath == dstUnqPathIn )
1132 return;
1133 // <--
1135 osl::FileBase::RC nError;
1136 rtl::OUString dstUnqPath( dstUnqPathIn );
1138 switch( NameClash )
1140 case NameClash::KEEP:
1142 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1143 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1145 installError( CommandId,
1146 TASKHANDLING_KEEPERROR_FOR_MOVE,
1147 nError );
1148 return;
1150 break;
1152 case NameClash::OVERWRITE:
1154 // stat to determine whether we have a symlink
1155 rtl::OUString targetPath(dstUnqPath);
1157 osl::FileStatus aStatus(FileStatusMask_Type|FileStatusMask_LinkTargetURL);
1158 osl::DirectoryItem aItem;
1159 osl::DirectoryItem::get(dstUnqPath,aItem);
1160 aItem.getFileStatus(aStatus);
1162 if( aStatus.isValid(FileStatusMask_Type) &&
1163 aStatus.isValid(FileStatusMask_LinkTargetURL) &&
1164 aStatus.getFileType() == osl::FileStatus::Link )
1165 targetPath = aStatus.getLinkTargetURL();
1167 // Will do nothing if file does not exist.
1168 osl::File::remove( targetPath );
1170 nError = osl_File_move( srcUnqPath,targetPath );
1171 if( nError != osl::FileBase::E_None )
1173 installError( CommandId,
1174 TASKHANDLING_OVERWRITE_FOR_MOVE,
1175 nError );
1176 return;
1178 break;
1180 case NameClash::RENAME:
1182 rtl::OUString newDstUnqPath;
1183 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1184 if( nError == osl::FileBase::E_EXIST )
1186 // "invent" a new valid title.
1188 sal_Int32 nPos = -1;
1189 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1190 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1191 if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1192 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1193 nPos = nLastDot;
1194 else
1195 nPos = dstUnqPath.getLength();
1197 sal_Int32 nTry = 0;
1201 newDstUnqPath = dstUnqPath;
1203 rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) );
1204 aPostFix += rtl::OUString::valueOf( ++nTry );
1206 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix );
1208 nError = osl_File_move( srcUnqPath,newDstUnqPath,true );
1210 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1213 if( nError == osl::FileBase::E_EXIST )
1215 installError( CommandId,
1216 TASKHANDLING_RENAME_FOR_MOVE );
1217 return;
1219 else if( nError != osl::FileBase::E_None )
1221 installError( CommandId,
1222 TASKHANDLING_RENAMEMOVE_FOR_MOVE,
1223 nError );
1224 return;
1226 else
1227 dstUnqPath = newDstUnqPath;
1229 break;
1231 case NameClash::ERROR:
1233 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1234 if( nError == osl::FileBase::E_EXIST )
1236 installError( CommandId,
1237 TASKHANDLING_NAMECLASH_FOR_MOVE );
1238 return;
1240 else if( nError != osl::FileBase::E_None )
1242 installError( CommandId,
1243 TASKHANDLING_NAMECLASHMOVE_FOR_MOVE,
1244 nError );
1245 return;
1247 break;
1249 case NameClash::ASK:
1250 default:
1252 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1253 if( nError == osl::FileBase::E_EXIST )
1255 installError( CommandId,
1256 TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE,
1257 NameClash::ASK);
1258 return;
1261 break;
1264 // Determine, whether we have moved a file or a folder
1265 osl::DirectoryItem aItem;
1266 nError = osl::DirectoryItem::get( dstUnqPath,aItem );
1267 if( nError != osl::FileBase::E_None )
1269 installError( CommandId,
1270 TASKHANDLING_TRANSFER_BY_MOVE_SOURCE,
1271 nError );
1272 return;
1274 osl::FileStatus aStatus( FileStatusMask_Type );
1275 nError = aItem.getFileStatus( aStatus );
1276 if( nError != osl::FileBase::E_None || ! aStatus.isValid( FileStatusMask_Type ) )
1278 installError( CommandId,
1279 TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT,
1280 nError );
1281 return;
1283 sal_Bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular );
1286 copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument );
1288 rtl::OUString aDstParent = getParentName( dstUnqPath );
1289 rtl::OUString aDstTitle = getTitle( dstUnqPath );
1291 rtl::OUString aSrcParent = getParentName( srcUnqPath );
1292 rtl::OUString aSrcTitle = getTitle( srcUnqPath );
1294 notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath );
1295 if( aDstParent != aSrcParent )
1296 notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath );
1298 notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) );
1299 erasePersistentSet( srcUnqPath,!isDocument );
1304 /********************************************************************************/
1305 /* */
1306 /* copy-implementation */
1307 /* */
1308 /********************************************************************************/
1310 // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
1313 namespace {
1315 bool getType(
1316 TaskManager & task, sal_Int32 id, rtl::OUString const & fileUrl,
1317 osl::DirectoryItem * item, osl::FileStatus::Type * type)
1319 OSL_ASSERT(item != 0 && type != 0);
1320 osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item);
1321 if (err != osl::FileBase::E_None) {
1322 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err);
1323 return false;
1325 osl::FileStatus stat(FileStatusMask_Type);
1326 err = item->getFileStatus(stat);
1327 if (err != osl::FileBase::E_None) {
1328 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err);
1329 return false;
1331 *type = stat.getFileType();
1332 return true;
1337 void SAL_CALL
1338 shell::copy(
1339 sal_Int32 CommandId,
1340 const rtl::OUString srcUnqPath,
1341 const rtl::OUString dstUnqPathIn,
1342 sal_Int32 NameClash )
1343 throw()
1345 osl::FileBase::RC nError;
1346 rtl::OUString dstUnqPath( dstUnqPathIn );
1348 // Resolve symbolic links within the source path. If srcUnqPath denotes a
1349 // symbolic link (targeting either a file or a folder), the contents of the
1350 // target is copied (recursively, in the case of a folder). However, if
1351 // recursively copying the contents of a folder causes a symbolic link to be
1352 // copied, the symbolic link itself is copied.
1353 osl::DirectoryItem item;
1354 osl::FileStatus::Type type;
1355 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1356 return;
1358 rtl::OUString rslvdSrcUnqPath;
1359 if (type == osl::FileStatus::Link) {
1360 osl::FileStatus stat(FileStatusMask_LinkTargetURL);
1361 nError = item.getFileStatus(stat);
1362 if (nError != osl::FileBase::E_None) {
1363 installError(
1364 CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError);
1365 return;
1367 rslvdSrcUnqPath = stat.getLinkTargetURL();
1368 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1369 return;
1371 } else {
1372 rslvdSrcUnqPath = srcUnqPath;
1375 sal_Bool isDocument
1376 = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume;
1377 sal_Int32 IsWhat = isDocument ? -1 : 1;
1379 switch( NameClash )
1381 case NameClash::KEEP:
1383 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1384 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1386 installError( CommandId,
1387 TASKHANDLING_KEEPERROR_FOR_COPY,
1388 nError );
1389 return;
1391 break;
1393 case NameClash::OVERWRITE:
1395 // remove (..., MustExist = sal_False).
1396 remove( CommandId, dstUnqPath, IsWhat, sal_False );
1398 // copy.
1399 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false );
1400 if( nError != osl::FileBase::E_None )
1402 installError( CommandId,
1403 TASKHANDLING_OVERWRITE_FOR_COPY,
1404 nError );
1405 return;
1407 break;
1409 case NameClash::RENAME:
1411 rtl::OUString newDstUnqPath;
1412 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1414 if( nError == osl::FileBase::E_EXIST )
1416 // "invent" a new valid title.
1418 sal_Int32 nPos = -1;
1419 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1420 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1421 if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1422 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1423 nPos = nLastDot;
1424 else
1425 nPos = dstUnqPath.getLength();
1427 sal_Int32 nTry = 0;
1431 newDstUnqPath = dstUnqPath;
1433 rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) );
1434 aPostFix += rtl::OUString::valueOf( ++nTry );
1436 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix );
1438 nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true );
1440 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1443 if( nError == osl::FileBase::E_EXIST )
1445 installError( CommandId,
1446 TASKHANDLING_RENAME_FOR_COPY );
1447 return;
1449 else if( nError != osl::FileBase::E_None )
1451 installError( CommandId,
1452 TASKHANDLING_RENAMEMOVE_FOR_COPY,
1453 nError );
1454 return;
1456 else
1457 dstUnqPath = newDstUnqPath;
1459 break;
1461 case NameClash::ERROR:
1463 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1465 if( nError == osl::FileBase::E_EXIST )
1467 installError( CommandId,
1468 TASKHANDLING_NAMECLASH_FOR_COPY );
1469 return;
1471 else if( nError != osl::FileBase::E_None )
1473 installError( CommandId,
1474 TASKHANDLING_NAMECLASHMOVE_FOR_COPY,
1475 nError );
1476 return;
1478 break;
1480 case NameClash::ASK:
1481 default:
1483 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1485 if( nError == osl::FileBase::E_EXIST )
1487 installError( CommandId,
1488 TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY,
1489 NameClash);
1490 return;
1492 break;
1496 copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument );
1497 notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath );
1502 /********************************************************************************/
1503 /* */
1504 /* remove-implementation */
1505 /* */
1506 /********************************************************************************/
1508 // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
1509 // Return: success of operation
1513 sal_Bool SAL_CALL
1514 shell::remove( sal_Int32 CommandId,
1515 const rtl::OUString& aUnqPath,
1516 sal_Int32 IsWhat,
1517 sal_Bool MustExist )
1518 throw()
1520 sal_Int32 nMask = FileStatusMask_Type | FileStatusMask_FileURL;
1522 osl::DirectoryItem aItem;
1523 osl::FileStatus aStatus( nMask );
1524 osl::FileBase::RC nError;
1526 if( IsWhat == 0 ) // Determine whether we are removing a directory or a file
1528 nError = osl::DirectoryItem::get( aUnqPath, aItem );
1529 if( nError != osl::FileBase::E_None )
1531 if (MustExist)
1533 installError( CommandId,
1534 TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE,
1535 nError );
1537 return (!MustExist);
1540 nError = aItem.getFileStatus( aStatus );
1541 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1543 installError( CommandId,
1544 TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE,
1545 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1546 return sal_False;
1549 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1550 aStatus.getFileType() == osl::FileStatus::Link )
1551 IsWhat = -1; // RemoveFile
1552 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1553 aStatus.getFileType() == osl::FileStatus::Volume )
1554 IsWhat = +1; // RemoveDirectory
1558 if( IsWhat == -1 ) // Removing a file
1560 nError = osl::File::remove( aUnqPath );
1561 if( nError != osl::FileBase::E_None )
1563 if (MustExist)
1565 installError( CommandId,
1566 TASKHANDLING_DELETEFILE_FOR_REMOVE,
1567 nError );
1569 return (!MustExist);
1571 else
1573 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1574 erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet
1577 else if( IsWhat == +1 ) // Removing a directory
1579 osl::Directory aDirectory( aUnqPath );
1581 nError = aDirectory.open();
1582 if( nError != osl::FileBase::E_None )
1584 if (MustExist)
1586 installError( CommandId,
1587 TASKHANDLING_OPENDIRECTORY_FOR_REMOVE,
1588 nError );
1590 return (!MustExist);
1593 sal_Bool whileSuccess = sal_True;
1594 sal_Int32 recurse = 0;
1595 rtl::OUString name;
1597 nError = aDirectory.getNextItem( aItem );
1598 while( nError == osl::FileBase::E_None )
1600 nError = aItem.getFileStatus( aStatus );
1601 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1603 installError( CommandId,
1604 TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE,
1605 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1606 whileSuccess = sal_False;
1607 break;
1610 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1611 aStatus.getFileType() == osl::FileStatus::Link )
1612 recurse = -1;
1613 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1614 aStatus.getFileType() == osl::FileStatus::Volume )
1615 recurse = +1;
1617 name = aStatus.getFileURL();
1618 whileSuccess = remove(
1619 CommandId, name, recurse, MustExist );
1620 if( !whileSuccess )
1621 break;
1623 nError = aDirectory.getNextItem( aItem );
1626 aDirectory.close();
1628 if( ! whileSuccess )
1629 return sal_False; // error code is installed
1631 if( nError != osl::FileBase::E_NOENT )
1633 installError( CommandId,
1634 TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE,
1635 nError );
1636 return sal_False;
1639 nError = osl::Directory::remove( aUnqPath );
1640 if( nError != osl::FileBase::E_None )
1642 if (MustExist)
1644 installError( CommandId,
1645 TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE,
1646 nError );
1648 return (!MustExist);
1650 else
1652 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1653 erasePersistentSet( aUnqPath );
1656 else // Don't know what to remove
1658 installError( CommandId,
1659 TASKHANDLING_FILETYPE_FOR_REMOVE );
1660 return sal_False;
1663 return sal_True;
1667 /********************************************************************************/
1668 /* */
1669 /* mkdir-implementation */
1670 /* */
1671 /********************************************************************************/
1673 // Creates new directory with given URL, recursively if necessary
1674 // Return:: success of operation
1677 sal_Bool SAL_CALL
1678 shell::mkdir( sal_Int32 CommandId,
1679 const rtl::OUString& rUnqPath,
1680 sal_Bool OverWrite )
1681 throw()
1683 rtl::OUString aUnqPath;
1685 // remove trailing slash
1686 if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) )
1687 aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
1688 else
1689 aUnqPath = rUnqPath;
1691 osl::FileBase::RC nError = osl::Directory::create( aUnqPath );
1693 switch ( nError )
1695 case osl::FileBase::E_EXIST: // Directory cannot be overwritten
1697 if( !OverWrite )
1699 installError( CommandId,
1700 TASKHANDLING_FOLDER_EXISTS_MKDIR );
1701 return sal_False;
1703 else
1704 return sal_True;
1706 case osl::FileBase::E_INVAL:
1708 installError(CommandId,
1709 TASKHANDLING_INVALID_NAME_MKDIR);
1710 return sal_False;
1712 case osl::FileBase::E_None:
1714 rtl::OUString aPrtPath = getParentName( aUnqPath );
1715 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1716 return sal_True;
1718 default:
1719 return ensuredir(
1720 CommandId,
1721 aUnqPath,
1722 TASKHANDLING_CREATEDIRECTORY_MKDIR );
1727 /********************************************************************************/
1728 /* */
1729 /* mkfil-implementation */
1730 /* */
1731 /********************************************************************************/
1733 // Creates new file with given URL.
1734 // The content of aInputStream becomes the content of the file
1735 // Return:: success of operation
1738 sal_Bool SAL_CALL
1739 shell::mkfil( sal_Int32 CommandId,
1740 const rtl::OUString& aUnqPath,
1741 sal_Bool Overwrite,
1742 const uno::Reference< io::XInputStream >& aInputStream )
1743 throw()
1745 // return value unimportant
1746 sal_Bool bSuccess = write( CommandId,
1747 aUnqPath,
1748 Overwrite,
1749 aInputStream );
1750 if ( bSuccess )
1752 rtl::OUString aPrtPath = getParentName( aUnqPath );
1753 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1755 return bSuccess;
1759 /********************************************************************************/
1760 /* */
1761 /* write-implementation */
1762 /* */
1763 /********************************************************************************/
1765 // writes to the file with given URL.
1766 // The content of aInputStream becomes the content of the file
1767 // Return:: success of operation
1770 sal_Bool SAL_CALL
1771 shell::write( sal_Int32 CommandId,
1772 const rtl::OUString& aUnqPath,
1773 sal_Bool OverWrite,
1774 const uno::Reference< io::XInputStream >& aInputStream )
1775 throw()
1777 if( ! aInputStream.is() )
1779 installError( CommandId,
1780 TASKHANDLING_INPUTSTREAM_FOR_WRITE );
1781 return sal_False;
1784 // Create parent path, if necessary.
1785 if ( ! ensuredir( CommandId,
1786 getParentName( aUnqPath ),
1787 TASKHANDLING_ENSUREDIR_FOR_WRITE ) )
1788 return sal_False;
1790 osl::FileBase::RC err;
1791 osl::File aFile( aUnqPath );
1793 if( OverWrite )
1795 err = aFile.open( OpenFlag_Write | OpenFlag_Create );
1797 if( err != osl::FileBase::E_None )
1799 aFile.close();
1800 err = aFile.open( OpenFlag_Write );
1803 if( err != osl::FileBase::E_None )
1805 installError( CommandId,
1806 TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE,
1807 err );
1808 return sal_False;
1811 else
1813 err = aFile.open( OpenFlag_Read | OpenFlag_NoLock );
1814 if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten
1816 installError( CommandId,
1817 TASKHANDLING_NOREPLACE_FOR_WRITE, // Now an exception
1818 err );
1820 aFile.close();
1821 return sal_False;
1824 // as a temporary solution the creation does not lock the file at all
1825 // in future it should be possible to create the file without lock explicitly
1826 err = aFile.open( OpenFlag_Write | OpenFlag_Create | OpenFlag_NoLock );
1828 if( err != osl::FileBase::E_None )
1830 aFile.close();
1831 installError( CommandId,
1832 TASKHANDLING_NO_OPEN_FILE_FOR_WRITE,
1833 err );
1834 return sal_False;
1838 sal_Bool bSuccess = sal_True;
1840 sal_uInt64 nTotalNumberOfBytes = 0;
1841 sal_uInt64 nWrittenBytes;
1842 sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/;
1843 uno::Sequence< sal_Int8 > seq( nRequestedBytes );
1849 nReadBytes = aInputStream->readBytes( seq,
1850 nRequestedBytes );
1852 catch( const io::NotConnectedException& )
1854 installError( CommandId,
1855 TASKHANDLING_NOTCONNECTED_FOR_WRITE );
1856 bSuccess = sal_False;
1857 break;
1859 catch( const io::BufferSizeExceededException& )
1861 installError( CommandId,
1862 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE );
1863 bSuccess = sal_False;
1864 break;
1866 catch( const io::IOException& )
1868 installError( CommandId,
1869 TASKHANDLING_IOEXCEPTION_FOR_WRITE );
1870 bSuccess = sal_False;
1871 break;
1874 if( nReadBytes )
1876 const sal_Int8* p = seq.getConstArray();
1878 err = aFile.write( ((void*)(p)),
1879 sal_uInt64( nReadBytes ),
1880 nWrittenBytes );
1882 if( err != osl::FileBase::E_None )
1884 installError( CommandId,
1885 TASKHANDLING_FILEIOERROR_FOR_WRITE,
1886 err );
1887 bSuccess = sal_False;
1888 break;
1890 else if( nWrittenBytes != sal_uInt64( nReadBytes ) )
1892 installError( CommandId,
1893 TASKHANDLING_FILEIOERROR_FOR_NO_SPACE );
1894 bSuccess = sal_False;
1895 break;
1898 nTotalNumberOfBytes += nWrittenBytes;
1900 } while( nReadBytes == nRequestedBytes );
1902 err = aFile.setSize( nTotalNumberOfBytes );
1903 if( err != osl::FileBase::E_None )
1905 installError( CommandId,
1906 TASKHANDLING_FILESIZE_FOR_WRITE,
1907 err );
1908 bSuccess = sal_False;
1911 err = aFile.close();
1912 if( err != osl::FileBase::E_None )
1914 installError( CommandId,
1915 TASKHANDLING_FILEIOERROR_FOR_WRITE,
1916 err );
1917 bSuccess = sal_False;
1920 return bSuccess;
1925 /*********************************************************************************/
1926 /* */
1927 /* insertDefaultProperties-Implementation */
1928 /* */
1929 /*********************************************************************************/
1932 void SAL_CALL shell::insertDefaultProperties( const rtl::OUString& aUnqPath )
1934 osl::MutexGuard aGuard( m_aMutex );
1936 ContentMap::iterator it =
1937 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
1939 load( it,false );
1941 MyProperty ContentTProperty( ContentType );
1943 PropertySet& properties = *(it->second.properties);
1944 sal_Bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end();
1946 shell::PropertySet::iterator it1 = m_aDefaultProperties.begin();
1947 while( it1 != m_aDefaultProperties.end() )
1949 if( ContentNotDefau && it1->getPropertyName() == ContentType )
1951 // No insertion
1953 else
1954 properties.insert( *it1 );
1955 ++it1;
1962 /******************************************************************************/
1963 /* */
1964 /* mapping of file urls */
1965 /* to uncpath and vice versa */
1966 /* */
1967 /******************************************************************************/
1970 sal_Bool SAL_CALL shell::getUnqFromUrl( const rtl::OUString& Url,rtl::OUString& Unq )
1972 if( 0 == Url.compareToAscii( "file:///" ) ||
1973 0 == Url.compareToAscii( "file://localhost/" ) ||
1974 0 == Url.compareToAscii( "file://127.0.0.1/" ) )
1976 Unq = rtl::OUString::createFromAscii( "file:///" );
1977 return false;
1980 sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq );
1982 Unq = Url;
1984 sal_Int32 l = Unq.getLength()-1;
1985 if( ! err && Unq.getStr()[ l ] == '/' &&
1986 Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) < l )
1987 Unq = Unq.copy(0, Unq.getLength() - 1);
1989 return err;
1994 sal_Bool SAL_CALL shell::getUrlFromUnq( const rtl::OUString& Unq,rtl::OUString& Url )
1996 sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url );
1998 Url = Unq;
2000 return err;
2005 // Helper function for public copy
2007 osl::FileBase::RC SAL_CALL
2008 shell::copy_recursive( const rtl::OUString& srcUnqPath,
2009 const rtl::OUString& dstUnqPath,
2010 sal_Int32 TypeToCopy,
2011 sal_Bool testExistBeforeCopy )
2012 throw()
2014 osl::FileBase::RC err = osl::FileBase::E_None;
2016 if( TypeToCopy == -1 ) // Document
2018 err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy );
2020 else if( TypeToCopy == +1 ) // Folder
2022 osl::Directory aDir( srcUnqPath );
2023 aDir.open();
2025 err = osl::Directory::create( dstUnqPath );
2026 osl::FileBase::RC next = err;
2027 if( err == osl::FileBase::E_None )
2029 sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type;
2031 osl::DirectoryItem aDirItem;
2033 while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None )
2035 sal_Bool IsDoc = false;
2036 osl::FileStatus aFileStatus( n_Mask );
2037 aDirItem.getFileStatus( aFileStatus );
2038 if( aFileStatus.isValid( FileStatusMask_Type ) )
2039 IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
2041 // Getting the information for the next recursive copy
2042 sal_Int32 newTypeToCopy = IsDoc ? -1 : +1;
2044 rtl::OUString newSrcUnqPath;
2045 if( aFileStatus.isValid( FileStatusMask_FileURL ) )
2046 newSrcUnqPath = aFileStatus.getFileURL();
2048 rtl::OUString newDstUnqPath = dstUnqPath;
2049 rtl::OUString tit;
2050 if( aFileStatus.isValid( FileStatusMask_FileName ) )
2051 tit = aFileStatus.getFileName();
2052 if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 )
2053 newDstUnqPath += rtl::OUString::createFromAscii( "/" );
2054 newDstUnqPath += tit;
2056 if ( newSrcUnqPath != dstUnqPath )
2057 err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false );
2060 if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
2061 err = next;
2063 aDir.close();
2066 return err;
2071 // Helper function for mkfil,mkdir and write
2072 // Creates whole path
2073 // returns success of the operation
2076 sal_Bool SAL_CALL shell::ensuredir( sal_Int32 CommandId,
2077 const rtl::OUString& rUnqPath,
2078 sal_Int32 errorCode )
2079 throw()
2081 rtl::OUString aPath;
2083 if ( rUnqPath.getLength() < 1 )
2084 return sal_False;
2086 if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) )
2087 aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
2088 else
2089 aPath = rUnqPath;
2092 // HACK: create directory on a mount point with nobrowse option
2093 // returns ENOSYS in any case !!
2094 osl::Directory aDirectory( aPath );
2095 osl::FileBase::RC nError = aDirectory.open();
2096 aDirectory.close();
2098 if( nError == osl::File::E_None )
2099 return sal_True;
2101 nError = osl::Directory::create( aPath );
2103 if( nError == osl::File::E_None )
2104 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2106 sal_Bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2108 if( ! bSuccess )
2110 rtl::OUString aParentDir = getParentName( aPath );
2112 if ( aParentDir != aPath )
2113 { // Create first the parent directory
2114 bSuccess = ensuredir( CommandId,
2115 getParentName( aPath ),
2116 errorCode );
2118 // After parent directory structure exists try it one's more
2120 if ( bSuccess )
2121 { // Parent directory exists, retry creation of directory
2122 nError = osl::Directory::create( aPath );
2124 if( nError == osl::File::E_None )
2125 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2127 bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2132 if( ! bSuccess )
2133 installError( CommandId,
2134 errorCode,
2135 nError );
2137 return bSuccess;
2144 // Given a sequence of properties seq, this method determines the mask
2145 // used to instantiate a osl::FileStatus, so that a call to
2146 // osl::DirectoryItem::getFileStatus fills the required fields.
2150 void SAL_CALL
2151 shell::getMaskFromProperties(
2152 sal_Int32& n_Mask,
2153 const uno::Sequence< beans::Property >& seq )
2155 n_Mask = 0;
2156 for(sal_Int32 j = 0; j < seq.getLength(); ++j) {
2157 if(seq[j].Name == Title)
2158 n_Mask |= FileStatusMask_FileName;
2159 else if(seq[j].Name == CasePreservingURL)
2160 n_Mask |= FileStatusMask_FileURL;
2161 else if(seq[j].Name == IsDocument ||
2162 seq[j].Name == IsFolder ||
2163 seq[j].Name == IsVolume ||
2164 seq[j].Name == IsRemoveable ||
2165 seq[j].Name == IsRemote ||
2166 seq[j].Name == IsCompactDisc ||
2167 seq[j].Name == IsFloppy ||
2168 seq[j].Name == ContentType)
2169 n_Mask |= (FileStatusMask_Type | FileStatusMask_LinkTargetURL);
2170 else if(seq[j].Name == Size)
2171 n_Mask |= (FileStatusMask_FileSize |
2172 FileStatusMask_Type |
2173 FileStatusMask_LinkTargetURL);
2174 else if(seq[j].Name == IsHidden ||
2175 seq[j].Name == IsReadOnly)
2176 n_Mask |= FileStatusMask_Attributes;
2177 else if(seq[j].Name == DateModified)
2178 n_Mask |= FileStatusMask_ModifyTime;
2179 // n_Mask = FileStatusMask_FileURL;
2180 // n_Mask |= FileStatusMask_LinkTargetURL;
2181 // n_Mask |= FileStatusMask_FileName;
2182 // n_Mask |= FileStatusMask_Type;
2183 // n_Mask |= FileStatusMask_ModifyTime;
2184 // n_Mask |= FileStatusMask_FileSize;
2185 // n_Mask |= FileStatusMask_Attributes;
2191 /*********************************************************************************/
2192 /* */
2193 /* load-Implementation */
2194 /* */
2195 /*********************************************************************************/
2197 // Load the properties from configuration, if create == true create them.
2198 // The Properties are stored under the url belonging to it->first.
2201 void SAL_CALL
2202 shell::load( const ContentMap::iterator& it, sal_Bool create )
2204 if( ! it->second.properties )
2205 it->second.properties = new PropertySet;
2207 if( ( ! it->second.xS.is() ||
2208 ! it->second.xC.is() ||
2209 ! it->second.xA.is() )
2210 && m_xFileRegistry.is() )
2213 uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create );
2214 if( xS.is() )
2216 uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY );
2217 uno::Reference< beans::XPropertyAccess > xA( xS,uno::UNO_QUERY );
2219 it->second.xS = xS;
2220 it->second.xC = xC;
2221 it->second.xA = xA;
2223 // Now put in all values in the storage in the local hash;
2225 PropertySet& properties = *(it->second.properties);
2226 uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties();
2228 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2230 MyProperty readProp( false,
2231 seq[i].Name,
2232 seq[i].Handle,
2233 seq[i].Type,
2234 xS->getPropertyValue( seq[i].Name ),
2235 beans::PropertyState_DIRECT_VALUE,
2236 seq[i].Attributes );
2237 if( properties.find( readProp ) == properties.end() )
2238 properties.insert( readProp );
2241 else if( create )
2243 // Catastrophic error
2251 /*********************************************************************************/
2252 /* */
2253 /* commit-Implementation */
2254 /* */
2255 /*********************************************************************************/
2256 // Commit inserts the determined properties in the filestatus object into
2257 // the internal map, so that is possible to determine on a subsequent
2258 // setting of file properties which properties have changed without filestat
2261 void SAL_CALL
2262 shell::commit( const shell::ContentMap::iterator& it,
2263 const osl::FileStatus& aFileStatus )
2265 uno::Any aAny;
2266 uno::Any emptyAny;
2267 shell::PropertySet::iterator it1;
2269 if( it->second.properties == 0 )
2271 rtl::OUString aPath = it->first;
2272 insertDefaultProperties( aPath );
2275 PropertySet& properties = *( it->second.properties );
2277 it1 = properties.find( MyProperty( Title ) );
2278 if( it1 != properties.end() )
2280 if( aFileStatus.isValid( FileStatusMask_FileName ) )
2282 aAny <<= aFileStatus.getFileName();
2283 it1->setValue( aAny );
2287 it1 = properties.find( MyProperty( CasePreservingURL ) );
2288 if( it1 != properties.end() )
2290 if( aFileStatus.isValid( FileStatusMask_FileURL ) )
2292 aAny <<= aFileStatus.getFileURL();
2293 it1->setValue( aAny );
2298 sal_Bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc;
2300 sal_Int64 dirSize = 0;
2302 if( aFileStatus.isValid( FileStatusMask_FileSize ) )
2303 dirSize = aFileStatus.getFileSize();
2305 if( aFileStatus.isValid( FileStatusMask_Type ) )
2307 if( osl::FileStatus::Link == aFileStatus.getFileType() &&
2308 aFileStatus.isValid( FileStatusMask_LinkTargetURL ) )
2310 osl::DirectoryItem aDirItem;
2311 osl::FileStatus aFileStatus2( FileStatusMask_Type );
2312 if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) &&
2313 osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) &&
2314 aFileStatus2.isValid( FileStatusMask_Type ) )
2316 isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType();
2317 isDirectory =
2318 osl::FileStatus::Volume == aFileStatus2.getFileType() ||
2319 osl::FileStatus::Directory == aFileStatus2.getFileType();
2320 isFile =
2321 osl::FileStatus::Regular == aFileStatus2.getFileType();
2323 if( aFileStatus2.isValid( FileStatusMask_FileSize ) )
2324 dirSize = aFileStatus2.getFileSize();
2326 else
2328 // extremly ugly, but otherwise default construction
2329 // of aDirItem and aFileStatus2
2330 // before the preciding if
2331 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2332 isDirectory =
2333 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2334 osl::FileStatus::Directory == aFileStatus.getFileType();
2335 isFile =
2336 osl::FileStatus::Regular == aFileStatus.getFileType();
2339 else
2341 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2342 isDirectory =
2343 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2344 osl::FileStatus::Directory == aFileStatus.getFileType();
2345 isFile =
2346 osl::FileStatus::Regular == aFileStatus.getFileType();
2349 aAny <<= isVolume;
2350 it1 = properties.find( MyProperty( IsVolume ) );
2351 if( it1 != properties.end() ) it1->setValue( aAny );
2353 aAny <<= isDirectory;
2354 it1 = properties.find( MyProperty( IsFolder ) );
2355 if( it1 != properties.end() ) it1->setValue( aAny );
2357 aAny <<= isFile;
2358 it1 = properties.find( MyProperty( IsDocument ) );
2359 if( it1 != properties.end() ) it1->setValue( aAny );
2361 osl::VolumeInfo aVolumeInfo( VolumeInfoMask_Attributes );
2362 if( isVolume &&
2363 osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) &&
2364 aVolumeInfo.isValid( VolumeInfoMask_Attributes ) )
2366 // Retrieve the flags;
2367 isRemote = aVolumeInfo.getRemoteFlag();
2368 isRemoveable = aVolumeInfo.getRemoveableFlag();
2369 isCompactDisc = aVolumeInfo.getCompactDiscFlag();
2370 isFloppy = aVolumeInfo.getFloppyDiskFlag();
2372 aAny <<= isRemote;
2373 it1 = properties.find( MyProperty( IsRemote ) );
2374 if( it1 != properties.end() ) it1->setValue( aAny );
2376 aAny <<= isRemoveable;
2377 it1 = properties.find( MyProperty( IsRemoveable ) );
2378 if( it1 != properties.end() ) it1->setValue( aAny );
2380 aAny <<= isCompactDisc;
2381 it1 = properties.find( MyProperty( IsCompactDisc ) );
2382 if( it1 != properties.end() ) it1->setValue( aAny );
2384 aAny <<= isFloppy;
2385 it1 = properties.find( MyProperty( IsFloppy ) );
2386 if( it1 != properties.end() ) it1->setValue( aAny );
2388 else
2390 sal_Bool dummy = false;
2391 aAny <<= dummy;
2392 it1 = properties.find( MyProperty( IsRemote ) );
2393 if( it1 != properties.end() ) it1->setValue( aAny );
2394 it1 = properties.find( MyProperty( IsRemoveable ) );
2395 if( it1 != properties.end() ) it1->setValue( aAny );
2396 it1 = properties.find( MyProperty( IsCompactDisc ) );
2397 if( it1 != properties.end() ) it1->setValue( aAny );
2398 it1 = properties.find( MyProperty( IsFloppy ) );
2399 if( it1 != properties.end() ) it1->setValue( aAny );
2403 it1 = properties.find( MyProperty( Size ) );
2404 if( it1 != properties.end() )
2406 aAny <<= dirSize;
2407 it1->setValue( aAny );
2411 it1 = properties.find( MyProperty( IsReadOnly ) );
2412 if( it1 != properties.end() )
2414 if( aFileStatus.isValid( FileStatusMask_Attributes ) )
2416 sal_uInt64 Attr = aFileStatus.getAttributes();
2417 sal_Bool readonly = ( Attr & Attribute_ReadOnly ) != 0;
2418 aAny <<= readonly;
2419 it1->setValue( aAny );
2423 it1 = properties.find( MyProperty( IsHidden ) );
2424 if( it1 != properties.end() )
2426 if( aFileStatus.isValid( FileStatusMask_Attributes ) )
2428 sal_uInt64 Attr = aFileStatus.getAttributes();
2429 sal_Bool ishidden = ( Attr & Attribute_Hidden ) != 0;
2430 aAny <<= ishidden;
2431 it1->setValue( aAny );
2435 it1 = properties.find( MyProperty( DateModified ) );
2437 if( it1 != properties.end() )
2439 if( aFileStatus.isValid( FileStatusMask_ModifyTime ) )
2441 TimeValue temp = aFileStatus.getModifyTime();
2443 // Convert system time to local time (for EA)
2444 TimeValue myLocalTime;
2445 osl_getLocalTimeFromSystemTime( &temp, &myLocalTime );
2447 oslDateTime myDateTime;
2448 osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime );
2449 util::DateTime aDateTime;
2451 aDateTime.HundredthSeconds = (unsigned short)(myDateTime.NanoSeconds / 10000000);
2452 aDateTime.Seconds = myDateTime.Seconds;
2453 aDateTime.Minutes = myDateTime.Minutes;
2454 aDateTime.Hours = myDateTime.Hours;
2455 aDateTime.Day = myDateTime.Day;
2456 aDateTime.Month = myDateTime.Month;
2457 aDateTime.Year = myDateTime.Year;
2458 aAny <<= aDateTime;
2459 it1->setValue( aAny );
2466 // Special optimized method for getting the properties of a
2467 // directoryitem, which is returned by osl::DirectoryItem::getNextItem()
2470 uno::Reference< sdbc::XRow > SAL_CALL
2471 shell::getv(
2472 Notifier* pNotifier,
2473 const uno::Sequence< beans::Property >& properties,
2474 osl::DirectoryItem& aDirItem,
2475 rtl::OUString& aUnqPath,
2476 sal_Bool& aIsRegular )
2478 uno::Sequence< uno::Any > seq( properties.getLength() );
2480 sal_Int32 n_Mask;
2481 getMaskFromProperties( n_Mask,properties );
2483 // Always retrieve the type and the target URL because item might be a link
2484 osl::FileStatus aFileStatus( n_Mask |
2485 FileStatusMask_FileURL |
2486 FileStatusMask_Type |
2487 FileStatusMask_LinkTargetURL );
2488 aDirItem.getFileStatus( aFileStatus );
2489 aUnqPath = aFileStatus.getFileURL();
2491 // If the directory item type is a link retrieve the type of the target
2493 if ( aFileStatus.getFileType() == osl::FileStatus::Link )
2495 // Assume failure
2496 aIsRegular = false;
2497 osl::FileBase::RC result = osl::FileBase::E_INVAL;
2498 osl::DirectoryItem aTargetItem;
2499 osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem );
2500 if ( aTargetItem.is() )
2502 osl::FileStatus aTargetStatus( FileStatusMask_Type );
2504 if ( osl::FileBase::E_None ==
2505 ( result = aTargetItem.getFileStatus( aTargetStatus ) ) )
2506 aIsRegular =
2507 aTargetStatus.getFileType() == osl::FileStatus::Regular;
2510 else
2511 aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular;
2513 registerNotifier( aUnqPath,pNotifier );
2514 insertDefaultProperties( aUnqPath );
2516 osl::MutexGuard aGuard( m_aMutex );
2518 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
2519 commit( it,aFileStatus );
2521 shell::PropertySet::iterator it1;
2522 PropertySet& propset = *(it->second.properties);
2524 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2526 MyProperty readProp( properties[i].Name );
2527 it1 = propset.find( readProp );
2528 if( it1 == propset.end() )
2529 seq[i] = uno::Any();
2530 else
2531 seq[i] = it1->getValue();
2534 deregisterNotifier( aUnqPath,pNotifier );
2536 XRow_impl* p = new XRow_impl( this,seq );
2537 return uno::Reference< sdbc::XRow >( p );
2545 // EventListener
2548 std::list< ContentEventNotifier* >* SAL_CALL
2549 shell::getContentEventListeners( const rtl::OUString& aName )
2551 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2552 std::list< ContentEventNotifier* >& listeners = *p;
2554 osl::MutexGuard aGuard( m_aMutex );
2555 shell::ContentMap::iterator it = m_aContent.find( aName );
2556 if( it != m_aContent.end() && it->second.notifier )
2558 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2559 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2560 while( it1 != listOfNotifiers.end() )
2562 Notifier* pointer = *it1;
2563 ContentEventNotifier* notifier = pointer->cCEL();
2564 if( notifier )
2565 listeners.push_back( notifier );
2566 ++it1;
2570 return p;
2575 std::list< ContentEventNotifier* >* SAL_CALL
2576 shell::getContentDeletedEventListeners( const rtl::OUString& aName )
2578 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2579 std::list< ContentEventNotifier* >& listeners = *p;
2581 osl::MutexGuard aGuard( m_aMutex );
2582 shell::ContentMap::iterator it = m_aContent.find( aName );
2583 if( it != m_aContent.end() && it->second.notifier )
2585 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2586 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2587 while( it1 != listOfNotifiers.end() )
2589 Notifier* pointer = *it1;
2590 ContentEventNotifier* notifier = pointer->cDEL();
2591 if( notifier )
2592 listeners.push_back( notifier );
2593 ++it1;
2597 return p;
2601 void SAL_CALL
2602 shell::notifyInsert( std::list< ContentEventNotifier* >* listeners,const rtl::OUString& aChildName )
2604 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2605 while( it != listeners->end() )
2607 (*it)->notifyChildInserted( aChildName );
2608 delete (*it);
2609 ++it;
2611 delete listeners;
2615 void SAL_CALL
2616 shell::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners )
2618 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2619 while( it != listeners->end() )
2621 (*it)->notifyDeleted();
2622 delete (*it);
2623 ++it;
2625 delete listeners;
2629 void SAL_CALL
2630 shell::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners,
2631 const rtl::OUString& aChildName )
2633 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2634 while( it != listeners->end() )
2636 (*it)->notifyRemoved( aChildName );
2637 delete (*it);
2638 ++it;
2640 delete listeners;
2646 std::list< PropertySetInfoChangeNotifier* >* SAL_CALL
2647 shell::getPropertySetListeners( const rtl::OUString& aName )
2649 std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >;
2650 std::list< PropertySetInfoChangeNotifier* >& listeners = *p;
2652 osl::MutexGuard aGuard( m_aMutex );
2653 shell::ContentMap::iterator it = m_aContent.find( aName );
2654 if( it != m_aContent.end() && it->second.notifier )
2656 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2657 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2658 while( it1 != listOfNotifiers.end() )
2660 Notifier* pointer = *it1;
2661 PropertySetInfoChangeNotifier* notifier = pointer->cPSL();
2662 if( notifier )
2663 listeners.push_back( notifier );
2664 ++it1;
2668 return p;
2672 void SAL_CALL
2673 shell::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners,
2674 const rtl::OUString& aPropertyName )
2676 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2677 while( it != listeners->end() )
2679 (*it)->notifyPropertyAdded( aPropertyName );
2680 delete (*it);
2681 ++it;
2683 delete listeners;
2687 void SAL_CALL
2688 shell::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners,
2689 const rtl::OUString& aPropertyName )
2691 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2692 while( it != listeners->end() )
2694 (*it)->notifyPropertyRemoved( aPropertyName );
2695 delete (*it);
2696 ++it;
2698 delete listeners;
2703 std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL
2704 shell::getContentExchangedEventListeners( const rtl::OUString aOldPrefix,
2705 const rtl::OUString aNewPrefix,
2706 sal_Bool withChilds )
2709 std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap =
2710 new std::vector< std::list< ContentEventNotifier* >* >;
2711 std::vector< std::list< ContentEventNotifier* >* >& aVector = *aVectorOnHeap;
2713 sal_Int32 count;
2714 rtl::OUString aOldName;
2715 rtl::OUString aNewName;
2716 std::vector< rtl::OUString > oldChildList;
2719 osl::MutexGuard aGuard( m_aMutex );
2721 if( ! withChilds )
2723 aOldName = aOldPrefix;
2724 aNewName = aNewPrefix;
2725 count = 1;
2727 else
2729 ContentMap::iterator itnames = m_aContent.begin();
2730 while( itnames != m_aContent.end() )
2732 if( isChild( aOldPrefix,itnames->first ) )
2734 oldChildList.push_back( itnames->first );
2736 ++itnames;
2738 count = oldChildList.size();
2742 for( sal_Int32 j = 0; j < count; ++j )
2744 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2745 std::list< ContentEventNotifier* >& listeners = *p;
2747 if( withChilds )
2749 aOldName = oldChildList[j];
2750 aNewName = newName( aNewPrefix,aOldPrefix,aOldName );
2753 shell::ContentMap::iterator itold = m_aContent.find( aOldName );
2754 if( itold != m_aContent.end() )
2756 shell::ContentMap::iterator itnew = m_aContent.insert(
2757 ContentMap::value_type( aNewName,UnqPathData() ) ).first;
2759 // copy Ownership also
2760 delete itnew->second.properties;
2761 itnew->second.properties = itold->second.properties;
2762 itold->second.properties = 0;
2764 // copy existing list
2765 std::list< Notifier* >* copyList = itnew->second.notifier;
2766 itnew->second.notifier = itold->second.notifier;
2767 itold->second.notifier = 0;
2769 m_aContent.erase( itold );
2771 if( itnew != m_aContent.end() && itnew->second.notifier )
2773 std::list<Notifier*>& listOfNotifiers = *( itnew->second.notifier );
2774 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2775 while( it1 != listOfNotifiers.end() )
2777 Notifier* pointer = *it1;
2778 ContentEventNotifier* notifier = pointer->cEXC( aNewName );
2779 if( notifier )
2780 listeners.push_back( notifier );
2781 ++it1;
2785 // Merge with preexisting notifiers
2786 // However, these may be in status BaseContent::Deleted
2787 if( copyList != 0 )
2789 std::list< Notifier* >::iterator copyIt = copyList->begin();
2790 while( copyIt != copyList->end() )
2792 itnew->second.notifier->push_back( *copyIt );
2793 ++copyIt;
2796 delete copyList;
2798 aVector.push_back( p );
2802 return aVectorOnHeap;
2807 void SAL_CALL
2808 shell::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec )
2810 std::list< ContentEventNotifier* >* listeners;
2811 for( sal_uInt32 i = 0; i < listeners_vec->size(); ++i )
2813 listeners = (*listeners_vec)[i];
2814 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2815 while( it != listeners->end() )
2817 (*it)->notifyExchanged();
2818 delete (*it);
2819 ++it;
2821 delete listeners;
2823 delete listeners_vec;
2828 std::list< PropertyChangeNotifier* >* SAL_CALL
2829 shell::getPropertyChangeNotifier( const rtl::OUString& aName )
2831 std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >;
2832 std::list< PropertyChangeNotifier* >& listeners = *p;
2834 osl::MutexGuard aGuard( m_aMutex );
2835 shell::ContentMap::iterator it = m_aContent.find( aName );
2836 if( it != m_aContent.end() && it->second.notifier )
2838 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2839 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2840 while( it1 != listOfNotifiers.end() )
2842 Notifier* pointer = *it1;
2843 PropertyChangeNotifier* notifier = pointer->cPCL();
2844 if( notifier )
2845 listeners.push_back( notifier );
2846 ++it1;
2850 return p;
2854 void SAL_CALL shell::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners,
2855 const uno::Sequence< beans::PropertyChangeEvent >& seqChanged )
2857 std::list< PropertyChangeNotifier* >::iterator it = listeners->begin();
2858 while( it != listeners->end() )
2860 (*it)->notifyPropertyChanged( seqChanged );
2861 delete (*it);
2862 ++it;
2864 delete listeners;
2870 /********************************************************************************/
2871 /* remove persistent propertyset */
2872 /********************************************************************************/
2874 void SAL_CALL
2875 shell::erasePersistentSet( const rtl::OUString& aUnqPath,
2876 sal_Bool withChilds )
2878 if( ! m_xFileRegistry.is() )
2880 OSL_ASSERT( m_xFileRegistry.is() );
2881 return;
2884 uno::Sequence< rtl::OUString > seqNames;
2886 if( withChilds )
2888 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2889 seqNames = xName->getElementNames();
2892 sal_Int32 count = withChilds ? seqNames.getLength() : 1;
2894 rtl::OUString
2895 old_Name = aUnqPath;
2897 for( sal_Int32 j = 0; j < count; ++j )
2899 if( withChilds && ! ( isChild( old_Name,seqNames[j] ) ) )
2900 continue;
2902 if( withChilds )
2904 old_Name = seqNames[j];
2908 // Release possible references
2909 osl::MutexGuard aGuard( m_aMutex );
2910 ContentMap::iterator it = m_aContent.find( old_Name );
2911 if( it != m_aContent.end() )
2913 it->second.xS = 0;
2914 it->second.xC = 0;
2915 it->second.xA = 0;
2917 delete it->second.properties;
2918 it->second.properties = 0;
2922 if( m_xFileRegistry.is() )
2923 m_xFileRegistry->removePropertySet( old_Name );
2930 /********************************************************************************/
2931 /* copy persistent propertyset */
2932 /* from srcUnqPath to dstUnqPath */
2933 /********************************************************************************/
2936 void SAL_CALL
2937 shell::copyPersistentSet( const rtl::OUString& srcUnqPath,
2938 const rtl::OUString& dstUnqPath,
2939 sal_Bool withChilds )
2941 if( ! m_xFileRegistry.is() )
2943 OSL_ASSERT( m_xFileRegistry.is() );
2944 return;
2947 uno::Sequence< rtl::OUString > seqNames;
2949 if( withChilds )
2951 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2952 seqNames = xName->getElementNames();
2955 sal_Int32 count = withChilds ? seqNames.getLength() : 1;
2957 rtl::OUString
2958 old_Name = srcUnqPath,
2959 new_Name = dstUnqPath;
2961 for( sal_Int32 j = 0; j < count; ++j )
2963 if( withChilds && ! ( isChild( srcUnqPath,seqNames[j] ) ) )
2964 continue;
2966 if( withChilds )
2968 old_Name = seqNames[j];
2969 new_Name = newName( dstUnqPath,srcUnqPath,old_Name );
2972 uno::Reference< XPersistentPropertySet > x_src;
2974 if( m_xFileRegistry.is() )
2976 x_src = m_xFileRegistry->openPropertySet( old_Name,false );
2977 m_xFileRegistry->removePropertySet( new_Name );
2980 if( x_src.is() )
2982 uno::Sequence< beans::Property > seqProperty =
2983 x_src->getPropertySetInfo()->getProperties();
2985 if( seqProperty.getLength() )
2987 uno::Reference< XPersistentPropertySet >
2988 x_dstS = m_xFileRegistry->openPropertySet( new_Name,true );
2989 uno::Reference< beans::XPropertyContainer >
2990 x_dstC( x_dstS,uno::UNO_QUERY );
2992 for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i )
2994 x_dstC->addProperty( seqProperty[i].Name,
2995 seqProperty[i].Attributes,
2996 x_src->getPropertyValue( seqProperty[i].Name ) );
3000 } // end for( sal_Int...
3003 /*******************************************************************************/
3004 /* */
3005 /* some misceancellous static functions */
3006 /* */
3007 /*******************************************************************************/
3009 void SAL_CALL
3010 shell::getScheme( rtl::OUString& Scheme )
3012 Scheme = rtl::OUString::createFromAscii( "file" );
3015 rtl::OUString SAL_CALL
3016 shell::getImplementationName_static( void )
3018 return rtl::OUString::createFromAscii( "com.sun.star.comp.ucb.FileProvider" );
3022 uno::Sequence< rtl::OUString > SAL_CALL
3023 shell::getSupportedServiceNames_static( void )
3025 rtl::OUString Supported = rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ) ;
3026 com::sun::star::uno::Sequence< rtl::OUString > Seq( &Supported,1 );
3027 return Seq;