/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_file.hxx" #ifndef INCLUDED_STL_STACK #include #define INCLUDED_STL_STACK #endif #include "osl/diagnose.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "filerror.hxx" #include "filglob.hxx" #include "filcmd.hxx" #include "filinpstr.hxx" #include "filstr.hxx" #include "filrset.hxx" #include "filrow.hxx" #include "filprp.hxx" #include "filid.hxx" #include "shell.hxx" #include "prov.hxx" #include "bc.hxx" using namespace fileaccess; using namespace com::sun::star; using namespace com::sun::star::ucb; shell::UnqPathData::UnqPathData() : properties( 0 ), notifier( 0 ), xS( 0 ), xC( 0 ), xA( 0 ) { // empty } shell::UnqPathData::UnqPathData( const UnqPathData& a ) : properties( a.properties ), notifier( a.notifier ), xS( a.xS ), xC( a.xC ), xA( a.xA ) { } shell::UnqPathData& shell::UnqPathData::operator=( UnqPathData& a ) { properties = a.properties; notifier = a.notifier; xS = a.xS; xC = a.xC; xA = a.xA; a.properties = 0; a.notifier = 0; a.xS = 0; a.xC = 0; a.xA = 0; return *this; } shell::UnqPathData::~UnqPathData() { if( properties ) delete properties; if( notifier ) delete notifier; } //////////////////////////////////////////////////////////////////////////////////////// shell::MyProperty::MyProperty( const rtl::OUString& __PropertyName ) : PropertyName( __PropertyName ) { // empty } shell::MyProperty::MyProperty( const sal_Bool& __isNative, const rtl::OUString& __PropertyName, const sal_Int32& __Handle, const com::sun::star::uno::Type& __Typ, const com::sun::star::uno::Any& __Value, const com::sun::star::beans::PropertyState& __State, const sal_Int16& __Attributes ) : PropertyName( __PropertyName ), Handle( __Handle ), isNative( __isNative ), Typ( __Typ ), Value( __Value ), State( __State ), Attributes( __Attributes ) { // empty } shell::MyProperty::~MyProperty() { // empty for now } #include "filinl.hxx" shell::shell( const uno::Reference< lang::XMultiServiceFactory >& xMultiServiceFactory, FileProvider* pProvider, sal_Bool bWithConfig ) : TaskManager(), m_bWithConfig( bWithConfig ), m_pProvider( pProvider ), m_xMultiServiceFactory( xMultiServiceFactory ), Title( rtl::OUString::createFromAscii( "Title" ) ), CasePreservingURL( rtl::OUString::createFromAscii( "CasePreservingURL" ) ), IsDocument( rtl::OUString::createFromAscii( "IsDocument" ) ), IsFolder( rtl::OUString::createFromAscii( "IsFolder" ) ), DateModified( rtl::OUString::createFromAscii( "DateModified" ) ), Size( rtl::OUString::createFromAscii( "Size" ) ), IsVolume( rtl::OUString::createFromAscii( "IsVolume" ) ), IsRemoveable( rtl::OUString::createFromAscii( "IsRemoveable" ) ), IsRemote( rtl::OUString::createFromAscii( "IsRemote" ) ), IsCompactDisc( rtl::OUString::createFromAscii( "IsCompactDisc" ) ), IsFloppy( rtl::OUString::createFromAscii( "IsFloppy" ) ), IsHidden( rtl::OUString::createFromAscii( "IsHidden" ) ), ContentType( rtl::OUString::createFromAscii( "ContentType" ) ), IsReadOnly( rtl::OUString::createFromAscii( "IsReadOnly" ) ), CreatableContentsInfo( rtl::OUString::createFromAscii( "CreatableContentsInfo" ) ), FolderContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-folder" ) ), FileContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-file" ) ), m_sCommandInfo( 9 ) { // Title m_aDefaultProperties.insert( MyProperty( true, Title, -1 , getCppuType( static_cast< rtl::OUString* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // CasePreservingURL m_aDefaultProperties.insert( MyProperty( true, CasePreservingURL, -1 , getCppuType( static_cast< rtl::OUString* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // IsFolder m_aDefaultProperties.insert( MyProperty( true, IsFolder, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // IsDocument m_aDefaultProperties.insert( MyProperty( true, IsDocument, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Removable m_aDefaultProperties.insert( MyProperty( true, IsVolume, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Removable m_aDefaultProperties.insert( MyProperty( true, IsRemoveable, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Remote m_aDefaultProperties.insert( MyProperty( true, IsRemote, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // CompactDisc m_aDefaultProperties.insert( MyProperty( true, IsCompactDisc, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Floppy m_aDefaultProperties.insert( MyProperty( true, IsFloppy, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Hidden m_aDefaultProperties.insert( MyProperty( true, IsHidden, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND #if defined( WNT ) || defined( OS2 ) )); #else | beans::PropertyAttribute::READONLY)); // under unix/linux only readable #endif // ContentType uno::Any aAny; aAny <<= rtl::OUString(); m_aDefaultProperties.insert( MyProperty( false, ContentType, -1 , getCppuType( static_cast< rtl::OUString* >( 0 ) ), aAny, beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // DateModified m_aDefaultProperties.insert( MyProperty( true, DateModified, -1 , getCppuType( static_cast< util::DateTime* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // Size m_aDefaultProperties.insert( MyProperty( true, Size, -1, getCppuType( static_cast< sal_Int64* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // IsReadOnly m_aDefaultProperties.insert( MyProperty( true, IsReadOnly, -1 , getCppuType( static_cast< sal_Bool* >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // CreatableContentsInfo m_aDefaultProperties.insert( MyProperty( true, CreatableContentsInfo, -1 , getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Commands m_sCommandInfo[0].Name = rtl::OUString::createFromAscii( "getCommandInfo" ); m_sCommandInfo[0].Handle = -1; m_sCommandInfo[0].ArgType = getCppuVoidType(); m_sCommandInfo[1].Name = rtl::OUString::createFromAscii( "getPropertySetInfo" ); m_sCommandInfo[1].Handle = -1; m_sCommandInfo[1].ArgType = getCppuVoidType(); m_sCommandInfo[2].Name = rtl::OUString::createFromAscii( "getPropertyValues" ); m_sCommandInfo[2].Handle = -1; m_sCommandInfo[2].ArgType = getCppuType( static_cast< uno::Sequence< beans::Property >* >( 0 ) ); m_sCommandInfo[3].Name = rtl::OUString::createFromAscii( "setPropertyValues" ); m_sCommandInfo[3].Handle = -1; m_sCommandInfo[3].ArgType = getCppuType( static_cast< uno::Sequence< beans::PropertyValue >* >( 0 ) ); m_sCommandInfo[4].Name = rtl::OUString::createFromAscii( "open" ); m_sCommandInfo[4].Handle = -1; m_sCommandInfo[4].ArgType = getCppuType( static_cast< OpenCommandArgument* >( 0 ) ); m_sCommandInfo[5].Name = rtl::OUString::createFromAscii( "transfer" ); m_sCommandInfo[5].Handle = -1; m_sCommandInfo[5].ArgType = getCppuType( static_cast< TransferInfo* >( 0 ) ); m_sCommandInfo[6].Name = rtl::OUString::createFromAscii( "delete" ); m_sCommandInfo[6].Handle = -1; m_sCommandInfo[6].ArgType = getCppuType( static_cast< sal_Bool* >( 0 ) ); m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "insert" ); m_sCommandInfo[7].Handle = -1; m_sCommandInfo[7].ArgType = getCppuType( static_cast< InsertCommandArgument* > ( 0 ) ); m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "createNewContent" ); m_sCommandInfo[7].Handle = -1; m_sCommandInfo[7].ArgType = getCppuType( static_cast< ucb::ContentInfo * > ( 0 ) ); if(m_bWithConfig) { rtl::OUString Store = rtl::OUString::createFromAscii( "com.sun.star.ucb.Store" ); uno::Reference< XPropertySetRegistryFactory > xRegFac( m_xMultiServiceFactory->createInstance( Store ), uno::UNO_QUERY ); if ( xRegFac.is() ) { // Open/create a registry m_xFileRegistry = xRegFac->createPropertySetRegistry( rtl::OUString() ); } } } shell::~shell() { } /*********************************************************************************/ /* */ /* de/registerNotifier-Implementation */ /* */ /*********************************************************************************/ // // This two methods register and deregister a change listener for the content belonging // to URL aUnqPath // void SAL_CALL shell::registerNotifier( const rtl::OUString& aUnqPath, Notifier* pNotifier ) { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; if( ! it->second.notifier ) it->second.notifier = new NotifierList(); std::list< Notifier* >& nlist = *( it->second.notifier ); std::list::iterator it1 = nlist.begin(); while( it1 != nlist.end() ) // Every "Notifier" only once { if( *it1 == pNotifier ) return; ++it1; } nlist.push_back( pNotifier ); } void SAL_CALL shell::deregisterNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier ) { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.find( aUnqPath ); if( it == m_aContent.end() ) return; it->second.notifier->remove( pNotifier ); if( ! it->second.notifier->size() ) m_aContent.erase( it ); } /*********************************************************************************/ /* */ /* de/associate-Implementation */ /* */ /*********************************************************************************/ // // Used to associate and deassociate a new property with // the content belonging to URL UnqPath. // The default value and the attributes are input // void SAL_CALL shell::associate( const rtl::OUString& aUnqPath, const rtl::OUString& PropertyName, const uno::Any& DefaultValue, const sal_Int16 Attributes ) throw( beans::PropertyExistException, beans::IllegalTypeException, uno::RuntimeException ) { MyProperty newProperty( false, PropertyName, -1, DefaultValue.getValueType(), DefaultValue, beans::PropertyState_DEFAULT_VALUE, Attributes ); shell::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty ); if( it1 != m_aDefaultProperties.end() ) throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; // Load the XPersistentPropertySetInfo and create it, if it does not exist load( it,true ); PropertySet& properties = *(it->second.properties); it1 = properties.find( newProperty ); if( it1 != properties.end() ) throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); // Property does not exist properties.insert( newProperty ); it->second.xC->addProperty( PropertyName,Attributes,DefaultValue ); } notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName ); } void SAL_CALL shell::deassociate( const rtl::OUString& aUnqPath, const rtl::OUString& PropertyName ) throw( beans::UnknownPropertyException, beans::NotRemoveableException, uno::RuntimeException ) { MyProperty oldProperty( PropertyName ); shell::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty ); if( it1 != m_aDefaultProperties.end() ) throw beans::NotRemoveableException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; load( it,false ); PropertySet& properties = *(it->second.properties); it1 = properties.find( oldProperty ); if( it1 == properties.end() ) throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); properties.erase( it1 ); if( it->second.xC.is() ) it->second.xC->removeProperty( PropertyName ); if( properties.size() == 9 ) { MyProperty ContentTProperty( ContentType ); if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE ) { it->second.xS = 0; it->second.xC = 0; it->second.xA = 0; if(m_xFileRegistry.is()) m_xFileRegistry->removePropertySet( aUnqPath ); } } notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName ); } /*********************************************************************************/ /* */ /* page-Implementation */ /* */ /*********************************************************************************/ // // Given an xOutputStream, this method writes the content of the file belonging to // URL aUnqPath into the XOutputStream // void SAL_CALL shell::page( sal_Int32 CommandId, const rtl::OUString& aUnqPath, const uno::Reference< io::XOutputStream >& xOutputStream ) throw() { uno::Reference< XContentProvider > xProvider( m_pProvider ); osl::File aFile( aUnqPath ); osl::FileBase::RC err = aFile.open( OpenFlag_Read ); if( err != osl::FileBase::E_None ) { aFile.close(); installError( CommandId, TASKHANDLING_OPEN_FILE_FOR_PAGING, err ); return; } const sal_uInt64 bfz = 4*1024; sal_Int8 BFF[bfz]; sal_uInt64 nrc; // Retrieved number of Bytes; do { err = aFile.read( (void*) BFF,bfz,nrc ); if( err == osl::FileBase::E_None ) { uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc ); try { xOutputStream->writeBytes( seq ); } catch( io::NotConnectedException ) { installError( CommandId, TASKHANDLING_NOTCONNECTED_FOR_PAGING ); break; } catch( io::BufferSizeExceededException ) { installError( CommandId, TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING ); break; } catch( io::IOException ) { installError( CommandId, TASKHANDLING_IOEXCEPTION_FOR_PAGING ); break; } } else { installError( CommandId, TASKHANDLING_READING_FILE_FOR_PAGING, err ); break; } } while( nrc == bfz ); aFile.close(); try { xOutputStream->closeOutput(); } catch( io::NotConnectedException ) { } catch( io::BufferSizeExceededException ) { } catch( io::IOException ) { } } /*********************************************************************************/ /* */ /* open-Implementation */ /* */ /*********************************************************************************/ // // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file. // uno::Reference< io::XInputStream > SAL_CALL shell::open( sal_Int32 CommandId, const rtl::OUString& aUnqPath, sal_Bool bLock ) throw() { XInputStream_impl* xInputStream = new XInputStream_impl( this, aUnqPath, bLock ); // from filinpstr.hxx sal_Int32 ErrorCode = xInputStream->CtorSuccess(); if( ErrorCode != TASKHANDLER_NO_ERROR ) { installError( CommandId, ErrorCode, xInputStream->getMinorError() ); delete xInputStream; xInputStream = 0; } return uno::Reference< io::XInputStream >( xInputStream ); } /*********************************************************************************/ /* */ /* open for read/write access-Implementation */ /* */ /*********************************************************************************/ // // Given a file URL aUnqPath, this methods returns a XStream which can be used // to read and write from/to the file. // uno::Reference< io::XStream > SAL_CALL shell::open_rw( sal_Int32 CommandId, const rtl::OUString& aUnqPath, sal_Bool bLock ) throw() { XStream_impl* xStream = new XStream_impl( this, aUnqPath, bLock ); // from filstr.hxx sal_Int32 ErrorCode = xStream->CtorSuccess(); if( ErrorCode != TASKHANDLER_NO_ERROR ) { installError( CommandId, ErrorCode, xStream->getMinorError() ); delete xStream; xStream = 0; } return uno::Reference< io::XStream >( xStream ); } /*********************************************************************************/ /* */ /* ls-Implementation */ /* */ /*********************************************************************************/ // // This method returns the result set containing the children of the directory belonging // to file URL aUnqPath // uno::Reference< XDynamicResultSet > SAL_CALL shell::ls( sal_Int32 CommandId, const rtl::OUString& aUnqPath, const sal_Int32 OpenMode, const uno::Sequence< beans::Property >& seq, const uno::Sequence< NumberedSortingInfo >& seqSort ) throw() { XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort ); sal_Int32 ErrorCode = p->CtorSuccess(); if( ErrorCode != TASKHANDLER_NO_ERROR ) { installError( CommandId, ErrorCode, p->getMinorError() ); delete p; p = 0; } return uno::Reference< XDynamicResultSet > ( p ); } /*********************************************************************************/ /* */ /* info_c implementation */ /* */ /*********************************************************************************/ // Info for commands uno::Reference< XCommandInfo > SAL_CALL shell::info_c() throw() { XCommandInfo_impl* p = new XCommandInfo_impl( this ); return uno::Reference< XCommandInfo >( p ); } /*********************************************************************************/ /* */ /* info_p-Implementation */ /* */ /*********************************************************************************/ // Info for the properties uno::Reference< beans::XPropertySetInfo > SAL_CALL shell::info_p( const rtl::OUString& aUnqPath ) throw() { osl::MutexGuard aGuard( m_aMutex ); XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath ); return uno::Reference< beans::XPropertySetInfo >( p ); } /*********************************************************************************/ /* */ /* setv-Implementation */ /* */ /*********************************************************************************/ // // Sets the values of the properties belonging to fileURL aUnqPath // uno::Sequence< uno::Any > SAL_CALL shell::setv( const rtl::OUString& aUnqPath, const uno::Sequence< beans::PropertyValue >& values ) throw() { osl::MutexGuard aGuard( m_aMutex ); sal_Int32 propChanged = 0; uno::Sequence< uno::Any > ret( values.getLength() ); uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() ); shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); PropertySet& properties = *( it->second.properties ); shell::PropertySet::iterator it1; uno::Any aAny; for( sal_Int32 i = 0; i < values.getLength(); ++i ) { MyProperty toset( values[i].Name ); it1 = properties.find( toset ); if( it1 == properties.end() ) { ret[i] <<= beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); continue; } aAny = it1->getValue(); if( aAny == values[i].Value ) continue; // nothing needs to be changed if( it1->getAttributes() & beans::PropertyAttribute::READONLY ) { ret[i] <<= lang::IllegalAccessException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); continue; } seqChanged[ propChanged ].PropertyName = values[i].Name; seqChanged[ propChanged ].PropertyHandle = -1; seqChanged[ propChanged ].Further = false; seqChanged[ propChanged ].OldValue <<= aAny; seqChanged[ propChanged++ ].NewValue = values[i].Value; it1->setValue( values[i].Value ); // Put the new value into the local cash if( ! it1->IsNative() ) { // Also put logical properties into storage if( !it->second.xS.is() ) load( it,true ); if( ( values[i].Name == ContentType ) && it1->getState() == beans::PropertyState_DEFAULT_VALUE ) { // Special logic for ContentType // 09.07.01: Not reached anymore, because ContentType is readonly it1->setState( beans::PropertyState_DIRECT_VALUE ); it->second.xC->addProperty( values[i].Name, beans::PropertyAttribute::MAYBEVOID, values[i].Value ); } try { it->second.xS->setPropertyValue( values[i].Name,values[i].Value ); } catch( const uno::Exception& e ) { --propChanged; // unsuccessful setting ret[i] <<= e; } } else { // native properties // Setting of physical file properties if( values[i].Name == Size ) { sal_Int64 newSize = 0; if( values[i].Value >>= newSize ) { // valid value for the size osl::File aFile(aUnqPath); bool err = aFile.open(OpenFlag_Write) != osl::FileBase::E_None || aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None || aFile.close() != osl::FileBase::E_None; if( err ) { --propChanged; // unsuccessful setting uno::Sequence< uno::Any > names( 1 ); ret[0] <<= beans::PropertyValue( rtl::OUString::createFromAscii("Uri"), -1, uno::makeAny(aUnqPath), beans::PropertyState_DIRECT_VALUE); IOErrorCode ioError(IOErrorCode_GENERAL); ret[i] <<= InteractiveAugmentedIOException( rtl::OUString(), 0, task::InteractionClassification_ERROR, ioError, names ); } } else ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } else if(values[i].Name == IsReadOnly || values[i].Name == IsHidden) { sal_Bool value = sal_False; if( values[i].Value >>= value ) { osl::DirectoryItem aDirItem; osl::FileBase::RC err = osl::DirectoryItem::get(aUnqPath,aDirItem); sal_uInt64 nAttributes(0); if(err == osl::FileBase::E_None) { osl::FileStatus aFileStatus(FileStatusMask_Attributes); err = aDirItem.getFileStatus(aFileStatus); if(err == osl::FileBase::E_None && aFileStatus.isValid(FileStatusMask_Attributes)) nAttributes = aFileStatus.getAttributes(); } // now we have the attributes provided all went well. if(err == osl::FileBase::E_None) { if(values[i].Name == IsReadOnly) { nAttributes &= ~(Attribute_OwnWrite | Attribute_GrpWrite | Attribute_OthWrite | Attribute_ReadOnly); if(value) nAttributes |= Attribute_ReadOnly; else nAttributes |= ( Attribute_OwnWrite | Attribute_GrpWrite | Attribute_OthWrite); } else if(values[i].Name == IsHidden) { nAttributes &= ~(Attribute_Hidden); if(value) nAttributes |= Attribute_Hidden; } err = osl::File::setAttributes( aUnqPath,nAttributes); } if( err != osl::FileBase::E_None ) { --propChanged; // unsuccessful setting uno::Sequence< uno::Any > names( 1 ); names[0] <<= beans::PropertyValue( rtl::OUString::createFromAscii("Uri"), -1, uno::makeAny(aUnqPath), beans::PropertyState_DIRECT_VALUE); IOErrorCode ioError; switch( err ) { case osl::FileBase::E_NOMEM: // not enough memory for allocating structures
ioError = IOErrorCode_OUT_OF_MEMORY; break; case osl::FileBase::E_INVAL: // the format of the parameters was not valid

