diff options
Diffstat (limited to 'ucb/source/ucp/file/shell.cxx')
-rw-r--r-- | ucb/source/ucp/file/shell.cxx | 3068 |
1 files changed, 3068 insertions, 0 deletions
diff --git a/ucb/source/ucp/file/shell.cxx b/ucb/source/ucp/file/shell.cxx new file mode 100644 index 000000000000..769e58c08819 --- /dev/null +++ b/ucb/source/ucp/file/shell.cxx @@ -0,0 +1,3068 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#ifndef INCLUDED_STL_STACK +#include <stack> +#define INCLUDED_STL_STACK +#endif + +#include "osl/diagnose.h" +#include <rtl/ustrbuf.hxx> +#include <osl/time.h> +#include <osl/file.hxx> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <com/sun/star/beans/IllegalTypeException.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/XContentIdentifier.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/ucb/OpenCommandArgument.hpp> +#include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/beans/XPropertiesChangeListener.hpp> +#include <rtl/string.hxx> +#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<Notifier*>::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 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 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 <br> + ioError = IOErrorCode_OUT_OF_MEMORY; + break; + case osl::FileBase::E_INVAL: + // the format of the parameters was not valid<p> + ioError = IOErrorCode_INVALID_PARAMETER; + break; + case osl::FileBase::E_NAMETOOLONG: + // File name too long<br> + ioError = IOErrorCode_NAME_TOO_LONG; + break; + case osl::FileBase::E_NOENT: + // No such file or directory<br> + case osl::FileBase::E_NOLINK: + // Link has been severed<br> + 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<br> + ioError = IOErrorCode_ACCESS_DENIED; + break; + case osl::FileBase::E_LOOP: + // Too many symbolic links encountered<br> + case osl::FileBase::E_FAULT: + // Bad address<br> + case osl::FileBase::E_IO: + // I/O error<br> + case osl::FileBase::E_NOSYS: + // Function not implemented<br> + case osl::FileBase::E_MULTIHOP: + // Multihop attempted<br> + case osl::FileBase::E_INTR: + // function call was interrupted<p> + 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; + } + } + 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 nTotalNumberOfBytes = 0; + 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; + } + + nTotalNumberOfBytes += nWrittenBytes; + } + } while( nReadBytes == nRequestedBytes ); + + err = aFile.setSize( nTotalNumberOfBytes ); + if( err != osl::FileBase::E_None ) + { + installError( CommandId, + TASKHANDLING_FILESIZE_FOR_WRITE, + err ); + bSuccess = sal_False; + } + + 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 = aFileStatus.getFileName(); + 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 + { + // extremly 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<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::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<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::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<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::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<Notifier*>& listOfNotifiers = *( itnew->second.notifier ); + std::list<Notifier*>::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<Notifier*>& listOfNotifiers = *( it->second.notifier ); + std::list<Notifier*>::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; +} |