/**************************************************************
 * 
 * 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_ucb.hxx"
#ifndef INCLUDED_STL_STACK
#include <stack>
#define INCLUDED_STL_STACK
#endif

#include "osl/diagnose.h"
#include <rtl/uri.hxx>
#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;
            }

            // 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
            {
                // 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;
}