ioError = IOErrorCode_INVALID_PARAMETER; break; case osl::FileBase::E_NAMETOOLONG: // File name too long
ioError = IOErrorCode_NAME_TOO_LONG; break; case osl::FileBase::E_NOENT: // No such file or directory
case osl::FileBase::E_NOLINK: // Link has been severed
ioError = IOErrorCode_NOT_EXISTING; break; case osl::FileBase::E_ROFS: // #i4735# handle ROFS transparently // as ACCESS_DENIED case osl::FileBase::E_PERM: case osl::FileBase::E_ACCES: // permission denied
ioError = IOErrorCode_ACCESS_DENIED; break; case osl::FileBase::E_LOOP: // Too many symbolic links encountered
case osl::FileBase::E_FAULT: // Bad address
case osl::FileBase::E_IO: // I/O error
case osl::FileBase::E_NOSYS: // Function not implemented
case osl::FileBase::E_MULTIHOP: // Multihop attempted
case osl::FileBase::E_INTR: // function call was interrupted

default: ioError = IOErrorCode_GENERAL; break; } ret[i] <<= InteractiveAugmentedIOException( rtl::OUString(), 0, task::InteractionClassification_ERROR, ioError, names ); } } else ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } } } // end for if( propChanged ) { seqChanged.realloc( propChanged ); notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged ); } return ret; } /*********************************************************************************/ /* */ /* getv-Implementation */ /* */ /*********************************************************************************/ // // Reads the values of the properties belonging to fileURL aUnqPath; // Returns an XRow object containing the values in the requested order. // uno::Reference< sdbc::XRow > SAL_CALL shell::getv( sal_Int32 CommandId, const rtl::OUString& aUnqPath, const uno::Sequence< beans::Property >& properties ) throw() { uno::Sequence< uno::Any > seq( properties.getLength() ); sal_Int32 n_Mask; getMaskFromProperties( n_Mask,properties ); osl::FileStatus aFileStatus( n_Mask ); osl::DirectoryItem aDirItem; osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem ); if( nError1 != osl::FileBase::E_None ) installError(CommandId, TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED nError1); osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus ); if( nError1 == osl::FileBase::E_None && nError2 != osl::FileBase::E_None ) installError(CommandId, TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED nError2); { osl::MutexGuard aGuard( m_aMutex ); shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); commit( it,aFileStatus ); shell::PropertySet::iterator it1; PropertySet& propset = *(it->second.properties); for( sal_Int32 i = 0; i < seq.getLength(); ++i ) { MyProperty readProp( properties[i].Name ); it1 = propset.find( readProp ); if( it1 == propset.end() ) seq[i] = uno::Any(); else seq[i] = it1->getValue(); } } XRow_impl* p = new XRow_impl( this,seq ); return uno::Reference< sdbc::XRow >( p ); } /********************************************************************************/ /* */ /* transfer-commandos */ /* */ /********************************************************************************/ /********************************************************************************/ /* */ /* move-implementation */ /* */ /********************************************************************************/ // // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath. // void SAL_CALL shell::move( sal_Int32 CommandId, const rtl::OUString srcUnqPath, const rtl::OUString dstUnqPathIn, const sal_Int32 NameClash ) throw() { // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if // srcUnqPath and dstUnqPathIn are equal if( srcUnqPath == dstUnqPathIn ) return; // <-- // osl::FileBase::RC nError; rtl::OUString dstUnqPath( dstUnqPathIn ); switch( NameClash ) { case NameClash::KEEP: { nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_KEEPERROR_FOR_MOVE, nError ); return; } break; } case NameClash::OVERWRITE: { // stat to determine whether we have a symlink rtl::OUString targetPath(dstUnqPath); osl::FileStatus aStatus(FileStatusMask_Type|FileStatusMask_LinkTargetURL); osl::DirectoryItem aItem; osl::DirectoryItem::get(dstUnqPath,aItem); aItem.getFileStatus(aStatus); if( aStatus.isValid(FileStatusMask_Type) && aStatus.isValid(FileStatusMask_LinkTargetURL) && aStatus.getFileType() == osl::FileStatus::Link ) targetPath = aStatus.getLinkTargetURL(); // Will do nothing if file does not exist. osl::File::remove( targetPath ); nError = osl_File_move( srcUnqPath,targetPath ); if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_OVERWRITE_FOR_MOVE, nError ); return; } break; } case NameClash::RENAME: { rtl::OUString newDstUnqPath; nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError == osl::FileBase::E_EXIST ) { // "invent" a new valid title. sal_Int32 nPos = -1; sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot nPos = nLastDot; else nPos = dstUnqPath.getLength(); sal_Int32 nTry = 0; do { newDstUnqPath = dstUnqPath; rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) ); aPostFix += rtl::OUString::valueOf( ++nTry ); newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix ); nError = osl_File_move( srcUnqPath,newDstUnqPath,true ); } while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); } if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_RENAME_FOR_MOVE ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_RENAMEMOVE_FOR_MOVE, nError ); return; } else dstUnqPath = newDstUnqPath; break; } case NameClash::ERROR: { nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASH_FOR_MOVE ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_NAMECLASHMOVE_FOR_MOVE, nError ); return; } break; } case NameClash::ASK: default: { nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE, NameClash::ASK); return; } } break; } // Determine, whether we have moved a file or a folder osl::DirectoryItem aItem; nError = osl::DirectoryItem::get( dstUnqPath,aItem ); if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_TRANSFER_BY_MOVE_SOURCE, nError ); return; } osl::FileStatus aStatus( FileStatusMask_Type ); nError = aItem.getFileStatus( aStatus ); if( nError != osl::FileBase::E_None || ! aStatus.isValid( FileStatusMask_Type ) ) { installError( CommandId, TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT, nError ); return; } sal_Bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular ); copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument ); rtl::OUString aDstParent = getParentName( dstUnqPath ); rtl::OUString aDstTitle = getTitle( dstUnqPath ); rtl::OUString aSrcParent = getParentName( srcUnqPath ); rtl::OUString aSrcTitle = getTitle( srcUnqPath ); notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath ); if( aDstParent != aSrcParent ) notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath ); notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); erasePersistentSet( srcUnqPath,!isDocument ); } /********************************************************************************/ /* */ /* copy-implementation */ /* */ /********************************************************************************/ // // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories ) // namespace { bool getType( TaskManager & task, sal_Int32 id, rtl::OUString const & fileUrl, osl::DirectoryItem * item, osl::FileStatus::Type * type) { OSL_ASSERT(item != 0 && type != 0); osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item); if (err != osl::FileBase::E_None) { task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err); return false; } osl::FileStatus stat(FileStatusMask_Type); err = item->getFileStatus(stat); if (err != osl::FileBase::E_None) { task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err); return false; } *type = stat.getFileType(); return true; } } void SAL_CALL shell::copy( sal_Int32 CommandId, const rtl::OUString srcUnqPath, const rtl::OUString dstUnqPathIn, sal_Int32 NameClash ) throw() { osl::FileBase::RC nError; rtl::OUString dstUnqPath( dstUnqPathIn ); // Resolve symbolic links within the source path. If srcUnqPath denotes a // symbolic link (targeting either a file or a folder), the contents of the // target is copied (recursively, in the case of a folder). However, if // recursively copying the contents of a folder causes a symbolic link to be // copied, the symbolic link itself is copied. osl::DirectoryItem item; osl::FileStatus::Type type; if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { return; } rtl::OUString rslvdSrcUnqPath; if (type == osl::FileStatus::Link) { osl::FileStatus stat(FileStatusMask_LinkTargetURL); nError = item.getFileStatus(stat); if (nError != osl::FileBase::E_None) { installError( CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError); return; } rslvdSrcUnqPath = stat.getLinkTargetURL(); if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { return; } } else { rslvdSrcUnqPath = srcUnqPath; } sal_Bool isDocument = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume; sal_Int32 IsWhat = isDocument ? -1 : 1; switch( NameClash ) { case NameClash::KEEP: { nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_KEEPERROR_FOR_COPY, nError ); return; } break; } case NameClash::OVERWRITE: { // remove (..., MustExist = sal_False). remove( CommandId, dstUnqPath, IsWhat, sal_False ); // copy. nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false ); if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_OVERWRITE_FOR_COPY, nError ); return; } break; } case NameClash::RENAME: { rtl::OUString newDstUnqPath; nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError == osl::FileBase::E_EXIST ) { // "invent" a new valid title. sal_Int32 nPos = -1; sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot nPos = nLastDot; else nPos = dstUnqPath.getLength(); sal_Int32 nTry = 0; do { newDstUnqPath = dstUnqPath; rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) ); aPostFix += rtl::OUString::valueOf( ++nTry ); newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix ); nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true ); } while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); } if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_RENAME_FOR_COPY ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_RENAMEMOVE_FOR_COPY, nError ); return; } else dstUnqPath = newDstUnqPath; break; } case NameClash::ERROR: { nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASH_FOR_COPY ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_NAMECLASHMOVE_FOR_COPY, nError ); return; } break; } case NameClash::ASK: default: { nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY, NameClash); return; } break; } } copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument ); notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath ); } /********************************************************************************/ /* */ /* remove-implementation */ /* */ /********************************************************************************/ // // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory ) // Return: success of operation // sal_Bool SAL_CALL shell::remove( sal_Int32 CommandId, const rtl::OUString& aUnqPath, sal_Int32 IsWhat, sal_Bool MustExist ) throw() { sal_Int32 nMask = FileStatusMask_Type | FileStatusMask_FileURL; osl::DirectoryItem aItem; osl::FileStatus aStatus( nMask ); osl::FileBase::RC nError; if( IsWhat == 0 ) // Determine whether we are removing a directory or a file { nError = osl::DirectoryItem::get( aUnqPath, aItem ); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE, nError ); } return (!MustExist); } nError = aItem.getFileStatus( aStatus ); if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) { installError( CommandId, TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE, nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); return sal_False; } if( aStatus.getFileType() == osl::FileStatus::Regular || aStatus.getFileType() == osl::FileStatus::Link ) IsWhat = -1; // RemoveFile else if( aStatus.getFileType() == osl::FileStatus::Directory || aStatus.getFileType() == osl::FileStatus::Volume ) IsWhat = +1; // RemoveDirectory } if( IsWhat == -1 ) // Removing a file { nError = osl::File::remove( aUnqPath ); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_DELETEFILE_FOR_REMOVE, nError ); } return (!MustExist); } else { notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet } } else if( IsWhat == +1 ) // Removing a directory { osl::Directory aDirectory( aUnqPath ); nError = aDirectory.open(); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_OPENDIRECTORY_FOR_REMOVE, nError ); } return (!MustExist); } sal_Bool whileSuccess = sal_True; sal_Int32 recurse = 0; rtl::OUString name; nError = aDirectory.getNextItem( aItem ); while( nError == osl::FileBase::E_None ) { nError = aItem.getFileStatus( aStatus ); if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) { installError( CommandId, TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE, nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); whileSuccess = sal_False; break; } if( aStatus.getFileType() == osl::FileStatus::Regular || aStatus.getFileType() == osl::FileStatus::Link ) recurse = -1; else if( aStatus.getFileType() == osl::FileStatus::Directory || aStatus.getFileType() == osl::FileStatus::Volume ) recurse = +1; name = aStatus.getFileURL(); whileSuccess = remove( CommandId, name, recurse, MustExist ); if( !whileSuccess ) break; nError = aDirectory.getNextItem( aItem ); } aDirectory.close(); if( ! whileSuccess ) return sal_False; // error code is installed if( nError != osl::FileBase::E_NOENT ) { installError( CommandId, TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE, nError ); return sal_False; } nError = osl::Directory::remove( aUnqPath ); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE, nError ); } return (!MustExist); } else { notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); erasePersistentSet( aUnqPath ); } } else // Don't know what to remove { installError( CommandId, TASKHANDLING_FILETYPE_FOR_REMOVE ); return sal_False; } return sal_True; } /********************************************************************************/ /* */ /* mkdir-implementation */ /* */ /********************************************************************************/ // // Creates new directory with given URL, recursively if necessary // Return:: success of operation // sal_Bool SAL_CALL shell::mkdir( sal_Int32 CommandId, const rtl::OUString& rUnqPath, sal_Bool OverWrite ) throw() { rtl::OUString aUnqPath; // remove trailing slash if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) ) aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); else aUnqPath = rUnqPath; osl::FileBase::RC nError = osl::Directory::create( aUnqPath ); switch ( nError ) { case osl::FileBase::E_EXIST: // Directory cannot be overwritten { if( !OverWrite ) { installError( CommandId, TASKHANDLING_FOLDER_EXISTS_MKDIR ); return sal_False; } else return sal_True; } case osl::FileBase::E_INVAL: { installError(CommandId, TASKHANDLING_INVALID_NAME_MKDIR); return sal_False; } case osl::FileBase::E_None: { rtl::OUString aPrtPath = getParentName( aUnqPath ); notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); return sal_True; } default: return ensuredir( CommandId, aUnqPath, TASKHANDLING_CREATEDIRECTORY_MKDIR ); } } /********************************************************************************/ /* */ /* mkfil-implementation */ /* */ /********************************************************************************/ // // Creates new file with given URL. // The content of aInputStream becomes the content of the file // Return:: success of operation // sal_Bool SAL_CALL shell::mkfil( sal_Int32 CommandId, const rtl::OUString& aUnqPath, sal_Bool Overwrite, const uno::Reference< io::XInputStream >& aInputStream ) throw() { // return value unimportant sal_Bool bSuccess = write( CommandId, aUnqPath, Overwrite, aInputStream ); if ( bSuccess ) { rtl::OUString aPrtPath = getParentName( aUnqPath ); notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); } return bSuccess; } /********************************************************************************/ /* */ /* write-implementation */ /* */ /********************************************************************************/ // // writes to the file with given URL. // The content of aInputStream becomes the content of the file // Return:: success of operation // sal_Bool SAL_CALL shell::write( sal_Int32 CommandId, const rtl::OUString& aUnqPath, sal_Bool OverWrite, const uno::Reference< io::XInputStream >& aInputStream ) throw() { if( ! aInputStream.is() ) { installError( CommandId, TASKHANDLING_INPUTSTREAM_FOR_WRITE ); return sal_False; } // Create parent path, if necessary. if ( ! ensuredir( CommandId, getParentName( aUnqPath ), TASKHANDLING_ENSUREDIR_FOR_WRITE ) ) return sal_False; osl::FileBase::RC err; osl::File aFile( aUnqPath ); if( OverWrite ) { err = aFile.open( OpenFlag_Write | OpenFlag_Create ); if( err != osl::FileBase::E_None ) { aFile.close(); err = aFile.open( OpenFlag_Write ); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE, err ); return sal_False; } // the existing file was just opened and should be overwritten now, // truncate it first err = aFile.setSize( 0 ); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_FILESIZE_FOR_WRITE, err ); return sal_False; } } } else { err = aFile.open( OpenFlag_Read | OpenFlag_NoLock ); if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten { installError( CommandId, TASKHANDLING_NOREPLACE_FOR_WRITE, // Now an exception err ); aFile.close(); return sal_False; } // as a temporary solution the creation does not lock the file at all // in future it should be possible to create the file without lock explicitly err = aFile.open( OpenFlag_Write | OpenFlag_Create | OpenFlag_NoLock ); if( err != osl::FileBase::E_None ) { aFile.close(); installError( CommandId, TASKHANDLING_NO_OPEN_FILE_FOR_WRITE, err ); return sal_False; } } sal_Bool bSuccess = sal_True; sal_uInt64 nWrittenBytes; sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/; uno::Sequence< sal_Int8 > seq( nRequestedBytes ); do { try { nReadBytes = aInputStream->readBytes( seq, nRequestedBytes ); } catch( const io::NotConnectedException& ) { installError( CommandId, TASKHANDLING_NOTCONNECTED_FOR_WRITE ); bSuccess = sal_False; break; } catch( const io::BufferSizeExceededException& ) { installError( CommandId, TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE ); bSuccess = sal_False; break; } catch( const io::IOException& ) { installError( CommandId, TASKHANDLING_IOEXCEPTION_FOR_WRITE ); bSuccess = sal_False; break; } if( nReadBytes ) { const sal_Int8* p = seq.getConstArray(); err = aFile.write( ((void*)(p)), sal_uInt64( nReadBytes ), nWrittenBytes ); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_FILEIOERROR_FOR_WRITE, err ); bSuccess = sal_False; break; } else if( nWrittenBytes != sal_uInt64( nReadBytes ) ) { installError( CommandId, TASKHANDLING_FILEIOERROR_FOR_NO_SPACE ); bSuccess = sal_False; break; } } } while( nReadBytes == nRequestedBytes ); err = aFile.close(); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_FILEIOERROR_FOR_WRITE, err ); bSuccess = sal_False; } return bSuccess; } /*********************************************************************************/ /* */ /* insertDefaultProperties-Implementation */ /* */ /*********************************************************************************/ void SAL_CALL shell::insertDefaultProperties( const rtl::OUString& aUnqPath ) { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; load( it,false ); MyProperty ContentTProperty( ContentType ); PropertySet& properties = *(it->second.properties); sal_Bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end(); shell::PropertySet::iterator it1 = m_aDefaultProperties.begin(); while( it1 != m_aDefaultProperties.end() ) { if( ContentNotDefau && it1->getPropertyName() == ContentType ) { // No insertion } else properties.insert( *it1 ); ++it1; } } /******************************************************************************/ /* */ /* mapping of file urls */ /* to uncpath and vice versa */ /* */ /******************************************************************************/ sal_Bool SAL_CALL shell::getUnqFromUrl( const rtl::OUString& Url,rtl::OUString& Unq ) { if( 0 == Url.compareToAscii( "file:///" ) || 0 == Url.compareToAscii( "file://localhost/" ) || 0 == Url.compareToAscii( "file://127.0.0.1/" ) ) { Unq = rtl::OUString::createFromAscii( "file:///" ); return false; } sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq ); Unq = Url; sal_Int32 l = Unq.getLength()-1; if( ! err && Unq.getStr()[ l ] == '/' && Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) < l ) Unq = Unq.copy(0, Unq.getLength() - 1); return err; } sal_Bool SAL_CALL shell::getUrlFromUnq( const rtl::OUString& Unq,rtl::OUString& Url ) { sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url ); Url = Unq; return err; } // Helper function for public copy osl::FileBase::RC SAL_CALL shell::copy_recursive( const rtl::OUString& srcUnqPath, const rtl::OUString& dstUnqPath, sal_Int32 TypeToCopy, sal_Bool testExistBeforeCopy ) throw() { osl::FileBase::RC err = osl::FileBase::E_None; if( TypeToCopy == -1 ) // Document { err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy ); } else if( TypeToCopy == +1 ) // Folder { osl::Directory aDir( srcUnqPath ); aDir.open(); err = osl::Directory::create( dstUnqPath ); osl::FileBase::RC next = err; if( err == osl::FileBase::E_None ) { sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type; osl::DirectoryItem aDirItem; while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None ) { sal_Bool IsDoc = false; osl::FileStatus aFileStatus( n_Mask ); aDirItem.getFileStatus( aFileStatus ); if( aFileStatus.isValid( FileStatusMask_Type ) ) IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; // Getting the information for the next recursive copy sal_Int32 newTypeToCopy = IsDoc ? -1 : +1; rtl::OUString newSrcUnqPath; if( aFileStatus.isValid( FileStatusMask_FileURL ) ) newSrcUnqPath = aFileStatus.getFileURL(); rtl::OUString newDstUnqPath = dstUnqPath; rtl::OUString tit; if( aFileStatus.isValid( FileStatusMask_FileName ) ) tit = rtl::Uri::encode( aFileStatus.getFileName(), rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 ); if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 ) newDstUnqPath += rtl::OUString::createFromAscii( "/" ); newDstUnqPath += tit; if ( newSrcUnqPath != dstUnqPath ) err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false ); } if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) err = next; } aDir.close(); } return err; } // Helper function for mkfil,mkdir and write // Creates whole path // returns success of the operation sal_Bool SAL_CALL shell::ensuredir( sal_Int32 CommandId, const rtl::OUString& rUnqPath, sal_Int32 errorCode ) throw() { rtl::OUString aPath; if ( rUnqPath.getLength() < 1 ) return sal_False; if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) ) aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); else aPath = rUnqPath; // HACK: create directory on a mount point with nobrowse option // returns ENOSYS in any case !! osl::Directory aDirectory( aPath ); osl::FileBase::RC nError = aDirectory.open(); aDirectory.close(); if( nError == osl::File::E_None ) return sal_True; nError = osl::Directory::create( aPath ); if( nError == osl::File::E_None ) notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); sal_Bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); if( ! bSuccess ) { rtl::OUString aParentDir = getParentName( aPath ); if ( aParentDir != aPath ) { // Create first the parent directory bSuccess = ensuredir( CommandId, getParentName( aPath ), errorCode ); // After parent directory structure exists try it one's more if ( bSuccess ) { // Parent directory exists, retry creation of directory nError = osl::Directory::create( aPath ); if( nError == osl::File::E_None ) notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); } } } if( ! bSuccess ) installError( CommandId, errorCode, nError ); return bSuccess; } // // Given a sequence of properties seq, this method determines the mask // used to instantiate a osl::FileStatus, so that a call to // osl::DirectoryItem::getFileStatus fills the required fields. // void SAL_CALL shell::getMaskFromProperties( sal_Int32& n_Mask, const uno::Sequence< beans::Property >& seq ) { n_Mask = 0; for(sal_Int32 j = 0; j < seq.getLength(); ++j) { if(seq[j].Name == Title) n_Mask |= FileStatusMask_FileName; else if(seq[j].Name == CasePreservingURL) n_Mask |= FileStatusMask_FileURL; else if(seq[j].Name == IsDocument || seq[j].Name == IsFolder || seq[j].Name == IsVolume || seq[j].Name == IsRemoveable || seq[j].Name == IsRemote || seq[j].Name == IsCompactDisc || seq[j].Name == IsFloppy || seq[j].Name == ContentType) n_Mask |= (FileStatusMask_Type | FileStatusMask_LinkTargetURL); else if(seq[j].Name == Size) n_Mask |= (FileStatusMask_FileSize | FileStatusMask_Type | FileStatusMask_LinkTargetURL); else if(seq[j].Name == IsHidden || seq[j].Name == IsReadOnly) n_Mask |= FileStatusMask_Attributes; else if(seq[j].Name == DateModified) n_Mask |= FileStatusMask_ModifyTime; // n_Mask = FileStatusMask_FileURL; // n_Mask |= FileStatusMask_LinkTargetURL; // n_Mask |= FileStatusMask_FileName; // n_Mask |= FileStatusMask_Type; // n_Mask |= FileStatusMask_ModifyTime; // n_Mask |= FileStatusMask_FileSize; // n_Mask |= FileStatusMask_Attributes; } } /*********************************************************************************/ /* */ /* load-Implementation */ /* */ /*********************************************************************************/ // // Load the properties from configuration, if create == true create them. // The Properties are stored under the url belonging to it->first. // void SAL_CALL shell::load( const ContentMap::iterator& it, sal_Bool create ) { if( ! it->second.properties ) it->second.properties = new PropertySet; if( ( ! it->second.xS.is() || ! it->second.xC.is() || ! it->second.xA.is() ) && m_xFileRegistry.is() ) { uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create ); if( xS.is() ) { uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY ); uno::Reference< beans::XPropertyAccess > xA( xS,uno::UNO_QUERY ); it->second.xS = xS; it->second.xC = xC; it->second.xA = xA; // Now put in all values in the storage in the local hash; PropertySet& properties = *(it->second.properties); uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties(); for( sal_Int32 i = 0; i < seq.getLength(); ++i ) { MyProperty readProp( false, seq[i].Name, seq[i].Handle, seq[i].Type, xS->getPropertyValue( seq[i].Name ), beans::PropertyState_DIRECT_VALUE, seq[i].Attributes ); if( properties.find( readProp ) == properties.end() ) properties.insert( readProp ); } } else if( create ) { // Catastrophic error } } } /*********************************************************************************/ /* */ /* commit-Implementation */ /* */ /*********************************************************************************/ // Commit inserts the determined properties in the filestatus object into // the internal map, so that is possible to determine on a subsequent // setting of file properties which properties have changed without filestat void SAL_CALL shell::commit( const shell::ContentMap::iterator& it, const osl::FileStatus& aFileStatus ) { uno::Any aAny; uno::Any emptyAny; shell::PropertySet::iterator it1; if( it->second.properties == 0 ) { rtl::OUString aPath = it->first; insertDefaultProperties( aPath ); } PropertySet& properties = *( it->second.properties ); it1 = properties.find( MyProperty( Title ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( FileStatusMask_FileName ) ) { aAny <<= aFileStatus.getFileName(); it1->setValue( aAny ); } } it1 = properties.find( MyProperty( CasePreservingURL ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( FileStatusMask_FileURL ) ) { aAny <<= aFileStatus.getFileURL(); it1->setValue( aAny ); } } sal_Bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc; sal_Int64 dirSize = 0; if( aFileStatus.isValid( FileStatusMask_FileSize ) ) dirSize = aFileStatus.getFileSize(); if( aFileStatus.isValid( FileStatusMask_Type ) ) { if( osl::FileStatus::Link == aFileStatus.getFileType() && aFileStatus.isValid( FileStatusMask_LinkTargetURL ) ) { osl::DirectoryItem aDirItem; osl::FileStatus aFileStatus2( FileStatusMask_Type ); if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) && osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) && aFileStatus2.isValid( FileStatusMask_Type ) ) { isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType(); isDirectory = osl::FileStatus::Volume == aFileStatus2.getFileType() || osl::FileStatus::Directory == aFileStatus2.getFileType(); isFile = osl::FileStatus::Regular == aFileStatus2.getFileType(); if( aFileStatus2.isValid( FileStatusMask_FileSize ) ) dirSize = aFileStatus2.getFileSize(); } else { // extremely ugly, but otherwise default construction // of aDirItem and aFileStatus2 // before the preciding if isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); isDirectory = osl::FileStatus::Volume == aFileStatus.getFileType() || osl::FileStatus::Directory == aFileStatus.getFileType(); isFile = osl::FileStatus::Regular == aFileStatus.getFileType(); } } else { isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); isDirectory = osl::FileStatus::Volume == aFileStatus.getFileType() || osl::FileStatus::Directory == aFileStatus.getFileType(); isFile = osl::FileStatus::Regular == aFileStatus.getFileType(); } it1 = properties.find( MyProperty( IsVolume ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isVolume ) ); it1 = properties.find( MyProperty( IsFolder ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isDirectory ) ); it1 = properties.find( MyProperty( IsDocument ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isFile ) ); osl::VolumeInfo aVolumeInfo( VolumeInfoMask_Attributes ); if( isVolume && osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) && aVolumeInfo.isValid( VolumeInfoMask_Attributes ) ) { // Retrieve the flags; isRemote = aVolumeInfo.getRemoteFlag(); isRemoveable = aVolumeInfo.getRemoveableFlag(); isCompactDisc = aVolumeInfo.getCompactDiscFlag(); isFloppy = aVolumeInfo.getFloppyDiskFlag(); it1 = properties.find( MyProperty( IsRemote ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isRemote ) ); it1 = properties.find( MyProperty( IsRemoveable ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isRemoveable ) ); it1 = properties.find( MyProperty( IsCompactDisc ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isCompactDisc ) ); it1 = properties.find( MyProperty( IsFloppy ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isFloppy ) ); } else { sal_Bool dummy = false; aAny <<= dummy; it1 = properties.find( MyProperty( IsRemote ) ); if( it1 != properties.end() ) it1->setValue( aAny ); it1 = properties.find( MyProperty( IsRemoveable ) ); if( it1 != properties.end() ) it1->setValue( aAny ); it1 = properties.find( MyProperty( IsCompactDisc ) ); if( it1 != properties.end() ) it1->setValue( aAny ); it1 = properties.find( MyProperty( IsFloppy ) ); if( it1 != properties.end() ) it1->setValue( aAny ); } } else { isDirectory = sal_False; } it1 = properties.find( MyProperty( Size ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( dirSize ) ); it1 = properties.find( MyProperty( IsReadOnly ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( FileStatusMask_Attributes ) ) { sal_uInt64 Attr = aFileStatus.getAttributes(); sal_Bool readonly = ( Attr & Attribute_ReadOnly ) != 0; it1->setValue( uno::makeAny( readonly ) ); } } it1 = properties.find( MyProperty( IsHidden ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( FileStatusMask_Attributes ) ) { sal_uInt64 Attr = aFileStatus.getAttributes(); sal_Bool ishidden = ( Attr & Attribute_Hidden ) != 0; it1->setValue( uno::makeAny( ishidden ) ); } } it1 = properties.find( MyProperty( DateModified ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( FileStatusMask_ModifyTime ) ) { TimeValue temp = aFileStatus.getModifyTime(); // Convert system time to local time (for EA) TimeValue myLocalTime; osl_getLocalTimeFromSystemTime( &temp, &myLocalTime ); oslDateTime myDateTime; osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime ); util::DateTime aDateTime; aDateTime.HundredthSeconds = (unsigned short)(myDateTime.NanoSeconds / 10000000); aDateTime.Seconds = myDateTime.Seconds; aDateTime.Minutes = myDateTime.Minutes; aDateTime.Hours = myDateTime.Hours; aDateTime.Day = myDateTime.Day; aDateTime.Month = myDateTime.Month; aDateTime.Year = myDateTime.Year; it1->setValue( uno::makeAny( aDateTime ) ); } } it1 = properties.find( MyProperty( CreatableContentsInfo ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isDirectory || !aFileStatus.isValid( FileStatusMask_Type ) ? queryCreatableContentsInfo() : uno::Sequence< ucb::ContentInfo >() ) ); } // Special optimized method for getting the properties of a // directoryitem, which is returned by osl::DirectoryItem::getNextItem() uno::Reference< sdbc::XRow > SAL_CALL shell::getv( Notifier* pNotifier, const uno::Sequence< beans::Property >& properties, osl::DirectoryItem& aDirItem, rtl::OUString& aUnqPath, sal_Bool& aIsRegular ) { uno::Sequence< uno::Any > seq( properties.getLength() ); sal_Int32 n_Mask; getMaskFromProperties( n_Mask,properties ); // Always retrieve the type and the target URL because item might be a link osl::FileStatus aFileStatus( n_Mask | FileStatusMask_FileURL | FileStatusMask_Type | FileStatusMask_LinkTargetURL ); aDirItem.getFileStatus( aFileStatus ); aUnqPath = aFileStatus.getFileURL(); // If the directory item type is a link retrieve the type of the target if ( aFileStatus.getFileType() == osl::FileStatus::Link ) { // Assume failure aIsRegular = false; osl::FileBase::RC result = osl::FileBase::E_INVAL; osl::DirectoryItem aTargetItem; osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem ); if ( aTargetItem.is() ) { osl::FileStatus aTargetStatus( FileStatusMask_Type ); if ( osl::FileBase::E_None == ( result = aTargetItem.getFileStatus( aTargetStatus ) ) ) aIsRegular = aTargetStatus.getFileType() == osl::FileStatus::Regular; } } else aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular; registerNotifier( aUnqPath,pNotifier ); insertDefaultProperties( aUnqPath ); { osl::MutexGuard aGuard( m_aMutex ); shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); commit( it,aFileStatus ); shell::PropertySet::iterator it1; PropertySet& propset = *(it->second.properties); for( sal_Int32 i = 0; i < seq.getLength(); ++i ) { MyProperty readProp( properties[i].Name ); it1 = propset.find( readProp ); if( it1 == propset.end() ) seq[i] = uno::Any(); else seq[i] = it1->getValue(); } } deregisterNotifier( aUnqPath,pNotifier ); XRow_impl* p = new XRow_impl( this,seq ); return uno::Reference< sdbc::XRow >( p ); } // EventListener std::list< ContentEventNotifier* >* SAL_CALL shell::getContentEventListeners( const rtl::OUString& aName ) { std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; std::list< ContentEventNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); shell::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; ContentEventNotifier* notifier = pointer->cCEL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } std::list< ContentEventNotifier* >* SAL_CALL shell::getContentDeletedEventListeners( const rtl::OUString& aName ) { std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; std::list< ContentEventNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); shell::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; ContentEventNotifier* notifier = pointer->cDEL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } void SAL_CALL shell::notifyInsert( std::list< ContentEventNotifier* >* listeners,const rtl::OUString& aChildName ) { std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyChildInserted( aChildName ); delete (*it); ++it; } delete listeners; } void SAL_CALL shell::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners ) { std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyDeleted(); delete (*it); ++it; } delete listeners; } void SAL_CALL shell::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners, const rtl::OUString& aChildName ) { std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyRemoved( aChildName ); delete (*it); ++it; } delete listeners; } std::list< PropertySetInfoChangeNotifier* >* SAL_CALL shell::getPropertySetListeners( const rtl::OUString& aName ) { std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >; std::list< PropertySetInfoChangeNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); shell::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; PropertySetInfoChangeNotifier* notifier = pointer->cPSL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } void SAL_CALL shell::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners, const rtl::OUString& aPropertyName ) { std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyPropertyAdded( aPropertyName ); delete (*it); ++it; } delete listeners; } void SAL_CALL shell::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners, const rtl::OUString& aPropertyName ) { std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyPropertyRemoved( aPropertyName ); delete (*it); ++it; } delete listeners; } std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL shell::getContentExchangedEventListeners( const rtl::OUString aOldPrefix, const rtl::OUString aNewPrefix, sal_Bool withChilds ) { std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap = new std::vector< std::list< ContentEventNotifier* >* >; std::vector< std::list< ContentEventNotifier* >* >& aVector = *aVectorOnHeap; sal_Int32 count; rtl::OUString aOldName; rtl::OUString aNewName; std::vector< rtl::OUString > oldChildList; { osl::MutexGuard aGuard( m_aMutex ); if( ! withChilds ) { aOldName = aOldPrefix; aNewName = aNewPrefix; count = 1; } else { ContentMap::iterator itnames = m_aContent.begin(); while( itnames != m_aContent.end() ) { if( isChild( aOldPrefix,itnames->first ) ) { oldChildList.push_back( itnames->first ); } ++itnames; } count = oldChildList.size(); } for( sal_Int32 j = 0; j < count; ++j ) { std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; std::list< ContentEventNotifier* >& listeners = *p; if( withChilds ) { aOldName = oldChildList[j]; aNewName = newName( aNewPrefix,aOldPrefix,aOldName ); } shell::ContentMap::iterator itold = m_aContent.find( aOldName ); if( itold != m_aContent.end() ) { shell::ContentMap::iterator itnew = m_aContent.insert( ContentMap::value_type( aNewName,UnqPathData() ) ).first; // copy Ownership also delete itnew->second.properties; itnew->second.properties = itold->second.properties; itold->second.properties = 0; // copy existing list std::list< Notifier* >* copyList = itnew->second.notifier; itnew->second.notifier = itold->second.notifier; itold->second.notifier = 0; m_aContent.erase( itold ); if( itnew != m_aContent.end() && itnew->second.notifier ) { std::list& listOfNotifiers = *( itnew->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; ContentEventNotifier* notifier = pointer->cEXC( aNewName ); if( notifier ) listeners.push_back( notifier ); ++it1; } } // Merge with preexisting notifiers // However, these may be in status BaseContent::Deleted if( copyList != 0 ) { std::list< Notifier* >::iterator copyIt = copyList->begin(); while( copyIt != copyList->end() ) { itnew->second.notifier->push_back( *copyIt ); ++copyIt; } } delete copyList; } aVector.push_back( p ); } } return aVectorOnHeap; } void SAL_CALL shell::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec ) { std::list< ContentEventNotifier* >* listeners; for( sal_uInt32 i = 0; i < listeners_vec->size(); ++i ) { listeners = (*listeners_vec)[i]; std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyExchanged(); delete (*it); ++it; } delete listeners; } delete listeners_vec; } std::list< PropertyChangeNotifier* >* SAL_CALL shell::getPropertyChangeNotifier( const rtl::OUString& aName ) { std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >; std::list< PropertyChangeNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); shell::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; PropertyChangeNotifier* notifier = pointer->cPCL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } void SAL_CALL shell::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners, const uno::Sequence< beans::PropertyChangeEvent >& seqChanged ) { std::list< PropertyChangeNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyPropertyChanged( seqChanged ); delete (*it); ++it; } delete listeners; } /********************************************************************************/ /* remove persistent propertyset */ /********************************************************************************/ void SAL_CALL shell::erasePersistentSet( const rtl::OUString& aUnqPath, sal_Bool withChilds ) { if( ! m_xFileRegistry.is() ) { OSL_ASSERT( m_xFileRegistry.is() ); return; } uno::Sequence< rtl::OUString > seqNames; if( withChilds ) { uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); seqNames = xName->getElementNames(); } sal_Int32 count = withChilds ? seqNames.getLength() : 1; rtl::OUString old_Name = aUnqPath; for( sal_Int32 j = 0; j < count; ++j ) { if( withChilds && ! ( isChild( old_Name,seqNames[j] ) ) ) continue; if( withChilds ) { old_Name = seqNames[j]; } { // Release possible references osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.find( old_Name ); if( it != m_aContent.end() ) { it->second.xS = 0; it->second.xC = 0; it->second.xA = 0; delete it->second.properties; it->second.properties = 0; } } if( m_xFileRegistry.is() ) m_xFileRegistry->removePropertySet( old_Name ); } } /********************************************************************************/ /* copy persistent propertyset */ /* from srcUnqPath to dstUnqPath */ /********************************************************************************/ void SAL_CALL shell::copyPersistentSet( const rtl::OUString& srcUnqPath, const rtl::OUString& dstUnqPath, sal_Bool withChilds ) { if( ! m_xFileRegistry.is() ) { OSL_ASSERT( m_xFileRegistry.is() ); return; } uno::Sequence< rtl::OUString > seqNames; if( withChilds ) { uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); seqNames = xName->getElementNames(); } sal_Int32 count = withChilds ? seqNames.getLength() : 1; rtl::OUString old_Name = srcUnqPath, new_Name = dstUnqPath; for( sal_Int32 j = 0; j < count; ++j ) { if( withChilds && ! ( isChild( srcUnqPath,seqNames[j] ) ) ) continue; if( withChilds ) { old_Name = seqNames[j]; new_Name = newName( dstUnqPath,srcUnqPath,old_Name ); } uno::Reference< XPersistentPropertySet > x_src; if( m_xFileRegistry.is() ) { x_src = m_xFileRegistry->openPropertySet( old_Name,false ); m_xFileRegistry->removePropertySet( new_Name ); } if( x_src.is() ) { uno::Sequence< beans::Property > seqProperty = x_src->getPropertySetInfo()->getProperties(); if( seqProperty.getLength() ) { uno::Reference< XPersistentPropertySet > x_dstS = m_xFileRegistry->openPropertySet( new_Name,true ); uno::Reference< beans::XPropertyContainer > x_dstC( x_dstS,uno::UNO_QUERY ); for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i ) { x_dstC->addProperty( seqProperty[i].Name, seqProperty[i].Attributes, x_src->getPropertyValue( seqProperty[i].Name ) ); } } } } // end for( sal_Int... } uno::Sequence< ucb::ContentInfo > shell::queryCreatableContentsInfo() { uno::Sequence< ucb::ContentInfo > seq(2); // file seq[0].Type = FileContentType; seq[0].Attributes = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | ucb::ContentInfoAttribute::KIND_DOCUMENT; uno::Sequence< beans::Property > props( 1 ); props[0] = beans::Property( rtl::OUString::createFromAscii( "Title" ), -1, getCppuType( static_cast< rtl::OUString* >( 0 ) ), beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ); seq[0].Properties = props; // folder seq[1].Type = FolderContentType; seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER; seq[1].Properties = props; return seq; } /*******************************************************************************/ /* */ /* some misceancellous static functions */ /* */ /*******************************************************************************/ void SAL_CALL shell::getScheme( rtl::OUString& Scheme ) { Scheme = rtl::OUString::createFromAscii( "file" ); } rtl::OUString SAL_CALL shell::getImplementationName_static( void ) { return rtl::OUString::createFromAscii( "com.sun.star.comp.ucb.FileProvider" ); } uno::Sequence< rtl::OUString > SAL_CALL shell::getSupportedServiceNames_static( void ) { rtl::OUString Supported = rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ) ; com::sun::star::uno::Sequence< rtl::OUString > Seq( &Supported,1 ); return Seq; }