Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / ucb / source / ucp / file / shell.cxx
blob348810e3785783ac6520ade85b572364616179ea
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 <stack>
21 #include "osl/diagnose.h"
22 #include <rtl/uri.hxx>
23 #include <rtl/ustrbuf.hxx>
24 #include <osl/time.h>
25 #include <osl/file.hxx>
26 #include <com/sun/star/lang/IllegalAccessException.hpp>
27 #include <com/sun/star/beans/IllegalTypeException.hpp>
28 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
29 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
30 #include <com/sun/star/ucb/NameClash.hpp>
31 #include <com/sun/star/ucb/Store.hpp>
32 #include <com/sun/star/ucb/XContentIdentifier.hpp>
33 #include <com/sun/star/lang/XComponent.hpp>
34 #include <com/sun/star/ucb/XContentAccess.hpp>
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #include <com/sun/star/io/XSeekable.hpp>
37 #include <com/sun/star/io/XTruncate.hpp>
38 #include <com/sun/star/ucb/OpenCommandArgument.hpp>
39 #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp>
40 #include <com/sun/star/ucb/TransferInfo.hpp>
41 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
42 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
43 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
44 #include <rtl/string.hxx>
45 #include "filerror.hxx"
46 #include "filglob.hxx"
47 #include "filcmd.hxx"
48 #include "filinpstr.hxx"
49 #include "filstr.hxx"
50 #include "filrset.hxx"
51 #include "filrow.hxx"
52 #include "filprp.hxx"
53 #include "filid.hxx"
54 #include "shell.hxx"
55 #include "prov.hxx"
56 #include "bc.hxx"
59 using namespace fileaccess;
60 using namespace com::sun::star;
61 using namespace com::sun::star::ucb;
64 shell::UnqPathData::UnqPathData()
65 : properties( 0 ),
66 notifier( 0 ),
67 xS( 0 ),
68 xC( 0 ),
69 xA( 0 )
71 // empty
75 shell::UnqPathData::UnqPathData( const UnqPathData& a )
76 : properties( a.properties ),
77 notifier( a.notifier ),
78 xS( a.xS ),
79 xC( a.xC ),
80 xA( a.xA )
85 shell::UnqPathData& shell::UnqPathData::operator=( UnqPathData& a )
87 properties = a.properties;
88 notifier = a.notifier;
89 xS = a.xS;
90 xC = a.xC;
91 xA = a.xA;
92 a.properties = 0;
93 a.notifier = 0;
94 a.xS = 0;
95 a.xC = 0;
96 a.xA = 0;
97 return *this;
100 shell::UnqPathData::~UnqPathData()
102 if( properties )
103 delete properties;
104 if( notifier )
105 delete notifier;
110 ////////////////////////////////////////////////////////////////////////////////////////
116 shell::MyProperty::MyProperty( const rtl::OUString& __PropertyName )
117 : PropertyName( __PropertyName )
119 // empty
123 shell::MyProperty::MyProperty( const sal_Bool& __isNative,
124 const rtl::OUString& __PropertyName,
125 const sal_Int32& __Handle,
126 const com::sun::star::uno::Type& __Typ,
127 const com::sun::star::uno::Any& __Value,
128 const com::sun::star::beans::PropertyState& __State,
129 const sal_Int16& __Attributes )
130 : PropertyName( __PropertyName ),
131 Handle( __Handle ),
132 isNative( __isNative ),
133 Typ( __Typ ),
134 Value( __Value ),
135 State( __State ),
136 Attributes( __Attributes )
138 // empty
141 shell::MyProperty::~MyProperty()
143 // empty for now
147 #include "filinl.hxx"
150 shell::shell( const uno::Reference< uno::XComponentContext >& rxContext,
151 FileProvider* pProvider, sal_Bool bWithConfig )
152 : TaskManager(),
153 m_bWithConfig( bWithConfig ),
154 m_pProvider( pProvider ),
155 m_xContext( rxContext ),
156 Title( "Title" ),
157 CasePreservingURL( "CasePreservingURL" ),
158 IsDocument( "IsDocument" ),
159 IsFolder( "IsFolder" ),
160 DateModified( "DateModified" ),
161 Size( "Size" ),
162 IsVolume( "IsVolume" ),
163 IsRemoveable( "IsRemoveable" ),
164 IsRemote( "IsRemote" ),
165 IsCompactDisc( "IsCompactDisc" ),
166 IsFloppy( "IsFloppy" ),
167 IsHidden( "IsHidden" ),
168 ContentType( "ContentType" ),
169 IsReadOnly( "IsReadOnly" ),
170 CreatableContentsInfo( "CreatableContentsInfo" ),
171 FolderContentType( "application/vnd.sun.staroffice.fsys-folder" ),
172 FileContentType( "application/vnd.sun.staroffice.fsys-file" ),
173 m_sCommandInfo( 9 )
175 // Title
176 m_aDefaultProperties.insert( MyProperty( true,
177 Title,
178 -1 ,
179 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
180 uno::Any(),
181 beans::PropertyState_DEFAULT_VALUE,
182 beans::PropertyAttribute::MAYBEVOID
183 | beans::PropertyAttribute::BOUND ) );
185 // CasePreservingURL
186 m_aDefaultProperties.insert(
187 MyProperty( true,
188 CasePreservingURL,
189 -1 ,
190 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
191 uno::Any(),
192 beans::PropertyState_DEFAULT_VALUE,
193 beans::PropertyAttribute::MAYBEVOID
194 | beans::PropertyAttribute::BOUND
195 | beans::PropertyAttribute::READONLY ) );
198 // IsFolder
199 m_aDefaultProperties.insert( MyProperty( true,
200 IsFolder,
201 -1 ,
202 getCppuType( static_cast< sal_Bool* >( 0 ) ),
203 uno::Any(),
204 beans::PropertyState_DEFAULT_VALUE,
205 beans::PropertyAttribute::MAYBEVOID
206 | beans::PropertyAttribute::BOUND
207 | beans::PropertyAttribute::READONLY ) );
210 // IsDocument
211 m_aDefaultProperties.insert( MyProperty( true,
212 IsDocument,
213 -1 ,
214 getCppuType( static_cast< sal_Bool* >( 0 ) ),
215 uno::Any(),
216 beans::PropertyState_DEFAULT_VALUE,
217 beans::PropertyAttribute::MAYBEVOID
218 | beans::PropertyAttribute::BOUND
219 | beans::PropertyAttribute::READONLY ) );
221 // Removable
222 m_aDefaultProperties.insert( MyProperty( true,
223 IsVolume,
224 -1 ,
225 getCppuType( static_cast< sal_Bool* >( 0 ) ),
226 uno::Any(),
227 beans::PropertyState_DEFAULT_VALUE,
228 beans::PropertyAttribute::MAYBEVOID
229 | beans::PropertyAttribute::BOUND
230 | beans::PropertyAttribute::READONLY ) );
233 // Removable
234 m_aDefaultProperties.insert( MyProperty( true,
235 IsRemoveable,
236 -1 ,
237 getCppuType( static_cast< sal_Bool* >( 0 ) ),
238 uno::Any(),
239 beans::PropertyState_DEFAULT_VALUE,
240 beans::PropertyAttribute::MAYBEVOID
241 | beans::PropertyAttribute::BOUND
242 | beans::PropertyAttribute::READONLY ) );
244 // Remote
245 m_aDefaultProperties.insert( MyProperty( true,
246 IsRemote,
247 -1 ,
248 getCppuType( static_cast< sal_Bool* >( 0 ) ),
249 uno::Any(),
250 beans::PropertyState_DEFAULT_VALUE,
251 beans::PropertyAttribute::MAYBEVOID
252 | beans::PropertyAttribute::BOUND
253 | beans::PropertyAttribute::READONLY ) );
255 // CompactDisc
256 m_aDefaultProperties.insert( MyProperty( true,
257 IsCompactDisc,
258 -1 ,
259 getCppuType( static_cast< sal_Bool* >( 0 ) ),
260 uno::Any(),
261 beans::PropertyState_DEFAULT_VALUE,
262 beans::PropertyAttribute::MAYBEVOID
263 | beans::PropertyAttribute::BOUND
264 | beans::PropertyAttribute::READONLY ) );
266 // Floppy
267 m_aDefaultProperties.insert( MyProperty( true,
268 IsFloppy,
269 -1 ,
270 getCppuType( static_cast< sal_Bool* >( 0 ) ),
271 uno::Any(),
272 beans::PropertyState_DEFAULT_VALUE,
273 beans::PropertyAttribute::MAYBEVOID
274 | beans::PropertyAttribute::BOUND
275 | beans::PropertyAttribute::READONLY ) );
277 // Hidden
278 m_aDefaultProperties.insert(
279 MyProperty(
280 true,
281 IsHidden,
282 -1 ,
283 getCppuType( static_cast< sal_Bool* >( 0 ) ),
284 uno::Any(),
285 beans::PropertyState_DEFAULT_VALUE,
286 beans::PropertyAttribute::MAYBEVOID
287 | beans::PropertyAttribute::BOUND
288 #if defined( WNT )
290 #else
291 | beans::PropertyAttribute::READONLY)); // under unix/linux only readable
292 #endif
295 // ContentType
296 uno::Any aAny;
297 aAny <<= rtl::OUString();
298 m_aDefaultProperties.insert( MyProperty( false,
299 ContentType,
300 -1 ,
301 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
302 aAny,
303 beans::PropertyState_DEFAULT_VALUE,
304 beans::PropertyAttribute::MAYBEVOID
305 | beans::PropertyAttribute::BOUND
306 | beans::PropertyAttribute::READONLY ) );
309 // DateModified
310 m_aDefaultProperties.insert( MyProperty( true,
311 DateModified,
312 -1 ,
313 getCppuType( static_cast< util::DateTime* >( 0 ) ),
314 uno::Any(),
315 beans::PropertyState_DEFAULT_VALUE,
316 beans::PropertyAttribute::MAYBEVOID
317 | beans::PropertyAttribute::BOUND ) );
319 // Size
320 m_aDefaultProperties.insert( MyProperty( true,
321 Size,
323 getCppuType( static_cast< sal_Int64* >( 0 ) ),
324 uno::Any(),
325 beans::PropertyState_DEFAULT_VALUE,
326 beans::PropertyAttribute::MAYBEVOID
327 | beans::PropertyAttribute::BOUND ) );
329 // IsReadOnly
330 m_aDefaultProperties.insert( MyProperty( true,
331 IsReadOnly,
332 -1 ,
333 getCppuType( static_cast< sal_Bool* >( 0 ) ),
334 uno::Any(),
335 beans::PropertyState_DEFAULT_VALUE,
336 beans::PropertyAttribute::MAYBEVOID
337 | beans::PropertyAttribute::BOUND ) );
340 // CreatableContentsInfo
341 m_aDefaultProperties.insert( MyProperty( true,
342 CreatableContentsInfo,
343 -1 ,
344 getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
345 uno::Any(),
346 beans::PropertyState_DEFAULT_VALUE,
347 beans::PropertyAttribute::MAYBEVOID
348 | beans::PropertyAttribute::BOUND
349 | beans::PropertyAttribute::READONLY ) );
351 // Commands
352 m_sCommandInfo[0].Name = rtl::OUString("getCommandInfo");
353 m_sCommandInfo[0].Handle = -1;
354 m_sCommandInfo[0].ArgType = getCppuVoidType();
356 m_sCommandInfo[1].Name = rtl::OUString("getPropertySetInfo");
357 m_sCommandInfo[1].Handle = -1;
358 m_sCommandInfo[1].ArgType = getCppuVoidType();
360 m_sCommandInfo[2].Name = rtl::OUString("getPropertyValues");
361 m_sCommandInfo[2].Handle = -1;
362 m_sCommandInfo[2].ArgType = getCppuType( static_cast< uno::Sequence< beans::Property >* >( 0 ) );
364 m_sCommandInfo[3].Name = rtl::OUString("setPropertyValues");
365 m_sCommandInfo[3].Handle = -1;
366 m_sCommandInfo[3].ArgType = getCppuType( static_cast< uno::Sequence< beans::PropertyValue >* >( 0 ) );
368 m_sCommandInfo[4].Name = rtl::OUString("open");
369 m_sCommandInfo[4].Handle = -1;
370 m_sCommandInfo[4].ArgType = getCppuType( static_cast< OpenCommandArgument* >( 0 ) );
372 m_sCommandInfo[5].Name = rtl::OUString("transfer");
373 m_sCommandInfo[5].Handle = -1;
374 m_sCommandInfo[5].ArgType = getCppuType( static_cast< TransferInfo* >( 0 ) );
376 m_sCommandInfo[6].Name = rtl::OUString("delete");
377 m_sCommandInfo[6].Handle = -1;
378 m_sCommandInfo[6].ArgType = getCppuType( static_cast< sal_Bool* >( 0 ) );
380 m_sCommandInfo[7].Name = rtl::OUString("insert");
381 m_sCommandInfo[7].Handle = -1;
382 m_sCommandInfo[7].ArgType = getCppuType( static_cast< InsertCommandArgument* > ( 0 ) );
384 m_sCommandInfo[7].Name = rtl::OUString("createNewContent");
385 m_sCommandInfo[7].Handle = -1;
386 m_sCommandInfo[7].ArgType = getCppuType( static_cast< ucb::ContentInfo * > ( 0 ) );
388 if(m_bWithConfig)
390 uno::Reference< XPropertySetRegistryFactory > xRegFac = ucb::Store::create( m_xContext );
391 // Open/create a registry
392 m_xFileRegistry = xRegFac->createPropertySetRegistry( rtl::OUString() );
397 shell::~shell()
402 /*********************************************************************************/
403 /* */
404 /* de/registerNotifier-Implementation */
405 /* */
406 /*********************************************************************************/
409 // This two methods register and deregister a change listener for the content belonging
410 // to URL aUnqPath
413 void SAL_CALL
414 shell::registerNotifier( const rtl::OUString& aUnqPath, Notifier* pNotifier )
416 osl::MutexGuard aGuard( m_aMutex );
418 ContentMap::iterator it =
419 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
421 if( ! it->second.notifier )
422 it->second.notifier = new NotifierList();
424 std::list< Notifier* >& nlist = *( it->second.notifier );
426 std::list<Notifier*>::iterator it1 = nlist.begin();
427 while( it1 != nlist.end() ) // Every "Notifier" only once
429 if( *it1 == pNotifier ) return;
430 ++it1;
432 nlist.push_back( pNotifier );
437 void SAL_CALL
438 shell::deregisterNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier )
440 osl::MutexGuard aGuard( m_aMutex );
442 ContentMap::iterator it = m_aContent.find( aUnqPath );
443 if( it == m_aContent.end() )
444 return;
446 it->second.notifier->remove( pNotifier );
448 if( ! it->second.notifier->size() )
449 m_aContent.erase( it );
454 /*********************************************************************************/
455 /* */
456 /* de/associate-Implementation */
457 /* */
458 /*********************************************************************************/
460 // Used to associate and deassociate a new property with
461 // the content belonging to URL UnqPath.
462 // The default value and the the attributes are input
465 void SAL_CALL
466 shell::associate( const rtl::OUString& aUnqPath,
467 const rtl::OUString& PropertyName,
468 const uno::Any& DefaultValue,
469 const sal_Int16 Attributes )
470 throw( beans::PropertyExistException,
471 beans::IllegalTypeException,
472 uno::RuntimeException )
474 MyProperty newProperty( false,
475 PropertyName,
477 DefaultValue.getValueType(),
478 DefaultValue,
479 beans::PropertyState_DEFAULT_VALUE,
480 Attributes );
482 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty );
483 if( it1 != m_aDefaultProperties.end() )
484 throw beans::PropertyExistException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
487 osl::MutexGuard aGuard( m_aMutex );
489 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
491 // Load the XPersistentPropertySetInfo and create it, if it does not exist
492 load( it,true );
494 PropertySet& properties = *(it->second.properties);
495 it1 = properties.find( newProperty );
496 if( it1 != properties.end() )
497 throw beans::PropertyExistException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
499 // Property does not exist
500 properties.insert( newProperty );
501 it->second.xC->addProperty( PropertyName,Attributes,DefaultValue );
503 notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName );
509 void SAL_CALL
510 shell::deassociate( const rtl::OUString& aUnqPath,
511 const rtl::OUString& PropertyName )
512 throw( beans::UnknownPropertyException,
513 beans::NotRemoveableException,
514 uno::RuntimeException )
516 MyProperty oldProperty( PropertyName );
518 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty );
519 if( it1 != m_aDefaultProperties.end() )
520 throw beans::NotRemoveableException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
522 osl::MutexGuard aGuard( m_aMutex );
524 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
526 load( it,false );
528 PropertySet& properties = *(it->second.properties);
530 it1 = properties.find( oldProperty );
531 if( it1 == properties.end() )
532 throw beans::UnknownPropertyException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
534 properties.erase( it1 );
536 if( it->second.xC.is() )
537 it->second.xC->removeProperty( PropertyName );
539 if( properties.size() == 9 )
541 MyProperty ContentTProperty( ContentType );
543 if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE )
545 it->second.xS = 0;
546 it->second.xC = 0;
547 it->second.xA = 0;
548 if(m_xFileRegistry.is())
549 m_xFileRegistry->removePropertySet( aUnqPath );
552 notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName );
558 /*********************************************************************************/
559 /* */
560 /* page-Implementation */
561 /* */
562 /*********************************************************************************/
564 // Given an xOutputStream, this method writes the content of the file belonging to
565 // URL aUnqPath into the XOutputStream
569 void SAL_CALL shell::page( sal_Int32 CommandId,
570 const rtl::OUString& aUnqPath,
571 const uno::Reference< io::XOutputStream >& xOutputStream )
572 throw()
574 uno::Reference< XContentProvider > xProvider( m_pProvider );
575 osl::File aFile( aUnqPath );
576 osl::FileBase::RC err = aFile.open( osl_File_OpenFlag_Read );
578 if( err != osl::FileBase::E_None )
580 aFile.close();
581 installError( CommandId,
582 TASKHANDLING_OPEN_FILE_FOR_PAGING,
583 err );
584 return;
587 const sal_uInt64 bfz = 4*1024;
588 sal_Int8 BFF[bfz];
589 sal_uInt64 nrc; // Retrieved number of Bytes;
593 err = aFile.read( (void*) BFF,bfz,nrc );
594 if( err == osl::FileBase::E_None )
596 uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc );
599 xOutputStream->writeBytes( seq );
601 catch (const io::NotConnectedException&)
603 installError( CommandId,
604 TASKHANDLING_NOTCONNECTED_FOR_PAGING );
605 break;
607 catch (const io::BufferSizeExceededException&)
609 installError( CommandId,
610 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING );
611 break;
613 catch (const io::IOException&)
615 installError( CommandId,
616 TASKHANDLING_IOEXCEPTION_FOR_PAGING );
617 break;
620 else
622 installError( CommandId,
623 TASKHANDLING_READING_FILE_FOR_PAGING,
624 err );
625 break;
627 } while( nrc == bfz );
630 aFile.close();
635 xOutputStream->closeOutput();
637 catch (const io::NotConnectedException&)
640 catch (const io::BufferSizeExceededException&)
643 catch (const io::IOException&)
649 /*********************************************************************************/
650 /* */
651 /* open-Implementation */
652 /* */
653 /*********************************************************************************/
655 // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
659 uno::Reference< io::XInputStream > SAL_CALL
660 shell::open( sal_Int32 CommandId,
661 const rtl::OUString& aUnqPath,
662 sal_Bool bLock )
663 throw()
665 XInputStream_impl* xInputStream = new XInputStream_impl( this, aUnqPath, bLock ); // from filinpstr.hxx
667 sal_Int32 ErrorCode = xInputStream->CtorSuccess();
669 if( ErrorCode != TASKHANDLER_NO_ERROR )
671 installError( CommandId,
672 ErrorCode,
673 xInputStream->getMinorError() );
675 delete xInputStream;
676 xInputStream = 0;
679 return uno::Reference< io::XInputStream >( xInputStream );
685 /*********************************************************************************/
686 /* */
687 /* open for read/write access-Implementation */
688 /* */
689 /*********************************************************************************/
691 // Given a file URL aUnqPath, this methods returns a XStream which can be used
692 // to read and write from/to the file.
696 uno::Reference< io::XStream > SAL_CALL
697 shell::open_rw( sal_Int32 CommandId,
698 const rtl::OUString& aUnqPath,
699 sal_Bool bLock )
700 throw()
702 XStream_impl* xStream = new XStream_impl( this, aUnqPath, bLock ); // from filstr.hxx
704 sal_Int32 ErrorCode = xStream->CtorSuccess();
706 if( ErrorCode != TASKHANDLER_NO_ERROR )
708 installError( CommandId,
709 ErrorCode,
710 xStream->getMinorError() );
712 delete xStream;
713 xStream = 0;
715 return uno::Reference< io::XStream >( xStream );
720 /*********************************************************************************/
721 /* */
722 /* ls-Implementation */
723 /* */
724 /*********************************************************************************/
726 // This method returns the result set containing the the children of the directory belonging
727 // to file URL aUnqPath
731 uno::Reference< XDynamicResultSet > SAL_CALL
732 shell::ls( sal_Int32 CommandId,
733 const rtl::OUString& aUnqPath,
734 const sal_Int32 OpenMode,
735 const uno::Sequence< beans::Property >& seq,
736 const uno::Sequence< NumberedSortingInfo >& seqSort )
737 throw()
739 XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort );
741 sal_Int32 ErrorCode = p->CtorSuccess();
743 if( ErrorCode != TASKHANDLER_NO_ERROR )
745 installError( CommandId,
746 ErrorCode,
747 p->getMinorError() );
749 delete p;
750 p = 0;
753 return uno::Reference< XDynamicResultSet > ( p );
759 /*********************************************************************************/
760 /* */
761 /* info_c implementation */
762 /* */
763 /*********************************************************************************/
764 // Info for commands
766 uno::Reference< XCommandInfo > SAL_CALL
767 shell::info_c()
768 throw()
770 XCommandInfo_impl* p = new XCommandInfo_impl( this );
771 return uno::Reference< XCommandInfo >( p );
777 /*********************************************************************************/
778 /* */
779 /* info_p-Implementation */
780 /* */
781 /*********************************************************************************/
782 // Info for the properties
784 uno::Reference< beans::XPropertySetInfo > SAL_CALL
785 shell::info_p( const rtl::OUString& aUnqPath )
786 throw()
788 osl::MutexGuard aGuard( m_aMutex );
789 XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath );
790 return uno::Reference< beans::XPropertySetInfo >( p );
796 /*********************************************************************************/
797 /* */
798 /* setv-Implementation */
799 /* */
800 /*********************************************************************************/
802 // Sets the values of the properties belonging to fileURL aUnqPath
806 uno::Sequence< uno::Any > SAL_CALL
807 shell::setv( const rtl::OUString& aUnqPath,
808 const uno::Sequence< beans::PropertyValue >& values )
809 throw()
811 osl::MutexGuard aGuard( m_aMutex );
813 sal_Int32 propChanged = 0;
814 uno::Sequence< uno::Any > ret( values.getLength() );
815 uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() );
817 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
818 PropertySet& properties = *( it->second.properties );
819 shell::PropertySet::iterator it1;
820 uno::Any aAny;
822 for( sal_Int32 i = 0; i < values.getLength(); ++i )
824 MyProperty toset( values[i].Name );
825 it1 = properties.find( toset );
826 if( it1 == properties.end() )
828 ret[i] <<= beans::UnknownPropertyException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
829 continue;
832 aAny = it1->getValue();
833 if( aAny == values[i].Value )
834 continue; // nothing needs to be changed
836 if( it1->getAttributes() & beans::PropertyAttribute::READONLY )
838 ret[i] <<= lang::IllegalAccessException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
839 continue;
842 seqChanged[ propChanged ].PropertyName = values[i].Name;
843 seqChanged[ propChanged ].PropertyHandle = -1;
844 seqChanged[ propChanged ].Further = false;
845 seqChanged[ propChanged ].OldValue <<= aAny;
846 seqChanged[ propChanged++ ].NewValue = values[i].Value;
848 it1->setValue( values[i].Value ); // Put the new value into the local cash
850 if( ! it1->IsNative() )
852 // Also put logical properties into storage
853 if( !it->second.xS.is() )
854 load( it,true );
856 if( ( values[i].Name == ContentType ) &&
857 it1->getState() == beans::PropertyState_DEFAULT_VALUE )
858 { // Special logic for ContentType
859 // 09.07.01: Not reached anymore, because ContentType is readonly
860 it1->setState( beans::PropertyState_DIRECT_VALUE );
861 it->second.xC->addProperty( values[i].Name,
862 beans::PropertyAttribute::MAYBEVOID,
863 values[i].Value );
868 it->second.xS->setPropertyValue( values[i].Name,values[i].Value );
870 catch (const uno::Exception&e)
872 --propChanged; // unsuccessful setting
873 ret[i] <<= e;
876 else
878 // native properties
879 // Setting of physical file properties
880 if( values[i].Name == Size )
882 sal_Int64 newSize = 0;
883 if( values[i].Value >>= newSize )
884 { // valid value for the size
885 osl::File aFile(aUnqPath);
886 bool err =
887 aFile.open(osl_File_OpenFlag_Write) != osl::FileBase::E_None ||
888 aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None ||
889 aFile.close() != osl::FileBase::E_None;
891 if( err )
893 --propChanged; // unsuccessful setting
894 uno::Sequence< uno::Any > names( 1 );
895 ret[0] <<= beans::PropertyValue(
896 rtl::OUString("Uri"), -1,
897 uno::makeAny(aUnqPath),
898 beans::PropertyState_DIRECT_VALUE);
899 IOErrorCode ioError(IOErrorCode_GENERAL);
900 ret[i] <<= InteractiveAugmentedIOException(
901 rtl::OUString(),
903 task::InteractionClassification_ERROR,
904 ioError,
905 names );
908 else
909 ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
911 else if(values[i].Name == IsReadOnly ||
912 values[i].Name == IsHidden)
914 sal_Bool value = sal_False;
915 if( values[i].Value >>= value )
917 osl::DirectoryItem aDirItem;
918 osl::FileBase::RC err =
919 osl::DirectoryItem::get(aUnqPath,aDirItem);
920 sal_uInt64 nAttributes(0);
921 if(err == osl::FileBase::E_None)
923 osl::FileStatus aFileStatus(osl_FileStatus_Mask_Attributes);
924 err = aDirItem.getFileStatus(aFileStatus);
925 if(err == osl::FileBase::E_None &&
926 aFileStatus.isValid(osl_FileStatus_Mask_Attributes))
927 nAttributes = aFileStatus.getAttributes();
929 // now we have the attributes provided all went well.
930 if(err == osl::FileBase::E_None) {
931 if(values[i].Name == IsReadOnly)
933 nAttributes &= ~(osl_File_Attribute_OwnWrite |
934 osl_File_Attribute_GrpWrite |
935 osl_File_Attribute_OthWrite |
936 osl_File_Attribute_ReadOnly);
937 if(value)
938 nAttributes |= osl_File_Attribute_ReadOnly;
939 else
940 nAttributes |= (
941 osl_File_Attribute_OwnWrite |
942 osl_File_Attribute_GrpWrite |
943 osl_File_Attribute_OthWrite);
945 else if(values[i].Name == IsHidden)
947 nAttributes &= ~(osl_File_Attribute_Hidden);
948 if(value)
949 nAttributes |= osl_File_Attribute_Hidden;
951 err = osl::File::setAttributes(
952 aUnqPath,nAttributes);
955 if( err != osl::FileBase::E_None )
957 --propChanged; // unsuccessful setting
958 uno::Sequence< uno::Any > names( 1 );
959 names[0] <<= beans::PropertyValue(
960 rtl::OUString("Uri"), -1,
961 uno::makeAny(aUnqPath),
962 beans::PropertyState_DIRECT_VALUE);
963 IOErrorCode ioError;
964 switch( err )
966 case osl::FileBase::E_NOMEM:
967 // not enough memory for allocating structures <br>
968 ioError = IOErrorCode_OUT_OF_MEMORY;
969 break;
970 case osl::FileBase::E_INVAL:
971 // the format of the parameters was not valid<p>
972 ioError = IOErrorCode_INVALID_PARAMETER;
973 break;
974 case osl::FileBase::E_NAMETOOLONG:
975 // File name too long<br>
976 ioError = IOErrorCode_NAME_TOO_LONG;
977 break;
978 case osl::FileBase::E_NOENT:
979 // No such file or directory<br>
980 case osl::FileBase::E_NOLINK:
981 // Link has been severed<br>
982 ioError = IOErrorCode_NOT_EXISTING;
983 break;
984 case osl::FileBase::E_ROFS:
985 // #i4735# handle ROFS transparently
986 // as ACCESS_DENIED
987 case osl::FileBase::E_PERM:
988 case osl::FileBase::E_ACCES:
989 // permission denied<br>
990 ioError = IOErrorCode_ACCESS_DENIED;
991 break;
992 case osl::FileBase::E_LOOP:
993 // Too many symbolic links encountered<br>
994 case osl::FileBase::E_FAULT:
995 // Bad address<br>
996 case osl::FileBase::E_IO:
997 // I/O error<br>
998 case osl::FileBase::E_NOSYS:
999 // Function not implemented<br>
1000 case osl::FileBase::E_MULTIHOP:
1001 // Multihop attempted<br>
1002 case osl::FileBase::E_INTR:
1003 // function call was interrupted<p>
1004 default:
1005 ioError = IOErrorCode_GENERAL;
1006 break;
1008 ret[i] <<= InteractiveAugmentedIOException(
1009 rtl::OUString(),
1011 task::InteractionClassification_ERROR,
1012 ioError,
1013 names );
1016 else
1017 ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( OSL_LOG_PREFIX ), uno::Reference< uno::XInterface >() );
1020 } // end for
1022 if( propChanged )
1024 seqChanged.realloc( propChanged );
1025 notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged );
1028 return ret;
1031 /*********************************************************************************/
1032 /* */
1033 /* getv-Implementation */
1034 /* */
1035 /*********************************************************************************/
1037 // Reads the values of the properties belonging to fileURL aUnqPath;
1038 // Returns an XRow object containing the values in the requested order.
1042 uno::Reference< sdbc::XRow > SAL_CALL
1043 shell::getv( sal_Int32 CommandId,
1044 const rtl::OUString& aUnqPath,
1045 const uno::Sequence< beans::Property >& properties )
1046 throw()
1048 uno::Sequence< uno::Any > seq( properties.getLength() );
1050 sal_Int32 n_Mask;
1051 getMaskFromProperties( n_Mask,properties );
1052 osl::FileStatus aFileStatus( n_Mask );
1054 osl::DirectoryItem aDirItem;
1055 osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem );
1056 if( nError1 != osl::FileBase::E_None )
1057 installError(CommandId,
1058 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1059 nError1);
1061 osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus );
1062 if( nError1 == osl::FileBase::E_None &&
1063 nError2 != osl::FileBase::E_None )
1064 installError(CommandId,
1065 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1066 nError2);
1069 osl::MutexGuard aGuard( m_aMutex );
1071 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
1072 commit( it,aFileStatus );
1074 shell::PropertySet::iterator it1;
1075 PropertySet& propset = *(it->second.properties);
1077 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
1079 MyProperty readProp( properties[i].Name );
1080 it1 = propset.find( readProp );
1081 if( it1 == propset.end() )
1082 seq[i] = uno::Any();
1083 else
1084 seq[i] = it1->getValue();
1088 XRow_impl* p = new XRow_impl( this,seq );
1089 return uno::Reference< sdbc::XRow >( p );
1093 /********************************************************************************/
1094 /* */
1095 /* transfer-commandos */
1096 /* */
1097 /********************************************************************************/
1100 /********************************************************************************/
1101 /* */
1102 /* move-implementation */
1103 /* */
1104 /********************************************************************************/
1106 // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath.
1109 void SAL_CALL
1110 shell::move( sal_Int32 CommandId,
1111 const rtl::OUString srcUnqPath,
1112 const rtl::OUString dstUnqPathIn,
1113 const sal_Int32 NameClash )
1114 throw()
1116 // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if
1117 // srcUnqPath and dstUnqPathIn are equal
1118 if( srcUnqPath == dstUnqPathIn )
1119 return;
1121 osl::FileBase::RC nError;
1122 rtl::OUString dstUnqPath( dstUnqPathIn );
1124 switch( NameClash )
1126 case NameClash::KEEP:
1128 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1129 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1131 installError( CommandId,
1132 TASKHANDLING_KEEPERROR_FOR_MOVE,
1133 nError );
1134 return;
1136 break;
1138 case NameClash::OVERWRITE:
1140 // stat to determine whether we have a symlink
1141 rtl::OUString targetPath(dstUnqPath);
1143 osl::FileStatus aStatus(osl_FileStatus_Mask_Type|osl_FileStatus_Mask_LinkTargetURL);
1144 osl::DirectoryItem aItem;
1145 osl::DirectoryItem::get(dstUnqPath,aItem);
1146 aItem.getFileStatus(aStatus);
1148 if( aStatus.isValid(osl_FileStatus_Mask_Type) &&
1149 aStatus.isValid(osl_FileStatus_Mask_LinkTargetURL) &&
1150 aStatus.getFileType() == osl::FileStatus::Link )
1151 targetPath = aStatus.getLinkTargetURL();
1153 // Will do nothing if file does not exist.
1154 osl::File::remove( targetPath );
1156 nError = osl_File_move( srcUnqPath,targetPath );
1157 if( nError != osl::FileBase::E_None )
1159 installError( CommandId,
1160 TASKHANDLING_OVERWRITE_FOR_MOVE,
1161 nError );
1162 return;
1164 break;
1166 case NameClash::RENAME:
1168 rtl::OUString newDstUnqPath;
1169 nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1170 if( nError == osl::FileBase::E_EXIST )
1172 // "invent" a new valid title.
1174 sal_Int32 nPos = -1;
1175 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1176 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1177 if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1178 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1179 nPos = nLastDot;
1180 else
1181 nPos = dstUnqPath.getLength();
1183 sal_Int32 nTry = 0;
1187 newDstUnqPath = dstUnqPath;
1189 rtl::OUString aPostFix( "_" );
1190 aPostFix += rtl::OUString::valueOf( ++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 sal_Bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular );
1272 copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument );
1274 rtl::OUString aDstParent = getParentName( dstUnqPath );
1275 rtl::OUString aDstTitle = getTitle( dstUnqPath );
1277 rtl::OUString aSrcParent = getParentName( srcUnqPath );
1278 rtl::OUString aSrcTitle = getTitle( srcUnqPath );
1280 notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath );
1281 if( aDstParent != aSrcParent )
1282 notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath );
1284 notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) );
1285 erasePersistentSet( srcUnqPath,!isDocument );
1290 /********************************************************************************/
1291 /* */
1292 /* copy-implementation */
1293 /* */
1294 /********************************************************************************/
1296 // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
1299 namespace {
1301 bool getType(
1302 TaskManager & task, sal_Int32 id, rtl::OUString const & fileUrl,
1303 osl::DirectoryItem * item, osl::FileStatus::Type * type)
1305 OSL_ASSERT(item != 0 && type != 0);
1306 osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item);
1307 if (err != osl::FileBase::E_None) {
1308 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err);
1309 return false;
1311 osl::FileStatus stat(osl_FileStatus_Mask_Type);
1312 err = item->getFileStatus(stat);
1313 if (err != osl::FileBase::E_None) {
1314 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err);
1315 return false;
1317 *type = stat.getFileType();
1318 return true;
1323 void SAL_CALL
1324 shell::copy(
1325 sal_Int32 CommandId,
1326 const rtl::OUString srcUnqPath,
1327 const rtl::OUString dstUnqPathIn,
1328 sal_Int32 NameClash )
1329 throw()
1331 osl::FileBase::RC nError;
1332 rtl::OUString dstUnqPath( dstUnqPathIn );
1334 // Resolve symbolic links within the source path. If srcUnqPath denotes a
1335 // symbolic link (targeting either a file or a folder), the contents of the
1336 // target is copied (recursively, in the case of a folder). However, if
1337 // recursively copying the contents of a folder causes a symbolic link to be
1338 // copied, the symbolic link itself is copied.
1339 osl::DirectoryItem item;
1340 osl::FileStatus::Type type;
1341 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1342 return;
1344 rtl::OUString rslvdSrcUnqPath;
1345 if (type == osl::FileStatus::Link) {
1346 osl::FileStatus stat(osl_FileStatus_Mask_LinkTargetURL);
1347 nError = item.getFileStatus(stat);
1348 if (nError != osl::FileBase::E_None) {
1349 installError(
1350 CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError);
1351 return;
1353 rslvdSrcUnqPath = stat.getLinkTargetURL();
1354 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1355 return;
1357 } else {
1358 rslvdSrcUnqPath = srcUnqPath;
1361 sal_Bool isDocument
1362 = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume;
1363 sal_Int32 IsWhat = isDocument ? -1 : 1;
1365 switch( NameClash )
1367 case NameClash::KEEP:
1369 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1370 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1372 installError( CommandId,
1373 TASKHANDLING_KEEPERROR_FOR_COPY,
1374 nError );
1375 return;
1377 break;
1379 case NameClash::OVERWRITE:
1381 // remove (..., MustExist = sal_False).
1382 remove( CommandId, dstUnqPath, IsWhat, sal_False );
1384 // copy.
1385 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false );
1386 if( nError != osl::FileBase::E_None )
1388 installError( CommandId,
1389 TASKHANDLING_OVERWRITE_FOR_COPY,
1390 nError );
1391 return;
1393 break;
1395 case NameClash::RENAME:
1397 rtl::OUString newDstUnqPath;
1398 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1400 if( nError == osl::FileBase::E_EXIST )
1402 // "invent" a new valid title.
1404 sal_Int32 nPos = -1;
1405 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1406 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1407 if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1408 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1409 nPos = nLastDot;
1410 else
1411 nPos = dstUnqPath.getLength();
1413 sal_Int32 nTry = 0;
1417 newDstUnqPath = dstUnqPath;
1419 rtl::OUString aPostFix( "_" );
1420 aPostFix += rtl::OUString::valueOf( ++nTry );
1422 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix );
1424 nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true );
1426 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1429 if( nError == osl::FileBase::E_EXIST )
1431 installError( CommandId,
1432 TASKHANDLING_RENAME_FOR_COPY );
1433 return;
1435 else if( nError != osl::FileBase::E_None )
1437 installError( CommandId,
1438 TASKHANDLING_RENAMEMOVE_FOR_COPY,
1439 nError );
1440 return;
1442 else
1443 dstUnqPath = newDstUnqPath;
1445 break;
1447 case NameClash::ERROR:
1449 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1451 if( nError == osl::FileBase::E_EXIST )
1453 installError( CommandId,
1454 TASKHANDLING_NAMECLASH_FOR_COPY );
1455 return;
1457 else if( nError != osl::FileBase::E_None )
1459 installError( CommandId,
1460 TASKHANDLING_NAMECLASHMOVE_FOR_COPY,
1461 nError );
1462 return;
1464 break;
1466 case NameClash::ASK:
1467 default:
1469 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1471 if( nError == osl::FileBase::E_EXIST )
1473 installError( CommandId,
1474 TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY,
1475 NameClash);
1476 return;
1478 break;
1482 copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument );
1483 notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath );
1488 /********************************************************************************/
1489 /* */
1490 /* remove-implementation */
1491 /* */
1492 /********************************************************************************/
1494 // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
1495 // Return: success of operation
1499 sal_Bool SAL_CALL
1500 shell::remove( sal_Int32 CommandId,
1501 const rtl::OUString& aUnqPath,
1502 sal_Int32 IsWhat,
1503 sal_Bool MustExist )
1504 throw()
1506 sal_Int32 nMask = osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL;
1508 osl::DirectoryItem aItem;
1509 osl::FileStatus aStatus( nMask );
1510 osl::FileBase::RC nError;
1512 if( IsWhat == 0 ) // Determine whether we are removing a directory or a file
1514 nError = osl::DirectoryItem::get( aUnqPath, aItem );
1515 if( nError != osl::FileBase::E_None )
1517 if (MustExist)
1519 installError( CommandId,
1520 TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE,
1521 nError );
1523 return (!MustExist);
1526 nError = aItem.getFileStatus( aStatus );
1527 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1529 installError( CommandId,
1530 TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE,
1531 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1532 return sal_False;
1535 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1536 aStatus.getFileType() == osl::FileStatus::Link )
1537 IsWhat = -1; // RemoveFile
1538 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1539 aStatus.getFileType() == osl::FileStatus::Volume )
1540 IsWhat = +1; // RemoveDirectory
1544 if( IsWhat == -1 ) // Removing a file
1546 nError = osl::File::remove( aUnqPath );
1547 if( nError != osl::FileBase::E_None )
1549 if (MustExist)
1551 installError( CommandId,
1552 TASKHANDLING_DELETEFILE_FOR_REMOVE,
1553 nError );
1555 return (!MustExist);
1557 else
1559 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1560 erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet
1563 else if( IsWhat == +1 ) // Removing a directory
1565 osl::Directory aDirectory( aUnqPath );
1567 nError = aDirectory.open();
1568 if( nError != osl::FileBase::E_None )
1570 if (MustExist)
1572 installError( CommandId,
1573 TASKHANDLING_OPENDIRECTORY_FOR_REMOVE,
1574 nError );
1576 return (!MustExist);
1579 sal_Bool whileSuccess = sal_True;
1580 sal_Int32 recurse = 0;
1581 rtl::OUString name;
1583 nError = aDirectory.getNextItem( aItem );
1584 while( nError == osl::FileBase::E_None )
1586 nError = aItem.getFileStatus( aStatus );
1587 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1589 installError( CommandId,
1590 TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE,
1591 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1592 whileSuccess = sal_False;
1593 break;
1596 if( aStatus.getFileType() == osl::FileStatus::Regular ||
1597 aStatus.getFileType() == osl::FileStatus::Link )
1598 recurse = -1;
1599 else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1600 aStatus.getFileType() == osl::FileStatus::Volume )
1601 recurse = +1;
1603 name = aStatus.getFileURL();
1604 whileSuccess = remove(
1605 CommandId, name, recurse, MustExist );
1606 if( !whileSuccess )
1607 break;
1609 nError = aDirectory.getNextItem( aItem );
1612 aDirectory.close();
1614 if( ! whileSuccess )
1615 return sal_False; // error code is installed
1617 if( nError != osl::FileBase::E_NOENT )
1619 installError( CommandId,
1620 TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE,
1621 nError );
1622 return sal_False;
1625 nError = osl::Directory::remove( aUnqPath );
1626 if( nError != osl::FileBase::E_None )
1628 if (MustExist)
1630 installError( CommandId,
1631 TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE,
1632 nError );
1634 return (!MustExist);
1636 else
1638 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1639 erasePersistentSet( aUnqPath );
1642 else // Don't know what to remove
1644 installError( CommandId,
1645 TASKHANDLING_FILETYPE_FOR_REMOVE );
1646 return sal_False;
1649 return sal_True;
1653 /********************************************************************************/
1654 /* */
1655 /* mkdir-implementation */
1656 /* */
1657 /********************************************************************************/
1659 // Creates new directory with given URL, recursively if necessary
1660 // Return:: success of operation
1663 sal_Bool SAL_CALL
1664 shell::mkdir( sal_Int32 CommandId,
1665 const rtl::OUString& rUnqPath,
1666 sal_Bool OverWrite )
1667 throw()
1669 rtl::OUString aUnqPath;
1671 // remove trailing slash
1672 if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) )
1673 aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
1674 else
1675 aUnqPath = rUnqPath;
1677 osl::FileBase::RC nError = osl::Directory::create( aUnqPath );
1679 switch ( nError )
1681 case osl::FileBase::E_EXIST: // Directory cannot be overwritten
1683 if( !OverWrite )
1685 installError( CommandId,
1686 TASKHANDLING_FOLDER_EXISTS_MKDIR );
1687 return sal_False;
1689 else
1690 return sal_True;
1692 case osl::FileBase::E_INVAL:
1694 installError(CommandId,
1695 TASKHANDLING_INVALID_NAME_MKDIR);
1696 return sal_False;
1698 case osl::FileBase::E_None:
1700 rtl::OUString aPrtPath = getParentName( aUnqPath );
1701 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1702 return sal_True;
1704 default:
1705 return ensuredir(
1706 CommandId,
1707 aUnqPath,
1708 TASKHANDLING_CREATEDIRECTORY_MKDIR );
1713 /********************************************************************************/
1714 /* */
1715 /* mkfil-implementation */
1716 /* */
1717 /********************************************************************************/
1719 // Creates new file with given URL.
1720 // The content of aInputStream becomes the content of the file
1721 // Return:: success of operation
1724 sal_Bool SAL_CALL
1725 shell::mkfil( sal_Int32 CommandId,
1726 const rtl::OUString& aUnqPath,
1727 sal_Bool Overwrite,
1728 const uno::Reference< io::XInputStream >& aInputStream )
1729 throw()
1731 // return value unimportant
1732 sal_Bool bSuccess = write( CommandId,
1733 aUnqPath,
1734 Overwrite,
1735 aInputStream );
1736 if ( bSuccess )
1738 rtl::OUString aPrtPath = getParentName( aUnqPath );
1739 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1741 return bSuccess;
1745 /********************************************************************************/
1746 /* */
1747 /* write-implementation */
1748 /* */
1749 /********************************************************************************/
1751 // writes to the file with given URL.
1752 // The content of aInputStream becomes the content of the file
1753 // Return:: success of operation
1756 sal_Bool SAL_CALL
1757 shell::write( sal_Int32 CommandId,
1758 const rtl::OUString& aUnqPath,
1759 sal_Bool OverWrite,
1760 const uno::Reference< io::XInputStream >& aInputStream )
1761 throw()
1763 if( ! aInputStream.is() )
1765 installError( CommandId,
1766 TASKHANDLING_INPUTSTREAM_FOR_WRITE );
1767 return sal_False;
1770 // Create parent path, if necessary.
1771 if ( ! ensuredir( CommandId,
1772 getParentName( aUnqPath ),
1773 TASKHANDLING_ENSUREDIR_FOR_WRITE ) )
1774 return sal_False;
1776 osl::FileBase::RC err;
1777 osl::File aFile( aUnqPath );
1779 if( OverWrite )
1781 err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
1783 if( err != osl::FileBase::E_None )
1785 aFile.close();
1786 err = aFile.open( osl_File_OpenFlag_Write );
1788 if( err != osl::FileBase::E_None )
1790 installError( CommandId,
1791 TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE,
1792 err );
1793 return sal_False;
1796 // the existing file was just opened and should be overwritten now,
1797 // truncate it first
1799 err = aFile.setSize( 0 );
1800 if( err != osl::FileBase::E_None )
1802 installError( CommandId,
1803 TASKHANDLING_FILESIZE_FOR_WRITE,
1804 err );
1805 return sal_False;
1809 else
1811 err = aFile.open( osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock );
1812 if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten
1814 installError( CommandId,
1815 TASKHANDLING_NOREPLACE_FOR_WRITE, // Now an exception
1816 err );
1818 aFile.close();
1819 return sal_False;
1822 // as a temporary solution the creation does not lock the file at all
1823 // in future it should be possible to create the file without lock explicitly
1824 err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock );
1826 if( err != osl::FileBase::E_None )
1828 aFile.close();
1829 installError( CommandId,
1830 TASKHANDLING_NO_OPEN_FILE_FOR_WRITE,
1831 err );
1832 return sal_False;
1836 sal_Bool bSuccess = sal_True;
1838 sal_uInt64 nWrittenBytes;
1839 sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/;
1840 uno::Sequence< sal_Int8 > seq( nRequestedBytes );
1846 nReadBytes = aInputStream->readBytes( seq,
1847 nRequestedBytes );
1849 catch( const io::NotConnectedException& )
1851 installError( CommandId,
1852 TASKHANDLING_NOTCONNECTED_FOR_WRITE );
1853 bSuccess = sal_False;
1854 break;
1856 catch( const io::BufferSizeExceededException& )
1858 installError( CommandId,
1859 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE );
1860 bSuccess = sal_False;
1861 break;
1863 catch( const io::IOException& )
1865 installError( CommandId,
1866 TASKHANDLING_IOEXCEPTION_FOR_WRITE );
1867 bSuccess = sal_False;
1868 break;
1871 if( nReadBytes )
1873 const sal_Int8* p = seq.getConstArray();
1875 err = aFile.write( ((void*)(p)),
1876 sal_uInt64( nReadBytes ),
1877 nWrittenBytes );
1879 if( err != osl::FileBase::E_None )
1881 installError( CommandId,
1882 TASKHANDLING_FILEIOERROR_FOR_WRITE,
1883 err );
1884 bSuccess = sal_False;
1885 break;
1887 else if( nWrittenBytes != sal_uInt64( nReadBytes ) )
1889 installError( CommandId,
1890 TASKHANDLING_FILEIOERROR_FOR_NO_SPACE );
1891 bSuccess = sal_False;
1892 break;
1895 } while( nReadBytes == nRequestedBytes );
1897 err = aFile.close();
1898 if( err != osl::FileBase::E_None )
1900 installError( CommandId,
1901 TASKHANDLING_FILEIOERROR_FOR_WRITE,
1902 err );
1903 bSuccess = sal_False;
1906 return bSuccess;
1911 /*********************************************************************************/
1912 /* */
1913 /* insertDefaultProperties-Implementation */
1914 /* */
1915 /*********************************************************************************/
1918 void SAL_CALL shell::insertDefaultProperties( const rtl::OUString& aUnqPath )
1920 osl::MutexGuard aGuard( m_aMutex );
1922 ContentMap::iterator it =
1923 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
1925 load( it,false );
1927 MyProperty ContentTProperty( ContentType );
1929 PropertySet& properties = *(it->second.properties);
1930 sal_Bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end();
1932 shell::PropertySet::iterator it1 = m_aDefaultProperties.begin();
1933 while( it1 != m_aDefaultProperties.end() )
1935 if( ContentNotDefau && it1->getPropertyName() == ContentType )
1937 // No insertion
1939 else
1940 properties.insert( *it1 );
1941 ++it1;
1948 /******************************************************************************/
1949 /* */
1950 /* mapping of file urls */
1951 /* to uncpath and vice versa */
1952 /* */
1953 /******************************************************************************/
1956 sal_Bool SAL_CALL shell::getUnqFromUrl( const rtl::OUString& Url,rtl::OUString& Unq )
1958 if ( Url == "file:///" || Url == "file://localhost/" || Url == "file://127.0.0.1/" )
1960 Unq = rtl::OUString("file:///");
1961 return false;
1964 sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq );
1966 Unq = Url;
1968 sal_Int32 l = Unq.getLength()-1;
1969 if( ! err && Unq.getStr()[ l ] == '/' &&
1970 Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) < l )
1971 Unq = Unq.copy(0, Unq.getLength() - 1);
1973 return err;
1978 sal_Bool SAL_CALL shell::getUrlFromUnq( const rtl::OUString& Unq,rtl::OUString& Url )
1980 sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url );
1982 Url = Unq;
1984 return err;
1989 // Helper function for public copy
1991 osl::FileBase::RC SAL_CALL
1992 shell::copy_recursive( const rtl::OUString& srcUnqPath,
1993 const rtl::OUString& dstUnqPath,
1994 sal_Int32 TypeToCopy,
1995 sal_Bool testExistBeforeCopy )
1996 throw()
1998 osl::FileBase::RC err = osl::FileBase::E_None;
2000 if( TypeToCopy == -1 ) // Document
2002 err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy );
2004 else if( TypeToCopy == +1 ) // Folder
2006 osl::Directory aDir( srcUnqPath );
2007 aDir.open();
2009 err = osl::Directory::create( dstUnqPath );
2010 osl::FileBase::RC next = err;
2011 if( err == osl::FileBase::E_None )
2013 sal_Int32 n_Mask = osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Type;
2015 osl::DirectoryItem aDirItem;
2017 while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None )
2019 sal_Bool IsDoc = false;
2020 osl::FileStatus aFileStatus( n_Mask );
2021 aDirItem.getFileStatus( aFileStatus );
2022 if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2023 IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
2025 // Getting the information for the next recursive copy
2026 sal_Int32 newTypeToCopy = IsDoc ? -1 : +1;
2028 rtl::OUString newSrcUnqPath;
2029 if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2030 newSrcUnqPath = aFileStatus.getFileURL();
2032 rtl::OUString newDstUnqPath = dstUnqPath;
2033 rtl::OUString tit;
2034 if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2035 tit = rtl::Uri::encode( aFileStatus.getFileName(),
2036 rtl_UriCharClassPchar,
2037 rtl_UriEncodeIgnoreEscapes,
2038 RTL_TEXTENCODING_UTF8 );
2040 if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 )
2041 newDstUnqPath += rtl::OUString("/");
2043 newDstUnqPath += tit;
2045 if ( newSrcUnqPath != dstUnqPath )
2046 err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false );
2049 if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
2050 err = next;
2052 aDir.close();
2055 return err;
2060 // Helper function for mkfil,mkdir and write
2061 // Creates whole path
2062 // returns success of the operation
2065 sal_Bool SAL_CALL shell::ensuredir( sal_Int32 CommandId,
2066 const rtl::OUString& rUnqPath,
2067 sal_Int32 errorCode )
2068 throw()
2070 rtl::OUString aPath;
2072 if ( rUnqPath.isEmpty() )
2073 return sal_False;
2075 if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) )
2076 aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
2077 else
2078 aPath = rUnqPath;
2081 // HACK: create directory on a mount point with nobrowse option
2082 // returns ENOSYS in any case !!
2083 osl::Directory aDirectory( aPath );
2084 osl::FileBase::RC nError = aDirectory.open();
2085 aDirectory.close();
2087 if( nError == osl::File::E_None )
2088 return sal_True;
2090 nError = osl::Directory::create( aPath );
2092 if( nError == osl::File::E_None )
2093 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2095 sal_Bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2097 if( ! bSuccess )
2099 rtl::OUString aParentDir = getParentName( aPath );
2101 if ( aParentDir != aPath )
2102 { // Create first the parent directory
2103 bSuccess = ensuredir( CommandId,
2104 getParentName( aPath ),
2105 errorCode );
2107 // After parent directory structure exists try it one's more
2109 if ( bSuccess )
2110 { // Parent directory exists, retry creation of directory
2111 nError = osl::Directory::create( aPath );
2113 if( nError == osl::File::E_None )
2114 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2116 bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2121 if( ! bSuccess )
2122 installError( CommandId,
2123 errorCode,
2124 nError );
2126 return bSuccess;
2133 // Given a sequence of properties seq, this method determines the mask
2134 // used to instantiate a osl::FileStatus, so that a call to
2135 // osl::DirectoryItem::getFileStatus fills the required fields.
2139 void SAL_CALL
2140 shell::getMaskFromProperties(
2141 sal_Int32& n_Mask,
2142 const uno::Sequence< beans::Property >& seq )
2144 n_Mask = 0;
2145 for(sal_Int32 j = 0; j < seq.getLength(); ++j) {
2146 if(seq[j].Name == Title)
2147 n_Mask |= osl_FileStatus_Mask_FileName;
2148 else if(seq[j].Name == CasePreservingURL)
2149 n_Mask |= osl_FileStatus_Mask_FileURL;
2150 else if(seq[j].Name == IsDocument ||
2151 seq[j].Name == IsFolder ||
2152 seq[j].Name == IsVolume ||
2153 seq[j].Name == IsRemoveable ||
2154 seq[j].Name == IsRemote ||
2155 seq[j].Name == IsCompactDisc ||
2156 seq[j].Name == IsFloppy ||
2157 seq[j].Name == ContentType)
2158 n_Mask |= (osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL);
2159 else if(seq[j].Name == Size)
2160 n_Mask |= (osl_FileStatus_Mask_FileSize |
2161 osl_FileStatus_Mask_Type |
2162 osl_FileStatus_Mask_LinkTargetURL);
2163 else if(seq[j].Name == IsHidden ||
2164 seq[j].Name == IsReadOnly)
2165 n_Mask |= osl_FileStatus_Mask_Attributes;
2166 else if(seq[j].Name == DateModified)
2167 n_Mask |= osl_FileStatus_Mask_ModifyTime;
2173 /*********************************************************************************/
2174 /* */
2175 /* load-Implementation */
2176 /* */
2177 /*********************************************************************************/
2179 // Load the properties from configuration, if create == true create them.
2180 // The Properties are stored under the url belonging to it->first.
2183 void SAL_CALL
2184 shell::load( const ContentMap::iterator& it, sal_Bool create )
2186 if( ! it->second.properties )
2187 it->second.properties = new PropertySet;
2189 if( ( ! it->second.xS.is() ||
2190 ! it->second.xC.is() ||
2191 ! it->second.xA.is() )
2192 && m_xFileRegistry.is() )
2195 uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create );
2196 if( xS.is() )
2198 uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY );
2199 uno::Reference< beans::XPropertyAccess > xA( xS,uno::UNO_QUERY );
2201 it->second.xS = xS;
2202 it->second.xC = xC;
2203 it->second.xA = xA;
2205 // Now put in all values in the storage in the local hash;
2207 PropertySet& properties = *(it->second.properties);
2208 uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties();
2210 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2212 MyProperty readProp( false,
2213 seq[i].Name,
2214 seq[i].Handle,
2215 seq[i].Type,
2216 xS->getPropertyValue( seq[i].Name ),
2217 beans::PropertyState_DIRECT_VALUE,
2218 seq[i].Attributes );
2219 if( properties.find( readProp ) == properties.end() )
2220 properties.insert( readProp );
2223 else if( create )
2225 // Catastrophic error
2233 /*********************************************************************************/
2234 /* */
2235 /* commit-Implementation */
2236 /* */
2237 /*********************************************************************************/
2238 // Commit inserts the determined properties in the filestatus object into
2239 // the internal map, so that is possible to determine on a subsequent
2240 // setting of file properties which properties have changed without filestat
2243 void SAL_CALL
2244 shell::commit( const shell::ContentMap::iterator& it,
2245 const osl::FileStatus& aFileStatus )
2247 uno::Any aAny;
2248 uno::Any emptyAny;
2249 shell::PropertySet::iterator it1;
2251 if( it->second.properties == 0 )
2253 rtl::OUString aPath = it->first;
2254 insertDefaultProperties( aPath );
2257 PropertySet& properties = *( it->second.properties );
2259 it1 = properties.find( MyProperty( Title ) );
2260 if( it1 != properties.end() )
2262 if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2264 aAny <<= aFileStatus.getFileName();
2265 it1->setValue( aAny );
2269 it1 = properties.find( MyProperty( CasePreservingURL ) );
2270 if( it1 != properties.end() )
2272 if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2274 aAny <<= aFileStatus.getFileURL();
2275 it1->setValue( aAny );
2280 sal_Bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc;
2282 sal_Int64 dirSize = 0;
2284 if( aFileStatus.isValid( osl_FileStatus_Mask_FileSize ) )
2285 dirSize = aFileStatus.getFileSize();
2287 if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2289 if( osl::FileStatus::Link == aFileStatus.getFileType() &&
2290 aFileStatus.isValid( osl_FileStatus_Mask_LinkTargetURL ) )
2292 osl::DirectoryItem aDirItem;
2293 osl::FileStatus aFileStatus2( osl_FileStatus_Mask_Type );
2294 if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) &&
2295 osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) &&
2296 aFileStatus2.isValid( osl_FileStatus_Mask_Type ) )
2298 isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType();
2299 isDirectory =
2300 osl::FileStatus::Volume == aFileStatus2.getFileType() ||
2301 osl::FileStatus::Directory == aFileStatus2.getFileType();
2302 isFile =
2303 osl::FileStatus::Regular == aFileStatus2.getFileType();
2305 if( aFileStatus2.isValid( osl_FileStatus_Mask_FileSize ) )
2306 dirSize = aFileStatus2.getFileSize();
2308 else
2310 // extremly ugly, but otherwise default construction
2311 // of aDirItem and aFileStatus2
2312 // before the preciding if
2313 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2314 isDirectory =
2315 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2316 osl::FileStatus::Directory == aFileStatus.getFileType();
2317 isFile =
2318 osl::FileStatus::Regular == aFileStatus.getFileType();
2321 else
2323 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2324 isDirectory =
2325 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2326 osl::FileStatus::Directory == aFileStatus.getFileType();
2327 isFile =
2328 osl::FileStatus::Regular == aFileStatus.getFileType();
2331 it1 = properties.find( MyProperty( IsVolume ) );
2332 if( it1 != properties.end() )
2333 it1->setValue( uno::makeAny( isVolume ) );
2335 it1 = properties.find( MyProperty( IsFolder ) );
2336 if( it1 != properties.end() )
2337 it1->setValue( uno::makeAny( isDirectory ) );
2339 it1 = properties.find( MyProperty( IsDocument ) );
2340 if( it1 != properties.end() )
2341 it1->setValue( uno::makeAny( isFile ) );
2343 osl::VolumeInfo aVolumeInfo( osl_VolumeInfo_Mask_Attributes );
2344 if( isVolume &&
2345 osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) &&
2346 aVolumeInfo.isValid( osl_VolumeInfo_Mask_Attributes ) )
2348 // Retrieve the flags;
2349 isRemote = aVolumeInfo.getRemoteFlag();
2350 isRemoveable = aVolumeInfo.getRemoveableFlag();
2351 isCompactDisc = aVolumeInfo.getCompactDiscFlag();
2352 isFloppy = aVolumeInfo.getFloppyDiskFlag();
2354 it1 = properties.find( MyProperty( IsRemote ) );
2355 if( it1 != properties.end() )
2356 it1->setValue( uno::makeAny( isRemote ) );
2358 it1 = properties.find( MyProperty( IsRemoveable ) );
2359 if( it1 != properties.end() )
2360 it1->setValue( uno::makeAny( isRemoveable ) );
2362 it1 = properties.find( MyProperty( IsCompactDisc ) );
2363 if( it1 != properties.end() )
2364 it1->setValue( uno::makeAny( isCompactDisc ) );
2366 it1 = properties.find( MyProperty( IsFloppy ) );
2367 if( it1 != properties.end() )
2368 it1->setValue( uno::makeAny( isFloppy ) );
2370 else
2372 sal_Bool dummy = false;
2373 aAny <<= dummy;
2374 it1 = properties.find( MyProperty( IsRemote ) );
2375 if( it1 != properties.end() )
2376 it1->setValue( aAny );
2378 it1 = properties.find( MyProperty( IsRemoveable ) );
2379 if( it1 != properties.end() )
2380 it1->setValue( aAny );
2382 it1 = properties.find( MyProperty( IsCompactDisc ) );
2383 if( it1 != properties.end() )
2384 it1->setValue( aAny );
2386 it1 = properties.find( MyProperty( IsFloppy ) );
2387 if( it1 != properties.end() )
2388 it1->setValue( aAny );
2391 else
2393 isDirectory = sal_False;
2396 it1 = properties.find( MyProperty( Size ) );
2397 if( it1 != properties.end() )
2398 it1->setValue( uno::makeAny( dirSize ) );
2400 it1 = properties.find( MyProperty( IsReadOnly ) );
2401 if( it1 != properties.end() )
2403 if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2405 sal_uInt64 Attr = aFileStatus.getAttributes();
2406 sal_Bool readonly = ( Attr & osl_File_Attribute_ReadOnly ) != 0;
2407 it1->setValue( uno::makeAny( readonly ) );
2411 it1 = properties.find( MyProperty( IsHidden ) );
2412 if( it1 != properties.end() )
2414 if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2416 sal_uInt64 Attr = aFileStatus.getAttributes();
2417 sal_Bool ishidden = ( Attr & osl_File_Attribute_Hidden ) != 0;
2418 it1->setValue( uno::makeAny( ishidden ) );
2422 it1 = properties.find( MyProperty( DateModified ) );
2423 if( it1 != properties.end() )
2425 if( aFileStatus.isValid( osl_FileStatus_Mask_ModifyTime ) )
2427 TimeValue temp = aFileStatus.getModifyTime();
2429 // Convert system time to local time (for EA)
2430 TimeValue myLocalTime;
2431 osl_getLocalTimeFromSystemTime( &temp, &myLocalTime );
2433 oslDateTime myDateTime;
2434 osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime );
2435 util::DateTime aDateTime;
2437 aDateTime.HundredthSeconds = (unsigned short)(myDateTime.NanoSeconds / 10000000);
2438 aDateTime.Seconds = myDateTime.Seconds;
2439 aDateTime.Minutes = myDateTime.Minutes;
2440 aDateTime.Hours = myDateTime.Hours;
2441 aDateTime.Day = myDateTime.Day;
2442 aDateTime.Month = myDateTime.Month;
2443 aDateTime.Year = myDateTime.Year;
2444 it1->setValue( uno::makeAny( aDateTime ) );
2448 it1 = properties.find( MyProperty( CreatableContentsInfo ) );
2449 if( it1 != properties.end() )
2450 it1->setValue( uno::makeAny(
2451 isDirectory || !aFileStatus.isValid( osl_FileStatus_Mask_Type )
2452 ? queryCreatableContentsInfo()
2453 : uno::Sequence< ucb::ContentInfo >() ) );
2457 // Special optimized method for getting the properties of a
2458 // directoryitem, which is returned by osl::DirectoryItem::getNextItem()
2461 uno::Reference< sdbc::XRow > SAL_CALL
2462 shell::getv(
2463 Notifier* pNotifier,
2464 const uno::Sequence< beans::Property >& properties,
2465 osl::DirectoryItem& aDirItem,
2466 rtl::OUString& aUnqPath,
2467 sal_Bool& aIsRegular )
2469 uno::Sequence< uno::Any > seq( properties.getLength() );
2471 sal_Int32 n_Mask;
2472 getMaskFromProperties( n_Mask,properties );
2474 // Always retrieve the type and the target URL because item might be a link
2475 osl::FileStatus aFileStatus( n_Mask |
2476 osl_FileStatus_Mask_FileURL |
2477 osl_FileStatus_Mask_Type |
2478 osl_FileStatus_Mask_LinkTargetURL );
2480 osl::FileBase::RC aRes = aDirItem.getFileStatus( aFileStatus );
2481 if ( aRes == osl::FileBase::E_None )
2483 aUnqPath = aFileStatus.getFileURL();
2485 // If the directory item type is a link retrieve the type of the target
2487 if ( aFileStatus.getFileType() == osl::FileStatus::Link )
2489 // Assume failure
2490 aIsRegular = false;
2491 osl::FileBase::RC result = osl::FileBase::E_INVAL;
2492 osl::DirectoryItem aTargetItem;
2493 osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem );
2494 if ( aTargetItem.is() )
2496 osl::FileStatus aTargetStatus( osl_FileStatus_Mask_Type );
2498 if ( osl::FileBase::E_None ==
2499 ( result = aTargetItem.getFileStatus( aTargetStatus ) ) )
2500 aIsRegular =
2501 aTargetStatus.getFileType() == osl::FileStatus::Regular;
2504 else
2505 aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular;
2507 registerNotifier( aUnqPath,pNotifier );
2508 insertDefaultProperties( aUnqPath );
2510 osl::MutexGuard aGuard( m_aMutex );
2512 shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
2513 commit( it,aFileStatus );
2515 shell::PropertySet::iterator it1;
2516 PropertySet& propset = *(it->second.properties);
2518 for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2520 MyProperty readProp( properties[i].Name );
2521 it1 = propset.find( readProp );
2522 if( it1 == propset.end() )
2523 seq[i] = uno::Any();
2524 else
2525 seq[i] = it1->getValue();
2528 deregisterNotifier( aUnqPath,pNotifier );
2530 XRow_impl* p = new XRow_impl( this,seq );
2531 return uno::Reference< sdbc::XRow >( p );
2539 // EventListener
2542 std::list< ContentEventNotifier* >* SAL_CALL
2543 shell::getContentEventListeners( const rtl::OUString& aName )
2545 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2546 std::list< ContentEventNotifier* >& listeners = *p;
2548 osl::MutexGuard aGuard( m_aMutex );
2549 shell::ContentMap::iterator it = m_aContent.find( aName );
2550 if( it != m_aContent.end() && it->second.notifier )
2552 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2553 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2554 while( it1 != listOfNotifiers.end() )
2556 Notifier* pointer = *it1;
2557 ContentEventNotifier* notifier = pointer->cCEL();
2558 if( notifier )
2559 listeners.push_back( notifier );
2560 ++it1;
2564 return p;
2569 std::list< ContentEventNotifier* >* SAL_CALL
2570 shell::getContentDeletedEventListeners( const rtl::OUString& aName )
2572 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2573 std::list< ContentEventNotifier* >& listeners = *p;
2575 osl::MutexGuard aGuard( m_aMutex );
2576 shell::ContentMap::iterator it = m_aContent.find( aName );
2577 if( it != m_aContent.end() && it->second.notifier )
2579 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2580 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2581 while( it1 != listOfNotifiers.end() )
2583 Notifier* pointer = *it1;
2584 ContentEventNotifier* notifier = pointer->cDEL();
2585 if( notifier )
2586 listeners.push_back( notifier );
2587 ++it1;
2591 return p;
2595 void SAL_CALL
2596 shell::notifyInsert( std::list< ContentEventNotifier* >* listeners,const rtl::OUString& aChildName )
2598 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2599 while( it != listeners->end() )
2601 (*it)->notifyChildInserted( aChildName );
2602 delete (*it);
2603 ++it;
2605 delete listeners;
2609 void SAL_CALL
2610 shell::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners )
2612 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2613 while( it != listeners->end() )
2615 (*it)->notifyDeleted();
2616 delete (*it);
2617 ++it;
2619 delete listeners;
2623 void SAL_CALL
2624 shell::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners,
2625 const rtl::OUString& aChildName )
2627 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2628 while( it != listeners->end() )
2630 (*it)->notifyRemoved( aChildName );
2631 delete (*it);
2632 ++it;
2634 delete listeners;
2640 std::list< PropertySetInfoChangeNotifier* >* SAL_CALL
2641 shell::getPropertySetListeners( const rtl::OUString& aName )
2643 std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >;
2644 std::list< PropertySetInfoChangeNotifier* >& listeners = *p;
2646 osl::MutexGuard aGuard( m_aMutex );
2647 shell::ContentMap::iterator it = m_aContent.find( aName );
2648 if( it != m_aContent.end() && it->second.notifier )
2650 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2651 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2652 while( it1 != listOfNotifiers.end() )
2654 Notifier* pointer = *it1;
2655 PropertySetInfoChangeNotifier* notifier = pointer->cPSL();
2656 if( notifier )
2657 listeners.push_back( notifier );
2658 ++it1;
2662 return p;
2666 void SAL_CALL
2667 shell::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners,
2668 const rtl::OUString& aPropertyName )
2670 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2671 while( it != listeners->end() )
2673 (*it)->notifyPropertyAdded( aPropertyName );
2674 delete (*it);
2675 ++it;
2677 delete listeners;
2681 void SAL_CALL
2682 shell::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners,
2683 const rtl::OUString& aPropertyName )
2685 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2686 while( it != listeners->end() )
2688 (*it)->notifyPropertyRemoved( aPropertyName );
2689 delete (*it);
2690 ++it;
2692 delete listeners;
2697 std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL
2698 shell::getContentExchangedEventListeners( const rtl::OUString aOldPrefix,
2699 const rtl::OUString aNewPrefix,
2700 sal_Bool withChildren )
2703 std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap =
2704 new std::vector< std::list< ContentEventNotifier* >* >;
2705 std::vector< std::list< ContentEventNotifier* >* >& aVector = *aVectorOnHeap;
2707 sal_Int32 count;
2708 rtl::OUString aOldName;
2709 rtl::OUString aNewName;
2710 std::vector< rtl::OUString > oldChildList;
2713 osl::MutexGuard aGuard( m_aMutex );
2715 if( ! withChildren )
2717 aOldName = aOldPrefix;
2718 aNewName = aNewPrefix;
2719 count = 1;
2721 else
2723 ContentMap::iterator itnames = m_aContent.begin();
2724 while( itnames != m_aContent.end() )
2726 if( isChild( aOldPrefix,itnames->first ) )
2728 oldChildList.push_back( itnames->first );
2730 ++itnames;
2732 count = oldChildList.size();
2736 for( sal_Int32 j = 0; j < count; ++j )
2738 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2739 std::list< ContentEventNotifier* >& listeners = *p;
2741 if( withChildren )
2743 aOldName = oldChildList[j];
2744 aNewName = newName( aNewPrefix,aOldPrefix,aOldName );
2747 shell::ContentMap::iterator itold = m_aContent.find( aOldName );
2748 if( itold != m_aContent.end() )
2750 shell::ContentMap::iterator itnew = m_aContent.insert(
2751 ContentMap::value_type( aNewName,UnqPathData() ) ).first;
2753 // copy Ownership also
2754 delete itnew->second.properties;
2755 itnew->second.properties = itold->second.properties;
2756 itold->second.properties = 0;
2758 // copy existing list
2759 std::list< Notifier* >* copyList = itnew->second.notifier;
2760 itnew->second.notifier = itold->second.notifier;
2761 itold->second.notifier = 0;
2763 m_aContent.erase( itold );
2765 if( itnew != m_aContent.end() && itnew->second.notifier )
2767 std::list<Notifier*>& listOfNotifiers = *( itnew->second.notifier );
2768 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2769 while( it1 != listOfNotifiers.end() )
2771 Notifier* pointer = *it1;
2772 ContentEventNotifier* notifier = pointer->cEXC( aNewName );
2773 if( notifier )
2774 listeners.push_back( notifier );
2775 ++it1;
2779 // Merge with preexisting notifiers
2780 // However, these may be in status BaseContent::Deleted
2781 if( copyList != 0 )
2783 std::list< Notifier* >::iterator copyIt = copyList->begin();
2784 while( copyIt != copyList->end() )
2786 itnew->second.notifier->push_back( *copyIt );
2787 ++copyIt;
2790 delete copyList;
2792 aVector.push_back( p );
2796 return aVectorOnHeap;
2801 void SAL_CALL
2802 shell::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec )
2804 std::list< ContentEventNotifier* >* listeners;
2805 for( sal_uInt32 i = 0; i < listeners_vec->size(); ++i )
2807 listeners = (*listeners_vec)[i];
2808 std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2809 while( it != listeners->end() )
2811 (*it)->notifyExchanged();
2812 delete (*it);
2813 ++it;
2815 delete listeners;
2817 delete listeners_vec;
2822 std::list< PropertyChangeNotifier* >* SAL_CALL
2823 shell::getPropertyChangeNotifier( const rtl::OUString& aName )
2825 std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >;
2826 std::list< PropertyChangeNotifier* >& listeners = *p;
2828 osl::MutexGuard aGuard( m_aMutex );
2829 shell::ContentMap::iterator it = m_aContent.find( aName );
2830 if( it != m_aContent.end() && it->second.notifier )
2832 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2833 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2834 while( it1 != listOfNotifiers.end() )
2836 Notifier* pointer = *it1;
2837 PropertyChangeNotifier* notifier = pointer->cPCL();
2838 if( notifier )
2839 listeners.push_back( notifier );
2840 ++it1;
2844 return p;
2848 void SAL_CALL shell::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners,
2849 const uno::Sequence< beans::PropertyChangeEvent >& seqChanged )
2851 std::list< PropertyChangeNotifier* >::iterator it = listeners->begin();
2852 while( it != listeners->end() )
2854 (*it)->notifyPropertyChanged( seqChanged );
2855 delete (*it);
2856 ++it;
2858 delete listeners;
2864 /********************************************************************************/
2865 /* remove persistent propertyset */
2866 /********************************************************************************/
2868 void SAL_CALL
2869 shell::erasePersistentSet( const rtl::OUString& aUnqPath,
2870 sal_Bool withChildren )
2872 if( ! m_xFileRegistry.is() )
2874 OSL_ASSERT( m_xFileRegistry.is() );
2875 return;
2878 uno::Sequence< rtl::OUString > seqNames;
2880 if( withChildren )
2882 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2883 seqNames = xName->getElementNames();
2886 sal_Int32 count = withChildren ? seqNames.getLength() : 1;
2888 rtl::OUString
2889 old_Name = aUnqPath;
2891 for( sal_Int32 j = 0; j < count; ++j )
2893 if( withChildren && ! ( isChild( old_Name,seqNames[j] ) ) )
2894 continue;
2896 if( withChildren )
2898 old_Name = seqNames[j];
2902 // Release possible references
2903 osl::MutexGuard aGuard( m_aMutex );
2904 ContentMap::iterator it = m_aContent.find( old_Name );
2905 if( it != m_aContent.end() )
2907 it->second.xS = 0;
2908 it->second.xC = 0;
2909 it->second.xA = 0;
2911 delete it->second.properties;
2912 it->second.properties = 0;
2916 if( m_xFileRegistry.is() )
2917 m_xFileRegistry->removePropertySet( old_Name );
2924 /********************************************************************************/
2925 /* copy persistent propertyset */
2926 /* from srcUnqPath to dstUnqPath */
2927 /********************************************************************************/
2930 void SAL_CALL
2931 shell::copyPersistentSet( const rtl::OUString& srcUnqPath,
2932 const rtl::OUString& dstUnqPath,
2933 sal_Bool withChildren )
2935 if( ! m_xFileRegistry.is() )
2937 OSL_ASSERT( m_xFileRegistry.is() );
2938 return;
2941 uno::Sequence< rtl::OUString > seqNames;
2943 if( withChildren )
2945 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2946 seqNames = xName->getElementNames();
2949 sal_Int32 count = withChildren ? seqNames.getLength() : 1;
2951 rtl::OUString
2952 old_Name = srcUnqPath,
2953 new_Name = dstUnqPath;
2955 for( sal_Int32 j = 0; j < count; ++j )
2957 if( withChildren && ! ( isChild( srcUnqPath,seqNames[j] ) ) )
2958 continue;
2960 if( withChildren )
2962 old_Name = seqNames[j];
2963 new_Name = newName( dstUnqPath,srcUnqPath,old_Name );
2966 uno::Reference< XPersistentPropertySet > x_src;
2968 if( m_xFileRegistry.is() )
2970 x_src = m_xFileRegistry->openPropertySet( old_Name,false );
2971 m_xFileRegistry->removePropertySet( new_Name );
2974 if( x_src.is() )
2976 uno::Sequence< beans::Property > seqProperty =
2977 x_src->getPropertySetInfo()->getProperties();
2979 if( seqProperty.getLength() )
2981 uno::Reference< XPersistentPropertySet >
2982 x_dstS = m_xFileRegistry->openPropertySet( new_Name,true );
2983 uno::Reference< beans::XPropertyContainer >
2984 x_dstC( x_dstS,uno::UNO_QUERY );
2986 for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i )
2988 x_dstC->addProperty( seqProperty[i].Name,
2989 seqProperty[i].Attributes,
2990 x_src->getPropertyValue( seqProperty[i].Name ) );
2994 } // end for( sal_Int...
2997 uno::Sequence< ucb::ContentInfo > shell::queryCreatableContentsInfo()
2999 uno::Sequence< ucb::ContentInfo > seq(2);
3001 // file
3002 seq[0].Type = FileContentType;
3003 seq[0].Attributes = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
3004 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
3006 uno::Sequence< beans::Property > props( 1 );
3007 props[0] = beans::Property(
3008 rtl::OUString("Title"),
3010 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
3011 beans::PropertyAttribute::MAYBEVOID
3012 | beans::PropertyAttribute::BOUND );
3013 seq[0].Properties = props;
3015 // folder
3016 seq[1].Type = FolderContentType;
3017 seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
3018 seq[1].Properties = props;
3019 return seq;
3022 /*******************************************************************************/
3023 /* */
3024 /* some misceancellous static functions */
3025 /* */
3026 /*******************************************************************************/
3028 void SAL_CALL
3029 shell::getScheme( rtl::OUString& Scheme )
3031 Scheme = rtl::OUString("file");
3034 rtl::OUString SAL_CALL
3035 shell::getImplementationName_static( void )
3037 return rtl::OUString("com.sun.star.comp.ucb.FileProvider");
3041 uno::Sequence< rtl::OUString > SAL_CALL
3042 shell::getSupportedServiceNames_static( void )
3044 rtl::OUString Supported("com.sun.star.ucb.FileContentProvider");
3045 com::sun::star::uno::Sequence< rtl::OUString > Seq( &Supported,1 );
3046 return Seq;
3049 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */