1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: webdavcontent.cxx,v $
10 * $Revision: 1.65.12.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
36 **************************************************************************
38 *************************************************************************/
39 #include <osl/diagnose.h>
40 #include <osl/thread.hxx>
42 #include "osl/doublecheckedlocking.h"
43 #include <rtl/uri.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include "com/sun/star/task/XPasswordContainer.hpp"
46 #include "com/sun/star/task/NoMasterException.hpp"
47 #include <com/sun/star/beans/PropertyAttribute.hpp>
48 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
49 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
50 #include <com/sun/star/beans/PropertyValue.hpp>
51 #include <com/sun/star/io/XActiveDataSink.hpp>
52 #include <com/sun/star/io/XActiveDataStreamer.hpp>
53 #include <com/sun/star/io/XOutputStream.hpp>
54 #include <com/sun/star/lang/IllegalAccessException.hpp>
55 #include "com/sun/star/ucb/AuthenticationRequest.hpp"
56 #include <com/sun/star/ucb/CommandFailedException.hpp>
57 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
58 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
59 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
60 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
61 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
62 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
63 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
64 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
65 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
66 #include <com/sun/star/ucb/NameClash.hpp>
67 #include <com/sun/star/ucb/NameClashException.hpp>
68 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
69 #include <com/sun/star/ucb/OpenMode.hpp>
70 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
71 #include <com/sun/star/ucb/TransferInfo.hpp>
72 #include <com/sun/star/ucb/XCommandInfo.hpp>
73 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
74 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
75 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
76 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
77 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
78 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
79 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
80 #include <ucbhelper/contentidentifier.hxx>
81 #include <ucbhelper/propertyvalueset.hxx>
82 #include <ucbhelper/simpleinteractionrequest.hxx>
83 #include <ucbhelper/cancelcommandexecution.hxx>
84 #include "webdavcontent.hxx"
85 #include "webdavprovider.hxx"
86 #include "webdavresultset.hxx"
87 #include "ContentProperties.hxx"
88 #include "NeonUri.hxx"
89 #include "UCBDeadPropertyValue.hxx"
91 #include "NeonInputStream.hxx"
93 using namespace com::sun::star
;
94 using namespace webdav_ucp
;
96 //=========================================================================
97 //=========================================================================
99 // CommandEnvironment_Impl Implementation.
101 //=========================================================================
102 //=========================================================================
104 class CommandEnvironment_Impl
: public cppu::OWeakObject
,
105 public ucb::XCommandEnvironment
,
106 public task::XInteractionHandler
110 CommandEnvironment_Impl(
111 const uno::Reference
< lang::XMultiServiceFactory
>& xSMgr
)
119 // XCommandEnvironment
120 virtual uno::Reference
< task::XInteractionHandler
> SAL_CALL
121 getInteractionHandler( )
122 throw (uno::RuntimeException
)
127 virtual uno::Reference
< ucb::XProgressHandler
> SAL_CALL
128 getProgressHandler( )
129 throw (uno::RuntimeException
)
134 // XInteractionHandler
135 virtual void SAL_CALL
136 handle( const uno::Reference
< task::XInteractionRequest
>& Request
)
137 throw (uno::RuntimeException
);
142 handleAuthenticationRequest(
143 ucb::AuthenticationRequest
const&,
144 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > const&)
145 SAL_THROW((uno::RuntimeException
))
149 uno::Reference
< lang::XMultiServiceFactory
> m_xSMgr
;
152 //=========================================================================
153 void SAL_CALL
CommandEnvironment_Impl::acquire()
156 OWeakObject::acquire();
159 //=========================================================================
160 void SAL_CALL
CommandEnvironment_Impl::release()
163 OWeakObject::release();
166 //=========================================================================
167 uno::Any SAL_CALL
CommandEnvironment_Impl::queryInterface(
168 const uno::Type
& rType
)
169 throw( uno::RuntimeException
)
171 uno::Any aRet
= cppu::queryInterface(
173 static_cast< ucb::XCommandEnvironment
* >( this ),
174 static_cast< task::XInteractionHandler
* >( this ) );
175 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
178 //=========================================================================
179 void SAL_CALL
CommandEnvironment_Impl::handle(
180 const uno::Reference
< task::XInteractionRequest
>& rIRequest
)
181 throw (uno::RuntimeException
)
186 uno::Any
aAnyRequest(rIRequest
->getRequest());
188 ucb::AuthenticationRequest rRequest
;
189 if (!(aAnyRequest
>>= rRequest
))
192 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> >
193 rContinuations
= rIRequest
->getContinuations();
196 uno::Reference
< task::XInteractionRetry
> xRetry
;
197 uno::Reference
< task::XInteractionAbort
> xAbort
;
198 uno::Reference
< ucb::XInteractionSupplyAuthentication
>
199 xSupplyAuthentication
;
201 for (sal_Int32 i
= 0; i
< rContinuations
.getLength(); ++i
) {
202 xRetry
= uno::Reference
< task::XInteractionRetry
>(
203 rContinuations
[i
], uno::UNO_QUERY
);
207 xAbort
= uno::Reference
< task::XInteractionAbort
>(
208 rContinuations
[i
], uno::UNO_QUERY
);
212 xSupplyAuthentication
213 = uno::Reference
< ucb::XInteractionSupplyAuthentication
>(
214 rContinuations
[i
], uno::UNO_QUERY
);
215 if( xSupplyAuthentication
.is() )
220 bool bRememberPersistent
;
221 if (xSupplyAuthentication
.is())
223 ucb::RememberAuthentication eDefault
;
224 uno::Sequence
< ucb::RememberAuthentication
> aModes(
225 xSupplyAuthentication
->getRememberPasswordModes(eDefault
));
226 bRemember
= eDefault
!= ucb::RememberAuthentication_NO
;
227 bRememberPersistent
= false;
228 for (sal_Int32 i
= 0; i
< aModes
.getLength(); ++i
)
229 if (aModes
[i
] == ucb::RememberAuthentication_PERSISTENT
)
231 bRememberPersistent
= true;
238 bRememberPersistent
= false;
241 uno::Reference
< task::XPasswordContainer
> xContainer
;
245 = uno::Reference
< task::XPasswordContainer
>(
246 m_xSMgr
->createInstance(
247 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
248 "com.sun.star.task.PasswordContainer"))),
251 catch (uno::Exception
const &)
255 // xContainer works with userName passwdSequences pairs:
256 if (xContainer
.is() && rRequest
.HasUserName
&& rRequest
.HasPassword
)
260 if (rRequest
.UserName
.getLength() == 0)
263 aRec(xContainer
->find(rRequest
.ServerName
, this));
264 if (aRec
.UserList
.getLength() != 0)
266 if (xSupplyAuthentication
->canSetUserName())
267 xSupplyAuthentication
->
268 setUserName(aRec
.UserList
[0].UserName
.getStr());
269 if (xSupplyAuthentication
->canSetPassword())
271 OSL_ENSURE(aRec
.UserList
[0].Passwords
.getLength() != 0,
272 "empty password list");
273 xSupplyAuthentication
->
274 setPassword(aRec
.UserList
[0].Passwords
[0].getStr());
276 if (aRec
.UserList
[0].Passwords
.getLength() > 1)
278 if (rRequest
.HasRealm
)
280 if (xSupplyAuthentication
->canSetRealm())
281 xSupplyAuthentication
->
282 setRealm(aRec
.UserList
[0].Passwords
[1].
285 else if (xSupplyAuthentication
->canSetAccount())
286 xSupplyAuthentication
->
287 setAccount(aRec
.UserList
[0].Passwords
[1].
290 xSupplyAuthentication
->select();
297 aRec(xContainer
->findForName(rRequest
.ServerName
,
300 if (aRec
.UserList
.getLength() != 0)
302 OSL_ENSURE(aRec
.UserList
[0].Passwords
.getLength() != 0,
303 "empty password list");
304 if (!rRequest
.HasPassword
305 || rRequest
.Password
!= aRec
.UserList
[0].Passwords
[0])
307 if (xSupplyAuthentication
->canSetUserName())
308 xSupplyAuthentication
->
309 setUserName(aRec
.UserList
[0].UserName
.getStr());
310 if (xSupplyAuthentication
->canSetPassword())
311 xSupplyAuthentication
->
312 setPassword(aRec
.UserList
[0].Passwords
[0].
314 if (aRec
.UserList
[0].Passwords
.getLength() > 1)
316 if (rRequest
.HasRealm
)
318 if (xSupplyAuthentication
->canSetRealm())
319 xSupplyAuthentication
->
320 setRealm(aRec
.UserList
[0].Passwords
[1].
323 else if (xSupplyAuthentication
->canSetAccount())
324 xSupplyAuthentication
->
325 setAccount(aRec
.UserList
[0].Passwords
[1].
328 xSupplyAuthentication
->select();
334 catch (task::NoMasterException
const &)
335 {} // user did not enter master password
340 //=========================================================================
341 //=========================================================================
343 // Content Implementation.
345 //=========================================================================
346 //=========================================================================
348 // Our signal - 246 is just a random number ;-)
349 #define TICKER_THREAD_USER_SIGNAL ( OSL_SIGNAL_USER_RESERVED + 246 )
351 // -------------------------------------------------------------------
352 // A thread that 'ticks' - emits the user signal every second
353 // -------------------------------------------------------------------
354 class TickerThread
: public osl::Thread
360 TickerThread() : osl::Thread(), m_bFinish( false ) {}
362 void finish() { m_bFinish
= true; }
366 virtual void SAL_CALL
run();
369 void TickerThread::run()
371 // we have to go through the loop more often to be able to finish ~quickly
379 osl_raiseSignal( TICKER_THREAD_USER_SIGNAL
, NULL
);
385 aTV
.Nanosec
= 1000000000/nNth
;
390 // -------------------------------------------------------------------
391 // A class that takes care of creating and destroying the ticker thread
392 // -------------------------------------------------------------------
393 class TickerThreadController
397 TickerThread
*m_pTickerThread
;
401 TickerThreadController() : m_nCount( 0 ), m_pTickerThread( NULL
) {}
407 void TickerThreadController::start()
409 osl::MutexGuard
aGuard( m_aMutex
);
411 if ( ( m_nCount
++ == 0 ) && !m_pTickerThread
)
413 m_pTickerThread
= new TickerThread();
414 m_pTickerThread
->create();
418 void TickerThreadController::stop()
420 osl::MutexGuard
aGuard( m_aMutex
);
422 if ( ( --m_nCount
== 0 ) && m_pTickerThread
)
424 m_pTickerThread
->finish();
425 m_pTickerThread
->join();
427 delete m_pTickerThread
;
428 m_pTickerThread
= NULL
;
432 // -------------------------------------------------------------------
434 // -------------------------------------------------------------------
435 oslSignalAction
Content::HandleLockingSignal( void* pData
, oslSignalInfo
* pSignalInfo
)
437 Content
*pContent
= static_cast< Content
*>( pData
);
439 #if OSL_DEBUG_LEVEL > 0
440 fprintf( stderr
, "Content::HandleLockingSignal: pContent=%p pSignalInfo=%p\n", pContent
, pSignalInfo
);
444 return osl_Signal_ActCallNextHdl
;
447 pSignalInfo
->Signal
== osl_Signal_User
&&
448 pSignalInfo
->UserSignal
== TICKER_THREAD_USER_SIGNAL
)
450 pContent
->RefreshLock();
452 else if ( !pSignalInfo
|| ( pSignalInfo
->Signal
!= osl_Signal_User
) )
454 // terminating or something
455 pContent
->m_xResAccess
->UNLOCK( *pContent
->m_pLock
, pContent
->m_xLockEnv
);
456 delete pContent
->m_pLock
;
457 pContent
->m_pLock
= NULL
;
460 return osl_Signal_ActCallNextHdl
;
463 static TickerThreadController sTickerThreadController
;
465 //=========================================================================
466 // ctr for content on an existing webdav resource
468 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
469 ContentProvider
* pProvider
,
470 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
471 rtl::Reference
< DAVSessionFactory
> const & rSessionFactory
)
472 throw ( ucb::ContentCreationException
)
473 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
474 m_eResourceType( UNKNOWN
),
475 m_pProvider( pProvider
),
476 m_bTransient( false ),
477 m_bCollection( false ),
478 m_bDidGetOrHead( false ),
479 m_bForceReadOnly( false ),
482 m_pSignalHandler( NULL
)
486 m_xResAccess
.reset( new DAVResourceAccess(
489 Identifier
->getContentIdentifier() ) );
491 NeonUri
aURI( Identifier
->getContentIdentifier() );
492 m_aEscapedTitle
= aURI
.GetPathBaseName();
494 m_pSignalHandler
= osl_addSignalHandler( HandleLockingSignal
, this );
496 #if OSL_DEBUG_LEVEL > 0
497 fprintf( stderr
, "Content::Content (existing resource): this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler
);
498 fprintf( stderr
, " identifier=%s\n", rtl::OUStringToOString( Identifier
->getContentIdentifier(), RTL_TEXTENCODING_UTF8
).getStr() );
500 sTickerThreadController
.start();
502 catch ( DAVException
const & )
504 throw ucb::ContentCreationException();
508 //=========================================================================
509 // ctr for content on an non-existing webdav resource
511 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
512 ContentProvider
* pProvider
,
513 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
514 rtl::Reference
< DAVSessionFactory
> const & rSessionFactory
,
515 sal_Bool isCollection
)
516 throw ( ucb::ContentCreationException
)
517 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
518 m_eResourceType( UNKNOWN
),
519 m_pProvider( pProvider
),
520 m_bTransient( true ),
521 m_bCollection( isCollection
),
522 m_bDidGetOrHead( false ),
523 m_bForceReadOnly( false ),
526 m_pSignalHandler( NULL
)
530 m_xResAccess
.reset( new DAVResourceAccess(
531 rxSMgr
, rSessionFactory
, Identifier
->getContentIdentifier() ) );
533 m_pSignalHandler
= osl_addSignalHandler( HandleLockingSignal
, this );
535 #if OSL_DEBUG_LEVEL > 0
536 fprintf( stderr
, "Content::Content (nonexistent resource): this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler
);
537 fprintf( stderr
, " identifier=%s\n", rtl::OUStringToOString( Identifier
->getContentIdentifier(), RTL_TEXTENCODING_UTF8
).getStr() );
539 sTickerThreadController
.start();
541 catch ( DAVException
const & )
543 throw ucb::ContentCreationException();
546 // Do not set m_aEscapedTitle here! Content::insert relays on this!!!
549 //=========================================================================
553 #if OSL_DEBUG_LEVEL > 0
554 fprintf( stderr
, "Content::~Content: this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler
);
556 sTickerThreadController
.stop();
558 osl_removeSignalHandler( m_pSignalHandler
);
563 m_xResAccess
->UNLOCK( *m_pLock
, m_xLockEnv
);
567 catch ( ucb::CommandFailedException
const & )
573 // -------------------------------------------------------------------
574 // Lock the resource again
575 // -------------------------------------------------------------------
576 void Content::RefreshLock( void )
578 osl::MutexGuard
aGuard( m_aLock
);
580 #if OSL_DEBUG_LEVEL > 0
581 fprintf( stderr
, "Content::RefreshLock(): m_nToExpire=%d m_pLock=%p\n", m_nToExpire
, m_pLock
);
584 if ( m_nToExpire
> 0 )
587 // Refresh the lock if it expires in less than 30 s
588 if ( m_pLock
&& m_nToExpire
>= 0 && m_nToExpire
< 30 )
590 m_xResAccess
->LOCK( *m_pLock
, m_xLockEnv
);
592 m_nToExpire
= m_pLock
->Timeout
;
596 //=========================================================================
598 // XInterface methods.
600 //=========================================================================
603 void SAL_CALL
Content::acquire()
606 ContentImplHelper::acquire();
609 //=========================================================================
611 void SAL_CALL
Content::release()
614 ContentImplHelper::release();
617 //=========================================================================
619 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
620 throw ( uno::RuntimeException
)
622 // Note: isFolder may require network activities! So call it only
623 // if it is really necessary!!!
624 uno::Any aRet
= cppu::queryInterface(
626 static_cast< ucb::XContentCreator
* >( this ) );
627 if ( aRet
.hasValue() )
631 return isFolder( new CommandEnvironment_Impl(m_xSMgr
) )
635 catch ( uno::RuntimeException
const & )
639 catch ( uno::Exception
const & )
644 return aRet
.hasValue() ? aRet
: ContentImplHelper::queryInterface( rType
);
647 //=========================================================================
649 // XTypeProvider methods.
651 //=========================================================================
653 XTYPEPROVIDER_COMMON_IMPL( Content
);
655 //=========================================================================
657 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
658 throw( uno::RuntimeException
)
660 sal_Bool bFolder
= sal_False
;
664 = isFolder( uno::Reference
< ucb::XCommandEnvironment
>() );
666 catch ( uno::RuntimeException
const & )
670 catch ( uno::Exception
const & )
674 cppu::OTypeCollection
* pCollection
= 0;
678 static cppu::OTypeCollection
* pFolderTypes
= 0;
680 pCollection
= pFolderTypes
;
683 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
685 pCollection
= pFolderTypes
;
688 static cppu::OTypeCollection
aCollection(
689 CPPU_TYPE_REF( lang::XTypeProvider
),
690 CPPU_TYPE_REF( lang::XServiceInfo
),
691 CPPU_TYPE_REF( lang::XComponent
),
692 CPPU_TYPE_REF( ucb::XContent
),
693 CPPU_TYPE_REF( ucb::XCommandProcessor
),
694 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
695 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
696 CPPU_TYPE_REF( beans::XPropertyContainer
),
697 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
698 CPPU_TYPE_REF( container::XChild
),
699 CPPU_TYPE_REF( ucb::XContentCreator
) ); // !!
700 pCollection
= &aCollection
;
701 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
702 pFolderTypes
= pCollection
;
706 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
711 static cppu::OTypeCollection
* pDocumentTypes
= 0;
713 pCollection
= pDocumentTypes
;
716 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
718 pCollection
= pDocumentTypes
;
721 static cppu::OTypeCollection
aCollection(
722 CPPU_TYPE_REF( lang::XTypeProvider
),
723 CPPU_TYPE_REF( lang::XServiceInfo
),
724 CPPU_TYPE_REF( lang::XComponent
),
725 CPPU_TYPE_REF( ucb::XContent
),
726 CPPU_TYPE_REF( ucb::XCommandProcessor
),
727 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
728 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
729 CPPU_TYPE_REF( beans::XPropertyContainer
),
730 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
731 CPPU_TYPE_REF( container::XChild
) );
732 pCollection
= &aCollection
;
733 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
734 pDocumentTypes
= pCollection
;
738 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
742 return (*pCollection
).getTypes();
745 //=========================================================================
747 // XServiceInfo methods.
749 //=========================================================================
752 rtl::OUString SAL_CALL
Content::getImplementationName()
753 throw( uno::RuntimeException
)
755 return rtl::OUString::createFromAscii(
756 "com.sun.star.comp.ucb.WebDAVContent" );
759 //=========================================================================
761 uno::Sequence
< rtl::OUString
> SAL_CALL
Content::getSupportedServiceNames()
762 throw( uno::RuntimeException
)
764 uno::Sequence
< rtl::OUString
> aSNS( 1 );
766 = rtl::OUString::createFromAscii( WEBDAV_CONTENT_SERVICE_NAME
);
770 //=========================================================================
774 //=========================================================================
777 rtl::OUString SAL_CALL
Content::getContentType()
778 throw( uno::RuntimeException
)
780 sal_Bool bFolder
= sal_False
;
784 = isFolder( uno::Reference
< ucb::XCommandEnvironment
>() );
786 catch ( uno::RuntimeException
const & )
790 catch ( uno::Exception
const & )
795 return rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE
);
797 return rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE
);
800 //=========================================================================
802 // XCommandProcessor methods.
804 //=========================================================================
807 uno::Any SAL_CALL
Content::execute(
808 const ucb::Command
& aCommand
,
809 sal_Int32
/*CommandId*/,
810 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
811 throw( uno::Exception
,
812 ucb::CommandAbortedException
,
813 uno::RuntimeException
)
815 #if OSL_DEBUG_LEVEL > 0
816 fprintf( stderr
, "WebDAV: Content::execute(): this=%p command=%s\n",
817 this, rtl::OUStringToOString( aCommand
.Name
, RTL_TEXTENCODING_UTF8
).getStr() );
822 if ( aCommand
.Name
.equalsAsciiL(
823 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
825 //////////////////////////////////////////////////////////////////
827 //////////////////////////////////////////////////////////////////
829 uno::Sequence
< beans::Property
> Properties
;
830 if ( !( aCommand
.Argument
>>= Properties
) )
832 ucbhelper::cancelCommandExecution(
833 uno::makeAny( lang::IllegalArgumentException(
834 rtl::OUString::createFromAscii(
835 "Wrong argument type!" ),
836 static_cast< cppu::OWeakObject
* >( this ),
842 aRet
<<= getPropertyValues( Properties
, Environment
);
844 else if ( aCommand
.Name
.equalsAsciiL(
845 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
847 //////////////////////////////////////////////////////////////////
849 //////////////////////////////////////////////////////////////////
851 uno::Sequence
< beans::PropertyValue
> aProperties
;
852 if ( !( aCommand
.Argument
>>= aProperties
) )
854 ucbhelper::cancelCommandExecution(
855 uno::makeAny( lang::IllegalArgumentException(
856 rtl::OUString::createFromAscii(
857 "Wrong argument type!" ),
858 static_cast< cppu::OWeakObject
* >( this ),
864 if ( !aProperties
.getLength() )
866 ucbhelper::cancelCommandExecution(
867 uno::makeAny( lang::IllegalArgumentException(
868 rtl::OUString::createFromAscii(
870 static_cast< cppu::OWeakObject
* >( this ),
876 aRet
<<= setPropertyValues( aProperties
, Environment
);
878 else if ( aCommand
.Name
.equalsAsciiL(
879 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
881 //////////////////////////////////////////////////////////////////
882 // getPropertySetInfo
883 //////////////////////////////////////////////////////////////////
885 // Note: Implemented by base class.
886 aRet
<<= getPropertySetInfo( Environment
,
887 sal_False
/* don't cache data */ );
889 else if ( aCommand
.Name
.equalsAsciiL(
890 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
892 //////////////////////////////////////////////////////////////////
894 //////////////////////////////////////////////////////////////////
896 // Note: Implemented by base class.
897 aRet
<<= getCommandInfo( Environment
, sal_False
);
899 else if ( aCommand
.Name
.equalsAsciiL(
900 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
902 //////////////////////////////////////////////////////////////////
904 //////////////////////////////////////////////////////////////////
906 ucb::OpenCommandArgument2 aOpenCommand
;
907 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
909 ucbhelper::cancelCommandExecution(
910 uno::makeAny( lang::IllegalArgumentException(
911 rtl::OUString::createFromAscii(
912 "Wrong argument type!" ),
913 static_cast< cppu::OWeakObject
* >( this ),
919 aRet
= open( aOpenCommand
, Environment
);
921 else if ( aCommand
.Name
.equalsAsciiL(
922 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
924 //////////////////////////////////////////////////////////////////
926 //////////////////////////////////////////////////////////////////
928 ucb::InsertCommandArgument arg
;
929 if ( !( aCommand
.Argument
>>= arg
) )
931 ucbhelper::cancelCommandExecution(
932 uno::makeAny( lang::IllegalArgumentException(
933 rtl::OUString::createFromAscii(
934 "Wrong argument type!" ),
935 static_cast< cppu::OWeakObject
* >( this ),
941 insert( arg
.Data
, arg
.ReplaceExisting
, Environment
);
943 else if ( aCommand
.Name
.equalsAsciiL(
944 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
946 //////////////////////////////////////////////////////////////////
948 //////////////////////////////////////////////////////////////////
950 sal_Bool bDeletePhysical
= sal_False
;
951 aCommand
.Argument
>>= bDeletePhysical
;
953 // KSO: Ignore parameter and destroy the content, if you don't support
954 // putting objects into trashcan. ( Since we do not have a trash can
955 // service yet (src603), you actually have no other choice. )
956 // if ( bDeletePhysical )
960 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
962 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
963 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
965 xResAccess
->DESTROY( Environment
);
967 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
968 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
971 catch ( DAVException
const & e
)
973 cancelCommandExecution( e
, Environment
, sal_True
);
978 // Propagate destruction.
979 destroy( bDeletePhysical
);
981 // Remove own and all children's Additional Core Properties.
982 removeAdditionalPropertySet( sal_True
);
984 else if ( aCommand
.Name
.equalsAsciiL(
985 RTL_CONSTASCII_STRINGPARAM( "transfer" ) )
986 && isFolder( Environment
) )
988 //////////////////////////////////////////////////////////////////
990 // ( Not available at documents )
991 //////////////////////////////////////////////////////////////////
993 ucb::TransferInfo transferArgs
;
994 if ( !( aCommand
.Argument
>>= transferArgs
) )
996 ucbhelper::cancelCommandExecution(
997 uno::makeAny( lang::IllegalArgumentException(
998 rtl::OUString::createFromAscii(
999 "Wrong argument type!" ),
1000 static_cast< cppu::OWeakObject
* >( this ),
1006 transfer( transferArgs
, Environment
);
1008 else if ( aCommand
.Name
.equalsAsciiL(
1009 RTL_CONSTASCII_STRINGPARAM( "post" ) ) )
1011 //////////////////////////////////////////////////////////////////
1013 //////////////////////////////////////////////////////////////////
1015 ucb::PostCommandArgument2 aArg
;
1016 if ( !( aCommand
.Argument
>>= aArg
) )
1018 ucbhelper::cancelCommandExecution(
1019 uno::makeAny( lang::IllegalArgumentException(
1020 rtl::OUString::createFromAscii(
1021 "Wrong argument type!" ),
1022 static_cast< cppu::OWeakObject
* >( this ),
1028 post( aArg
, Environment
);
1032 //////////////////////////////////////////////////////////////////
1033 // Unsupported command
1034 //////////////////////////////////////////////////////////////////
1036 ucbhelper::cancelCommandExecution(
1037 uno::makeAny( ucb::UnsupportedCommandException(
1039 static_cast< cppu::OWeakObject
* >( this ) ) ),
1047 //=========================================================================
1049 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
1050 throw( uno::RuntimeException
)
1054 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1056 osl::MutexGuard
aGuard( m_aMutex
);
1058 new DAVResourceAccess( *m_xResAccess
.get() ) );
1060 xResAccess
->ABORT();
1062 catch ( DAVException
const & /*e*/ )
1064 // ABORT command failed!
1068 //=========================================================================
1070 // XPropertyContainer methods.
1072 //=========================================================================
1075 void SAL_CALL
Content::addProperty( const rtl::OUString
& Name
,
1076 sal_Int16 Attributes
,
1077 const uno::Any
& DefaultValue
)
1078 throw( beans::PropertyExistException
,
1079 beans::IllegalTypeException
,
1080 lang::IllegalArgumentException
,
1081 uno::RuntimeException
)
1083 // if ( m_bTransient )
1086 if ( !Name
.getLength() )
1087 throw lang::IllegalArgumentException();
1089 #if OSL_DEBUG_LEVEL > 0
1090 fprintf( stderr
, "WebDAV: Content::addProperty(): this=%p property=%s\n",
1091 this, rtl::OUStringToOString( Name
, RTL_TEXTENCODING_UTF8
).getStr() );
1094 // Check property type.
1095 if ( !UCBDeadPropertyValue::supportsType( DefaultValue
.getValueType() ) )
1097 OSL_ENSURE( sal_False
, "Content::addProperty - "
1098 "Unsupported property type!" );
1099 throw beans::IllegalTypeException();
1102 //////////////////////////////////////////////////////////////////////
1103 // Make sure a property with the requested name does not already
1104 // exist in dynamic and static(!) properties.
1105 //////////////////////////////////////////////////////////////////////
1107 // @@@ Need real command environment here, but where to get it from?
1108 // XPropertyContainer interface should be replaced by
1109 // XCommandProcessor commands!
1110 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
1112 // Note: This requires network access!
1113 if ( getPropertySetInfo( xEnv
, sal_False
/* don't cache data */ )
1114 ->hasPropertyByName( Name
) )
1116 // Property does already exist.
1117 throw beans::PropertyExistException();
1120 //////////////////////////////////////////////////////////////////////
1121 // Add a new dynamic property.
1122 //////////////////////////////////////////////////////////////////////
1124 ProppatchValue
aValue( PROPSET
, Name
, DefaultValue
);
1126 std::vector
< ProppatchValue
> aProppatchValues
;
1127 aProppatchValues
.push_back( aValue
);
1131 // Set property value at server.
1132 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1134 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1135 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1137 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
1139 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1140 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
1143 // Notify propertyset info change listeners.
1144 beans::PropertySetInfoChangeEvent
evt(
1145 static_cast< cppu::OWeakObject
* >( this ),
1147 -1, // No handle available
1148 beans::PropertySetInfoChange::PROPERTY_INSERTED
);
1149 notifyPropertySetInfoChange( evt
);
1151 catch ( DAVException
const & e
)
1153 if ( e
.getStatus() == SC_FORBIDDEN
)
1155 // Support for setting arbitrary dead properties is optional!
1157 // Store property locally.
1158 ContentImplHelper::addProperty(
1159 Name
, Attributes
, DefaultValue
);
1163 if ( shouldAccessNetworkAfterException( e
) )
1167 const ResourceType
& rType
= getResourceType( xEnv
);
1172 throw lang::IllegalArgumentException();
1176 // Store property locally.
1177 ContentImplHelper::addProperty( Name
,
1183 OSL_ENSURE( sal_False
,
1184 "Content::addProperty - "
1185 "Unsupported resource type!" );
1189 catch ( uno::Exception
const & )
1191 OSL_ENSURE( sal_False
,
1192 "Content::addProperty - "
1193 "Unable to determine resource type!" );
1198 OSL_ENSURE( sal_False
,
1199 "Content::addProperty - "
1200 "Unable to determine resource type!" );
1206 //=========================================================================
1208 void SAL_CALL
Content::removeProperty( const rtl::OUString
& Name
)
1209 throw( beans::UnknownPropertyException
,
1210 beans::NotRemoveableException
,
1211 uno::RuntimeException
)
1213 // @@@ Need real command environment here, but where to get it from?
1214 // XPropertyContainer interface should be replaced by
1215 // XCommandProcessor commands!
1216 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
1219 // @@@ REMOVEABLE z.Z. nicht richtig an der PropSetInfo gesetzt!!!
1222 beans::Property aProp
1223 = getPropertySetInfo( xEnv
, sal_False
/* don't cache data */ )
1224 ->getPropertyByName( Name
);
1226 if ( !( aProp
.Attributes
& beans::PropertyAttribute::REMOVEABLE
) )
1229 throw beans::NotRemoveableException();
1232 catch ( beans::UnknownPropertyException
const & )
1234 // OSL_ENSURE( sal_False, "removeProperty - Unknown property!" );
1239 //////////////////////////////////////////////////////////////////////
1240 // Try to remove property from server.
1241 //////////////////////////////////////////////////////////////////////
1243 #if OSL_DEBUG_LEVEL > 0
1244 fprintf( stderr
, "WebDAV: Content::removeProperty(): this=%p property=%s\n",
1245 this, rtl::OUStringToOString( Name
, RTL_TEXTENCODING_UTF8
).getStr() );
1250 std::vector
< ProppatchValue
> aProppatchValues
;
1251 ProppatchValue
aValue( PROPREMOVE
, Name
, uno::Any() );
1252 aProppatchValues
.push_back( aValue
);
1254 // Remove property value from server.
1255 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1257 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1258 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1260 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
1262 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1263 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
1266 // Notify propertyset info change listeners.
1267 beans::PropertySetInfoChangeEvent
evt(
1268 static_cast< cppu::OWeakObject
* >( this ),
1270 -1, // No handle available
1271 beans::PropertySetInfoChange::PROPERTY_REMOVED
);
1272 notifyPropertySetInfoChange( evt
);
1274 catch ( DAVException
const & e
)
1276 if ( e
.getStatus() == SC_FORBIDDEN
)
1278 // Support for setting arbitrary dead properties is optional!
1280 // Try to remove property from local store.
1281 ContentImplHelper::removeProperty( Name
);
1285 if ( shouldAccessNetworkAfterException( e
) )
1289 const ResourceType
& rType
= getResourceType( xEnv
);
1294 throw beans::UnknownPropertyException();
1298 // Try to remove property from local store.
1299 ContentImplHelper::removeProperty( Name
);
1303 OSL_ENSURE( sal_False
,
1304 "Content::removeProperty - "
1305 "Unsupported resource type!" );
1309 catch ( uno::Exception
const & )
1311 OSL_ENSURE( sal_False
,
1312 "Content::removeProperty - "
1313 "Unable to determine resource type!" );
1318 OSL_ENSURE( sal_False
,
1319 "Content::removeProperty - "
1320 "Unable to determine resource type!" );
1321 // throw beans::UnknownPropertyException();
1327 //=========================================================================
1329 // XContentCreator methods.
1331 //=========================================================================
1334 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
1335 Content::queryCreatableContentsInfo()
1336 throw( uno::RuntimeException
)
1338 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1340 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
1343 aSeq
.getArray()[ 0 ].Type
1344 = rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE
);
1345 aSeq
.getArray()[ 0 ].Attributes
1346 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
1347 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
1349 beans::Property aProp
;
1350 m_pProvider
->getProperty(
1351 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), aProp
);
1353 uno::Sequence
< beans::Property
> aDocProps( 1 );
1354 aDocProps
.getArray()[ 0 ] = aProp
;
1355 aSeq
.getArray()[ 0 ].Properties
= aDocProps
;
1358 aSeq
.getArray()[ 1 ].Type
1359 = rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE
);
1360 aSeq
.getArray()[ 1 ].Attributes
1361 = ucb::ContentInfoAttribute::KIND_FOLDER
;
1363 uno::Sequence
< beans::Property
> aFolderProps( 1 );
1364 aFolderProps
.getArray()[ 0 ] = aProp
;
1365 aSeq
.getArray()[ 1 ].Properties
= aFolderProps
;
1369 //=========================================================================
1371 uno::Reference
< ucb::XContent
> SAL_CALL
1372 Content::createNewContent( const ucb::ContentInfo
& Info
)
1373 throw( uno::RuntimeException
)
1375 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1377 if ( !Info
.Type
.getLength() )
1378 return uno::Reference
< ucb::XContent
>();
1380 if ( ( !Info
.Type
.equalsAsciiL(
1381 RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE
) ) )
1383 ( !Info
.Type
.equalsAsciiL(
1384 RTL_CONSTASCII_STRINGPARAM( WEBDAV_CONTENT_TYPE
) ) ) )
1385 return uno::Reference
< ucb::XContent
>();
1387 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
1389 OSL_ENSURE( aURL
.getLength() > 0,
1390 "WebdavContent::createNewContent - empty identifier!" );
1392 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
1393 aURL
+= rtl::OUString::createFromAscii( "/" );
1395 sal_Bool isCollection
;
1396 if ( Info
.Type
.equalsAsciiL(
1397 RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE
) ) )
1399 aURL
+= rtl::OUString::createFromAscii( "New_Collection" );
1400 isCollection
= sal_True
;
1404 aURL
+= rtl::OUString::createFromAscii( "New_Content" );
1405 isCollection
= sal_False
;
1408 uno::Reference
< ucb::XContentIdentifier
> xId(
1409 new ::ucbhelper::ContentIdentifier( m_xSMgr
, aURL
) );
1411 // create the local content
1414 return new ::webdav_ucp::Content( m_xSMgr
,
1417 m_xResAccess
->getSessionFactory(),
1420 catch ( ucb::ContentCreationException
& )
1422 return uno::Reference
< ucb::XContent
>();
1426 //=========================================================================
1428 rtl::OUString
Content::getParentURL()
1430 // <scheme>:// -> ""
1431 // <scheme>://foo -> ""
1432 // <scheme>://foo/ -> ""
1433 // <scheme>://foo/bar -> <scheme>://foo/
1434 // <scheme>://foo/bar/ -> <scheme>://foo/
1435 // <scheme>://foo/bar/abc -> <scheme>://foo/bar/
1437 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
1439 sal_Int32 nPos
= aURL
.lastIndexOf( '/' );
1440 if ( nPos
== ( aURL
.getLength() - 1 ) )
1442 // Trailing slash found. Skip.
1443 nPos
= aURL
.lastIndexOf( '/', nPos
);
1446 sal_Int32 nPos1
= aURL
.lastIndexOf( '/', nPos
);
1448 nPos1
= aURL
.lastIndexOf( '/', nPos1
);
1451 return rtl::OUString();
1453 return rtl::OUString( aURL
.copy( 0, nPos
+ 1 ) );
1456 //=========================================================================
1458 // Non-interface methods.
1460 //=========================================================================
1463 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1464 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
1465 const uno::Sequence
< beans::Property
>& rProperties
,
1466 const ContentProperties
& rData
,
1467 const rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
>& rProvider
,
1468 const rtl::OUString
& rContentId
)
1470 // Note: Empty sequence means "get values of all supported properties".
1472 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
1473 = new ::ucbhelper::PropertyValueSet( rSMgr
);
1475 sal_Int32 nCount
= rProperties
.getLength();
1478 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
1479 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1481 const beans::Property
* pProps
= rProperties
.getConstArray();
1482 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1484 const beans::Property
& rProp
= pProps
[ n
];
1486 // Process standard UCB, DAV and HTTP properties.
1487 const uno::Any
& rValue
= rData
.getValue( rProp
.Name
);
1488 if ( rValue
.hasValue() )
1490 xRow
->appendObject( rProp
, rValue
);
1494 // Process local Additional Properties.
1495 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1498 = uno::Reference
< beans::XPropertySet
>(
1499 rProvider
->getAdditionalPropertySet( rContentId
,
1502 bTriedToGetAdditonalPropSet
= sal_True
;
1505 if ( !xAdditionalPropSet
.is() ||
1506 !xRow
->appendPropertySetValue(
1507 xAdditionalPropSet
, rProp
) )
1509 // Append empty entry.
1510 xRow
->appendVoid( rProp
);
1517 // Append all standard UCB, DAV and HTTP properties.
1519 const std::auto_ptr
< PropertyValueMap
> & xProps
= rData
.getProperties();
1521 PropertyValueMap::const_iterator it
= xProps
->begin();
1522 PropertyValueMap::const_iterator end
= xProps
->end();
1524 ContentProvider
* pProvider
1525 = static_cast< ContentProvider
* >( rProvider
.get() );
1526 beans::Property aProp
;
1530 if ( pProvider
->getProperty( (*it
).first
, aProp
) )
1531 xRow
->appendObject( aProp
, (*it
).second
.value() );
1536 // Append all local Additional Properties.
1537 uno::Reference
< beans::XPropertySet
> xSet(
1538 rProvider
->getAdditionalPropertySet( rContentId
, sal_False
),
1540 xRow
->appendPropertySet( xSet
);
1543 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1546 //=========================================================================
1547 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1548 const uno::Sequence
< beans::Property
>& rProperties
,
1549 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1550 throw ( uno::Exception
)
1552 std::auto_ptr
< ContentProperties
> xProps
;
1553 std::auto_ptr
< ContentProperties
> xCachedProps
;
1554 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1555 rtl::OUString aEscapedTitle
;
1556 bool bHasAll
= false;
1557 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
1558 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
1559 rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
> xProvider
;
1561 #if OSL_DEBUG_LEVEL > 0
1562 fprintf( stderr
, "WebDAV: Content::getPropertyValues(): answering the following properties: " );
1563 for ( int i
= 0; i
< rProperties
.getLength(); ++i
)
1564 fprintf( stderr
, " %s,",
1565 rtl::OUStringToOString( rProperties
[i
].Name
, RTL_TEXTENCODING_UTF8
).getStr() );
1566 fprintf( stderr
, "\n" );
1569 // WebDAV supports XActiveDataStreamer
1570 // We have to return TRUE on
1571 // - SupportsActiveStreaming - always
1572 // - IsReadOnly - if we forced read only due to failed locking
1573 if ( rProperties
.getLength() == 1 )
1575 if ( rProperties
[ 0 ].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SupportsActiveStreaming" ) ) ||
1576 ( rProperties
[ 0 ].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) && m_bForceReadOnly
) )
1578 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
1579 = new ::ucbhelper::PropertyValueSet( m_xSMgr
);
1580 xRow
->appendBoolean( rProperties
[0], sal_True
);
1582 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1587 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1589 aEscapedTitle
= NeonUri::unescape( m_aEscapedTitle
);
1590 xSMgr
.set( m_xSMgr
);
1591 xIdentifier
.set( m_xIdentifier
);
1592 xProvider
.set( m_xProvider
.get() );
1593 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1595 // First, ask cache...
1596 if ( m_xCachedProps
.get() )
1598 xCachedProps
.reset( new ContentProperties( *m_xCachedProps
.get() ) );
1600 std::vector
< rtl::OUString
> aMissingProps
;
1601 if ( xCachedProps
->containsAllNames( rProperties
, aMissingProps
) )
1603 // All properties are already in cache! No server access needed.
1607 // use the cached ContentProperties instance
1608 xProps
.reset( new ContentProperties( *xCachedProps
.get() ) );
1612 if ( !m_bTransient
&& !bHasAll
)
1614 /////////////////////////////////////////////////////////////////////
1615 // Obtain values from server...
1616 /////////////////////////////////////////////////////////////////////
1618 // First, identify whether resource is DAV or not
1619 const ResourceType
& rType
= getResourceType( xEnv
, xResAccess
);
1621 bool bNetworkAccessAllowed
= true;
1625 // cache lookup... getResourceType may fill the props cache via PROPFIND!
1626 if ( m_xCachedProps
.get() )
1628 xCachedProps
.reset( new ContentProperties( *m_xCachedProps
.get() ) );
1630 std::vector
< rtl::OUString
> aMissingProps
;
1631 if ( xCachedProps
->containsAllNames( rProperties
, aMissingProps
) )
1633 // All properties are already in cache! No server access needed.
1637 // use the cached ContentProperties instance
1638 xProps
.reset( new ContentProperties( *xCachedProps
.get() ) );
1643 // Only DAV resources support PROPFIND
1644 std::vector
< rtl::OUString
> aPropNames
;
1646 uno::Sequence
< beans::Property
> aProperties( rProperties
.getLength() );
1648 if ( m_aFailedPropNames
.size() > 0 )
1650 sal_Int32 nProps
= 0;
1651 sal_Int32 nCount
= rProperties
.getLength();
1652 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1654 const rtl::OUString
& rName
= rProperties
[ n
].Name
;
1656 std::vector
< rtl::OUString
>::const_iterator it
1657 = m_aFailedPropNames
.begin();
1658 std::vector
< rtl::OUString
>::const_iterator end
1659 = m_aFailedPropNames
.end();
1671 aProperties
[ nProps
] = rProperties
[ n
];
1676 aProperties
.realloc( nProps
);
1680 aProperties
= rProperties
;
1683 if ( aProperties
.getLength() > 0 )
1684 ContentProperties::UCBNamesToDAVNames(
1685 aProperties
, aPropNames
);
1687 if ( aPropNames
.size() > 0 )
1689 std::vector
< DAVResource
> resources
;
1692 xResAccess
->PROPFIND(
1693 DAVZERO
, aPropNames
, resources
, xEnv
);
1695 if ( 1 == resources
.size() )
1698 xProps
->addProperties(
1699 aPropNames
, ContentProperties( resources
[ 0 ] ));
1702 new ContentProperties( resources
[ 0 ] ) );
1705 catch ( DAVException
const & e
)
1707 bNetworkAccessAllowed
1708 = shouldAccessNetworkAfterException( e
);
1710 if ( !bNetworkAccessAllowed
)
1712 if ( e
.getStatus() == SC_NOT_FOUND
)
1716 cancelCommandExecution( e
, xEnv
);
1725 if ( bNetworkAccessAllowed
)
1727 // All properties obtained already?
1728 std::vector
< rtl::OUString
> aMissingProps
;
1729 if ( !( xProps
.get()
1730 && xProps
->containsAllNames(
1731 rProperties
, aMissingProps
) )
1732 && !m_bDidGetOrHead
)
1734 // Possibly the missing props can be obtained using a HEAD
1737 std::vector
< rtl::OUString
> aHeaderNames
;
1738 ContentProperties::UCBNamesToHTTPNames(
1741 true /* bIncludeUnmatched */ );
1743 if ( aHeaderNames
.size() > 0 )
1747 DAVResource resource
;
1748 xResAccess
->HEAD( aHeaderNames
, resource
, xEnv
);
1749 m_bDidGetOrHead
= true;
1752 xProps
->addProperties(
1754 ContentProperties( resource
) );
1756 xProps
.reset ( new ContentProperties( resource
) );
1758 if ( m_eResourceType
== NON_DAV
)
1759 xProps
->addProperties( aMissingProps
,
1764 catch ( DAVException
const & e
)
1766 bNetworkAccessAllowed
1767 = shouldAccessNetworkAfterException( e
);
1769 if ( !bNetworkAccessAllowed
)
1771 cancelCommandExecution( e
, xEnv
);
1778 // might trigger HTTP redirect.
1779 // Therefore, title must be upadated here.
1780 NeonUri
aUri( xResAccess
->getURL() );
1781 aEscapedTitle
= aUri
.GetPathBaseName();
1783 if ( UNKNOWN
== rType
)
1786 new ContentProperties( aEscapedTitle
) );
1789 // For DAV resources we only know the Title, for non-DAV
1790 // resources we additionally know that it is a document.
1794 // new ContentProperties( aEscapedTitle ) );
1795 xProps
->addProperty( rtl::OUString(
1796 RTL_CONSTASCII_USTRINGPARAM(
1798 uno::makeAny( aEscapedTitle
), true);
1802 if ( !xProps
.get() )
1804 new ContentProperties( aEscapedTitle
, false ) );
1806 xProps
->addProperty( rtl::OUString(
1807 RTL_CONSTASCII_USTRINGPARAM(
1809 uno::makeAny( aEscapedTitle
), true);
1811 xProps
->addProperty( rtl::OUString(
1812 RTL_CONSTASCII_USTRINGPARAM(
1814 uno::makeAny( false), true);
1815 xProps
->addProperty( rtl::OUString(
1816 RTL_CONSTASCII_USTRINGPARAM(
1818 uno::makeAny( true), true);
1824 // No server access for just created (not yet committed) objects.
1825 // Only a minimal set of properties supported at this stage.
1827 xProps
.reset( new ContentProperties( aEscapedTitle
,
1831 // Add BaseURI property, if requested.
1832 if ( !xProps
->contains(
1833 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ) ) )
1835 xProps
->addProperty( rtl::OUString(
1836 RTL_CONSTASCII_USTRINGPARAM(
1839 getBaseURI( xResAccess
) ),
1843 uno::Reference
< sdbc::XRow
> xResultRow
1844 = getPropertyValues( xSMgr
,
1848 xIdentifier
->getContentIdentifier() );
1851 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1853 if ( !m_xCachedProps
.get() )
1854 m_xCachedProps
.reset( new ContentProperties( *xProps
.get() ) );
1856 m_xCachedProps
->addProperties( *xProps
.get() );
1858 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
1859 m_aEscapedTitle
= aEscapedTitle
;
1865 //=========================================================================
1866 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1867 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1868 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1869 throw ( uno::Exception
)
1871 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
1872 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
1873 rtl::Reference
< ContentProvider
> xProvider
;
1874 sal_Bool bTransient
;
1875 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1878 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1880 xProvider
.set( m_pProvider
);
1881 xIdentifier
.set( m_xIdentifier
);
1882 bTransient
= m_bTransient
;
1883 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1884 xSMgr
.set( m_xSMgr
);
1887 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1888 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1889 sal_Int32 nChanged
= 0;
1891 beans::PropertyChangeEvent aEvent
;
1892 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1893 aEvent
.Further
= sal_False
;
1894 // aEvent.PropertyName =
1895 aEvent
.PropertyHandle
= -1;
1896 // aEvent.OldValue =
1897 // aEvent.NewValue =
1899 std::vector
< ProppatchValue
> aProppatchValues
;
1900 std::vector
< sal_Int32
> aProppatchPropsPositions
;
1902 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1903 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1905 sal_Bool bExchange
= sal_False
;
1906 rtl::OUString aNewTitle
;
1907 rtl::OUString aOldTitle
;
1908 sal_Int32 nTitlePos
= -1;
1910 uno::Reference
< beans::XPropertySetInfo
> xInfo
;
1912 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1913 sal_Int32 nCount
= rValues
.getLength();
1914 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1916 const beans::PropertyValue
& rValue
= pValues
[ n
];
1917 const rtl::OUString
& rName
= rValue
.Name
;
1919 beans::Property aTmpProp
;
1920 xProvider
->getProperty( rName
, aTmpProp
);
1922 if ( aTmpProp
.Attributes
& beans::PropertyAttribute::READONLY
)
1924 // Read-only property!
1925 aRet
[ n
] <<= lang::IllegalAccessException(
1926 rtl::OUString::createFromAscii(
1927 "Property is read-only!" ),
1928 static_cast< cppu::OWeakObject
* >( this ) );
1932 //////////////////////////////////////////////////////////////////
1934 //////////////////////////////////////////////////////////////////
1936 if ( rName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1938 // Read-only property!
1939 aRet
[ n
] <<= lang::IllegalAccessException(
1940 rtl::OUString::createFromAscii(
1941 "Property is read-only!" ),
1942 static_cast< cppu::OWeakObject
* >( this ) );
1944 else if ( rName
.equalsAsciiL(
1945 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1947 // Read-only property!
1948 aRet
[ n
] <<= lang::IllegalAccessException(
1949 rtl::OUString::createFromAscii(
1950 "Property is read-only!" ),
1951 static_cast< cppu::OWeakObject
* >( this ) );
1953 else if ( rName
.equalsAsciiL(
1954 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1956 // Read-only property!
1957 aRet
[ n
] <<= lang::IllegalAccessException(
1958 rtl::OUString::createFromAscii(
1959 "Property is read-only!" ),
1960 static_cast< cppu::OWeakObject
* >( this ) );
1962 else if ( rName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1964 rtl::OUString aNewValue
;
1965 if ( rValue
.Value
>>= aNewValue
)
1968 if ( aNewValue
.getLength() > 0 )
1972 NeonUri
aURI( xIdentifier
->getContentIdentifier() );
1973 aOldTitle
= aURI
.GetPathBaseNameUnescaped();
1975 if ( aNewValue
!= aOldTitle
)
1977 // modified title -> modified URL -> exchange !
1979 bExchange
= sal_True
;
1981 // new value will be set later...
1982 aNewTitle
= aNewValue
;
1984 // remember position within sequence of values (for
1989 catch ( DAVException
const & )
1991 aRet
[ n
] <<= lang::IllegalArgumentException(
1992 rtl::OUString::createFromAscii(
1993 "Invalid content identifier!" ),
1994 static_cast< cppu::OWeakObject
* >( this ),
2000 aRet
[ n
] <<= lang::IllegalArgumentException(
2001 rtl::OUString::createFromAscii(
2002 "Empty title not allowed!" ),
2003 static_cast< cppu::OWeakObject
* >( this ),
2009 aRet
[ n
] <<= beans::IllegalTypeException(
2010 rtl::OUString::createFromAscii(
2011 "Property value has wrong type!" ),
2012 static_cast< cppu::OWeakObject
* >( this ) );
2017 //////////////////////////////////////////////////////////////
2019 //////////////////////////////////////////////////////////////
2022 xInfo
= getPropertySetInfo( xEnv
,
2023 sal_False
/* don't cache data */ );
2025 if ( !xInfo
->hasPropertyByName( rName
) )
2027 // Check, whether property exists. Skip otherwise.
2028 // PROPPATCH::set would add the property automatically, which
2029 // is not allowed for "setPropertyValues" command!
2030 aRet
[ n
] <<= beans::UnknownPropertyException(
2031 rtl::OUString::createFromAscii(
2032 "Property is unknown!" ),
2033 static_cast< cppu::OWeakObject
* >( this ) );
2037 if ( rName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
2039 // Read-only property!
2040 aRet
[ n
] <<= lang::IllegalAccessException(
2041 rtl::OUString::createFromAscii(
2042 "Property is read-only!" ),
2043 static_cast< cppu::OWeakObject
* >( this ) );
2045 else if ( rName
.equalsAsciiL(
2046 RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) )
2048 // Read-only property!
2049 aRet
[ n
] <<= lang::IllegalAccessException(
2050 rtl::OUString::createFromAscii(
2051 "Property is read-only!" ),
2052 static_cast< cppu::OWeakObject
* >( this ) );
2054 else if ( rName
.equalsAsciiL(
2055 RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
2057 // Read-only property!
2058 aRet
[ n
] <<= lang::IllegalAccessException(
2059 rtl::OUString::createFromAscii(
2060 "Property is read-only!" ),
2061 static_cast< cppu::OWeakObject
* >( this ) );
2063 else if ( rName
.equalsAsciiL(
2064 RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
2066 // Read-only property!
2067 // (but could be writable, if 'getcontenttype' would be)
2068 aRet
[ n
] <<= lang::IllegalAccessException(
2069 rtl::OUString::createFromAscii(
2070 "Property is read-only!" ),
2071 static_cast< cppu::OWeakObject
* >( this ) );
2075 if ( getResourceType( xEnv
, xResAccess
) == DAV
)
2077 // Property value will be set on server.
2078 ProppatchValue
aValue( PROPSET
, rName
, rValue
.Value
);
2079 aProppatchValues
.push_back( aValue
);
2081 // remember position within sequence of values (for
2083 aProppatchPropsPositions
.push_back( n
);
2087 // Property value will be stored in local property store.
2088 if ( !bTriedToGetAdditonalPropSet
&&
2089 !xAdditionalPropSet
.is() )
2092 = getAdditionalPropertySet( sal_False
);
2093 bTriedToGetAdditonalPropSet
= sal_True
;
2096 if ( xAdditionalPropSet
.is() )
2101 = xAdditionalPropSet
->getPropertyValue( rName
);
2102 if ( aOldValue
!= rValue
.Value
)
2104 xAdditionalPropSet
->setPropertyValue(
2105 rName
, rValue
.Value
);
2107 aEvent
.PropertyName
= rName
;
2108 aEvent
.OldValue
= aOldValue
;
2109 aEvent
.NewValue
= rValue
.Value
;
2111 aChanges
.getArray()[ nChanged
] = aEvent
;
2115 catch ( beans::UnknownPropertyException
const & e
)
2119 catch ( lang::WrappedTargetException
const & e
)
2123 catch ( beans::PropertyVetoException
const & e
)
2127 catch ( lang::IllegalArgumentException
const & e
)
2134 aRet
[ n
] <<= uno::Exception(
2135 rtl::OUString::createFromAscii(
2136 "No property set for storing the value!" ),
2137 static_cast< cppu::OWeakObject
* >( this ) );
2144 if ( !bTransient
&& aProppatchValues
.size() )
2148 // Set property values at server.
2149 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
2151 std::vector
< ProppatchValue
>::const_iterator it
2152 = aProppatchValues
.begin();
2153 std::vector
< ProppatchValue
>::const_iterator end
2154 = aProppatchValues
.end();
2158 aEvent
.PropertyName
= (*it
).name
;
2159 aEvent
.OldValue
= uno::Any(); // @@@ to expensive to obtain!
2160 aEvent
.NewValue
= (*it
).value
;
2162 aChanges
.getArray()[ nChanged
] = aEvent
;
2168 catch ( DAVException
const & e
)
2170 // OSL_ENSURE( sal_False,
2171 // "Content::setPropertyValues - PROPPATCH failed!" );
2174 cancelCommandExecution( e
, xEnv
);
2177 // Note: PROPPATCH either sets ALL property values OR NOTHING.
2179 std::vector
< sal_Int32
>::const_iterator it
2180 = aProppatchPropsPositions
.begin();
2181 std::vector
< sal_Int32
>::const_iterator end
2182 = aProppatchPropsPositions
.end();
2187 aRet
[ (*it
) ] <<= MapDAVException( e
, sal_True
);
2196 // Assemble new content identifier...
2198 rtl::OUString aNewURL
= getParentURL();
2199 if ( aNewURL
.lastIndexOf( '/' ) != ( aNewURL
.getLength() - 1 ) )
2200 aNewURL
+= rtl::OUString::createFromAscii( "/" );
2202 aNewURL
+= NeonUri::escapeSegment( aNewTitle
);
2204 uno::Reference
< ucb::XContentIdentifier
> xNewId
2205 = new ::ucbhelper::ContentIdentifier( xSMgr
, aNewURL
);
2206 uno::Reference
< ucb::XContentIdentifier
> xOldId
= xIdentifier
;
2210 NeonUri
sourceURI( xOldId
->getContentIdentifier() );
2211 NeonUri
targetURI( xNewId
->getContentIdentifier() );
2212 targetURI
.SetScheme( sourceURI
.GetScheme() );
2215 sourceURI
.GetPath(), targetURI
.GetURI(), sal_False
, xEnv
);
2216 // @@@ Should check for resources that could not be moved
2217 // (due to source access or target overwrite) and send
2218 // this information through the interaction handler.
2220 // @@@ Existing content should be checked to see if it needs
2221 // to be deleted at the source
2223 // @@@ Existing content should be checked to see if it has
2224 // been overwritten at the target
2226 if ( exchangeIdentity( xNewId
) )
2228 xResAccess
->setURL( aNewURL
);
2230 // DAV resources store all additional props on server!
2231 // // Adapt Additional Core Properties.
2232 // renameAdditionalPropertySet( xOldId->getContentIdentifier(),
2233 // xNewId->getContentIdentifier(),
2238 // Do not set new title!
2239 aNewTitle
= rtl::OUString();
2242 aRet
[ nTitlePos
] <<= uno::Exception(
2243 rtl::OUString::createFromAscii( "Exchange failed!" ),
2244 static_cast< cppu::OWeakObject
* >( this ) );
2247 catch ( DAVException
const & e
)
2249 // Do not set new title!
2250 aNewTitle
= rtl::OUString();
2253 aRet
[ nTitlePos
] <<= MapDAVException( e
, sal_True
);
2257 if ( aNewTitle
.getLength() )
2259 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2261 aEvent
.PropertyName
= rtl::OUString::createFromAscii( "Title" );
2262 aEvent
.OldValue
= uno::makeAny( aOldTitle
);
2263 aEvent
.NewValue
= uno::makeAny( aNewTitle
);
2265 m_aEscapedTitle
= NeonUri::escapeSegment( aNewTitle
);
2267 aChanges
.getArray()[ nChanged
] = aEvent
;
2273 aChanges
.realloc( nChanged
);
2274 notifyPropertiesChange( aChanges
);
2278 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2279 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2285 //=========================================================================
2286 uno::Any
Content::open(
2287 const ucb::OpenCommandArgument2
& rArg
,
2288 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2289 throw( uno::Exception
)
2293 #if OSL_DEBUG_LEVEL > 0
2294 fprintf( stderr
, "WebDAV: Content::open() this=%p\n", this );
2297 sal_Bool bOpenFolder
= ( ( rArg
.Mode
== ucb::OpenMode::ALL
) ||
2298 ( rArg
.Mode
== ucb::OpenMode::FOLDERS
) ||
2299 ( rArg
.Mode
== ucb::OpenMode::DOCUMENTS
) );
2302 if ( isFolder( xEnv
) )
2306 uno::Reference
< ucb::XDynamicResultSet
> xSet
2307 = new DynamicResultSet( m_xSMgr
, this, rArg
, xEnv
);
2312 // Error: Not a folder!
2314 rtl::OUStringBuffer aMsg
;
2315 if ( getResourceType( xEnv
) == FTP
)
2318 aMsg
.appendAscii( "FTP over HTTP proxy: resource cannot "
2319 "be opened as folder! Wrong Open Mode!" );
2323 aMsg
.appendAscii( "Non-folder resource cannot be "
2324 "opened as folder! Wrong Open Mode!" );
2327 ucbhelper::cancelCommandExecution(
2329 lang::IllegalArgumentException(
2330 aMsg
.makeStringAndClear(),
2331 static_cast< cppu::OWeakObject
* >( this ),
2338 if ( !rArg
.Sink
.is() )
2343 if ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
)
2345 #if OSL_DEBUG_LEVEL > 0
2346 fprintf( stderr
, "WebDAV: rArg.Mode currently(?) unsupported\n" );
2348 // Currently(?) unsupported.
2349 ucbhelper::cancelCommandExecution(
2351 ucb::UnsupportedOpenModeException(
2353 static_cast< cppu::OWeakObject
* >( this ),
2354 sal_Int16( rArg
.Mode
) ) ),
2359 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
2360 uno::Reference
< io::XOutputStream
> xOut
2361 = uno::Reference
< io::XOutputStream
>( rArg
.Sink
, uno::UNO_QUERY
);
2364 #if OSL_DEBUG_LEVEL > 0
2365 fprintf( stderr
, "WebDAV: rArg.Sink is XOutputStream\n" );
2370 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2373 osl::MutexGuard
aGuard( m_aMutex
);
2376 new DAVResourceAccess( *m_xResAccess
.get() ) );
2379 DAVResource aResource
;
2380 std::vector
< rtl::OUString
> aHeaders
;
2382 xResAccess
->GET( xOut
, aHeaders
, aResource
, xEnv
);
2383 m_bDidGetOrHead
= true;
2386 osl::MutexGuard
aGuard( m_aMutex
);
2389 if ( !m_xCachedProps
.get())
2390 m_xCachedProps
.reset( new ContentProperties( aResource
) );
2392 m_xCachedProps
->addProperties( aResource
);
2395 new DAVResourceAccess( *xResAccess
.get() ) );
2398 catch ( DAVException
const & e
)
2400 cancelCommandExecution( e
, xEnv
);
2406 uno::Reference
< io::XActiveDataSink
> xDataSink
2407 = uno::Reference
< io::XActiveDataSink
>( rArg
.Sink
,
2409 if ( xDataSink
.is() )
2411 #if OSL_DEBUG_LEVEL > 0
2412 fprintf( stderr
, "WebDAV: rArg.Sink is XActiveDataSink\n" );
2414 // PULL: wait for client read
2418 osl::MutexGuard
aGuard( m_aMutex
);
2420 // throw away previously cached headers.
2421 m_xCachedProps
.reset();
2423 // fill inputsream sync; return if all data present
2424 DAVResource aResource
;
2425 std::vector
< rtl::OUString
> aHeaders
;
2426 // // Obtain list containing all HTTP headers that can
2427 // // be mapped to UCB properties.
2428 // ContentProperties::getMappableHTTPHeaders( aHeaders );
2429 uno::Reference
< io::XInputStream
> xIn
2430 = m_xResAccess
->GET( aHeaders
, aResource
, xEnv
)->getInputStream();
2433 osl::MutexGuard
aGuard( m_aMutex
);
2435 m_xCachedProps
.reset(
2436 new ContentProperties( aResource
) );
2439 xDataSink
->setInputStream( xIn
);
2441 catch ( DAVException
const & e
)
2443 cancelCommandExecution( e
, xEnv
);
2449 uno::Reference
< io::XActiveDataStreamer
> xDataStreamer
2450 = uno::Reference
< io::XActiveDataStreamer
>( rArg
.Sink
,
2452 if ( xDataStreamer
.is() && !m_bForceReadOnly
)
2454 #if OSL_DEBUG_LEVEL > 0
2455 fprintf( stderr
, "WebDAV: rArg.Sink is XActiveDataStreamer\n" );
2458 m_pLock
= new ucb::Lock
;
2459 m_pLock
->Depth
= ucb::LockDepth_ZERO
;
2460 m_pLock
->Scope
= ucb::LockScope_EXCLUSIVE
;
2461 m_pLock
->Timeout
= 2*60; // 2 minutes
2463 m_nToExpire
= m_pLock
->Timeout
;
2465 // PULL: wait for client read
2468 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2470 osl::MutexGuard
aGuard( m_aMutex
);
2473 new DAVResourceAccess( *m_xResAccess
.get() ) );
2476 // fill inputsream sync; return if all data present
2477 DAVResource aResource
;
2478 std::vector
< rtl::OUString
> aHeaders
;
2481 m_xResAccess
->LOCK( *m_pLock
, xEnv
);
2484 catch ( ucb::CommandFailedException
const &e
)
2487 ucb::InteractiveIOException aIoException
;
2488 if ( ( e
.Reason
>>= aIoException
) && ( aIoException
.Code
== ucb::IOErrorCode_LOCKING_VIOLATION
) )
2492 // yes => we must be read only at the next try
2493 m_bForceReadOnly
= sal_True
;
2499 uno::Reference
< io::XStream
> xStream
2500 = xResAccess
->GET( aHeaders
, aResource
, xEnv
, sal_True
);
2501 m_bDidGetOrHead
= true;
2503 // pass the URL to the stream
2504 static_cast< NeonInputStream
* >( xStream
.get() )->SetURL( m_xResAccess
->getURL() );
2507 osl::MutexGuard
aGuard( m_aMutex
);
2510 if ( !m_xCachedProps
.get())
2511 m_xCachedProps
.reset( new ContentProperties( aResource
) );
2513 m_xCachedProps
->addProperties( aResource
.properties
);
2516 new DAVResourceAccess( *xResAccess
.get() ) );
2519 xDataStreamer
->setStream( xStream
);
2521 catch ( DAVException
const & e
)
2523 m_xResAccess
->UNLOCK( *m_pLock
, xEnv
);
2526 m_bForceReadOnly
= sal_False
;
2528 cancelCommandExecution( e
, xEnv
);
2534 #if OSL_DEBUG_LEVEL > 0
2535 fprintf( stderr
, "WebDAV: unsupported rArg.Sink\n" );
2537 // Note: aOpenCommand.Sink may contain an XStream
2538 // implementation. Support for this type of
2539 // sink is optional...
2540 ucbhelper::cancelCommandExecution(
2542 ucb::UnsupportedDataSinkException(
2544 static_cast< cppu::OWeakObject
* >( this ),
2555 //=========================================================================
2557 const ucb::PostCommandArgument2
& rArg
,
2558 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2559 throw( uno::Exception
)
2561 #if OSL_DEBUG_LEVEL > 0
2562 fprintf( stderr
, "WebDAV: Content::post() this=%p\n", this );
2565 uno::Reference
< io::XActiveDataSink
> xSink( rArg
.Sink
, uno::UNO_QUERY
);
2568 #if OSL_DEBUG_LEVEL > 0
2569 fprintf( stderr
, "WebDAV: rArg.Sink is XActiveDataSink\n" );
2573 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2575 osl::MutexGuard
aGuard( m_aMutex
);
2577 new DAVResourceAccess( *m_xResAccess
.get() ) );
2580 uno::Reference
< io::XInputStream
> xResult
2581 = xResAccess
->POST( rArg
.MediaType
,
2587 osl::MutexGuard
aGuard( m_aMutex
);
2589 new DAVResourceAccess( *xResAccess
.get() ) );
2592 xSink
->setInputStream( xResult
);
2594 catch ( DAVException
const & e
)
2596 cancelCommandExecution( e
, xEnv
, sal_True
);
2602 uno::Reference
< io::XOutputStream
> xResult( rArg
.Sink
, uno::UNO_QUERY
);
2605 #if OSL_DEBUG_LEVEL > 0
2606 fprintf( stderr
, "WebDAV: rArg.Sink is XOutputStream\n" );
2610 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2612 osl::MutexGuard
aGuard( m_aMutex
);
2614 new DAVResourceAccess( *m_xResAccess
.get() ) );
2617 xResAccess
->POST( rArg
.MediaType
,
2624 osl::MutexGuard
aGuard( m_aMutex
);
2626 new DAVResourceAccess( *xResAccess
.get() ) );
2629 catch ( DAVException
const & e
)
2631 cancelCommandExecution( e
, xEnv
, sal_True
);
2637 #if OSL_DEBUG_LEVEL > 0
2638 fprintf( stderr
, "WebDAV: rArg.Sink is XActiveDataStreamer (or something)\n" );
2640 ucbhelper::cancelCommandExecution(
2642 ucb::UnsupportedDataSinkException(
2644 static_cast< cppu::OWeakObject
* >( this ),
2652 //=========================================================================
2653 void Content::queryChildren( ContentRefList
& rChildren
)
2655 // Obtain a list with a snapshot of all currently instanciated contents
2656 // from provider and extract the contents which are direct children
2659 ::ucbhelper::ContentRefList aAllContents
;
2660 m_xProvider
->queryExistingContents( aAllContents
);
2662 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
2663 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
2665 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
2667 // No trailing slash found. Append.
2668 aURL
+= rtl::OUString::createFromAscii( "/" );
2671 sal_Int32 nLen
= aURL
.getLength();
2673 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
2674 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
2678 ::ucbhelper::ContentImplHelperRef xChild
= (*it
);
2679 rtl::OUString aChildURL
2680 = xChild
->getIdentifier()->getContentIdentifier();
2682 // Is aURL a prefix of aChildURL?
2683 if ( ( aChildURL
.getLength() > nLen
) &&
2684 ( aChildURL
.compareTo( aURL
, nLen
) == 0 ) )
2686 sal_Int32 nPos
= nLen
;
2687 nPos
= aChildURL
.indexOf( '/', nPos
);
2689 if ( ( nPos
== -1 ) ||
2690 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
2692 // No further slashes / only a final slash. It's a child!
2693 rChildren
.push_back(
2694 ::webdav_ucp::Content::ContentRef(
2695 static_cast< ::webdav_ucp::Content
* >(
2703 //=========================================================================
2704 void Content::insert(
2705 const uno::Reference
< io::XInputStream
> & xInputStream
,
2706 sal_Bool bReplaceExisting
,
2707 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2708 throw( uno::Exception
)
2710 sal_Bool bTransient
, bCollection
;
2711 rtl::OUString aEscapedTitle
;
2712 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2714 #if OSL_DEBUG_LEVEL > 0
2715 fprintf( stderr
, "WebDAV: Content::insert() this=%p\n", this );
2719 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2721 bTransient
= m_bTransient
;
2722 bCollection
= m_bCollection
;
2723 aEscapedTitle
= m_aEscapedTitle
;
2724 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2727 // Check, if all required properties are present.
2729 if ( aEscapedTitle
.getLength() == 0 )
2731 OSL_ENSURE( sal_False
, "Content::insert - Title missing!" );
2733 uno::Sequence
< rtl::OUString
> aProps( 1 );
2734 aProps
[ 0 ] = rtl::OUString::createFromAscii( "Title" );
2735 ucbhelper::cancelCommandExecution(
2736 uno::makeAny( ucb::MissingPropertiesException(
2738 static_cast< cppu::OWeakObject
* >( this ),
2744 if ( !bReplaceExisting
)
2746 /* [RFC 2616] - HTTP
2748 The PUT method requests that the enclosed entity be stored under the
2749 supplied Request-URI. If the Request-URI refers to an already
2750 existing resource, the enclosed entity SHOULD be considered as a
2751 modified version of the one residing on the origin server.
2754 /* [RFC 2518] - WebDAV
2756 MKCOL creates a new collection resource at the location specified by
2757 the Request-URI. If the resource identified by the Request-URI is
2758 non-null then the MKCOL MUST fail.
2761 // ==> Complain on PUT, continue on MKCOL.
2762 if ( !bTransient
|| ( bTransient
&& !bCollection
) )
2764 ucb::UnsupportedNameClashException
aEx(
2765 rtl::OUString::createFromAscii(
2766 "Unable to write without overwrite!" ),
2767 static_cast< cppu::OWeakObject
* >( this ),
2768 ucb::NameClash::ERROR
);
2770 uno::Reference
< task::XInteractionHandler
> xIH
;
2772 if ( Environment
.is() )
2773 xIH
= Environment
->getInteractionHandler();
2777 uno::Any
aExAsAny( uno::makeAny( aEx
) );
2779 rtl::Reference
< ucbhelper::SimpleInteractionRequest
> xRequest
2780 = new ucbhelper::SimpleInteractionRequest(
2782 ucbhelper::CONTINUATION_APPROVE
2783 | ucbhelper::CONTINUATION_DISAPPROVE
);
2784 xIH
->handle( xRequest
.get() );
2786 const sal_Int32 nResp
= xRequest
->getResponse();
2790 case ucbhelper::CONTINUATION_UNKNOWN
:
2791 // Not handled; throw.
2795 case ucbhelper::CONTINUATION_APPROVE
:
2796 // Continue -> Overwrite.
2797 bReplaceExisting
= sal_True
;
2800 case ucbhelper::CONTINUATION_DISAPPROVE
:
2802 throw ucb::CommandFailedException(
2804 uno::Reference
< uno::XInterface
>(),
2809 OSL_ENSURE( sal_False
,
2810 "Content::insert - "
2811 "Unknown interaction selection!" );
2812 throw ucb::CommandFailedException(
2813 rtl::OUString::createFromAscii(
2814 "Unknown interaction selection!" ),
2815 uno::Reference
< uno::XInterface
>(),
2830 // Assemble new content identifier...
2831 rtl::OUString aURL
= getParentURL();
2832 if ( aURL
.lastIndexOf( '/' ) != ( aURL
.getLength() - 1 ) )
2833 aURL
+= rtl::OUString::createFromAscii( "/" );
2835 aURL
+= aEscapedTitle
;
2839 xResAccess
->setURL( aURL
);
2842 xResAccess
->MKCOL( Environment
);
2844 xResAccess
->PUT( xInputStream
, Environment
);
2846 catch ( DAVException
const & except
)
2850 if ( except
.getStatus() == SC_METHOD_NOT_ALLOWED
)
2852 // [RFC 2518] - WebDAV
2853 // 405 (Method Not Allowed) - MKCOL can only be
2854 // executed on a deleted/non-existent resource.
2856 if ( bReplaceExisting
)
2858 // Destroy old resource.
2861 xResAccess
->DESTROY( Environment
);
2863 catch ( DAVException
const & e
)
2865 cancelCommandExecution( e
, Environment
, sal_True
);
2869 // Insert (recursion!).
2870 insert( xInputStream
, bReplaceExisting
, Environment
);
2873 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2875 new DAVResourceAccess( *xResAccess
.get() ) );
2883 rtl::OUString aTitle
;
2886 NeonUri
aURI( aURL
);
2887 aTitle
= aURI
.GetPathBaseNameUnescaped();
2889 catch ( DAVException
const & )
2893 ucbhelper::cancelCommandExecution(
2895 ucb::NameClashException(
2897 static_cast< cppu::OWeakObject
* >( this ),
2898 task::InteractionClassification_ERROR
,
2906 cancelCommandExecution( except
, Environment
, sal_True
);
2911 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2913 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aURL
);
2919 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2920 m_bTransient
= sal_False
;
2925 if ( !xInputStream
.is() )
2927 ucbhelper::cancelCommandExecution(
2929 ucb::MissingInputStreamException(
2931 static_cast< cppu::OWeakObject
* >( this ) ) ),
2938 xResAccess
->PUT( xInputStream
, Environment
);
2940 catch ( DAVException
const & e
)
2942 cancelCommandExecution( e
, Environment
, sal_True
);
2948 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2949 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2953 //=========================================================================
2954 void Content::transfer(
2955 const ucb::TransferInfo
& rArgs
,
2956 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2957 throw( uno::Exception
)
2959 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
2960 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
2961 uno::Reference
< ucb::XContentProvider
> xProvider
;
2962 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2965 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2967 xSMgr
.set( m_xSMgr
);
2968 xIdentifier
.set( m_xIdentifier
);
2969 xProvider
.set( m_xProvider
.get() );
2970 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2973 rtl::OUString aTargetURI
;
2976 NeonUri
sourceURI( rArgs
.SourceURL
);
2977 NeonUri
targetURI( xIdentifier
->getContentIdentifier() );
2978 aTargetURI
= targetURI
.GetPathBaseNameUnescaped();
2980 // Check source's and target's URL scheme
2982 const rtl::OUString aScheme
= sourceURI
.GetScheme().toAsciiLowerCase();
2983 if ( aScheme
.equalsAsciiL(
2984 RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME
) ) )
2986 sourceURI
.SetScheme(
2987 rtl::OUString::createFromAscii( HTTP_URL_SCHEME
) );
2989 else if ( aScheme
.equalsAsciiL(
2990 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME
) ) )
2992 sourceURI
.SetScheme(
2993 rtl::OUString::createFromAscii( HTTP_URL_SCHEME
) );
2995 else if ( aScheme
.equalsAsciiL(
2996 RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME
) ) )
2998 sourceURI
.SetScheme(
2999 rtl::OUString::createFromAscii( HTTP_URL_SCHEME
) );
3001 else if ( aScheme
.equalsAsciiL(
3002 RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME
) ) )
3004 sourceURI
.SetScheme(
3005 rtl::OUString::createFromAscii( HTTPS_URL_SCHEME
) );
3007 else if ( aScheme
.equalsAsciiL(
3008 RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME
) ) )
3010 sourceURI
.SetScheme(
3011 rtl::OUString::createFromAscii( HTTPS_URL_SCHEME
) );
3015 if ( !aScheme
.equalsAsciiL(
3016 RTL_CONSTASCII_STRINGPARAM( HTTP_URL_SCHEME
) ) &&
3017 !aScheme
.equalsAsciiL(
3018 RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME
) ) )
3020 ucbhelper::cancelCommandExecution(
3022 ucb::InteractiveBadTransferURLException(
3023 rtl::OUString::createFromAscii(
3024 "Unsupported URL scheme!" ),
3025 static_cast< cppu::OWeakObject
* >( this ) ) ),
3031 if ( targetURI
.GetScheme().toAsciiLowerCase().equalsAsciiL(
3032 RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME
) ) )
3033 targetURI
.SetScheme(
3034 rtl::OUString::createFromAscii( HTTP_URL_SCHEME
) );
3035 else if ( targetURI
.GetScheme().toAsciiLowerCase().equalsAsciiL(
3036 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME
) ) )
3037 targetURI
.SetScheme(
3038 rtl::OUString::createFromAscii( HTTP_URL_SCHEME
) );
3039 else if ( targetURI
.GetScheme().toAsciiLowerCase().equalsAsciiL(
3040 RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME
) ) )
3041 targetURI
.SetScheme(
3042 rtl::OUString::createFromAscii( HTTP_URL_SCHEME
) );
3043 else if ( targetURI
.GetScheme().toAsciiLowerCase().equalsAsciiL(
3044 RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME
) ) )
3045 targetURI
.SetScheme(
3046 rtl::OUString::createFromAscii( HTTPS_URL_SCHEME
) );
3047 else if ( targetURI
.GetScheme().toAsciiLowerCase().equalsAsciiL(
3048 RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME
) ) )
3049 targetURI
.SetScheme(
3050 rtl::OUString::createFromAscii( HTTPS_URL_SCHEME
) );
3052 // @@@ This implementation of 'transfer' only works
3053 // if the source and target are located at same host.
3054 // (Neon does not support cross-server copy/move)
3056 // Check for same host
3058 if ( sourceURI
.GetHost().getLength() &&
3059 ( sourceURI
.GetHost() != targetURI
.GetHost() ) )
3061 ucbhelper::cancelCommandExecution(
3062 uno::makeAny( ucb::InteractiveBadTransferURLException(
3063 rtl::OUString::createFromAscii(
3064 "Different hosts!" ),
3065 static_cast< cppu::OWeakObject
* >( this ) ) ),
3070 rtl::OUString aTitle
= rArgs
.NewTitle
;
3072 if ( !aTitle
.getLength() )
3073 aTitle
= sourceURI
.GetPathBaseNameUnescaped();
3075 if ( aTitle
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "/" ) ) )
3078 aTitle
= rtl::OUString();
3081 targetURI
.AppendPath( aTitle
);
3083 rtl::OUString aTargetURL
= xIdentifier
->getContentIdentifier();
3084 if ( ( aTargetURL
.lastIndexOf( '/' ) + 1 )
3085 != aTargetURL
.getLength() )
3086 aTargetURL
+= rtl::OUString::createFromAscii( "/" );
3088 aTargetURL
+= aTitle
;
3090 uno::Reference
< ucb::XContentIdentifier
> xTargetId
3091 = new ::ucbhelper::ContentIdentifier( xSMgr
, aTargetURL
);
3093 DAVResourceAccess
aSourceAccess( xSMgr
,
3094 xResAccess
->getSessionFactory(),
3095 sourceURI
.GetURI() );
3097 if ( rArgs
.MoveData
== sal_True
)
3099 uno::Reference
< ucb::XContentIdentifier
> xId
3100 = new ::ucbhelper::ContentIdentifier( xSMgr
, rArgs
.SourceURL
);
3102 // Note: The static cast is okay here, because its sure that
3103 // xProvider is always the WebDAVContentProvider.
3104 rtl::Reference
< Content
> xSource
3105 = static_cast< Content
* >(
3106 xProvider
->queryContent( xId
).get() );
3108 // [RFC 2518] - WebDAV
3109 // If a resource exists at the destination and the Overwrite
3110 // header is "T" then prior to performing the move the server
3111 // MUST perform a DELETE with "Depth: infinity" on the
3112 // destination resource. If the Overwrite header is set to
3113 // "F" then the operation will fail.
3115 aSourceAccess
.MOVE( sourceURI
.GetPath(),
3118 == ucb::NameClash::OVERWRITE
,
3123 // Propagate destruction to listeners.
3124 xSource
->destroy( sal_True
);
3127 // DAV resources store all additional props on server!
3128 // // Rename own and all children's Additional Core Properties.
3129 // renameAdditionalPropertySet( xId->getContentIdentifier(),
3130 // xTargetId->getContentIdentifier(),
3135 // [RFC 2518] - WebDAV
3136 // If a resource exists at the destination and the Overwrite
3137 // header is "T" then prior to performing the copy the server
3138 // MUST perform a DELETE with "Depth: infinity" on the
3139 // destination resource. If the Overwrite header is set to
3140 // "F" then the operation will fail.
3142 aSourceAccess
.COPY( sourceURI
.GetPath(),
3145 == ucb::NameClash::OVERWRITE
,
3148 // DAV resources store all additional props on server!
3149 // // Copy own and all children's Additional Core Properties.
3150 // copyAdditionalPropertySet( xId->getContentIdentifier(),
3151 // xTargetId->getContentIdentifier(),
3155 // Note: The static cast is okay here, because its sure that
3156 // xProvider is always the WebDAVContentProvider.
3157 rtl::Reference
< Content
> xTarget
3158 = static_cast< Content
* >(
3159 xProvider
->queryContent( xTargetId
).get() );
3161 // Announce transfered content in its new folder.
3162 xTarget
->inserted();
3164 catch ( ucb::IllegalIdentifierException
const & )
3168 catch ( DAVException
const & e
)
3170 // [RFC 2518] - WebDAV
3171 // 412 (Precondition Failed) - The server was unable to maintain
3172 // the liveness of the properties listed in the propertybehavior
3173 // XML element or the Overwrite header is "F" and the state of
3174 // the destination resource is non-null.
3176 if ( e
.getStatus() == SC_PRECONDITION_FAILED
)
3178 switch ( rArgs
.NameClash
)
3180 case ucb::NameClash::ERROR
:
3182 ucbhelper::cancelCommandExecution(
3184 ucb::NameClashException(
3186 static_cast< cppu::OWeakObject
* >( this ),
3187 task::InteractionClassification_ERROR
,
3193 case ucb::NameClash::OVERWRITE
:
3196 case ucb::NameClash::KEEP
: // deprecated
3197 case ucb::NameClash::RENAME
:
3198 case ucb::NameClash::ASK
:
3201 ucbhelper::cancelCommandExecution(
3203 ucb::UnsupportedNameClashException(
3205 static_cast< cppu::OWeakObject
* >( this ),
3206 rArgs
.NameClash
) ),
3213 cancelCommandExecution( e
, Environment
, sal_True
);
3218 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3219 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
3223 //=========================================================================
3224 void Content::destroy( sal_Bool bDeletePhysical
)
3225 throw( uno::Exception
)
3227 // @@@ take care about bDeletePhysical -> trashcan support
3228 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
3230 uno::Reference
< ucb::XContent
> xThis
= this;
3234 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3236 // Process instanciated children...
3238 ::webdav_ucp::Content::ContentRefList aChildren
;
3239 queryChildren( aChildren
);
3241 ContentRefList::const_iterator it
= aChildren
.begin();
3242 ContentRefList::const_iterator end
= aChildren
.end();
3246 (*it
)->destroy( bDeletePhysical
);
3251 //=========================================================================
3252 sal_Bool
Content::exchangeIdentity(
3253 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
3258 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
3260 uno::Reference
< ucb::XContent
> xThis
= this;
3262 // Already persistent?
3265 OSL_ENSURE( sal_False
, "Content::exchangeIdentity - Not persistent!" );
3269 // Exchange own identitity.
3271 // Fail, if a content with given id already exists.
3272 // if ( !hasData( xNewId ) )
3274 rtl::OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
3277 if ( exchange( xNewId
) )
3279 // Process instanciated children...
3281 ContentRefList aChildren
;
3282 queryChildren( aChildren
);
3284 ContentRefList::const_iterator it
= aChildren
.begin();
3285 ContentRefList::const_iterator end
= aChildren
.end();
3289 ContentRef xChild
= (*it
);
3291 // Create new content identifier for the child...
3292 uno::Reference
< ucb::XContentIdentifier
>
3293 xOldChildId
= xChild
->getIdentifier();
3294 rtl::OUString aOldChildURL
3295 = xOldChildId
->getContentIdentifier();
3296 rtl::OUString aNewChildURL
3297 = aOldChildURL
.replaceAt(
3299 aOldURL
.getLength(),
3300 xNewId
->getContentIdentifier() );
3301 uno::Reference
< ucb::XContentIdentifier
>
3303 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aNewChildURL
);
3305 if ( !xChild
->exchangeIdentity( xNewChildId
) )
3314 OSL_ENSURE( sal_False
,
3315 "Content::exchangeIdentity - "
3316 "Panic! Cannot exchange identity!" );
3320 //=========================================================================
3321 sal_Bool
Content::isFolder(
3322 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
3323 throw( uno::Exception
)
3326 osl::MutexGuard
aGuard( m_aMutex
);
3329 return m_bCollection
;
3332 uno::Sequence
< beans::Property
> aProperties( 1 );
3333 aProperties
[ 0 ].Name
= rtl::OUString::createFromAscii( "IsFolder" );
3334 aProperties
[ 0 ].Handle
= -1;
3335 uno::Reference
< sdbc::XRow
> xRow( getPropertyValues( aProperties
, xEnv
) );
3340 return xRow
->getBoolean( 1 );
3342 catch ( sdbc::SQLException
const & )
3350 //=========================================================================
3351 uno::Any
Content::MapDAVException( const DAVException
& e
, sal_Bool bWrite
)
3353 // Map DAVException...
3354 uno::Any aException
;
3356 switch ( e
.getStatus() )
3360 uno::Sequence
< uno::Any
> aArgs( 1 );
3361 aArgs
[ 0 ] <<= beans::PropertyValue(
3362 rtl::OUString::createFromAscii("Uri"), -1,
3363 uno::makeAny(m_xIdentifier
->getContentIdentifier()),
3364 beans::PropertyState_DIRECT_VALUE
);
3367 ucb::InteractiveAugmentedIOException(
3368 rtl::OUString::createFromAscii( "Not found!" ),
3369 static_cast< cppu::OWeakObject
* >( this ),
3370 task::InteractionClassification_ERROR
,
3371 ucb::IOErrorCode_NOT_EXISTING
,
3380 switch ( e
.getError() )
3382 case DAVException::DAV_HTTP_ERROR
:
3386 ucb::InteractiveNetworkWriteException(
3388 static_cast< cppu::OWeakObject
* >( this ),
3389 task::InteractionClassification_ERROR
,
3393 ucb::InteractiveNetworkReadException(
3395 static_cast< cppu::OWeakObject
* >( this ),
3396 task::InteractionClassification_ERROR
,
3401 case DAVException::DAV_HTTP_LOOKUP
:
3403 ucb::InteractiveNetworkResolveNameException(
3405 static_cast< cppu::OWeakObject
* >( this ),
3406 task::InteractionClassification_ERROR
,
3410 // @@@ No matching InteractiveNetwork*Exception
3411 // case DAVException::DAV_HTTP_AUTH:
3414 // @@@ No matching InteractiveNetwork*Exception
3415 // case DAVException::DAV_HTTP_AUTHPROXY:
3418 case DAVException::DAV_HTTP_CONNECT
:
3420 ucb::InteractiveNetworkConnectException(
3422 static_cast< cppu::OWeakObject
* >( this ),
3423 task::InteractionClassification_ERROR
,
3427 // @@@ No matching InteractiveNetwork*Exception
3428 // case DAVException::DAV_HTTP_TIMEOUT:
3431 // @@@ No matching InteractiveNetwork*Exception
3432 // case DAVException::DAV_HTTP_REDIRECT:
3435 // @@@ No matching InteractiveNetwork*Exception
3436 // case DAVException::DAV_SESSION_CREATE:
3439 case DAVException::DAV_INVALID_ARG
:
3441 lang::IllegalArgumentException(
3443 static_cast< cppu::OWeakObject
* >( this ),
3449 ucb::InteractiveNetworkGeneralException(
3451 static_cast< cppu::OWeakObject
* >( this ),
3452 task::InteractionClassification_ERROR
);
3459 //=========================================================================
3461 bool Content::shouldAccessNetworkAfterException( const DAVException
& e
)
3463 if ( ( e
.getStatus() == SC_NOT_FOUND
) ||
3464 ( e
.getError() == DAVException::DAV_HTTP_LOOKUP
) ||
3465 ( e
.getError() == DAVException::DAV_HTTP_CONNECT
) ||
3466 ( e
.getError() == DAVException::DAV_HTTP_AUTH
) ||
3467 ( e
.getError() == DAVException::DAV_HTTP_AUTHPROXY
) )
3473 //=========================================================================
3474 void Content::cancelCommandExecution(
3475 const DAVException
& e
,
3476 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
3477 sal_Bool bWrite
/* = sal_False */ )
3478 throw ( uno::Exception
)
3480 ucbhelper::cancelCommandExecution( MapDAVException( e
, bWrite
), xEnv
);
3484 //=========================================================================
3485 const rtl::OUString
Content::getBaseURI( const std::auto_ptr
< DAVResourceAccess
> & rResAccess
)
3487 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3489 // First, try to obtain value of response header "Content-Location".
3490 if ( m_xCachedProps
.get() )
3492 rtl::OUString aLocation
;
3493 m_xCachedProps
->getValue( rtl::OUString(
3494 RTL_CONSTASCII_USTRINGPARAM(
3495 "Content-Location" ) ) ) >>= aLocation
;
3496 if ( aLocation
.getLength() )
3500 // Do not use m_xIdentifier->getContentIdentifier() because it
3501 // for example does not reflect redirects applied to requests
3502 // done using the original URI but m_xResAccess' URI does.
3503 return rtl::Uri::convertRelToAbs( rResAccess
->getURL(),
3506 catch ( rtl::MalformedUriException
const & )
3512 return rtl::OUString( rResAccess
->getURL() );
3515 //=========================================================================
3516 const Content::ResourceType
& Content::getResourceType(
3517 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
,
3518 const std::auto_ptr
< DAVResourceAccess
> & rResAccess
)
3519 throw ( uno::Exception
)
3521 if ( m_eResourceType
== UNKNOWN
)
3523 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3525 ResourceType eResourceType
;
3526 eResourceType
= m_eResourceType
;
3528 const rtl::OUString
& rURL
= rResAccess
->getURL();
3529 const rtl::OUString
aScheme(
3530 rURL
.copy( 0, rURL
.indexOf( ':' ) ).toAsciiLowerCase() );
3532 if ( aScheme
.equalsAsciiL(
3533 RTL_CONSTASCII_STRINGPARAM( FTP_URL_SCHEME
) ) )
3535 eResourceType
= FTP
;
3541 // Try to fetch some frequently used property value, e.g. those
3542 // used when loading documents... along with identifying whether
3543 // this is a DAV resource.
3544 std::vector
< DAVResource
> resources
;
3545 std::vector
< rtl::OUString
> aPropNames
;
3546 uno::Sequence
< beans::Property
> aProperties( 4 );
3547 aProperties
[ 0 ].Name
= rtl::OUString::createFromAscii( "IsFolder" );
3548 aProperties
[ 1 ].Name
= rtl::OUString::createFromAscii( "IsDocument" );
3549 aProperties
[ 2 ].Name
= rtl::OUString::createFromAscii( "IsReadOnly" );
3550 aProperties
[ 3 ].Name
= rtl::OUString::createFromAscii( "MediaType" );
3552 ContentProperties::UCBNamesToDAVNames(
3553 aProperties
, aPropNames
);
3555 rResAccess
->PROPFIND(
3556 DAVZERO
, aPropNames
, resources
, xEnv
);
3558 if ( resources
.size() == 1 )
3560 m_xCachedProps
.reset( new ContentProperties( resources
[ 0 ] ) );
3561 m_xCachedProps
->containsAllNames( aProperties
, m_aFailedPropNames
);
3563 eResourceType
= DAV
;
3565 catch ( DAVException
const& e
)
3567 rResAccess
->resetUri();
3569 if (e
.getStatus() == SC_METHOD_NOT_ALLOWED
)
3571 // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the
3572 // resource is NON_DAV
3573 eResourceType
= NON_DAV
;
3577 m_eResourceType
= eResourceType
;
3580 return m_eResourceType
;
3583 //=========================================================================
3584 const Content::ResourceType
& Content::getResourceType(
3585 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
3586 throw ( uno::Exception
)
3588 return getResourceType( xEnv
, m_xResAccess
);