ooo-build r11327 - in trunk: . patches/src680



Author: jholesovsky
Date: Fri Jan 18 21:46:31 2008
New Revision: 11327
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11327&view=rev

Log:
2008-01-18  Jan Holesovsky  <kendy suse cz>

        * patches/src680/webdav-locking.diff,
          patches/src680/apply: Implement locking for WebDAV UCP.


Added:
   trunk/patches/src680/webdav-locking.diff
Modified:
   trunk/ChangeLog
   trunk/patches/src680/apply

Modified: trunk/patches/src680/apply
==============================================================================
--- trunk/patches/src680/apply	(original)
+++ trunk/patches/src680/apply	Fri Jan 18 21:46:31 2008
@@ -527,6 +527,10 @@
 # Move gnome-vfs out of the startup sequence, load it only when needed
 gnome-vfs-late-init.diff, i#84137, jholesov
 
+# WebDAV locking
+# It is in this section because it needs part of the gvfs-related patches
+webdav-locking.diff, n#346711, i#29152, jholesov
+
 
 [ QuickStarter < ooh680-m2 ]
 # External splash screen implementation / 2nd time accelerator

Added: trunk/patches/src680/webdav-locking.diff
==============================================================================
--- (empty file)
+++ trunk/patches/src680/webdav-locking.diff	Fri Jan 18 21:46:31 2008
@@ -0,0 +1,1579 @@
+diff --git a/comphelper/source/misc/mediadescriptor.cxx b/comphelper/source/misc/mediadescriptor.cxx
+index 078309b..5e5d476 100644
+--- comphelper/source/misc/mediadescriptor.cxx
++++ comphelper/source/misc/mediadescriptor.cxx
+@@ -754,9 +754,12 @@ sal_Bool MediaDescriptor::impl_openStreamWithURL(const ::rtl::OUString& sURL)
+     throw(::com::sun::star::uno::RuntimeException)
+ {
+     // prepare the environment
++	css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
+ 	css::uno::Reference< css::task::XInteractionHandler > xOrgInteraction = getUnpackedValueOrDefault(
+ 		MediaDescriptor::PROP_INTERACTIONHANDLER(),
+-		css::uno::Reference< css::task::XInteractionHandler >());
++		css::uno::Reference< css::task::XInteractionHandler > (
++			xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), css::uno::UNO_QUERY )
++		);
+ 
+     StillReadWriteInteraction* pInteraction = new StillReadWriteInteraction(xOrgInteraction);
+ 	css::uno::Reference< css::task::XInteractionHandler > xInteraction(static_cast< css::task::XInteractionHandler* >(pInteraction), css::uno::UNO_QUERY);
+diff --git a/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx b/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
+index 069faa7..7efa34e 100644
+--- ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
++++ ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
+@@ -45,6 +45,10 @@
+ #include "DAVAuthListener.hxx"
+ #endif
+ 
++#ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_HPP_
++#include <com/sun/star/ucb/XCommandEnvironment.hpp>
++#endif
++
+ namespace webdav_ucp
+ {
+     typedef std::pair< rtl::OUString, rtl::OUString > DAVRequestHeader;
+@@ -57,12 +61,12 @@ struct DAVRequestEnvironment
+ //    rtl::Reference< DAVStatusListener >   m_xStatusListener;
+ //    rtl::Reference< DAVProgressListener > m_xStatusListener;
+     DAVRequestHeaders                     m_aRequestHeaders;
+-    uno::Reference< ucb::XCommandEnvironment > m_xEnv;
++    com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > m_xEnv;
+ 
+-DAVRequestEnvironment( const rtl::OUString & rRequestURI,
++    DAVRequestEnvironment( const rtl::OUString & rRequestURI,
+                            const rtl::Reference< DAVAuthListener > & xListener,
+                            const DAVRequestHeaders & rRequestHeaders,
+-                           const uno::Reference< ucb::XCommandEnvironment > & xEnv)
++                           const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv)
+     : m_aRequestURI( rRequestURI ), 
+       m_xAuthListener( xListener ),
+       m_aRequestHeaders( rRequestHeaders ),
+diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.cxx b/ucb/source/ucp/webdav/DAVResourceAccess.cxx
+index aa1c821..668fe20 100644
+--- ucb/source/ucp/webdav/DAVResourceAccess.cxx
++++ ucb/source/ucp/webdav/DAVResourceAccess.cxx
+@@ -47,6 +47,13 @@
+ #include "DAVAuthListenerImpl.hxx"
+ #include "DAVResourceAccess.hxx"
+ 
++#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
++#include <comphelper/processfactory.hxx>
++#endif
++#ifndef _UCBHELPER_COMMANDENVIRONMENT_HXX
++#include <ucbhelper/commandenvironment.hxx>
++#endif
++
+ using namespace webdav_ucp;
+ using namespace com::sun::star;
+ 
+@@ -66,56 +73,55 @@ int DAVAuthListener_Impl::authenticate(
+     ::rtl::OUString & inoutUserName,
+     ::rtl::OUString & outPassWord )
+ {
++    uno::Reference< task::XInteractionHandler > xIH;
++
+     if ( m_xEnv.is() )
+-    {
+-        uno::Reference< task::XInteractionHandler > xIH
+-            = m_xEnv->getInteractionHandler();
+-        if ( xIH.is() )
+-        {
+-            // #102871# - Supply username and password from previous try.
+-            // Password container service depends on this!
+-            if ( inoutUserName.getLength() == 0 )
+-                inoutUserName = m_aPrevUsername;
+-
+-            if ( outPassWord.getLength() == 0 )
+-                outPassWord = m_aPrevPassword;
+-
+-            rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
+-                = new ucbhelper::SimpleAuthenticationRequest( inHostName,
+-                                                              inRealm,
+-                                                              inoutUserName,
+-                                                              outPassWord );
+-            xIH->handle( xRequest.get() );
+-
+-            rtl::Reference< ucbhelper::InteractionContinuation > xSelection
+-				= xRequest->getSelection();
+-            
+-            if ( xSelection.is() )
+-            {
+-                // Handler handled the request.
+-                uno::Reference< task::XInteractionAbort > xAbort(
+-                    xSelection.get(), uno::UNO_QUERY );
+-                if ( !xAbort.is() )
+-                {
+-                    const rtl::Reference<
+-                        ucbhelper::InteractionSupplyAuthentication > & xSupp
+-                        = xRequest->getAuthenticationSupplier();
+-
+-                    inoutUserName = xSupp->getUserName();
+-                    outPassWord   = xSupp->getPassword();
+-		    
+-                    // #102871# - Remember username and password.
+-                    m_aPrevUsername = inoutUserName;
+-                    m_aPrevPassword = outPassWord;
+-
+-                    // go on.
+-                    return 0;
+-                }
+-            }
+-        }
+-    }
+-    // Abort.
+-    return -1;
++        xIH = m_xEnv->getInteractionHandler();
++    else
++        xIH = DAVResourceAccess::createCommandEnvironment()->getInteractionHandler();
++
++    if ( !xIH.is() )
++        return -1;
++
++    // #102871# - Supply username and password from previous try.
++    // Password container service depends on this!
++    if ( inoutUserName.getLength() == 0 )
++        inoutUserName = m_aPrevUsername;
++
++    if ( outPassWord.getLength() == 0 )
++        outPassWord = m_aPrevPassword;
++
++    rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
++        = new ucbhelper::SimpleAuthenticationRequest( inHostName,
++                inRealm,
++                inoutUserName,
++                outPassWord );
++    xIH->handle( xRequest.get() );
++
++    rtl::Reference< ucbhelper::InteractionContinuation > xSelection
++        = xRequest->getSelection();
++
++    if ( !xSelection.is() )
++        return -1;
++
++    // Handler handled the request.
++    uno::Reference< task::XInteractionAbort > xAbort(
++            xSelection.get(), uno::UNO_QUERY );
++    if ( xAbort.is() )
++        return -1;
++
++    const rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp
++        = xRequest->getAuthenticationSupplier();
++
++    inoutUserName = xSupp->getUserName();
++    outPassWord   = xSupp->getPassword();
++
++    // #102871# - Remember username and password.
++    m_aPrevUsername = inoutUserName;
++    m_aPrevPassword = outPassWord;
++
++    // go on.
++    return 0;
+ }
+ 
+ //=========================================================================
+@@ -435,7 +441,7 @@ void DAVResourceAccess::GET(
+ }
+ 
+ //=========================================================================
+-uno::Reference< io::XInputStream > DAVResourceAccess::GET(
++uno::Reference< io::XStream > DAVResourceAccess::GET(
+     const std::vector< rtl::OUString > & rHeaderNames,
+     DAVResource & rResource,
+     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+@@ -443,7 +449,7 @@ uno::Reference< io::XInputStream > DAVResourceAccess::GET(
+ {
+     initialize();
+ 
+-    uno::Reference< io::XInputStream > xStream;
++    uno::Reference< io::XStream > xStream;
+     bool bRetry;
+     do
+     {
+@@ -864,22 +870,44 @@ void DAVResourceAccess::DESTROY(
+ 
+ //=========================================================================
+ void DAVResourceAccess::LOCK ( 
+-    const ucb::Lock & /*rLock*/,
+-    const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
++    ucb::Lock & rLock,
++    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+   throw( DAVException )
+ {
+-//    initialize();
+-    OSL_ENSURE( sal_False, "DAVResourceAccess::LOCK - NYI" );
++    initialize();
++
++    DAVRequestHeaders aHeaders;
++    getUserRequestHeaders( xEnv, 
++            getRequestURI(), 
++            rtl::OUString::createFromAscii( "LOCK" ), 
++            aHeaders );
++    
++    m_xSession->LOCK( rLock,
++            DAVRequestEnvironment(
++                getRequestURI(),
++                new DAVAuthListener_Impl( xEnv ),
++                aHeaders, xEnv ) );
+ }
+ 
+ //=========================================================================
+ void DAVResourceAccess::UNLOCK ( 
+-    const ucb::Lock & /*rLock*/,
+-    const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
++    ucb::Lock & rLock,
++    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+   throw( DAVException )
+ {
+-//    initialize();
+-    OSL_ENSURE( sal_False, "DAVResourceAccess::UNLOCK - NYI" );
++    initialize();
++
++    DAVRequestHeaders aHeaders;
++    getUserRequestHeaders( xEnv, 
++            getRequestURI(), 
++            rtl::OUString::createFromAscii( "UNLOCK" ), 
++            aHeaders );
++
++    m_xSession->UNLOCK( rLock,
++            DAVRequestEnvironment(
++                getRequestURI(),
++                new DAVAuthListener_Impl( xEnv ),
++                aHeaders, xEnv ) );
+ }
+ 
+ //=========================================================================
+@@ -984,6 +1012,18 @@ void DAVResourceAccess::getUserRequestHeaders(
+     }
+ }
+ 
++// static
++com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > DAVResourceAccess::createCommandEnvironment( void )
++{
++    uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
++    uno::Reference< task::XInteractionHandler > xInteractionHandler = uno::Reference< task::XInteractionHandler > (
++            xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), uno::UNO_QUERY );
++    ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, uno::Reference< ucb::XProgressHandler >() );
++
++    return uno::Reference< ucb::XCommandEnvironment >( static_cast< ucb::XCommandEnvironment* >( pCommandEnv ), uno::UNO_QUERY );
++}
++
++
+ //=========================================================================
+ sal_Bool DAVResourceAccess::detectRedirectCycle(
+                                 const rtl::OUString& rRedirectURL )
+diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.hxx b/ucb/source/ucp/webdav/DAVResourceAccess.hxx
+index 66f758c..5069ae7 100644
+--- ucb/source/ucp/webdav/DAVResourceAccess.hxx
++++ ucb/source/ucp/webdav/DAVResourceAccess.hxx
+@@ -167,7 +167,7 @@ public:
+ 	     com::sun::star::ucb::XCommandEnvironment > & xEnv )
+         throw( DAVException );
+ 
+-    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
++    com::sun::star::uno::Reference< com::sun::star::io::XStream >
+     GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
+          DAVResource & rResource,
+          const com::sun::star::uno::Reference<
+@@ -237,13 +237,13 @@ public:
+ 	throw( DAVException );
+ 
+     void
+-    LOCK( const com::sun::star::ucb::Lock & rLock,
++    LOCK( com::sun::star::ucb::Lock & rLock,
+ 	  const com::sun::star::uno::Reference<
+ 	      com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ 	throw( DAVException );
+ 
+     void
+-    UNLOCK( const com::sun::star::ucb::Lock & rLock,
++    UNLOCK( com::sun::star::ucb::Lock & rLock,
+ 	    const com::sun::star::uno::Reference<
+ 	        com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ 	throw( DAVException );
+@@ -256,6 +256,8 @@ public:
+ 	const rtl::OUString & rMethod,
+     DAVRequestHeaders & rRequestHeaders );
+ 
++    static com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > createCommandEnvironment( void );
++
+ private:
+     const rtl::OUString & getRequestURI() const;
+     sal_Bool detectRedirectCycle( const rtl::OUString& rRedirectURL )
+diff --git a/ucb/source/ucp/webdav/DAVSession.hxx b/ucb/source/ucp/webdav/DAVSession.hxx
+index 8462f5a..df5ac71 100644
+--- ucb/source/ucp/webdav/DAVSession.hxx
++++ ucb/source/ucp/webdav/DAVSession.hxx
+@@ -42,12 +42,18 @@
+ #include <rtl/ustring.hxx>
+ #endif
+ 
++#ifndef _COM_SUN_STAR_IO_XSTREAM_HPP_
++#include <com/sun/star/io/XStream.hpp>
++#endif
+ #ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
+ #include <com/sun/star/io/XInputStream.hpp>
+ #endif
+ #ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
+ #include <com/sun/star/io/XOutputStream.hpp>
+ #endif
++#ifndef _COM_SUN_STAR_UCB_LOCK_HPP_
++#include <com/sun/star/ucb/Lock.hpp>
++#endif
+ 
+ #ifndef _DAVEXCEPTION_HXX_
+ #include "DAVException.hxx"
+@@ -140,7 +146,7 @@ public:
+         const DAVRequestEnvironment & rEnv )
+ 		throw( DAVException ) = 0;
+ 
+-    virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
++    virtual com::sun::star::uno::Reference< com::sun::star::io::XStream >
+                     GET( const ::rtl::OUString & inPath,
+                          const std::vector< ::rtl::OUString > & inHeaderNames,
+                          DAVResource & ioResource,
+@@ -199,16 +205,14 @@ public:
+                              const DAVRequestEnvironment & rEnv )
+ 		throw( DAVException ) = 0;
+ 
+-	// Note: Uncomment the following if locking support is required
+-	/*
+-	virtual void LOCK ( const Lock & inLock,
++	virtual void LOCK ( com::sun::star::ucb::Lock & rLock,
+                         const DAVRequestEnvironment & rEnv )
+ 		throw( DAVException ) = 0;
+ 
+-	virtual void UNLOCK ( const Lock & inLock,
++	virtual void UNLOCK ( com::sun::star::ucb::Lock & rLock,
+                           const DAVRequestEnvironment & rEnv )
+ 		throw( DAVException ) = 0;
+-	*/
++
+ protected:
+     rtl::Reference< DAVSessionFactory > m_xFactory;
+ 
+diff --git a/ucb/source/ucp/webdav/NeonInputStream.cxx b/ucb/source/ucp/webdav/NeonInputStream.cxx
+index 334e457..720bd65 100644
+--- ucb/source/ucp/webdav/NeonInputStream.cxx
++++ ucb/source/ucp/webdav/NeonInputStream.cxx
+@@ -36,24 +36,32 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_ucb.hxx"
+ #include "NeonInputStream.hxx"
++#include "DAVResourceAccess.hxx"
+ 
+ #ifndef _RTL_MEMORY_H_
+ #include <rtl/memory.h>
+ #endif
+ 
++#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
++#include <comphelper/processfactory.hxx>
++#endif
++
++#include <cstdio>
++
+ using namespace cppu;
+-using namespace rtl;
+ using namespace com::sun::star::io;
+-using namespace com::sun::star::uno;
++using namespace com::sun::star;
+ using namespace webdav_ucp;
+ 
+ 
+ // -------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------
+-NeonInputStream::NeonInputStream( void )
+-: mLen( 0 ),
+-  mPos( 0 )
++NeonInputStream::NeonInputStream()
++: m_nLen( 0 ),
++  m_nPos( 0 ),
++  m_bDirty( sal_False ),
++  m_pLock( NULL )
+ {
+ }
+ 
+@@ -62,6 +70,7 @@ NeonInputStream::NeonInputStream( void )
+ // -------------------------------------------------------------------
+ NeonInputStream::~NeonInputStream( void )
+ {
++    Unlock();
+ }
+ 
+ // -------------------------------------------------------------------
+@@ -70,24 +79,63 @@ NeonInputStream::~NeonInputStream( void )
+ // -------------------------------------------------------------------
+ void NeonInputStream::AddToStream( const char * inBuf, sal_Int32 inLen )
+ {
+-    mInputBuffer.realloc( sal::static_int_cast<sal_Int32>(mLen) + inLen );
+-    rtl_copyMemory( mInputBuffer.getArray() + mLen, inBuf, inLen );
+-	mLen += inLen;
++    OSL_ENSURE( !m_bDirty, "Cannot AddToStream() when it was already written to it." );
++
++    m_aInputBuffer.realloc( sal::static_int_cast<sal_Int32>(m_nLen) + inLen );
++    rtl_copyMemory( m_aInputBuffer.getArray() + m_nLen, inBuf, inLen );
++    m_nLen += inLen;
++}
++
++// -------------------------------------------------------------------
++// Associate a lock with this stream
++// -------------------------------------------------------------------
++void NeonInputStream::SetLock( const com::sun::star::ucb::Lock &rLock,
++        const rtl::OUString &rURL )
++{
++    m_aURL = rURL;
++
++    if ( !m_pLock )
++        m_pLock = new ucb::Lock( rLock );
++    else
++        *m_pLock = rLock;
+ }
+ 
+ // -------------------------------------------------------------------
+ // queryInterface
+ // -------------------------------------------------------------------
+-Any NeonInputStream::queryInterface( const Type &type )
+-						throw( RuntimeException )
++uno::Any NeonInputStream::queryInterface( const uno::Type &type )
++						throw( uno::RuntimeException )
+ {
+-	Any aRet = ::cppu::queryInterface( type,
+-									   static_cast< XInputStream * >( this ),
+-									   static_cast< XSeekable * >( this ) );
++    uno::Any aRet = ::cppu::queryInterface( type,
++            static_cast< XStream * >( this ),
++            static_cast< XInputStream * >( this ),
++            static_cast< XOutputStream * >( this ),
++            static_cast< XSeekable * >( this ),
++            static_cast< XTruncate * >( this ) );
+ 	return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type );
+ }
+ 
+ // -------------------------------------------------------------------
++// getInputStream
++// -------------------------------------------------------------------
++com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL
++NeonInputStream::getInputStream( void )
++	throw( com::sun::star::uno::RuntimeException )
++{
++    return uno::Reference< XInputStream >( this );
++}
++
++// -------------------------------------------------------------------
++// getOutputStream
++// -------------------------------------------------------------------
++com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL
++NeonInputStream::getOutputStream( void )
++	throw( com::sun::star::uno::RuntimeException )
++{
++    return uno::Reference< XOutputStream >( this );
++}
++
++// -------------------------------------------------------------------
+ // readBytes
+ // "Reads" the specified number of bytes from the stream
+ // -------------------------------------------------------------------
+@@ -100,7 +148,7 @@ sal_Int32 SAL_CALL NeonInputStream::readBytes(
+ {
+ 	// Work out how much we're actually going to write
+ 	sal_Int32 theBytes2Read = nBytesToRead;
+-	sal_Int32 theBytesLeft  = sal::static_int_cast<sal_Int32>(mLen - mPos);
++	sal_Int32 theBytesLeft  = sal::static_int_cast<sal_Int32>(m_nLen - m_nPos);
+ 	if ( theBytes2Read > theBytesLeft )
+ 		theBytes2Read = theBytesLeft;
+ 
+@@ -109,10 +157,10 @@ sal_Int32 SAL_CALL NeonInputStream::readBytes(
+ 
+ 	// Write the data
+ 	rtl_copyMemory(
+-		aData.getArray(), mInputBuffer.getConstArray() + mPos, theBytes2Read );
++		aData.getArray(), m_aInputBuffer.getConstArray() + m_nPos, theBytes2Read );
+ 
+ 	// Update our stream position for next time
+-	mPos += theBytes2Read;
++	m_nPos += theBytes2Read;
+ 
+     return theBytes2Read;
+ }
+@@ -141,9 +189,9 @@ void SAL_CALL NeonInputStream::skipBytes( sal_Int32 nBytesToSkip )
+                ::com::sun::star::io::IOException,
+                ::com::sun::star::uno::RuntimeException )
+ {
+-	mPos += nBytesToSkip;
+-	if ( mPos >= mLen )
+-		mPos = mLen;
++    m_nPos += nBytesToSkip;
++    if ( m_nPos >= m_nLen )
++        m_nPos = m_nLen;
+ }
+ 
+ // -------------------------------------------------------------------
+@@ -155,7 +203,7 @@ sal_Int32 SAL_CALL NeonInputStream::available(  )
+                ::com::sun::star::io::IOException,
+                ::com::sun::star::uno::RuntimeException )
+ {
+-	return sal::static_int_cast<sal_Int32>(mLen - mPos);
++    return sal::static_int_cast<sal_Int32>(m_nLen - m_nPos);
+ }
+ 
+ // -------------------------------------------------------------------
+@@ -176,12 +224,12 @@ void SAL_CALL NeonInputStream::seek( sal_Int64 location )
+ 			   ::com::sun::star::io::IOException,
+ 			   ::com::sun::star::uno::RuntimeException )
+ {
+-	if ( location < 0 )
+-		throw ::com::sun::star::lang::IllegalArgumentException();
++    if ( location < 0 )
++        throw ::com::sun::star::lang::IllegalArgumentException();
+ 
+-    if ( location <= mLen )
+-		mPos = location;
+-	else
++    if ( location <= m_nLen )
++        m_nPos = location;
++    else
+         throw ::com::sun::star::lang::IllegalArgumentException();
+ }
+ 
+@@ -192,7 +240,7 @@ sal_Int64 SAL_CALL NeonInputStream::getPosition()
+ 		throw( ::com::sun::star::io::IOException,
+ 			   ::com::sun::star::uno::RuntimeException )
+ {
+-	return mPos;
++    return m_nPos;
+ }
+ 
+ // -------------------------------------------------------------------
+@@ -202,5 +250,107 @@ sal_Int64 SAL_CALL NeonInputStream::getLength()
+ 		throw( ::com::sun::star::io::IOException,
+ 			   ::com::sun::star::uno::RuntimeException )
+ {
+-	return mLen;
++    return m_nLen;
++}
++
++// -------------------------------------------------------------------
++// writeBytes
++// -------------------------------------------------------------------
++void SAL_CALL NeonInputStream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData )
++	throw( com::sun::star::io::NotConnectedException,
++	       com::sun::star::io::BufferSizeExceededException,
++	       com::sun::star::io::IOException,
++	       com::sun::star::uno::RuntimeException)
++{
++#if OSL_DEBUG_LEVEL > 0
++    fprintf( stderr, "WebDAV: writeBytes()\n" );
++#endif
++
++    sal_Int32 nDataLen = aData.getLength();
++    OSL_ASSERT( nDataLen >= 0 );
++
++    // Anything to do?
++    if ( nDataLen == 0 )
++        return;
++
++    // Update the length of the stream & size of the buffer
++    if ( m_nLen < m_nPos + nDataLen )
++    {
++        m_nLen = m_nPos + nDataLen;
++        if ( m_aInputBuffer.getLength() < m_nLen )
++            m_aInputBuffer.realloc( sal::static_int_cast<sal_Int32>( m_nLen ) );
++    }
++
++    rtl_copyMemory( m_aInputBuffer.getArray() + m_nPos, aData.getConstArray(), nDataLen );
++    m_nPos += nDataLen;
++
++    m_bDirty = sal_True;
++}
++
++// -------------------------------------------------------------------
++// flush
++// -------------------------------------------------------------------
++void SAL_CALL NeonInputStream::flush( void )
++	throw( NotConnectedException, BufferSizeExceededException,
++	       IOException, uno::RuntimeException )
++{
++#if OSL_DEBUG_LEVEL > 0
++    fprintf( stderr, "WebDAV: flush()\n" );
++#endif
++    // Nothing to do, we transfer the data in closeOutput() (if dirty)
++}
++        
++// -------------------------------------------------------------------
++// closeOutput
++// -------------------------------------------------------------------
++void SAL_CALL NeonInputStream::closeOutput( void )
++	throw( com::sun::star::io::NotConnectedException,
++	       com::sun::star::io::IOException,
++	       com::sun::star::uno::RuntimeException )
++{
++    if ( m_bDirty )
++    {
++#if OSL_DEBUG_LEVEL > 0
++        fprintf( stderr, "WebDAV: TODO write on closeOutput(), the stream is dirty!\n" );
++#endif
++    }
++}
++
++// -------------------------------------------------------------------
++// truncate
++// -------------------------------------------------------------------
++void SAL_CALL NeonInputStream::truncate( void )
++	throw( com::sun::star::io::IOException,
++	       com::sun::star::uno::RuntimeException )
++{
++#if OSL_DEBUG_LEVEL > 0
++    fprintf( stderr, "WebDAV: truncate()\n" );
++#endif
++
++    if ( m_nLen > 0 )
++    {
++        m_nLen = m_nPos = 0;
++        m_bDirty = sal_True;
++    }
++}
++
++// -------------------------------------------------------------------
++// Unlock the stream & destroy the lock
++// -------------------------------------------------------------------
++void NeonInputStream::Unlock( void )
++{
++    if ( m_pLock )
++    {
++        // FIXME I guess it is a bit hacky to create the new session just for
++        // the unlock?  But so far it seems I have no other chance...
++        uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
++        rtl::Reference< DAVSessionFactory > rDAVFactory( new DAVSessionFactory() );
++        
++        DAVResourceAccess aResourceAccess( xFactory, rDAVFactory, m_aURL );
++
++        aResourceAccess.UNLOCK( *m_pLock, DAVResourceAccess::createCommandEnvironment() );
++
++        delete m_pLock;
++        m_pLock = NULL;
++    }
+ }
+diff --git a/ucb/source/ucp/webdav/NeonInputStream.hxx b/ucb/source/ucp/webdav/NeonInputStream.hxx
+index 517e6d8..ba470e6 100644
+--- ucb/source/ucp/webdav/NeonInputStream.hxx
++++ ucb/source/ucp/webdav/NeonInputStream.hxx
+@@ -45,12 +45,27 @@
+ #include <cppuhelper/weak.hxx>
+ #endif
+ 
++#ifndef _COM_SUN_STAR_IO_XSTREAM_HPP_
++#include <com/sun/star/io/XStream.hpp>
++#endif
+ #ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
+ #include <com/sun/star/io/XInputStream.hpp>
+ #endif
++#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
++#include <com/sun/star/io/XOutputStream.hpp>
++#endif
+ #ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_
+ #include <com/sun/star/io/XSeekable.hpp>
+ #endif
++#ifndef _COM_SUN_STAR_IO_XTRUNCATE_HPP_
++#include <com/sun/star/io/XTruncate.hpp>
++#endif
++
++#ifndef _COM_SUN_STAR_UCB_LOCK_HPP_
++#include <com/sun/star/ucb/Lock.hpp>
++#endif
++
++#include "DAVRequestEnvironment.hxx"
+ 
+ 
+ namespace webdav_ucp
+@@ -61,21 +76,33 @@ namespace webdav_ucp
+ // A simple XInputStream implementation provided specifically for use
+ // by the DAVSession::GET method.
+ // -------------------------------------------------------------------
+-class NeonInputStream : public ::com::sun::star::io::XInputStream,
++class NeonInputStream : public ::com::sun::star::io::XStream,
++                        public ::com::sun::star::io::XInputStream,
++                        public ::com::sun::star::io::XOutputStream,
+ 						public ::com::sun::star::io::XSeekable,
++                        public ::com::sun::star::io::XTruncate,
+ 						public ::cppu::OWeakObject
+ {
+-	private:
+-		com::sun::star::uno::Sequence< sal_Int8 > mInputBuffer;
+-		sal_Int64 mLen;
+-		sal_Int64 mPos;
++private:
++    com::sun::star::uno::Sequence< sal_Int8 > m_aInputBuffer;
++    sal_Int64                  m_nLen; // cannot be just m_aInputBuffer.getLength() - the buffer can be bigger
++    sal_Int64                  m_nPos;
+ 
+-	public:
+-				 NeonInputStream( void );
+-		virtual ~NeonInputStream();
++    sal_Bool                   m_bDirty;
+ 
+-		// Add some data to the end of the stream
+-		void AddToStream( const char * inBuf, sal_Int32 inLen );
++    com::sun::star::ucb::Lock *m_pLock;
++    rtl::OUString              m_aURL;
++
++public:
++             NeonInputStream( void );
++    virtual ~NeonInputStream();
++
++    // Add some data to the end of the stream
++    void AddToStream( const char * inBuf, sal_Int32 inLen );
++
++    // Associate a lock with this stream
++    void SetLock( const com::sun::star::ucb::Lock &rLock,
++                  const rtl::OUString &rURL );
+ 
+ 	// XInterface
+ 	virtual com::sun::star::uno::Any SAL_CALL queryInterface(
+@@ -90,6 +117,12 @@ class NeonInputStream : public ::com::sun::star::io::XInputStream,
+ 							throw()
+ 								{ OWeakObject::release(); }
+ 
++    // XStream
++    virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL getInputStream( void )
++        throw( com::sun::star::uno::RuntimeException );
++
++    virtual com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL getOutputStream( void )
++        throw( com::sun::star::uno::RuntimeException );
+ 
+ 	// XInputStream
+ 	virtual sal_Int32 SAL_CALL readBytes(
+@@ -137,6 +170,35 @@ class NeonInputStream : public ::com::sun::star::io::XInputStream,
+ 	virtual sal_Int64 SAL_CALL getLength()
+ 		throw( ::com::sun::star::io::IOException,
+ 			   ::com::sun::star::uno::RuntimeException );
++
++    // XOutputStream
++    virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData )
++        throw( com::sun::star::io::NotConnectedException,
++                com::sun::star::io::BufferSizeExceededException,
++                com::sun::star::io::IOException,
++                com::sun::star::uno::RuntimeException);
++
++    virtual void SAL_CALL flush( void )
++        throw( com::sun::star::io::NotConnectedException,
++                com::sun::star::io::BufferSizeExceededException,
++                com::sun::star::io::IOException,
++                com::sun::star::uno::RuntimeException);
++
++
++    virtual void SAL_CALL closeOutput( void )
++        throw( com::sun::star::io::NotConnectedException,
++                com::sun::star::io::IOException,
++                com::sun::star::uno::RuntimeException );
++
++    // XTruncate
++    virtual void SAL_CALL truncate( void )
++        throw( com::sun::star::io::IOException,
++                com::sun::star::uno::RuntimeException );
++    
++protected:
++
++    // Unlock the stream & destroy the lock
++    void Unlock( void );
+ };
+ 
+ } // namespace webdav_ucp
+diff --git a/ucb/source/ucp/webdav/NeonSession.cxx b/ucb/source/ucp/webdav/NeonSession.cxx
+index 0fef0bb..f1ddbf0 100644
+--- ucb/source/ucp/webdav/NeonSession.cxx
++++ ucb/source/ucp/webdav/NeonSession.cxx
+@@ -122,6 +122,9 @@
+ #ifndef _SIMPLECERTIFICATIONVALIDATIONREQUEST_HXX_
+ #include "ucbhelper/simplecertificatevalidationrequest.hxx"
+ #endif
++#ifndef _UCBHELPER_CANCELCOMMANDEXECUTION_HXX_
++#include <ucbhelper/cancelcommandexecution.hxx>
++#endif
+ 
+ #include <cppuhelper/bootstrap.hxx> 
+ 
+@@ -253,12 +256,13 @@ struct NeonRequestContext
+ // -------------------------------------------------------------------
+ 
+ #if NEON_VERSION >= 0250
+-extern "C" int NeonSession_ResponseBlockReader(void * inUserData, 
++extern "C" int
+ #else
+-extern "C" void NeonSession_ResponseBlockReader(void * inUserData, 
++extern "C" void
+ #endif
+-                                               const char * inBuf, 
+-                                               size_t inLen )
++NeonSession_ResponseBlockReader(void * inUserData, 
++                                       const char * inBuf, 
++                                       size_t inLen )
+ {
+     // neon calls this function with (inLen == 0)...
+     if ( inLen > 0 )
+@@ -283,12 +287,13 @@ extern "C" void NeonSession_ResponseBlockReader(void * inUserData,
+ // -------------------------------------------------------------------
+ 
+ #if NEON_VERSION >= 0250
+-extern "C" int NeonSession_ResponseBlockWriter( void * inUserData, 
++extern "C" int
+ #else
+-extern "C" void NeonSession_ResponseBlockWriter( void * inUserData, 
++extern "C" void
+ #endif
+-                                                const char * inBuf, 
+-                                                size_t inLen )
++NeonSession_ResponseBlockWriter( void * inUserData, 
++                                 const char * inBuf, 
++                                 size_t inLen )
+ {
+     // neon calls this function with (inLen == 0)...
+     if ( inLen > 0 )
+@@ -646,16 +651,14 @@ NeonSession::~NeonSession( )
+ {
+     if ( m_pHttpSession )
+     {
++        if ( m_NeonLockStore != NULL )
++        {
++            ne_lockstore_destroy( m_NeonLockStore );
++            m_NeonLockStore = NULL;
++        }
++
+         ne_session_destroy( m_pHttpSession );
+         m_pHttpSession = 0;
+-	// Note: Uncomment the following if locking support is required
+-	/*
+-	  if ( mNeonLockSession != NULL )
+-	  {
+-	  ne_lock_unregister( mNeonLockSession );
+-	  mNeonLockSession = NULL;
+-	  }
+-	*/
+     }
+ 
+     delete static_cast<RequestDataMap*>(m_pRequestData);
+@@ -797,14 +800,14 @@ void NeonSession::Init()
+                               m_nProxyPort );
+         }
+ 
+-        // Note: Uncomment the following if locking support is required
+-        /*
+-        mNeonLockSession = ne_lock_register( m_pHttpSession );
++        m_NeonLockStore = ne_lockstore_create();
+ 
+-        if ( mNeonLockSession == NULL )
++        if ( m_NeonLockStore == NULL )
+             throw DAVException( DAVException::DAV_SESSION_CREATE,
+-                                theUri::makeConnectionEndPointString() );
+-        */
++                                NeonUri::makeConnectionEndPointString( m_aHostName, m_nPort ) );
++
++        // Register the lock store
++        ne_lockstore_register( m_NeonLockStore, m_pHttpSession );
+ 
+         // Register for redirects.
+         ne_redirect_register( m_pHttpSession );
+@@ -1136,7 +1139,7 @@ void NeonSession::GET( const rtl::OUString &                 inPath,
+ // -------------------------------------------------------------------
+ // GET
+ // -------------------------------------------------------------------
+-uno::Reference< io::XInputStream > 
++uno::Reference< io::XStream > 
+ NeonSession::GET( const rtl::OUString & inPath,
+ 		  const std::vector< ::rtl::OUString > & inHeaderNames,
+ 		  DAVResource & ioResource,
+@@ -1152,8 +1155,8 @@ NeonSession::GET( const rtl::OUString & inPath,
+     ioResource.uri = inPath;
+     ioResource.properties.clear();
+ 
+-    rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
+-    NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource );
++    rtl::Reference< NeonInputStream > xStream( new NeonInputStream );
++    NeonRequestContext aCtx( xStream, inHeaderNames, ioResource );
+     int theRetVal = GET( m_pHttpSession,
+                          rtl::OUStringToOString(
+                              inPath, RTL_TEXTENCODING_UTF8 ),
+@@ -1161,7 +1164,7 @@ NeonSession::GET( const rtl::OUString & inPath,
+                          true,
+                          &aCtx );
+     HandleError( theRetVal );
+-    return uno::Reference< io::XInputStream >( xInputStream.get() );
++    return uno::Reference< io::XStream >( xStream.get() );
+ }
+ 
+ // -------------------------------------------------------------------
+@@ -1392,9 +1395,7 @@ void NeonSession::DESTROY( const rtl::OUString & inPath,
+ // -------------------------------------------------------------------
+ // LOCK
+ // -------------------------------------------------------------------
+-// Note: Uncomment the following if locking support is required
+-/*
+-void NeonSession::LOCK( const Lock & inLock,
++void NeonSession::LOCK( ucb::Lock & rLock,
+                         const DAVRequestEnvironment & rEnv )
+ 	throw ( DAVException )
+ {
+@@ -1404,16 +1405,20 @@ void NeonSession::LOCK( const Lock & inLock,
+ 
+     m_aEnv = rEnv;
+ 
+-	Lockit( inLock, true );
++    if ( !Lockit( rLock, true ) )
++    {
++        ucbhelper::cancelCommandExecution( ucb::IOErrorCode_LOCKING_VIOLATION,
++                uno::Sequence< uno::Any >( 0 ), // FIXME more info about the file?
++                rEnv.m_xEnv,
++                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "a locking error occured" ) ),
++                uno::Reference< ucb::XCommandProcessor >() );
++    }
+ }
+-*/
+ 
+ // -------------------------------------------------------------------
+ // UNLOCK
+ // -------------------------------------------------------------------
+-// Note: Uncomment the following if locking support is required
+-/*
+-void NeonSession::UNLOCK( const Lock & inLock,
++void NeonSession::UNLOCK( ucb::Lock & rLock,
+                           const DAVRequestEnvironment & rEnv )
+ 	throw ( DAVException )
+ {
+@@ -1423,9 +1428,15 @@ void NeonSession::UNLOCK( const Lock & inLock,
+ 
+     m_aEnv = rEnv;
+ 
+-	Lockit( inLock, false );
++    if ( !Lockit( rLock, false ) )
++    {
++        ucbhelper::cancelCommandExecution( ucb::IOErrorCode_LOCKING_VIOLATION,
++                uno::Sequence< uno::Any >( 0 ), // FIXME more info about the file?
++                rEnv.m_xEnv,
++                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "a locking error occured" ) ),
++                uno::Reference< ucb::XCommandProcessor >() );
++    }
+ }
+-*/
+ 
+ // -------------------------------------------------------------------
+ const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const
+@@ -1521,77 +1532,97 @@ void NeonSession::HandleError( int nError )
+     }
+ }
+ 
+-// Note: Uncomment the following if locking support is required
+-/*
+-void NeonSession::Lockit( const Lock & inLock, bool inLockit )
++sal_Bool NeonSession::Lockit( ucb::Lock & rLock, bool bLockit )
+ 	throw ( DAVException )
+ {
+     osl::Guard< osl::Mutex > theGuard( m_aMutex );
+ 
+-	// Create the neon lock
+-	NeonLock * theLock = new NeonLock;
+-	int theRetVal;
++    if ( !m_NeonLockStore )
++        throw DAVException( DAVException::DAV_INVALID_ARG );
+ 
+-	// Set the lock uri
+-	NeonUri theUri( inLock.uri );
+-	theLock->uri = const_cast< char * >
+-        ( rtl::OUStringToOString(
+-                theUri.GetPath(), RTL_TEXTENCODING_UTF8 ).getStr() );
++    ne_uri aUri;
++    ne_uri_parse( rtl::OUStringToOString( m_aEnv.m_aRequestURI, RTL_TEXTENCODING_UTF8 ).getStr(),
++            &aUri );
+ 
+-	if ( inLockit )
+-	{
+-		// Set the lock depth
+-		switch( inLock.depth )
+-		{
+-			case DAVZERO:
+-			case DAVINFINITY:
+-				theLock->depth = int ( inLock.depth );
+-				break;
+-			default:
+-				throw DAVException( DAVException::DAV_INVALID_ARG );
+-				break;
+-		}
++    // Create the neon lock
++    NeonLock * theLock = ne_lockstore_findbyuri( m_NeonLockStore, &aUri );
++    if ( !theLock )
++    {
++        theLock = ne_lock_create();
+ 
+-		// Set the lock scope
+-		switch ( inLock.scope )
+-		{
+-			case EXCLUSIVE:
+-                theLock->scope = ne_lockscope_exclusive;
+-				break;
+-			case SHARED:
+-                theLock->scope = ne_lockscope_shared;
+-				break;
+-			default:
+-				throw DAVException( DAVException::DAV_INVALID_ARG );
+-				break;
+-		}
++        // Set the lock uri
++        theLock->uri = aUri;
++
++        // Set the lock depth
++        switch( rLock.Depth )
++        {
++            case ucb::LockDepth_ZERO:     theLock->depth = NE_DEPTH_ZERO;     break;
++            case ucb::LockDepth_ONE:      theLock->depth = NE_DEPTH_ONE;      break;
++            case ucb::LockDepth_INFINITY: theLock->depth = NE_DEPTH_INFINITE; break;
++            default:
++                                          throw DAVException( DAVException::DAV_INVALID_ARG );
++        }
++
++        // Set the lock scope
++        switch ( rLock.Scope )
++        {
++            case ucb::LockScope_EXCLUSIVE: theLock->scope = ne_lockscope_exclusive; break;
++            case ucb::LockScope_SHARED:    theLock->scope = ne_lockscope_shared;    break;
++            default:
++                                           throw DAVException( DAVException::DAV_INVALID_ARG );
++                                           break;
++        }
++
++        // Set the lock owner
++        rtl::OUString aValue;
++        rLock.Owner >>= aValue;
+ 
+-		// Set the lock owner
+-        const char * theOwner = rtl::OUStringToOString( inLock.owner,
+-                                                        RTL_TEXTENCODING_UTF8 );
+-		theLock->owner = const_cast< char * > ( theOwner );
++        theLock->owner = strdup( rtl::OUStringToOString( aValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+ 
+-		// Set the lock timeout
+-		// Note: Neon ignores the timeout
+-		//theLock->timeout = inLock.timeout;
++        // Set the lock timeout
++        // Note: Neon ignores the timeout
++        //theLock->timeout = rLock.timeout;
++        theLock->timeout = -1;
+ 
++        ne_lockstore_add( m_NeonLockStore, theLock );
++    }
++
++    int theRetVal;
++    if ( bLockit )
++    {
+         theRetVal = ne_lock( m_pHttpSession, theLock );
+-	}
+-	else
+-	{
+ 
+-		// Set the lock token
+-        rtl::OUString theToken = inLock.locktoken.getConstArray()[ 0 ];
+-		theLock->token = const_cast< char * >
+-            ( rtl::OUStringToOString(
+-                    theToken, RTL_TEXTENCODING_UTF8 ).getStr() );
++        if ( theRetVal != NE_OK )
++            return sal_False;
++
++        uno::Sequence< rtl::OUString > aTokens( 1 );
++        aTokens[0] = rtl::OUString::createFromAscii( theLock->token );
++        rLock.LockTokens = aTokens;
++
++#if OSL_DEBUG_LEVEL > 0
++        fprintf( stderr, "WebDAV: locked the URL, the token is: %s\n", theLock->token );
++#endif
++    }
++    else
++    {
++        // Set the lock token
++        if ( rLock.LockTokens.getLength() > 0 )
++        {
++            rtl::OUString theToken = rLock.LockTokens.getConstArray()[ 0 ];
++            theLock->token = strdup( rtl::OUStringToOString( theToken, RTL_TEXTENCODING_UTF8 ).getStr() );
++
++#if OSL_DEBUG_LEVEL > 0
++            fprintf( stderr, "WebDAV: going to unlock the URL, the token is: %s\n", theLock->token );
++#endif
++        }
+ 
+         theRetVal = ne_unlock( m_pHttpSession, theLock );
+-	}
++    }
+ 
+-	HandleError( theRetVal );
++    HandleError( theRetVal );
++
++    return sal_True;
+ }
+-*/
+ 
+ // -------------------------------------------------------------------
+ namespace {
+diff --git a/ucb/source/ucp/webdav/NeonSession.hxx b/ucb/source/ucp/webdav/NeonSession.hxx
+index 911939f..f35468a 100644
+--- ucb/source/ucp/webdav/NeonSession.hxx
++++ ucb/source/ucp/webdav/NeonSession.hxx
+@@ -84,8 +84,7 @@ class NeonSession : public DAVSession
+         // moment.
+         DAVRequestEnvironment m_aEnv;
+ 
+-		// Note: Uncomment the following if locking support is required
+-        // NeonLockSession *      mNeonLockSession;
++        NeonLockStore    *m_NeonLockStore;
+ 
+         static bool       m_bGlobalsInited;
+ 
+@@ -156,7 +155,7 @@ class NeonSession : public DAVSession
+ 			throw ( DAVException );
+ 
+         virtual com::sun::star::uno::Reference<
+-            com::sun::star::io::XInputStream >
++            com::sun::star::io::XStream >
+         GET( const ::rtl::OUString & inPath,
+              const std::vector< ::rtl::OUString > & inHeaderNames,
+              DAVResource & ioResource,
+@@ -223,16 +222,13 @@ class NeonSession : public DAVSession
+                               const DAVRequestEnvironment & rEnv )
+ 			throw ( DAVException );
+ 
+-		// Note: Uncomment the following if locking support is required
+-		/*
+-		virtual void LOCK (const Lock & inLock,
+-                           const DAVRequestEnvironment & rEnv )
++		virtual void LOCK ( com::sun::star::ucb::Lock & rLock,
++                            const DAVRequestEnvironment & rEnv )
+ 			throw ( DAVException );
+ 
+-		virtual void UNLOCK (const Lock & inLock,
+-                             const DAVRequestEnvironment & rEnv )
++		virtual void UNLOCK ( com::sun::star::ucb::Lock & rLock,
++                              const DAVRequestEnvironment & rEnv )
+ 			throw ( DAVException );
+-		*/
+ 
+         // helpers
+         const rtl::OUString & getHostName() const { return m_aHostName; }
+@@ -257,9 +253,8 @@ class NeonSession : public DAVSession
+ 
+         const ucbhelper::InternetProxyServer & getProxySettings() const;
+ 
+-		// Note: Uncomment the following if locking support is required
+-		// void			Lockit( const Lock & inLock, bool inLockit )
+-		//	throw ( DAVException );
++		sal_Bool Lockit( com::sun::star::ucb::Lock & rLock, bool bLockit )
++			throw ( DAVException );
+ 
+         // low level GET implementation, used by public GET implementations
+         static int GET( ne_session * sess,
+diff --git a/ucb/source/ucp/webdav/NeonTypes.hxx b/ucb/source/ucp/webdav/NeonTypes.hxx
+index 63a8d68..5086f96 100644
+--- ucb/source/ucp/webdav/NeonTypes.hxx
++++ ucb/source/ucp/webdav/NeonTypes.hxx
+@@ -48,6 +48,9 @@
+ #ifndef NE_PROPS_H
+ #include <ne_props.h>
+ #endif
++#ifndef NE_LOCKS_H
++#include <ne_locks.h>
++#endif
+ 
+ typedef ne_session                  HttpSession;
+ typedef ne_status                   HttpStatus;
+@@ -56,4 +59,7 @@ typedef ne_server_capabilities      HttpServerCapabilities;
+ typedef ne_propname                 NeonPropName;
+ typedef ne_prop_result_set          NeonPropFindResultSet;
+ 
++typedef ne_lock_store               NeonLockStore;
++typedef struct ne_lock              NeonLock;
++
+ #endif // _NEONTYPES_HXX_
+diff --git a/ucb/source/ucp/webdav/webdavcontent.cxx b/ucb/source/ucp/webdav/webdavcontent.cxx
+index 7b3d7c5..80f752e 100644
+--- ucb/source/ucp/webdav/webdavcontent.cxx
++++ ucb/source/ucp/webdav/webdavcontent.cxx
+@@ -76,6 +76,9 @@
+ #ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_
+ #include <com/sun/star/io/XActiveDataSink.hpp>
+ #endif
++#ifndef _COM_SUN_STAR_IO_XACTIVEDATASTREAMER_HPP_
++#include <com/sun/star/io/XActiveDataStreamer.hpp>
++#endif
+ #ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
+ #include <com/sun/star/io/XOutputStream.hpp>
+ #endif
+@@ -190,6 +193,8 @@
+ #include "UCBDeadPropertyValue.hxx"
+ #endif
+ 
++#include "NeonInputStream.hxx"
++
+ using namespace com::sun::star;
+ using namespace webdav_ucp;
+ 
+@@ -453,7 +458,8 @@ Content::Content(
+   m_eResourceType( UNKNOWN ),
+   m_pProvider( pProvider ),
+   m_bTransient( sal_False ),
+-  m_bCollection( sal_False )
++  m_bCollection( sal_False ),
++  m_bForceReadOnly( sal_False )
+ {
+     try
+     {
+@@ -722,6 +728,11 @@ uno::Any SAL_CALL Content::execute(
+            ucb::CommandAbortedException,
+            uno::RuntimeException )
+ {
++#if OSL_DEBUG_LEVEL > 0
++    fprintf( stderr, "WebDAV: Execute command '%s'\n",
++            rtl::OUStringToOString( aCommand.Name, RTL_TEXTENCODING_UTF8 ).getStr() );
++#endif
++
+     uno::Any aRet;
+     
+     if ( aCommand.Name.equalsAsciiL(
+@@ -1414,16 +1425,29 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues(
+     uno::Reference< ucb::XContentIdentifier >    xIdentifier;
+     rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider;
+ 
+-    // webdav does not support active streaming, we can immediately return
+-    if ( ( rProperties.getLength() == 1 ) &&
+-            rProperties[ 0 ].Name.equalsAsciiL(
+-                RTL_CONSTASCII_STRINGPARAM( "SupportsActiveStreaming" ) ) )
++#if OSL_DEBUG_LEVEL > 0
++    fprintf( stderr, "WebDAV: getPropertyValues: answering the following properties: " );
++    for ( int i = 0; i < rProperties.getLength(); ++i )
++        fprintf( stderr, " %s,",
++                rtl::OUStringToOString( rProperties[i].Name, RTL_TEXTENCODING_UTF8 ).getStr() );
++    fprintf( stderr, "\n" );
++#endif
++
++    // WebDAV supports XActiveDataStreamer
++    // We have to return TRUE on
++    // - SupportsActiveStreaming - always
++    // - IsReadOnly - if we forced read only due to failed locking
++    if ( rProperties.getLength() == 1 )
+     {
+-        rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
+-            = new ::ucbhelper::PropertyValueSet( m_xSMgr );
+-        xRow->appendBoolean( rProperties[0], sal_False );
++        if ( rProperties[ 0 ].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SupportsActiveStreaming" ) ) ||
++             ( rProperties[ 0 ].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) && m_bForceReadOnly ) )
++        {
++            rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
++                = new ::ucbhelper::PropertyValueSet( m_xSMgr );
++            xRow->appendBoolean( rProperties[0], sal_True );
+ 
+-        return uno::Reference< sdbc::XRow >( xRow.get() );
++            return uno::Reference< sdbc::XRow >( xRow.get() );
++        }
+     }
+ 
+     {
+@@ -2114,61 +2138,108 @@ uno::Any Content::open(
+         }
+     }
+ 
+-    if ( rArg.Sink.is() )
+-    {
+-        // Open document.
++    if ( !rArg.Sink.is() )
++        return aRet;
+ 
+-        if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
+-             ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
+-        {
+-            // Currently(?) unsupported.
+-            ucbhelper::cancelCommandExecution(
++    // Open document.
++
++    if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
++         ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
++    {
++        // Currently(?) unsupported.
++        ucbhelper::cancelCommandExecution(
+                 uno::makeAny(
+                     ucb::UnsupportedOpenModeException(
+-                            rtl::OUString(),
+-                            static_cast< cppu::OWeakObject * >( this ),
+-                            sal_Int16( rArg.Mode ) ) ),
++                        rtl::OUString(),
++                        static_cast< cppu::OWeakObject * >( this ),
++                        sal_Int16( rArg.Mode ) ) ),
+                 xEnv );
++        // Unreachable
++    }
++
++    rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
++    uno::Reference< io::XOutputStream > xOut
++        = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY );
++    if ( xOut.is() )
++    {
++#if OSL_DEBUG_LEVEL > 0
++        fprintf( stderr, "WebDAV: rArg.Sink is XOutputStream\n" );
++#endif
++        // PUSH: write data
++        try
++        {
++            std::auto_ptr< DAVResourceAccess > xResAccess;
++
++            {
++                osl::MutexGuard aGuard( m_aMutex );
++
++                // throw away previously cached headers.
++                m_xCachedProps.reset();
++
++                xResAccess.reset(
++                        new DAVResourceAccess( *m_xResAccess.get() ) );
++            }
++
++            DAVResource aResource;
++            std::vector< rtl::OUString > aHeaders;
++            //                // Obtain list containing all HTTP headers that can
++            //                // be mapped to UCB properties.
++            //                ContentProperties::getMappableHTTPHeaders( aHeaders );
++
++            xResAccess->GET( xOut, aHeaders, aResource, xEnv );
++
++            {
++                osl::MutexGuard aGuard( m_aMutex );
++
++                // cache headers.
++                m_xCachedProps.reset( new ContentProperties( aResource ) );
++
++                m_xResAccess.reset( 
++                    new DAVResourceAccess( *xResAccess.get() ) );
++            }
++        }
++        catch ( DAVException const & e )
++        {
++            cancelCommandExecution( e, xEnv );
+             // Unreachable
+         }
+-
+-        rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+-        uno::Reference< io::XOutputStream > xOut
+-            = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY );
+-        if ( xOut.is() )
++    }
++    else
++    {
++        uno::Reference< io::XActiveDataSink > xDataSink
++            = uno::Reference< io::XActiveDataSink >( rArg.Sink,
++                    uno::UNO_QUERY );
++        if ( xDataSink.is() )
+         {
+-            // PUSH: write data
++#if OSL_DEBUG_LEVEL > 0
++            fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataSink\n" );
++#endif
++            // PULL: wait for client read
+             try
+             {
+-                std::auto_ptr< DAVResourceAccess > xResAccess;
+-
+                 {
+                     osl::MutexGuard aGuard( m_aMutex );
+ 
+                     // throw away previously cached headers.
+                     m_xCachedProps.reset();
+-
+-                    xResAccess.reset(
+-                        new DAVResourceAccess( *m_xResAccess.get() ) );
+                 }
+-
++                // fill inputsream sync; return if all data present
+                 DAVResource aResource;
+                 std::vector< rtl::OUString > aHeaders;
+-//                // Obtain list containing all HTTP headers that can
+-//                // be mapped to UCB properties.
+-//                ContentProperties::getMappableHTTPHeaders( aHeaders );
+-
+-                xResAccess->GET( xOut, aHeaders, aResource, xEnv );
++                //                        // Obtain list containing all HTTP headers that can
++                //                        // be mapped to UCB properties.
++                //                        ContentProperties::getMappableHTTPHeaders( aHeaders );
++                uno::Reference< io::XInputStream > xIn
++                    = m_xResAccess->GET( aHeaders, aResource, xEnv )->getInputStream();
+ 
+                 {
+                     osl::MutexGuard aGuard( m_aMutex );
+ 
+-                    // cache headers.
+-                    m_xCachedProps.reset( new ContentProperties( aResource ) );
+-
+-                    m_xResAccess.reset( 
+-                        new DAVResourceAccess( *xResAccess.get() ) );
++                    m_xCachedProps.reset(
++                            new ContentProperties( aResource ) );
+                 }
++
++                xDataSink->setInputStream( xIn );
+             }
+             catch ( DAVException const & e )
+             {
+@@ -2175,11 +2246,19 @@ uno::Any Content::open(
+         }
+         else
+         {
+-            uno::Reference< io::XActiveDataSink > xDataSink
+-                = uno::Reference< io::XActiveDataSink >( rArg.Sink,
+-                                                         uno::UNO_QUERY );
+-            if ( xDataSink.is() )
++            uno::Reference< io::XActiveDataStreamer > xDataStreamer
++                = uno::Reference< io::XActiveDataStreamer >( rArg.Sink,
++                        uno::UNO_QUERY );
++            if ( xDataStreamer.is() && !m_bForceReadOnly )
+             {
++#if OSL_DEBUG_LEVEL > 0
++                fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataStreamer\n" );
++#endif
++                // prepare the lock
++                ucb::Lock aLock;
++                aLock.Depth = ucb::LockDepth_ZERO;
++                aLock.Scope = ucb::LockScope_EXCLUSIVE;
++
+                 // PULL: wait for client read
+                 try
+                 {
+@@ -2192,39 +2271,58 @@ uno::Any Content::open(
+                     // fill inputsream sync; return if all data present
+                     DAVResource aResource;
+                     std::vector< rtl::OUString > aHeaders;
+-//                        // Obtain list containing all HTTP headers that can
+-//                        // be mapped to UCB properties.
+-//                        ContentProperties::getMappableHTTPHeaders( aHeaders );
+-                    uno::Reference< io::XInputStream > xIn
++                    //                        // Obtain list containing all HTTP headers that can
++                    //                        // be mapped to UCB properties.
++                    //                        ContentProperties::getMappableHTTPHeaders( aHeaders );
++
++                    // if the locking or the creation of the stream below
++                    // fails, we are read only at the next try
++                    m_bForceReadOnly = sal_True;
++
++                    m_xResAccess->LOCK( aLock, xEnv );
++
++                    uno::Reference< io::XStream > xStream
+                         = m_xResAccess->GET( aHeaders, aResource, xEnv );
++
++                    // pass the lock to the stream
++                    static_cast< NeonInputStream* >( xStream.get() )->SetLock( aLock, m_xResAccess->getURL() );
++
++                    // everything went well wrt. locking
++                    m_bForceReadOnly = sal_False;
+                     
+                     {
+                         osl::MutexGuard aGuard( m_aMutex );
+ 
+                         m_xCachedProps.reset(
+-                            new ContentProperties( aResource ) );
++                                new ContentProperties( aResource ) );
+                     }
+ 
+-                    xDataSink->setInputStream( xIn );
++                    xDataStreamer->setStream( xStream );
+                 }
+                 catch ( DAVException const & e )
+                 {
++                    m_xResAccess->UNLOCK( aLock, xEnv );
++                    m_bForceReadOnly = sal_False;
++
+                     cancelCommandExecution( e, xEnv );
+                     // Unreachable
+                 }
+             }
+             else
+             {
++#if OSL_DEBUG_LEVEL > 0
++                fprintf( stderr, "WebDAV: unsupported rArg.Sink\n" );
++#endif
+                 // Note: aOpenCommand.Sink may contain an XStream
+                 //       implementation. Support for this type of
+                 //       sink is optional...
+                 ucbhelper::cancelCommandExecution(
+-                    uno::makeAny(
+-                        ucb::UnsupportedDataSinkException(
+-                            rtl::OUString(),
+-                            static_cast< cppu::OWeakObject * >( this ),
+-                            rArg.Sink ) ),
+-                    xEnv );
++                        uno::makeAny(
++                            ucb::UnsupportedDataSinkException(
++                                rtl::OUString(),
++                                static_cast< cppu::OWeakObject * >( this ),
++                                rArg.Sink ) ),
++                        xEnv );
+                 // Unreachable
+             }
+         }
+@@ -2242,6 +2340,9 @@ void Content::post(
+     uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY );
+     if ( xSink.is() )
+     {
++#if OSL_DEBUG_LEVEL > 0
++        fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataSink\n" );
++#endif
+         try
+         {
+             uno::Reference< io::XInputStream > xResult
+@@ -2262,6 +2363,9 @@ void Content::post(
+         uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY );
+         if ( xResult.is() )
+         {
++#if OSL_DEBUG_LEVEL > 0
++            fprintf( stderr, "WebDAV: rArg.Sink is XOutputStream\n" );
++#endif
+             try
+             {
+                 m_xResAccess->POST( rArg.MediaType,
+@@ -2278,6 +2382,9 @@ void Content::post(
+         }
+         else
+         {
++#if OSL_DEBUG_LEVEL > 0
++            fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataStreamer (or something)\n" );
++#endif
+             ucbhelper::cancelCommandExecution(
+                 uno::makeAny(
+                     ucb::UnsupportedDataSinkException(
+diff --git a/ucb/source/ucp/webdav/webdavcontent.hxx b/ucb/source/ucp/webdav/webdavcontent.hxx
+index a4589a5..073c57f 100644
+--- ucb/source/ucp/webdav/webdavcontent.hxx
++++ ucb/source/ucp/webdav/webdavcontent.hxx
+@@ -111,6 +111,7 @@ class Content : public ::ucbhelper::ContentImplHelper,
+ 	ContentProvider*  m_pProvider; // No need for a ref, base class holds object
+   	sal_Bool 		  m_bTransient;
+ 	sal_Bool          m_bCollection;
++	sal_Bool          m_bForceReadOnly;
+ 
+ private:
+ 	virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property >
+diff --git a/ucb/source/ucp/webdav/webdavcontentcaps.cxx b/ucb/source/ucp/webdav/webdavcontentcaps.cxx
+index c514903..abf958e 100644
+--- ucb/source/ucp/webdav/webdavcontentcaps.cxx
++++ ucb/source/ucp/webdav/webdavcontentcaps.cxx
+@@ -298,6 +298,24 @@ bool ContentProvider::getProperty(
+ 				    -1,
+                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+                     beans::PropertyAttribute::BOUND ) );
++
++			m_pProps->insert(
++				beans::Property(
++					rtl::OUString(
++						RTL_CONSTASCII_USTRINGPARAM( "SupportsActiveStreaming" ) ),
++					-1,
++					getCppuBooleanType(),
++					beans::PropertyAttribute::BOUND
++						| beans::PropertyAttribute::READONLY ) );
++
++			m_pProps->insert(
++				beans::Property(
++					rtl::OUString(
++						RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ),
++					-1,
++					getCppuBooleanType(),
++					beans::PropertyAttribute::BOUND
++						| beans::PropertyAttribute::READONLY ) );
+ 		}
+ 	}
+ 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]