1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
32 **************************************************************************
34 *************************************************************************/
36 #include <comphelper/processfactory.hxx>
37 #include <osl/diagnose.h>
38 #include "osl/doublecheckedlocking.h"
39 #include <rtl/uri.hxx>
40 #include <rtl/ustrbuf.hxx>
41 #include <ucbhelper/contentidentifier.hxx>
42 #include <ucbhelper/propertyvalueset.hxx>
43 #include <ucbhelper/simpleinteractionrequest.hxx>
44 #include <ucbhelper/cancelcommandexecution.hxx>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
48 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <com/sun/star/io/XActiveDataSink.hpp>
51 #include <com/sun/star/io/XOutputStream.hpp>
52 #include <com/sun/star/lang/IllegalAccessException.hpp>
53 #include <com/sun/star/task/PasswordContainerInteractionHandler.hpp>
54 #include <com/sun/star/ucb/CommandEnvironment.hpp>
55 #include <com/sun/star/ucb/CommandFailedException.hpp>
56 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
57 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
58 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
59 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
60 #include "com/sun/star/ucb/InteractiveLockingLockedException.hpp"
61 #include "com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp"
62 #include "com/sun/star/ucb/InteractiveLockingNotLockedException.hpp"
63 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
64 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
65 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
66 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
67 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
68 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
69 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
70 #include <com/sun/star/ucb/NameClash.hpp>
71 #include <com/sun/star/ucb/NameClashException.hpp>
72 #include <com/sun/star/ucb/OpenCommandArgument3.hpp>
73 #include <com/sun/star/ucb/OpenMode.hpp>
74 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
75 #include <com/sun/star/ucb/PropertyCommandArgument.hpp>
76 #include <com/sun/star/ucb/TransferInfo.hpp>
77 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
78 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
79 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
80 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
81 #include <com/sun/star/ucb/XCommandInfo.hpp>
82 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
83 #include <com/sun/star/uno/XComponentContext.hpp>
85 #include "webdavcontent.hxx"
86 #include "webdavprovider.hxx"
87 #include "webdavresultset.hxx"
88 #include "ContentProperties.hxx"
89 #include "NeonUri.hxx"
90 #include "UCBDeadPropertyValue.hxx"
92 using namespace com::sun::star
;
93 using namespace webdav_ucp
;
98 // Content Implementation.
104 // ctr for content on an existing webdav resource
106 const uno::Reference
< uno::XComponentContext
>& rxContext
,
107 ContentProvider
* pProvider
,
108 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
109 rtl::Reference
< DAVSessionFactory
> const & rSessionFactory
)
110 throw ( ucb::ContentCreationException
)
111 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
112 m_eResourceType( UNKNOWN
),
113 m_pProvider( pProvider
),
114 m_bTransient( false ),
115 m_bCollection( false ),
116 m_bDidGetOrHead( false )
120 m_xResAccess
.reset( new DAVResourceAccess(
123 Identifier
->getContentIdentifier() ) );
125 NeonUri
aURI( Identifier
->getContentIdentifier() );
126 m_aEscapedTitle
= aURI
.GetPathBaseName();
128 catch ( DAVException
const & )
130 throw ucb::ContentCreationException();
135 // ctr for content on an non-existing webdav resource
137 const uno::Reference
< uno::XComponentContext
>& rxContext
,
138 ContentProvider
* pProvider
,
139 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
140 rtl::Reference
< DAVSessionFactory
> const & rSessionFactory
,
142 throw ( ucb::ContentCreationException
)
143 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
144 m_eResourceType( UNKNOWN
),
145 m_pProvider( pProvider
),
146 m_bTransient( true ),
147 m_bCollection( isCollection
),
148 m_bDidGetOrHead( false )
152 m_xResAccess
.reset( new DAVResourceAccess(
153 rxContext
, rSessionFactory
, Identifier
->getContentIdentifier() ) );
155 catch ( DAVException
const & )
157 throw ucb::ContentCreationException();
160 // Do not set m_aEscapedTitle here! Content::insert relays on this!!!
171 // XInterface methods.
176 void SAL_CALL
Content::acquire()
179 ContentImplHelper::acquire();
184 void SAL_CALL
Content::release()
187 ContentImplHelper::release();
192 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
193 throw ( uno::RuntimeException
, std::exception
)
195 // Note: isFolder may require network activities! So call it only
196 // if it is really necessary!!!
197 uno::Any aRet
= cppu::queryInterface(
199 static_cast< ucb::XContentCreator
* >( this ) );
200 if ( aRet
.hasValue() )
204 uno::Reference
< task::XInteractionHandler
> xIH(
205 task::PasswordContainerInteractionHandler::create( m_xContext
) );
207 // Supply a command env to isFolder() that contains an interaction
208 // handler that uses the password container service to obtain
209 // credentials without displaying a password gui.
211 uno::Reference
< ucb::XCommandEnvironment
> xCmdEnv(
212 ucb::CommandEnvironment::create(
215 uno::Reference
< ucb::XProgressHandler
>() ) );
217 return isFolder( xCmdEnv
) ? aRet
: uno::Any();
219 catch ( uno::RuntimeException
const & )
223 catch ( uno::Exception
const & )
228 return aRet
.hasValue() ? aRet
: ContentImplHelper::queryInterface( rType
);
233 // XTypeProvider methods.
237 XTYPEPROVIDER_COMMON_IMPL( Content
);
241 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
242 throw( uno::RuntimeException
, std::exception
)
244 bool bFolder
= false;
248 = isFolder( uno::Reference
< ucb::XCommandEnvironment
>() );
250 catch ( uno::RuntimeException
const & )
254 catch ( uno::Exception
const & )
258 cppu::OTypeCollection
* pCollection
= 0;
262 static cppu::OTypeCollection
* pFolderTypes
= 0;
264 pCollection
= pFolderTypes
;
267 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
269 pCollection
= pFolderTypes
;
272 static cppu::OTypeCollection
aCollection(
273 CPPU_TYPE_REF( lang::XTypeProvider
),
274 CPPU_TYPE_REF( lang::XServiceInfo
),
275 CPPU_TYPE_REF( lang::XComponent
),
276 CPPU_TYPE_REF( ucb::XContent
),
277 CPPU_TYPE_REF( ucb::XCommandProcessor
),
278 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
279 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
280 CPPU_TYPE_REF( beans::XPropertyContainer
),
281 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
282 CPPU_TYPE_REF( container::XChild
),
283 CPPU_TYPE_REF( ucb::XContentCreator
) ); // !!
284 pCollection
= &aCollection
;
285 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
286 pFolderTypes
= pCollection
;
290 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
295 static cppu::OTypeCollection
* pDocumentTypes
= 0;
297 pCollection
= pDocumentTypes
;
300 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
302 pCollection
= pDocumentTypes
;
305 static cppu::OTypeCollection
aCollection(
306 CPPU_TYPE_REF( lang::XTypeProvider
),
307 CPPU_TYPE_REF( lang::XServiceInfo
),
308 CPPU_TYPE_REF( lang::XComponent
),
309 CPPU_TYPE_REF( ucb::XContent
),
310 CPPU_TYPE_REF( ucb::XCommandProcessor
),
311 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
312 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
313 CPPU_TYPE_REF( beans::XPropertyContainer
),
314 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
315 CPPU_TYPE_REF( container::XChild
) );
316 pCollection
= &aCollection
;
317 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
318 pDocumentTypes
= pCollection
;
322 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
326 return (*pCollection
).getTypes();
331 // XServiceInfo methods.
336 OUString SAL_CALL
Content::getImplementationName()
337 throw( uno::RuntimeException
, std::exception
)
339 return OUString( "com.sun.star.comp.ucb.WebDAVContent" );
344 uno::Sequence
< OUString
> SAL_CALL
Content::getSupportedServiceNames()
345 throw( uno::RuntimeException
, std::exception
)
347 uno::Sequence
< OUString
> aSNS( 1 );
348 aSNS
[ 0 ] = WEBDAV_CONTENT_SERVICE_NAME
;
359 OUString SAL_CALL
Content::getContentType()
360 throw( uno::RuntimeException
, std::exception
)
362 bool bFolder
= false;
366 = isFolder( uno::Reference
< ucb::XCommandEnvironment
>() );
368 catch ( uno::RuntimeException
const & )
372 catch ( uno::Exception
const & )
377 return OUString( WEBDAV_COLLECTION_TYPE
);
379 return OUString( WEBDAV_CONTENT_TYPE
);
384 // XCommandProcessor methods.
389 uno::Any SAL_CALL
Content::execute(
390 const ucb::Command
& aCommand
,
391 sal_Int32
/*CommandId*/,
392 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
393 throw( uno::Exception
,
394 ucb::CommandAbortedException
,
395 uno::RuntimeException
, std::exception
)
397 SAL_INFO( "ucb.ucp.webdav", "Content::execute: start: command: " <<
398 aCommand
.Name
<< ", env: " <<
399 (Environment
.is() ? "present" : "missing") );
403 if ( aCommand
.Name
== "getPropertyValues" )
409 uno::Sequence
< beans::Property
> Properties
;
410 if ( !( aCommand
.Argument
>>= Properties
) )
412 ucbhelper::cancelCommandExecution(
413 uno::makeAny( lang::IllegalArgumentException(
414 OUString( "Wrong argument type!" ),
415 static_cast< cppu::OWeakObject
* >( this ),
421 aRet
<<= getPropertyValues( Properties
, Environment
);
423 else if ( aCommand
.Name
== "setPropertyValues" )
429 uno::Sequence
< beans::PropertyValue
> aProperties
;
430 if ( !( aCommand
.Argument
>>= aProperties
) )
432 ucbhelper::cancelCommandExecution(
433 uno::makeAny( lang::IllegalArgumentException(
434 OUString( "Wrong argument type!" ),
435 static_cast< cppu::OWeakObject
* >( this ),
441 if ( !aProperties
.getLength() )
443 ucbhelper::cancelCommandExecution(
444 uno::makeAny( lang::IllegalArgumentException(
445 OUString( "No properties!" ),
446 static_cast< cppu::OWeakObject
* >( this ),
452 aRet
<<= setPropertyValues( aProperties
, Environment
);
454 else if ( aCommand
.Name
== "getPropertySetInfo" )
457 // getPropertySetInfo
460 // Note: Implemented by base class.
461 aRet
<<= getPropertySetInfo( Environment
,
462 false /* don't cache data */ );
464 else if ( aCommand
.Name
== "getCommandInfo" )
470 // Note: Implemented by base class.
471 aRet
<<= getCommandInfo( Environment
, false );
473 else if ( aCommand
.Name
== "open" )
479 ucb::OpenCommandArgument3 aOpenCommand
;
480 ucb::OpenCommandArgument2 aTmp
;
481 if ( !( aCommand
.Argument
>>= aTmp
) )
483 ucbhelper::cancelCommandExecution(
484 uno::makeAny( lang::IllegalArgumentException(
485 OUString( "Wrong argument type!" ),
486 static_cast< cppu::OWeakObject
* >( this ),
491 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
493 // compat mode, extract Arg2 info into newer structure
494 aOpenCommand
.Mode
= aTmp
.Mode
;
495 aOpenCommand
.Priority
= aTmp
.Priority
;
496 aOpenCommand
.Sink
= aTmp
.Sink
;
497 aOpenCommand
.Properties
= aTmp
.Properties
;
498 aOpenCommand
.SortingInfo
= aTmp
.SortingInfo
;
501 aRet
= open( aOpenCommand
, Environment
);
503 if ( (aOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT
||
504 aOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) &&
505 supportsExclusiveWriteLock( Environment
) )
508 else if ( aCommand
.Name
== "insert" )
514 ucb::InsertCommandArgument arg
;
515 if ( !( aCommand
.Argument
>>= arg
) )
517 ucbhelper::cancelCommandExecution(
518 uno::makeAny( lang::IllegalArgumentException(
519 OUString( "Wrong argument type!" ),
520 static_cast< cppu::OWeakObject
* >( this ),
526 insert( arg
.Data
, arg
.ReplaceExisting
, Environment
);
528 else if ( aCommand
.Name
== "delete" )
534 bool bDeletePhysical
= false;
535 aCommand
.Argument
>>= bDeletePhysical
;
537 // KSO: Ignore parameter and destroy the content, if you don't support
538 // putting objects into trashcan. ( Since we do not have a trash can
539 // service yet (src603), you actually have no other choice. )
540 // if ( bDeletePhysical )
544 SAL_WNODEPRECATED_DECLARATIONS_PUSH
545 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
546 SAL_WNODEPRECATED_DECLARATIONS_POP
548 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
549 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
551 xResAccess
->DESTROY( Environment
);
553 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
554 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
557 catch ( DAVException
const & e
)
559 cancelCommandExecution( e
, Environment
, true );
564 // Propagate destruction.
565 destroy( bDeletePhysical
);
567 // Remove own and all children's Additional Core Properties.
568 removeAdditionalPropertySet( true );
570 else if ( aCommand
.Name
== "transfer" && isFolder( Environment
) )
574 // ( Not available at documents )
577 ucb::TransferInfo transferArgs
;
578 if ( !( aCommand
.Argument
>>= transferArgs
) )
580 ucbhelper::cancelCommandExecution(
581 uno::makeAny( lang::IllegalArgumentException(
582 OUString( "Wrong argument type!" ),
583 static_cast< cppu::OWeakObject
* >( this ),
589 transfer( transferArgs
, Environment
);
591 else if ( aCommand
.Name
== "post" )
597 ucb::PostCommandArgument2 aArg
;
598 if ( !( aCommand
.Argument
>>= aArg
) )
600 ucbhelper::cancelCommandExecution(
601 uno::makeAny( lang::IllegalArgumentException(
602 OUString( "Wrong argument type!" ),
603 static_cast< cppu::OWeakObject
* >( this ),
609 post( aArg
, Environment
);
611 else if ( aCommand
.Name
== "lock" && supportsExclusiveWriteLock( Environment
) )
619 else if ( aCommand
.Name
== "unlock" && supportsExclusiveWriteLock( Environment
) )
625 unlock( Environment
);
627 else if ( aCommand
.Name
== "createNewContent" && isFolder( Environment
) )
633 ucb::ContentInfo aArg
;
634 if ( !( aCommand
.Argument
>>= aArg
) )
636 ucbhelper::cancelCommandExecution(
637 uno::makeAny( lang::IllegalArgumentException(
638 OUString( "Wrong argument type!" ),
639 static_cast< cppu::OWeakObject
* >( this ),
645 aRet
= uno::makeAny( createNewContent( aArg
) );
647 else if ( aCommand
.Name
== "addProperty" )
649 ucb::PropertyCommandArgument aPropArg
;
650 if ( !( aCommand
.Argument
>>= aPropArg
))
652 ucbhelper::cancelCommandExecution(
653 uno::makeAny( lang::IllegalArgumentException(
654 "Wrong argument type!",
655 static_cast< cppu::OWeakObject
* >( this ),
660 // TODO when/if XPropertyContainer is removed,
661 // the command execution can be canceled in addProperty
664 addProperty( aPropArg
, Environment
);
666 catch ( const beans::PropertyExistException
&e
)
668 ucbhelper::cancelCommandExecution( uno::makeAny( e
), Environment
);
670 catch ( const beans::IllegalTypeException
&e
)
672 ucbhelper::cancelCommandExecution( uno::makeAny( e
), Environment
);
674 catch ( const lang::IllegalArgumentException
&e
)
676 ucbhelper::cancelCommandExecution( uno::makeAny( e
), Environment
);
679 else if ( aCommand
.Name
== "removeProperty" )
682 if ( !( aCommand
.Argument
>>= sPropName
) )
684 ucbhelper::cancelCommandExecution(
685 uno::makeAny( lang::IllegalArgumentException(
686 "Wrong argument type!",
687 static_cast< cppu::OWeakObject
* >( this ),
692 // TODO when/if XPropertyContainer is removed,
693 // the command execution can be canceled in removeProperty
696 removeProperty( sPropName
, Environment
);
698 catch( const beans::UnknownPropertyException
&e
)
700 ucbhelper::cancelCommandExecution( uno::makeAny( e
), Environment
);
702 catch( const beans::NotRemoveableException
&e
)
704 ucbhelper::cancelCommandExecution( uno::makeAny( e
), Environment
);
710 // Unsupported command
713 ucbhelper::cancelCommandExecution(
714 uno::makeAny( ucb::UnsupportedCommandException(
716 static_cast< cppu::OWeakObject
* >( this ) ) ),
721 OSL_TRACE( "<<<<< Content::execute: end: command: %s",
722 OUStringToOString( aCommand
.Name
,
723 RTL_TEXTENCODING_UTF8
).getStr() );
730 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
731 throw( uno::RuntimeException
, std::exception
)
735 SAL_WNODEPRECATED_DECLARATIONS_PUSH
736 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
737 SAL_WNODEPRECATED_DECLARATIONS_POP
739 osl::MutexGuard
aGuard( m_aMutex
);
740 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
744 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
745 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
748 catch ( DAVException
const & )
756 // XPropertyContainer methods.
760 void Content::addProperty( const ucb::PropertyCommandArgument
& aCmdArg
,
761 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
762 throw( beans::PropertyExistException
,
763 beans::IllegalTypeException
,
764 lang::IllegalArgumentException
,
765 uno::RuntimeException
)
767 // if ( m_bTransient )
770 if ( aCmdArg
.Property
.Name
.isEmpty() )
771 throw lang::IllegalArgumentException(
772 "\"addProperty\" with empty Property.Name",
773 static_cast< cppu::OWeakObject
* >( this ),
776 // Check property type.
777 if ( !UCBDeadPropertyValue::supportsType( aCmdArg
.Property
.Type
) )
779 throw beans::IllegalTypeException(
780 "\"addProperty\" unsupported Property.Type",
781 static_cast< cppu::OWeakObject
* >( this ) );
784 if ( aCmdArg
.DefaultValue
.hasValue()
785 && aCmdArg
.DefaultValue
.getValueType() != aCmdArg
.Property
.Type
)
787 throw beans::IllegalTypeException(
788 "\"addProperty\" DefaultValue does not match Property.Type",
789 static_cast< ::cppu::OWeakObject
* >( this ) );
793 // Make sure a property with the requested name does not already
794 // exist in dynamic and static(!) properties.
797 // Take into account special properties with custom namespace
798 // using <prop:the_propname xmlns:prop="the_namespace">
799 OUString aSpecialName
;
800 bool bIsSpecial
= DAVProperties::isUCBSpecialProperty(
801 aCmdArg
.Property
.Name
, aSpecialName
);
803 // Note: This requires network access!
804 if ( getPropertySetInfo( xEnv
, false /* don't cache data */ )
806 bIsSpecial
? aSpecialName
: aCmdArg
.Property
.Name
) )
808 // Property does already exist.
809 throw beans::PropertyExistException();
813 // Add a new dynamic property.
816 ProppatchValue
aValue(
817 PROPSET
, aCmdArg
.Property
.Name
, aCmdArg
.DefaultValue
);
819 std::vector
< ProppatchValue
> aProppatchValues
;
820 aProppatchValues
.push_back( aValue
);
824 // Set property value at server.
825 SAL_WNODEPRECATED_DECLARATIONS_PUSH
826 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
827 SAL_WNODEPRECATED_DECLARATIONS_POP
829 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
830 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
832 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
834 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
835 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
838 // Notify propertyset info change listeners.
839 beans::PropertySetInfoChangeEvent
evt(
840 static_cast< cppu::OWeakObject
* >( this ),
841 bIsSpecial
? aSpecialName
: aCmdArg
.Property
.Name
,
842 -1, // No handle available
843 beans::PropertySetInfoChange::PROPERTY_INSERTED
);
844 notifyPropertySetInfoChange( evt
);
846 catch ( DAVException
const & e
)
848 if ( e
.getStatus() == SC_FORBIDDEN
)
850 // Support for setting arbitrary dead properties is optional!
852 // Store property locally.
853 ContentImplHelper::addProperty(
854 bIsSpecial
? aSpecialName
: aCmdArg
.Property
.Name
,
855 aCmdArg
.Property
.Attributes
, aCmdArg
.DefaultValue
);
859 if ( shouldAccessNetworkAfterException( e
) )
863 ResourceType eType
= getResourceType( xEnv
);
868 throw lang::IllegalArgumentException();
872 // Store property locally.
873 ContentImplHelper::addProperty(
874 bIsSpecial
? aSpecialName
: aCmdArg
.Property
.Name
,
875 aCmdArg
.Property
.Attributes
, aCmdArg
.DefaultValue
);
879 OSL_FAIL( "Content::addProperty - "
880 "Unsupported resource type!" );
884 catch ( uno::Exception
const & )
886 OSL_FAIL( "Content::addProperty - "
887 "Unable to determine resource type!" );
892 OSL_FAIL( "Content::addProperty - "
893 "Unable to determine resource type!" );
899 void Content::removeProperty( const OUString
& Name
,
900 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
901 throw( beans::UnknownPropertyException
,
902 beans::NotRemoveableException
,
903 uno::RuntimeException
)
906 // Try to remove property from server.
911 std::vector
< ProppatchValue
> aProppatchValues
;
912 ProppatchValue
aValue( PROPREMOVE
, Name
, uno::Any() );
913 aProppatchValues
.push_back( aValue
);
915 // Remove property value from server.
916 SAL_WNODEPRECATED_DECLARATIONS_PUSH
917 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
918 SAL_WNODEPRECATED_DECLARATIONS_POP
920 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
921 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
923 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
925 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
926 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
929 // Notify propertyset info change listeners.
930 beans::PropertySetInfoChangeEvent
evt(
931 static_cast< cppu::OWeakObject
* >( this ),
933 -1, // No handle available
934 beans::PropertySetInfoChange::PROPERTY_REMOVED
);
935 notifyPropertySetInfoChange( evt
);
937 catch ( DAVException
const & e
)
939 if ( e
.getStatus() == SC_FORBIDDEN
)
941 // Support for setting arbitrary dead properties is optional!
943 // Try to remove property from local store.
944 ContentImplHelper::removeProperty( Name
);
948 if ( shouldAccessNetworkAfterException( e
) )
952 ResourceType eType
= getResourceType( xEnv
);
957 throw beans::UnknownPropertyException();
961 // Try to remove property from local store.
962 ContentImplHelper::removeProperty( Name
);
966 OSL_FAIL( "Content::removeProperty - "
967 "Unsupported resource type!" );
971 catch ( uno::Exception
const & )
973 OSL_FAIL( "Content::removeProperty - "
974 "Unable to determine resource type!" );
979 OSL_FAIL( "Content::removeProperty - "
980 "Unable to determine resource type!" );
981 // throw beans::UnknownPropertyException();
988 void SAL_CALL
Content::addProperty( const OUString
& Name
,
989 sal_Int16 Attributes
,
990 const uno::Any
& DefaultValue
)
991 throw( beans::PropertyExistException
,
992 beans::IllegalTypeException
,
993 lang::IllegalArgumentException
,
994 uno::RuntimeException
, std::exception
)
996 beans::Property aProperty
;
997 aProperty
.Name
= Name
;
998 aProperty
.Type
= DefaultValue
.getValueType();
999 aProperty
.Attributes
= Attributes
;
1000 aProperty
.Handle
= -1;
1002 addProperty( ucb::PropertyCommandArgument( aProperty
, DefaultValue
),
1003 uno::Reference
< ucb::XCommandEnvironment
>());
1007 void SAL_CALL
Content::removeProperty( const OUString
& Name
)
1008 throw( beans::UnknownPropertyException
,
1009 beans::NotRemoveableException
,
1010 uno::RuntimeException
, std::exception
)
1012 removeProperty( Name
,
1013 uno::Reference
< ucb::XCommandEnvironment
>() );
1018 // XContentCreator methods.
1023 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
1024 Content::queryCreatableContentsInfo()
1025 throw( uno::RuntimeException
, std::exception
)
1027 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1029 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
1032 aSeq
.getArray()[ 0 ].Type
= WEBDAV_CONTENT_TYPE
;
1033 aSeq
.getArray()[ 0 ].Attributes
1034 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
1035 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
1037 beans::Property aProp
;
1038 m_pProvider
->getProperty(
1039 OUString( "Title" ), aProp
);
1041 uno::Sequence
< beans::Property
> aDocProps( 1 );
1042 aDocProps
.getArray()[ 0 ] = aProp
;
1043 aSeq
.getArray()[ 0 ].Properties
= aDocProps
;
1046 aSeq
.getArray()[ 1 ].Type
= WEBDAV_COLLECTION_TYPE
;
1047 aSeq
.getArray()[ 1 ].Attributes
1048 = ucb::ContentInfoAttribute::KIND_FOLDER
;
1050 uno::Sequence
< beans::Property
> aFolderProps( 1 );
1051 aFolderProps
.getArray()[ 0 ] = aProp
;
1052 aSeq
.getArray()[ 1 ].Properties
= aFolderProps
;
1058 uno::Reference
< ucb::XContent
> SAL_CALL
1059 Content::createNewContent( const ucb::ContentInfo
& Info
)
1060 throw( uno::RuntimeException
, std::exception
)
1062 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1064 if ( Info
.Type
.isEmpty() )
1065 return uno::Reference
< ucb::XContent
>();
1067 if ( ( Info
.Type
!= WEBDAV_COLLECTION_TYPE
) && ( Info
.Type
!= WEBDAV_CONTENT_TYPE
) )
1068 return uno::Reference
< ucb::XContent
>();
1070 OUString aURL
= m_xIdentifier
->getContentIdentifier();
1072 OSL_ENSURE( !aURL
.isEmpty(),
1073 "WebdavContent::createNewContent - empty identifier!" );
1075 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
1079 if ( Info
.Type
== WEBDAV_COLLECTION_TYPE
)
1081 aURL
+= "New_Collection";
1082 isCollection
= true;
1086 aURL
+= "New_Content";
1087 isCollection
= false;
1090 uno::Reference
< ucb::XContentIdentifier
> xId(
1091 new ::ucbhelper::ContentIdentifier( aURL
) );
1093 // create the local content
1096 return new ::webdav_ucp::Content( m_xContext
,
1099 m_xResAccess
->getSessionFactory(),
1102 catch ( ucb::ContentCreationException
& )
1104 return uno::Reference
< ucb::XContent
>();
1110 OUString
Content::getParentURL()
1112 // <scheme>:// -> ""
1113 // <scheme>://foo -> ""
1114 // <scheme>://foo/ -> ""
1115 // <scheme>://foo/bar -> <scheme>://foo/
1116 // <scheme>://foo/bar/ -> <scheme>://foo/
1117 // <scheme>://foo/bar/abc -> <scheme>://foo/bar/
1119 OUString aURL
= m_xIdentifier
->getContentIdentifier();
1121 sal_Int32 nPos
= aURL
.lastIndexOf( '/' );
1122 if ( nPos
== ( aURL
.getLength() - 1 ) )
1124 // Trailing slash found. Skip.
1125 nPos
= aURL
.lastIndexOf( '/', nPos
);
1128 sal_Int32 nPos1
= aURL
.lastIndexOf( '/', nPos
);
1130 nPos1
= aURL
.lastIndexOf( '/', nPos1
);
1135 return OUString( aURL
.copy( 0, nPos
+ 1 ) );
1140 // Non-interface methods.
1145 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1146 const uno::Reference
< uno::XComponentContext
>& rxContext
,
1147 const uno::Sequence
< beans::Property
>& rProperties
,
1148 const ContentProperties
& rData
,
1149 const rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
>& rProvider
,
1150 const OUString
& rContentId
)
1152 // Note: Empty sequence means "get values of all supported properties".
1154 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
1155 = new ::ucbhelper::PropertyValueSet( rxContext
);
1157 sal_Int32 nCount
= rProperties
.getLength();
1160 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
1161 bool bTriedToGetAdditionalPropSet
= false;
1163 const beans::Property
* pProps
= rProperties
.getConstArray();
1164 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1166 const beans::Property
& rProp
= pProps
[ n
];
1168 // Process standard UCB, DAV and HTTP properties.
1169 const uno::Any
& rValue
= rData
.getValue( rProp
.Name
);
1170 if ( rValue
.hasValue() )
1172 xRow
->appendObject( rProp
, rValue
);
1176 // Process local Additional Properties.
1177 if ( !bTriedToGetAdditionalPropSet
&& !xAdditionalPropSet
.is() )
1180 = uno::Reference
< beans::XPropertySet
>(
1181 rProvider
->getAdditionalPropertySet( rContentId
,
1184 bTriedToGetAdditionalPropSet
= true;
1187 if ( !xAdditionalPropSet
.is() ||
1188 !xRow
->appendPropertySetValue(
1189 xAdditionalPropSet
, rProp
) )
1191 // Append empty entry.
1192 xRow
->appendVoid( rProp
);
1199 // Append all standard UCB, DAV and HTTP properties.
1200 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1201 const std::auto_ptr
< PropertyValueMap
> & xProps
= rData
.getProperties();
1202 SAL_WNODEPRECATED_DECLARATIONS_POP
1204 PropertyValueMap::const_iterator it
= xProps
->begin();
1205 PropertyValueMap::const_iterator end
= xProps
->end();
1207 ContentProvider
* pProvider
1208 = static_cast< ContentProvider
* >( rProvider
.get() );
1209 beans::Property aProp
;
1213 if ( pProvider
->getProperty( (*it
).first
, aProp
) )
1214 xRow
->appendObject( aProp
, (*it
).second
.value() );
1219 // Append all local Additional Properties.
1220 uno::Reference
< beans::XPropertySet
> xSet(
1221 rProvider
->getAdditionalPropertySet( rContentId
, false ),
1223 xRow
->appendPropertySet( xSet
);
1226 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1230 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1231 const uno::Sequence
< beans::Property
>& rProperties
,
1232 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1233 throw ( uno::Exception
, std::exception
)
1235 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1236 std::auto_ptr
< ContentProperties
> xProps
;
1237 std::auto_ptr
< ContentProperties
> xCachedProps
;
1238 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1239 SAL_WNODEPRECATED_DECLARATIONS_POP
1240 OUString aUnescapedTitle
;
1241 bool bHasAll
= false;
1242 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
1243 rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
> xProvider
;
1246 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1248 aUnescapedTitle
= NeonUri::unescape( m_aEscapedTitle
);
1249 xIdentifier
.set( m_xIdentifier
);
1250 xProvider
.set( m_xProvider
.get() );
1251 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1253 // First, ask cache...
1254 if ( m_xCachedProps
.get() )
1256 xCachedProps
.reset( new ContentProperties( *m_xCachedProps
.get() ) );
1258 std::vector
< OUString
> aMissingProps
;
1259 if ( xCachedProps
->containsAllNames( rProperties
, aMissingProps
) )
1261 // All properties are already in cache! No server access needed.
1265 // use the cached ContentProperties instance
1266 xProps
.reset( new ContentProperties( *xCachedProps
.get() ) );
1270 if ( !m_bTransient
&& !bHasAll
)
1273 // Obtain values from server...
1276 // First, identify whether resource is DAV or not
1277 bool bNetworkAccessAllowed
= true;
1278 ResourceType eType
= getResourceType(
1279 xEnv
, xResAccess
, &bNetworkAccessAllowed
);
1283 // cache lookup... getResourceType may fill the props cache via
1285 if ( m_xCachedProps
.get() )
1288 new ContentProperties( *m_xCachedProps
.get() ) );
1290 std::vector
< OUString
> aMissingProps
;
1291 if ( xCachedProps
->containsAllNames(
1292 rProperties
, aMissingProps
) )
1294 // All properties are already in cache! No server access
1299 // use the cached ContentProperties instance
1300 xProps
.reset( new ContentProperties( *xCachedProps
.get() ) );
1305 // Only DAV resources support PROPFIND
1306 std::vector
< OUString
> aPropNames
;
1308 uno::Sequence
< beans::Property
> aProperties(
1309 rProperties
.getLength() );
1311 if ( !m_aFailedPropNames
.empty() )
1313 sal_Int32 nProps
= 0;
1314 sal_Int32 nCount
= rProperties
.getLength();
1315 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1317 const OUString
& rName
= rProperties
[ n
].Name
;
1319 std::vector
< OUString
>::const_iterator it
1320 = m_aFailedPropNames
.begin();
1321 std::vector
< OUString
>::const_iterator end
1322 = m_aFailedPropNames
.end();
1334 aProperties
[ nProps
] = rProperties
[ n
];
1339 aProperties
.realloc( nProps
);
1343 aProperties
= rProperties
;
1346 if ( aProperties
.getLength() > 0 )
1347 ContentProperties::UCBNamesToDAVNames(
1348 aProperties
, aPropNames
);
1350 if ( !aPropNames
.empty() )
1352 std::vector
< DAVResource
> resources
;
1355 xResAccess
->PROPFIND(
1356 DAVZERO
, aPropNames
, resources
, xEnv
);
1358 if ( 1 == resources
.size() )
1361 xProps
->addProperties(
1363 ContentProperties( resources
[ 0 ] ));
1366 new ContentProperties( resources
[ 0 ] ) );
1369 catch ( DAVException
const & e
)
1371 bNetworkAccessAllowed
= bNetworkAccessAllowed
1372 && shouldAccessNetworkAfterException( e
);
1374 if ( !bNetworkAccessAllowed
)
1376 cancelCommandExecution( e
, xEnv
);
1384 if ( bNetworkAccessAllowed
)
1386 // All properties obtained already?
1387 std::vector
< OUString
> aMissingProps
;
1388 if ( !( xProps
.get()
1389 && xProps
->containsAllNames(
1390 rProperties
, aMissingProps
) )
1391 && !m_bDidGetOrHead
)
1393 // Possibly the missing props can be obtained using a HEAD
1396 std::vector
< OUString
> aHeaderNames
;
1397 ContentProperties::UCBNamesToHTTPNames(
1400 true /* bIncludeUnmatched */ );
1402 if ( !aHeaderNames
.empty() )
1406 DAVResource resource
;
1407 xResAccess
->HEAD( aHeaderNames
, resource
, xEnv
);
1408 m_bDidGetOrHead
= true;
1411 xProps
->addProperties(
1413 ContentProperties( resource
) );
1415 xProps
.reset ( new ContentProperties( resource
) );
1417 if ( m_eResourceType
== NON_DAV
)
1418 xProps
->addProperties( aMissingProps
,
1423 catch ( DAVException
const & e
)
1425 bNetworkAccessAllowed
1426 = shouldAccessNetworkAfterException( e
);
1428 if ( !bNetworkAccessAllowed
)
1430 cancelCommandExecution( e
, xEnv
);
1438 // might trigger HTTP redirect.
1439 // Therefore, title must be updated here.
1440 NeonUri
aUri( xResAccess
->getURL() );
1441 aUnescapedTitle
= aUri
.GetPathBaseNameUnescaped();
1443 if ( eType
== UNKNOWN
)
1445 xProps
.reset( new ContentProperties( aUnescapedTitle
) );
1448 // For DAV resources we only know the Title, for non-DAV
1449 // resources we additionally know that it is a document.
1454 // new ContentProperties( aUnescapedTitle ) );
1455 xProps
->addProperty(
1456 OUString( "Title" ),
1457 uno::makeAny( aUnescapedTitle
),
1462 if ( !xProps
.get() )
1463 xProps
.reset( new ContentProperties( aUnescapedTitle
, false ) );
1465 xProps
->addProperty(
1466 OUString( "Title" ),
1467 uno::makeAny( aUnescapedTitle
),
1470 xProps
->addProperty(
1471 OUString( "IsFolder" ),
1472 uno::makeAny( false ),
1474 xProps
->addProperty(
1475 OUString( "IsDocument" ),
1476 uno::makeAny( true ),
1482 // No server access for just created (not yet committed) objects.
1483 // Only a minimal set of properties supported at this stage.
1485 xProps
.reset( new ContentProperties( aUnescapedTitle
,
1489 sal_Int32 nCount
= rProperties
.getLength();
1490 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1492 const OUString rName
= rProperties
[ n
].Name
;
1493 if ( rName
== "BaseURI" )
1495 // Add BaseURI property, if requested.
1496 xProps
->addProperty(
1497 OUString( "BaseURI" ),
1498 uno::makeAny( getBaseURI( xResAccess
) ),
1501 else if ( rName
== "CreatableContentsInfo" )
1503 // Add CreatableContentsInfo property, if requested.
1504 bool bFolder
= false;
1506 OUString( "IsFolder" ) )
1508 xProps
->addProperty(
1509 OUString( "CreatableContentsInfo" ),
1510 uno::makeAny( bFolder
1511 ? queryCreatableContentsInfo()
1512 : uno::Sequence
< ucb::ContentInfo
>() ),
1517 uno::Reference
< sdbc::XRow
> xResultRow
1518 = getPropertyValues( m_xContext
,
1522 xIdentifier
->getContentIdentifier() );
1525 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1527 if ( !m_xCachedProps
.get() )
1528 m_xCachedProps
.reset( new CachableContentProperties( *xProps
.get() ) );
1530 m_xCachedProps
->addProperties( *xProps
.get() );
1532 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
1533 m_aEscapedTitle
= NeonUri::escapeSegment( aUnescapedTitle
);
1540 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1541 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1542 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1543 throw ( uno::Exception
, std::exception
)
1545 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
1546 rtl::Reference
< ContentProvider
> xProvider
;
1548 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1549 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1550 SAL_WNODEPRECATED_DECLARATIONS_POP
1553 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1555 xProvider
.set( m_pProvider
);
1556 xIdentifier
.set( m_xIdentifier
);
1557 bTransient
= m_bTransient
;
1558 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1561 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1562 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1563 sal_Int32 nChanged
= 0;
1565 beans::PropertyChangeEvent aEvent
;
1566 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1567 aEvent
.Further
= sal_False
;
1568 // aEvent.PropertyName =
1569 aEvent
.PropertyHandle
= -1;
1570 // aEvent.OldValue =
1571 // aEvent.NewValue =
1573 std::vector
< ProppatchValue
> aProppatchValues
;
1574 std::vector
< sal_Int32
> aProppatchPropsPositions
;
1576 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1577 bool bTriedToGetAdditionalPropSet
= false;
1579 bool bExchange
= false;
1582 sal_Int32 nTitlePos
= -1;
1584 uno::Reference
< beans::XPropertySetInfo
> xInfo
;
1586 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1587 sal_Int32 nCount
= rValues
.getLength();
1588 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1590 const beans::PropertyValue
& rValue
= pValues
[ n
];
1591 const OUString
& rName
= rValue
.Name
;
1593 beans::Property aTmpProp
;
1594 xProvider
->getProperty( rName
, aTmpProp
);
1596 if ( aTmpProp
.Attributes
& beans::PropertyAttribute::READONLY
)
1598 // Read-only property!
1599 aRet
[ n
] <<= lang::IllegalAccessException(
1600 OUString( "Property is read-only!" ),
1601 static_cast< cppu::OWeakObject
* >( this ) );
1609 if ( rName
== "ContentType" )
1611 // Read-only property!
1612 aRet
[ n
] <<= lang::IllegalAccessException(
1613 OUString( "Property is read-only!" ),
1614 static_cast< cppu::OWeakObject
* >( this ) );
1616 else if ( rName
== "IsDocument" )
1618 // Read-only property!
1619 aRet
[ n
] <<= lang::IllegalAccessException(
1620 OUString( "Property is read-only!" ),
1621 static_cast< cppu::OWeakObject
* >( this ) );
1623 else if ( rName
== "IsFolder" )
1625 // Read-only property!
1626 aRet
[ n
] <<= lang::IllegalAccessException(
1627 OUString( "Property is read-only!" ),
1628 static_cast< cppu::OWeakObject
* >( this ) );
1630 else if ( rName
== "Title" )
1633 if ( rValue
.Value
>>= aNewValue
)
1636 if ( !aNewValue
.isEmpty() )
1640 NeonUri
aURI( xIdentifier
->getContentIdentifier() );
1641 aOldTitle
= aURI
.GetPathBaseNameUnescaped();
1643 if ( aNewValue
!= aOldTitle
)
1645 // modified title -> modified URL -> exchange !
1649 // new value will be set later...
1650 aNewTitle
= aNewValue
;
1652 // remember position within sequence of values (for
1657 catch ( DAVException
const & )
1659 aRet
[ n
] <<= lang::IllegalArgumentException(
1660 OUString( "Invalid content identifier!" ),
1661 static_cast< cppu::OWeakObject
* >( this ),
1667 aRet
[ n
] <<= lang::IllegalArgumentException(
1668 OUString( "Empty title not allowed!" ),
1669 static_cast< cppu::OWeakObject
* >( this ),
1675 aRet
[ n
] <<= beans::IllegalTypeException(
1676 OUString( "Property value has wrong type!" ),
1677 static_cast< cppu::OWeakObject
* >( this ) );
1686 OUString aSpecialName
;
1687 bool bIsSpecial
= DAVProperties::isUCBSpecialProperty(
1688 rName
, aSpecialName
);
1691 xInfo
= getPropertySetInfo( xEnv
,
1692 false /* don't cache data */ );
1694 if ( !xInfo
->hasPropertyByName(
1695 bIsSpecial
? aSpecialName
: rName
) )
1697 // Check, whether property exists. Skip otherwise.
1698 // PROPPATCH::set would add the property automatically, which
1699 // is not allowed for "setPropertyValues" command!
1700 aRet
[ n
] <<= beans::UnknownPropertyException(
1701 OUString( "Property is unknown!" ),
1702 static_cast< cppu::OWeakObject
* >( this ) );
1706 if ( rName
== "Size" )
1708 // Read-only property!
1709 aRet
[ n
] <<= lang::IllegalAccessException(
1710 OUString( "Property is read-only!" ),
1711 static_cast< cppu::OWeakObject
* >( this ) );
1713 else if ( rName
== "DateCreated" )
1715 // Read-only property!
1716 aRet
[ n
] <<= lang::IllegalAccessException(
1717 OUString( "Property is read-only!" ),
1718 static_cast< cppu::OWeakObject
* >( this ) );
1720 else if ( rName
== "DateModified" )
1722 // Read-only property!
1723 aRet
[ n
] <<= lang::IllegalAccessException(
1724 OUString( "Property is read-only!" ),
1725 static_cast< cppu::OWeakObject
* >( this ) );
1727 else if ( rName
== "MediaType" )
1729 // Read-only property!
1730 // (but could be writable, if 'getcontenttype' would be)
1731 aRet
[ n
] <<= lang::IllegalAccessException(
1732 OUString( "Property is read-only!" ),
1733 static_cast< cppu::OWeakObject
* >( this ) );
1735 if ( rName
== "CreatableContentsInfo" )
1737 // Read-only property!
1738 aRet
[ n
] <<= lang::IllegalAccessException(
1739 OUString( "Property is read-only!" ),
1740 static_cast< cppu::OWeakObject
* >( this ) );
1744 if ( getResourceType( xEnv
, xResAccess
) == DAV
)
1746 // Property value will be set on server.
1747 ProppatchValue
aValue( PROPSET
, rName
, rValue
.Value
);
1748 aProppatchValues
.push_back( aValue
);
1750 // remember position within sequence of values (for
1752 aProppatchPropsPositions
.push_back( n
);
1756 // Property value will be stored in local property store.
1757 if ( !bTriedToGetAdditionalPropSet
&&
1758 !xAdditionalPropSet
.is() )
1761 = getAdditionalPropertySet( false );
1762 bTriedToGetAdditionalPropSet
= true;
1765 if ( xAdditionalPropSet
.is() )
1770 = xAdditionalPropSet
->getPropertyValue( rName
);
1771 if ( aOldValue
!= rValue
.Value
)
1773 xAdditionalPropSet
->setPropertyValue(
1774 rName
, rValue
.Value
);
1776 aEvent
.PropertyName
= rName
;
1777 aEvent
.OldValue
= aOldValue
;
1778 aEvent
.NewValue
= rValue
.Value
;
1780 aChanges
.getArray()[ nChanged
] = aEvent
;
1784 catch ( beans::UnknownPropertyException
const & e
)
1788 catch ( lang::WrappedTargetException
const & e
)
1792 catch ( beans::PropertyVetoException
const & e
)
1796 catch ( lang::IllegalArgumentException
const & e
)
1803 aRet
[ n
] <<= uno::Exception(
1804 OUString( "No property set for storing the value!" ),
1805 static_cast< cppu::OWeakObject
* >( this ) );
1812 if ( !bTransient
&& !aProppatchValues
.empty() )
1816 // Set property values at server.
1817 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
1819 std::vector
< ProppatchValue
>::const_iterator it
1820 = aProppatchValues
.begin();
1821 std::vector
< ProppatchValue
>::const_iterator end
1822 = aProppatchValues
.end();
1826 aEvent
.PropertyName
= (*it
).name
;
1827 aEvent
.OldValue
= uno::Any(); // @@@ to expensive to obtain!
1828 aEvent
.NewValue
= (*it
).value
;
1830 aChanges
.getArray()[ nChanged
] = aEvent
;
1836 catch ( DAVException
const & e
)
1838 // OSL_FAIL( // "Content::setPropertyValues - PROPPATCH failed!" );
1840 cancelCommandExecution( e
, xEnv
);
1847 // Assemble new content identifier...
1849 OUString aNewURL
= getParentURL();
1850 if ( aNewURL
.lastIndexOf( '/' ) != ( aNewURL
.getLength() - 1 ) )
1853 aNewURL
+= NeonUri::escapeSegment( aNewTitle
);
1855 uno::Reference
< ucb::XContentIdentifier
> xNewId
1856 = new ::ucbhelper::ContentIdentifier( aNewURL
);
1857 uno::Reference
< ucb::XContentIdentifier
> xOldId
= xIdentifier
;
1861 NeonUri
sourceURI( xOldId
->getContentIdentifier() );
1862 NeonUri
targetURI( xNewId
->getContentIdentifier() );
1863 targetURI
.SetScheme( sourceURI
.GetScheme() );
1866 sourceURI
.GetPath(), targetURI
.GetURI(), false, xEnv
);
1867 // @@@ Should check for resources that could not be moved
1868 // (due to source access or target overwrite) and send
1869 // this information through the interaction handler.
1871 // @@@ Existing content should be checked to see if it needs
1872 // to be deleted at the source
1874 // @@@ Existing content should be checked to see if it has
1875 // been overwritten at the target
1877 if ( exchangeIdentity( xNewId
) )
1879 xResAccess
->setURL( aNewURL
);
1881 // DAV resources store all additional props on server!
1882 // // Adapt Additional Core Properties.
1883 // renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1884 // xNewId->getContentIdentifier(),
1889 // Do not set new title!
1893 aRet
[ nTitlePos
] <<= uno::Exception(
1894 OUString("Exchange failed!"),
1895 static_cast< cppu::OWeakObject
* >( this ) );
1898 catch ( DAVException
const & e
)
1900 // Do not set new title!
1904 aRet
[ nTitlePos
] <<= MapDAVException( e
, true );
1908 if ( !aNewTitle
.isEmpty() )
1910 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1912 aEvent
.PropertyName
= "Title";
1913 aEvent
.OldValue
= uno::makeAny( aOldTitle
);
1914 aEvent
.NewValue
= uno::makeAny( aNewTitle
);
1916 m_aEscapedTitle
= NeonUri::escapeSegment( aNewTitle
);
1918 aChanges
.getArray()[ nChanged
] = aEvent
;
1924 aChanges
.realloc( nChanged
);
1925 notifyPropertiesChange( aChanges
);
1929 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1930 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
1937 uno::Any
Content::open(
1938 const ucb::OpenCommandArgument3
& rArg
,
1939 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1940 throw( uno::Exception
)
1944 bool bOpenFolder
= ( ( rArg
.Mode
== ucb::OpenMode::ALL
) ||
1945 ( rArg
.Mode
== ucb::OpenMode::FOLDERS
) ||
1946 ( rArg
.Mode
== ucb::OpenMode::DOCUMENTS
) );
1949 if ( isFolder( xEnv
) )
1953 uno::Reference
< ucb::XDynamicResultSet
> xSet
1954 = new DynamicResultSet( m_xContext
, this, rArg
, xEnv
);
1959 // Error: Not a folder!
1961 OUStringBuffer aMsg
;
1962 if ( getResourceType( xEnv
) == FTP
)
1965 aMsg
.appendAscii( "FTP over HTTP proxy: resource cannot "
1966 "be opened as folder! Wrong Open Mode!" );
1970 aMsg
.appendAscii( "Non-folder resource cannot be "
1971 "opened as folder! Wrong Open Mode!" );
1974 ucbhelper::cancelCommandExecution(
1976 lang::IllegalArgumentException(
1977 aMsg
.makeStringAndClear(),
1978 static_cast< cppu::OWeakObject
* >( this ),
1985 if ( rArg
.Sink
.is() )
1989 if ( ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
1990 ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
1992 // Currently(?) unsupported.
1993 ucbhelper::cancelCommandExecution(
1995 ucb::UnsupportedOpenModeException(
1997 static_cast< cppu::OWeakObject
* >( this ),
1998 sal_Int16( rArg
.Mode
) ) ),
2003 uno::Reference
< io::XOutputStream
> xOut
2004 = uno::Reference
< io::XOutputStream
>( rArg
.Sink
, uno::UNO_QUERY
);
2010 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2011 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2012 SAL_WNODEPRECATED_DECLARATIONS_POP
2015 osl::MutexGuard
aGuard( m_aMutex
);
2018 new DAVResourceAccess( *m_xResAccess
.get() ) );
2021 xResAccess
->setFlags( rArg
.OpeningFlags
);
2022 DAVResource aResource
;
2023 std::vector
< OUString
> aHeaders
;
2025 xResAccess
->GET( xOut
, aHeaders
, aResource
, xEnv
);
2026 m_bDidGetOrHead
= true;
2029 osl::MutexGuard
aGuard( m_aMutex
);
2032 if ( !m_xCachedProps
.get())
2033 m_xCachedProps
.reset(
2034 new CachableContentProperties( aResource
) );
2036 m_xCachedProps
->addProperties( aResource
);
2039 new DAVResourceAccess( *xResAccess
.get() ) );
2042 catch ( DAVException
const & e
)
2044 cancelCommandExecution( e
, xEnv
);
2050 uno::Reference
< io::XActiveDataSink
> xDataSink
2051 = uno::Reference
< io::XActiveDataSink
>( rArg
.Sink
,
2053 if ( xDataSink
.is() )
2055 // PULL: wait for client read
2058 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2059 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2060 SAL_WNODEPRECATED_DECLARATIONS_POP
2062 osl::MutexGuard
aGuard( m_aMutex
);
2065 new DAVResourceAccess( *m_xResAccess
.get() ) );
2068 xResAccess
->setFlags( rArg
.OpeningFlags
);
2070 // fill inputsream sync; return if all data present
2071 DAVResource aResource
;
2072 std::vector
< OUString
> aHeaders
;
2074 uno::Reference
< io::XInputStream
> xIn
2075 = xResAccess
->GET( aHeaders
, aResource
, xEnv
);
2076 m_bDidGetOrHead
= true;
2079 osl::MutexGuard
aGuard( m_aMutex
);
2082 if ( !m_xCachedProps
.get())
2083 m_xCachedProps
.reset(
2084 new CachableContentProperties( aResource
) );
2086 m_xCachedProps
->addProperties(
2087 aResource
.properties
);
2090 new DAVResourceAccess( *xResAccess
.get() ) );
2093 xDataSink
->setInputStream( xIn
);
2095 catch ( DAVException
const & e
)
2097 cancelCommandExecution( e
, xEnv
);
2103 // Note: aOpenCommand.Sink may contain an XStream
2104 // implementation. Support for this type of
2105 // sink is optional...
2106 ucbhelper::cancelCommandExecution(
2108 ucb::UnsupportedDataSinkException(
2110 static_cast< cppu::OWeakObject
* >( this ),
2123 const ucb::PostCommandArgument2
& rArg
,
2124 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2125 throw( uno::Exception
)
2127 uno::Reference
< io::XActiveDataSink
> xSink( rArg
.Sink
, uno::UNO_QUERY
);
2132 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2133 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2134 SAL_WNODEPRECATED_DECLARATIONS_POP
2136 osl::MutexGuard
aGuard( m_aMutex
);
2138 new DAVResourceAccess( *m_xResAccess
.get() ) );
2141 uno::Reference
< io::XInputStream
> xResult
2142 = xResAccess
->POST( rArg
.MediaType
,
2148 osl::MutexGuard
aGuard( m_aMutex
);
2150 new DAVResourceAccess( *xResAccess
.get() ) );
2153 xSink
->setInputStream( xResult
);
2155 catch ( DAVException
const & e
)
2157 cancelCommandExecution( e
, xEnv
, true );
2163 uno::Reference
< io::XOutputStream
> xResult( rArg
.Sink
, uno::UNO_QUERY
);
2168 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2169 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2170 SAL_WNODEPRECATED_DECLARATIONS_POP
2172 osl::MutexGuard
aGuard( m_aMutex
);
2174 new DAVResourceAccess( *m_xResAccess
.get() ) );
2177 xResAccess
->POST( rArg
.MediaType
,
2184 osl::MutexGuard
aGuard( m_aMutex
);
2186 new DAVResourceAccess( *xResAccess
.get() ) );
2189 catch ( DAVException
const & e
)
2191 cancelCommandExecution( e
, xEnv
, true );
2197 ucbhelper::cancelCommandExecution(
2199 ucb::UnsupportedDataSinkException(
2201 static_cast< cppu::OWeakObject
* >( this ),
2210 void Content::queryChildren( ContentRefList
& rChildren
)
2212 // Obtain a list with a snapshot of all currently instanciated contents
2213 // from provider and extract the contents which are direct children
2216 ::ucbhelper::ContentRefList aAllContents
;
2217 m_xProvider
->queryExistingContents( aAllContents
);
2219 OUString aURL
= m_xIdentifier
->getContentIdentifier();
2220 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
2222 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
2224 // No trailing slash found. Append.
2228 sal_Int32 nLen
= aURL
.getLength();
2230 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
2231 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
2235 ::ucbhelper::ContentImplHelperRef xChild
= (*it
);
2237 = xChild
->getIdentifier()->getContentIdentifier();
2239 // Is aURL a prefix of aChildURL?
2240 if ( ( aChildURL
.getLength() > nLen
) &&
2241 ( aChildURL
.compareTo( aURL
, nLen
) == 0 ) )
2243 sal_Int32 nPos
= nLen
;
2244 nPos
= aChildURL
.indexOf( '/', nPos
);
2246 if ( ( nPos
== -1 ) ||
2247 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
2249 // No further slashes / only a final slash. It's a child!
2250 rChildren
.push_back(
2251 ::webdav_ucp::Content::ContentRef(
2252 static_cast< ::webdav_ucp::Content
* >(
2261 void Content::insert(
2262 const uno::Reference
< io::XInputStream
> & xInputStream
,
2263 bool bReplaceExisting
,
2264 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2265 throw( uno::Exception
)
2267 bool bTransient
, bCollection
;
2268 OUString aEscapedTitle
;
2269 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2270 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2271 SAL_WNODEPRECATED_DECLARATIONS_POP
2274 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2276 bTransient
= m_bTransient
;
2277 bCollection
= m_bCollection
;
2278 aEscapedTitle
= m_aEscapedTitle
;
2279 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2282 // Check, if all required properties are present.
2284 if ( aEscapedTitle
.isEmpty() )
2286 OSL_FAIL( "Content::insert - Title missing!" );
2288 uno::Sequence
< OUString
> aProps( 1 );
2289 aProps
[ 0 ] = "Title";
2290 ucbhelper::cancelCommandExecution(
2291 uno::makeAny( ucb::MissingPropertiesException(
2293 static_cast< cppu::OWeakObject
* >( this ),
2299 if ( !bReplaceExisting
)
2301 /* [RFC 2616] - HTTP
2303 The PUT method requests that the enclosed entity be stored under the
2304 supplied Request-URI. If the Request-URI refers to an already
2305 existing resource, the enclosed entity SHOULD be considered as a
2306 modified version of the one residing on the origin server.
2309 /* [RFC 2518] - WebDAV
2311 MKCOL creates a new collection resource at the location specified by
2312 the Request-URI. If the resource identified by the Request-URI is
2313 non-null then the MKCOL MUST fail.
2316 // ==> Complain on PUT, continue on MKCOL.
2317 if ( !bTransient
|| ( bTransient
&& !bCollection
) )
2319 ucb::UnsupportedNameClashException
aEx(
2320 OUString( "Unable to write without overwrite!" ),
2321 static_cast< cppu::OWeakObject
* >( this ),
2322 ucb::NameClash::ERROR
);
2324 uno::Reference
< task::XInteractionHandler
> xIH
;
2326 if ( Environment
.is() )
2327 xIH
= Environment
->getInteractionHandler();
2331 uno::Any
aExAsAny( uno::makeAny( aEx
) );
2333 rtl::Reference
< ucbhelper::SimpleInteractionRequest
> xRequest
2334 = new ucbhelper::SimpleInteractionRequest(
2336 ucbhelper::CONTINUATION_APPROVE
2337 | ucbhelper::CONTINUATION_DISAPPROVE
);
2338 xIH
->handle( xRequest
.get() );
2340 const sal_Int32 nResp
= xRequest
->getResponse();
2344 case ucbhelper::CONTINUATION_UNKNOWN
:
2345 // Not handled; throw.
2349 case ucbhelper::CONTINUATION_APPROVE
:
2350 // Continue -> Overwrite.
2351 bReplaceExisting
= true;
2354 case ucbhelper::CONTINUATION_DISAPPROVE
:
2356 throw ucb::CommandFailedException(
2358 uno::Reference
< uno::XInterface
>(),
2363 OSL_FAIL( "Content::insert - "
2364 "Unknown interaction selection!" );
2365 throw ucb::CommandFailedException(
2366 OUString( "Unknown interaction selection!" ),
2367 uno::Reference
< uno::XInterface
>(),
2382 // Assemble new content identifier...
2383 OUString aURL
= getParentURL();
2384 if ( aURL
.lastIndexOf( '/' ) != ( aURL
.getLength() - 1 ) )
2387 aURL
+= aEscapedTitle
;
2391 xResAccess
->setURL( aURL
);
2394 xResAccess
->MKCOL( Environment
);
2396 xResAccess
->PUT( xInputStream
, Environment
);
2398 catch ( DAVException
const & except
)
2402 if ( except
.getStatus() == SC_METHOD_NOT_ALLOWED
)
2404 // [RFC 2518] - WebDAV
2405 // 405 (Method Not Allowed) - MKCOL can only be
2406 // executed on a deleted/non-existent resource.
2408 if ( bReplaceExisting
)
2410 // Destroy old resource.
2413 xResAccess
->DESTROY( Environment
);
2415 catch ( DAVException
const & e
)
2417 cancelCommandExecution( e
, Environment
, true );
2421 // Insert (recursion!).
2422 insert( xInputStream
, bReplaceExisting
, Environment
);
2425 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2427 new DAVResourceAccess( *xResAccess
.get() ) );
2438 NeonUri
aURI( aURL
);
2439 aTitle
= aURI
.GetPathBaseNameUnescaped();
2441 catch ( DAVException
const & )
2445 ucbhelper::cancelCommandExecution(
2447 ucb::NameClashException(
2449 static_cast< cppu::OWeakObject
* >( this ),
2450 task::InteractionClassification_ERROR
,
2458 cancelCommandExecution( except
, Environment
, true );
2463 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2464 m_xIdentifier
= new ::ucbhelper::ContentIdentifier( aURL
);
2470 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2471 m_bTransient
= false;
2476 if ( !xInputStream
.is() )
2478 ucbhelper::cancelCommandExecution(
2480 ucb::MissingInputStreamException(
2482 static_cast< cppu::OWeakObject
* >( this ) ) ),
2489 xResAccess
->PUT( xInputStream
, Environment
);
2491 catch ( DAVException
const & e
)
2493 cancelCommandExecution( e
, Environment
, true );
2499 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2500 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2505 void Content::transfer(
2506 const ucb::TransferInfo
& rArgs
,
2507 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2508 throw( uno::Exception
)
2510 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
2511 uno::Reference
< ucb::XContentProvider
> xProvider
;
2512 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2513 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2514 SAL_WNODEPRECATED_DECLARATIONS_POP
2517 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2519 xIdentifier
.set( m_xIdentifier
);
2520 xProvider
.set( m_xProvider
.get() );
2521 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2524 OUString aTargetURI
;
2527 NeonUri
sourceURI( rArgs
.SourceURL
);
2528 NeonUri
targetURI( xIdentifier
->getContentIdentifier() );
2529 aTargetURI
= targetURI
.GetPathBaseNameUnescaped();
2531 // Check source's and target's URL scheme
2533 const OUString aScheme
= sourceURI
.GetScheme().toAsciiLowerCase();
2534 if ( aScheme
== WEBDAV_URL_SCHEME
)
2536 sourceURI
.SetScheme(
2537 OUString( HTTP_URL_SCHEME
) );
2539 else if ( aScheme
== DAV_URL_SCHEME
)
2541 sourceURI
.SetScheme(
2542 OUString( HTTP_URL_SCHEME
) );
2544 else if ( aScheme
== DAVS_URL_SCHEME
)
2546 sourceURI
.SetScheme(
2547 OUString( HTTPS_URL_SCHEME
) );
2551 if ( aScheme
!= HTTP_URL_SCHEME
&& aScheme
!= HTTPS_URL_SCHEME
)
2553 ucbhelper::cancelCommandExecution(
2555 ucb::InteractiveBadTransferURLException(
2556 OUString( "Unsupported URL scheme!" ),
2557 static_cast< cppu::OWeakObject
* >( this ) ) ),
2563 if ( targetURI
.GetScheme().toAsciiLowerCase() == WEBDAV_URL_SCHEME
)
2564 targetURI
.SetScheme(
2565 OUString( HTTP_URL_SCHEME
) );
2566 else if ( targetURI
.GetScheme().toAsciiLowerCase() == DAV_URL_SCHEME
)
2567 targetURI
.SetScheme(
2568 OUString( HTTP_URL_SCHEME
) );
2570 // @@@ This implementation of 'transfer' only works
2571 // if the source and target are located at same host.
2572 // (Neon does not support cross-server copy/move)
2574 // Check for same host
2576 if ( !sourceURI
.GetHost().isEmpty() &&
2577 ( sourceURI
.GetHost() != targetURI
.GetHost() ) )
2579 ucbhelper::cancelCommandExecution(
2580 uno::makeAny( ucb::InteractiveBadTransferURLException(
2581 OUString( "Different hosts!" ),
2582 static_cast< cppu::OWeakObject
* >( this ) ) ),
2587 OUString aTitle
= rArgs
.NewTitle
;
2589 if ( aTitle
.isEmpty() )
2590 aTitle
= sourceURI
.GetPathBaseNameUnescaped();
2592 if ( aTitle
== "/" )
2598 targetURI
.AppendPath( aTitle
);
2600 OUString aTargetURL
= xIdentifier
->getContentIdentifier();
2601 if ( ( aTargetURL
.lastIndexOf( '/' ) + 1 )
2602 != aTargetURL
.getLength() )
2605 aTargetURL
+= aTitle
;
2607 uno::Reference
< ucb::XContentIdentifier
> xTargetId
2608 = new ::ucbhelper::ContentIdentifier( aTargetURL
);
2610 DAVResourceAccess
aSourceAccess( m_xContext
,
2611 xResAccess
->getSessionFactory(),
2612 sourceURI
.GetURI() );
2614 if ( rArgs
.MoveData
== sal_True
)
2616 uno::Reference
< ucb::XContentIdentifier
> xId
2617 = new ::ucbhelper::ContentIdentifier( rArgs
.SourceURL
);
2619 // Note: The static cast is okay here, because its sure that
2620 // xProvider is always the WebDAVContentProvider.
2621 rtl::Reference
< Content
> xSource
2622 = static_cast< Content
* >(
2623 xProvider
->queryContent( xId
).get() );
2625 // [RFC 2518] - WebDAV
2626 // If a resource exists at the destination and the Overwrite
2627 // header is "T" then prior to performing the move the server
2628 // MUST perform a DELETE with "Depth: infinity" on the
2629 // destination resource. If the Overwrite header is set to
2630 // "F" then the operation will fail.
2632 aSourceAccess
.MOVE( sourceURI
.GetPath(),
2635 == ucb::NameClash::OVERWRITE
,
2640 // Propagate destruction to listeners.
2641 xSource
->destroy( true );
2644 // DAV resources store all additional props on server!
2645 // // Rename own and all children's Additional Core Properties.
2646 // renameAdditionalPropertySet( xId->getContentIdentifier(),
2647 // xTargetId->getContentIdentifier(),
2652 // [RFC 2518] - WebDAV
2653 // If a resource exists at the destination and the Overwrite
2654 // header is "T" then prior to performing the copy the server
2655 // MUST perform a DELETE with "Depth: infinity" on the
2656 // destination resource. If the Overwrite header is set to
2657 // "F" then the operation will fail.
2659 aSourceAccess
.COPY( sourceURI
.GetPath(),
2662 == ucb::NameClash::OVERWRITE
,
2665 // DAV resources store all additional props on server!
2666 // // Copy own and all children's Additional Core Properties.
2667 // copyAdditionalPropertySet( xId->getContentIdentifier(),
2668 // xTargetId->getContentIdentifier(),
2672 // Note: The static cast is okay here, because its sure that
2673 // xProvider is always the WebDAVContentProvider.
2674 rtl::Reference
< Content
> xTarget
2675 = static_cast< Content
* >(
2676 xProvider
->queryContent( xTargetId
).get() );
2678 // Announce transferred content in its new folder.
2679 xTarget
->inserted();
2681 catch ( ucb::IllegalIdentifierException
const & )
2685 catch ( DAVException
const & e
)
2687 // [RFC 2518] - WebDAV
2688 // 412 (Precondition Failed) - The server was unable to maintain
2689 // the liveness of the properties listed in the propertybehavior
2690 // XML element or the Overwrite header is "F" and the state of
2691 // the destination resource is non-null.
2693 if ( e
.getStatus() == SC_PRECONDITION_FAILED
)
2695 switch ( rArgs
.NameClash
)
2697 case ucb::NameClash::ERROR
:
2699 ucbhelper::cancelCommandExecution(
2701 ucb::NameClashException(
2703 static_cast< cppu::OWeakObject
* >( this ),
2704 task::InteractionClassification_ERROR
,
2710 case ucb::NameClash::OVERWRITE
:
2713 case ucb::NameClash::KEEP
: // deprecated
2714 case ucb::NameClash::RENAME
:
2715 case ucb::NameClash::ASK
:
2718 ucbhelper::cancelCommandExecution(
2720 ucb::UnsupportedNameClashException(
2722 static_cast< cppu::OWeakObject
* >( this ),
2723 rArgs
.NameClash
) ),
2730 cancelCommandExecution( e
, Environment
, true );
2735 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2736 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2741 void Content::destroy( bool bDeletePhysical
)
2742 throw( uno::Exception
)
2744 // @@@ take care about bDeletePhysical -> trashcan support
2745 uno::Reference
< ucb::XContent
> xThis
= this;
2749 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2751 // Process instanciated children...
2753 ::webdav_ucp::Content::ContentRefList aChildren
;
2754 queryChildren( aChildren
);
2756 ContentRefList::const_iterator it
= aChildren
.begin();
2757 ContentRefList::const_iterator end
= aChildren
.end();
2761 (*it
)->destroy( bDeletePhysical
);
2767 bool Content::supportsExclusiveWriteLock(
2768 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2770 if ( getResourceType( Environment
) == DAV
)
2772 if ( m_xCachedProps
.get() )
2774 uno::Sequence
< ucb::LockEntry
> aSupportedLocks
;
2775 if ( m_xCachedProps
->getValue( DAVProperties::SUPPORTEDLOCK
)
2776 >>= aSupportedLocks
)
2778 for ( sal_Int32 n
= 0; n
< aSupportedLocks
.getLength(); ++n
)
2780 if ( aSupportedLocks
[ n
].Scope
2781 == ucb::LockScope_EXCLUSIVE
&&
2782 aSupportedLocks
[ n
].Type
2783 == ucb::LockType_WRITE
)
2794 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2795 throw( uno::Exception
)
2799 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2800 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2801 SAL_WNODEPRECATED_DECLARATIONS_POP
2803 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2804 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2809 <<= OUString("http://ucb.openoffice.org");
2812 ucb::LockScope_EXCLUSIVE
,
2813 ucb::LockType_WRITE
,
2814 ucb::LockDepth_ZERO
,
2816 180, // lock timeout in secs
2817 //-1, // infinite lock
2818 uno::Sequence
< OUString
>() );
2820 xResAccess
->LOCK( aLock
, Environment
);
2823 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2824 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2827 catch ( DAVException
const & e
)
2829 cancelCommandExecution( e
, Environment
, false );
2835 void Content::unlock(
2836 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2837 throw( uno::Exception
)
2841 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2842 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2843 SAL_WNODEPRECATED_DECLARATIONS_POP
2845 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2846 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2849 xResAccess
->UNLOCK( Environment
);
2852 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2853 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2856 catch ( DAVException
const & e
)
2858 cancelCommandExecution( e
, Environment
, false );
2864 bool Content::exchangeIdentity(
2865 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
2870 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
2872 uno::Reference
< ucb::XContent
> xThis
= this;
2874 // Already persistent?
2877 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
2881 // Exchange own identitity.
2883 // Fail, if a content with given id already exists.
2884 // if ( !hasData( xNewId ) )
2886 OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
2889 if ( exchange( xNewId
) )
2891 // Process instanciated children...
2893 ContentRefList aChildren
;
2894 queryChildren( aChildren
);
2896 ContentRefList::const_iterator it
= aChildren
.begin();
2897 ContentRefList::const_iterator end
= aChildren
.end();
2901 ContentRef xChild
= (*it
);
2903 // Create new content identifier for the child...
2904 uno::Reference
< ucb::XContentIdentifier
>
2905 xOldChildId
= xChild
->getIdentifier();
2906 OUString aOldChildURL
2907 = xOldChildId
->getContentIdentifier();
2908 OUString aNewChildURL
2909 = aOldChildURL
.replaceAt(
2911 aOldURL
.getLength(),
2912 xNewId
->getContentIdentifier() );
2913 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
2914 = new ::ucbhelper::ContentIdentifier( aNewChildURL
);
2916 if ( !xChild
->exchangeIdentity( xNewChildId
) )
2925 OSL_FAIL( "Content::exchangeIdentity - "
2926 "Panic! Cannot exchange identity!" );
2931 bool Content::isFolder(
2932 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
2933 throw( uno::Exception
, std::exception
)
2936 osl::MutexGuard
aGuard( m_aMutex
);
2939 return m_bCollection
;
2942 uno::Sequence
< beans::Property
> aProperties( 1 );
2943 aProperties
[ 0 ].Name
= "IsFolder";
2944 aProperties
[ 0 ].Handle
= -1;
2945 uno::Reference
< sdbc::XRow
> xRow( getPropertyValues( aProperties
, xEnv
) );
2950 return xRow
->getBoolean( 1 );
2952 catch ( sdbc::SQLException
const & )
2961 uno::Any
Content::MapDAVException( const DAVException
& e
, bool bWrite
)
2963 // Map DAVException...
2964 uno::Any aException
;
2969 aURL
= getParentURL();
2970 if ( aURL
.lastIndexOf('/') != ( aURL
.getLength() - 1 ) )
2973 aURL
+= m_aEscapedTitle
;
2977 aURL
= m_xIdentifier
->getContentIdentifier();
2980 switch ( e
.getStatus() )
2984 uno::Sequence
< uno::Any
> aArgs( 1 );
2985 aArgs
[ 0 ] <<= beans::PropertyValue(
2986 OUString("Uri"), -1,
2988 beans::PropertyState_DIRECT_VALUE
);
2991 ucb::InteractiveAugmentedIOException(
2992 OUString("Not found!"),
2993 static_cast< cppu::OWeakObject
* >( this ),
2994 task::InteractionClassification_ERROR
,
2995 ucb::IOErrorCode_NOT_EXISTING
,
3003 switch ( e
.getError() )
3005 case DAVException::DAV_HTTP_ERROR
:
3009 ucb::InteractiveNetworkWriteException(
3011 static_cast< cppu::OWeakObject
* >( this ),
3012 task::InteractionClassification_ERROR
,
3016 ucb::InteractiveNetworkReadException(
3018 static_cast< cppu::OWeakObject
* >( this ),
3019 task::InteractionClassification_ERROR
,
3024 case DAVException::DAV_HTTP_LOOKUP
:
3026 ucb::InteractiveNetworkResolveNameException(
3028 static_cast< cppu::OWeakObject
* >( this ),
3029 task::InteractionClassification_ERROR
,
3033 // @@@ No matching InteractiveNetwork*Exception
3034 // case DAVException::DAV_HTTP_AUTH:
3037 // @@@ No matching InteractiveNetwork*Exception
3038 // case DAVException::DAV_HTTP_AUTHPROXY:
3041 case DAVException::DAV_HTTP_CONNECT
:
3043 ucb::InteractiveNetworkConnectException(
3045 static_cast< cppu::OWeakObject
* >( this ),
3046 task::InteractionClassification_ERROR
,
3050 // @@@ No matching InteractiveNetwork*Exception
3051 // case DAVException::DAV_HTTP_TIMEOUT:
3054 // @@@ No matching InteractiveNetwork*Exception
3055 // case DAVException::DAV_HTTP_REDIRECT:
3058 // @@@ No matching InteractiveNetwork*Exception
3059 // case DAVException::DAV_SESSION_CREATE:
3062 case DAVException::DAV_INVALID_ARG
:
3064 lang::IllegalArgumentException(
3066 static_cast< cppu::OWeakObject
* >( this ),
3070 case DAVException::DAV_LOCKED
:
3072 ucb::InteractiveLockingLockedException(
3073 OUString("Locked!"),
3074 static_cast< cppu::OWeakObject
* >( this ),
3075 task::InteractionClassification_ERROR
,
3077 sal_False
); // not SelfOwned
3080 case DAVException::DAV_LOCKED_SELF
:
3082 ucb::InteractiveLockingLockedException(
3083 OUString("Locked (self!)"),
3084 static_cast< cppu::OWeakObject
* >( this ),
3085 task::InteractionClassification_ERROR
,
3087 sal_True
); // SelfOwned
3090 case DAVException::DAV_NOT_LOCKED
:
3092 ucb::InteractiveLockingNotLockedException(
3093 OUString("Not locked!"),
3094 static_cast< cppu::OWeakObject
* >( this ),
3095 task::InteractionClassification_ERROR
,
3099 case DAVException::DAV_LOCK_EXPIRED
:
3101 ucb::InteractiveLockingLockExpiredException(
3102 OUString("Lock expired!"),
3103 static_cast< cppu::OWeakObject
* >( this ),
3104 task::InteractionClassification_ERROR
,
3110 ucb::InteractiveNetworkGeneralException(
3112 static_cast< cppu::OWeakObject
* >( this ),
3113 task::InteractionClassification_ERROR
);
3122 bool Content::shouldAccessNetworkAfterException( const DAVException
& e
)
3124 if ( ( e
.getStatus() == SC_NOT_FOUND
) ||
3125 ( e
.getError() == DAVException::DAV_HTTP_LOOKUP
) ||
3126 ( e
.getError() == DAVException::DAV_HTTP_CONNECT
) ||
3127 ( e
.getError() == DAVException::DAV_HTTP_AUTH
) ||
3128 ( e
.getError() == DAVException::DAV_HTTP_AUTHPROXY
) )
3135 void Content::cancelCommandExecution(
3136 const DAVException
& e
,
3137 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
3138 bool bWrite
/* = sal_False */ )
3139 throw ( uno::Exception
)
3141 ucbhelper::cancelCommandExecution( MapDAVException( e
, bWrite
), xEnv
);
3146 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3148 Content::getBaseURI( const std::auto_ptr
< DAVResourceAccess
> & rResAccess
)
3150 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3152 // First, try to obtain value of response header "Content-Location".
3153 if ( m_xCachedProps
.get() )
3156 m_xCachedProps
->getValue( OUString( "Content-Location" ) ) >>= aLocation
;
3157 if ( !aLocation
.isEmpty() )
3161 // Do not use m_xIdentifier->getContentIdentifier() because it
3162 // for example does not reflect redirects applied to requests
3163 // done using the original URI but m_xResAccess' URI does.
3164 return rtl::Uri::convertRelToAbs( rResAccess
->getURL(),
3167 catch ( rtl::MalformedUriException
const & )
3173 return OUString( rResAccess
->getURL() );
3177 Content::ResourceType
Content::getResourceType(
3178 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
,
3179 const std::auto_ptr
< DAVResourceAccess
> & rResAccess
,
3180 bool * networkAccessAllowed
)
3181 throw ( uno::Exception
, std::exception
)
3184 osl::MutexGuard
g(m_aMutex
);
3185 if (m_eResourceType
!= UNKNOWN
) {
3186 return m_eResourceType
;
3190 ResourceType eResourceType
= UNKNOWN
;
3192 const OUString
& rURL
= rResAccess
->getURL();
3193 const OUString
aScheme(
3194 rURL
.copy( 0, rURL
.indexOf( ':' ) ).toAsciiLowerCase() );
3196 if ( aScheme
== FTP_URL_SCHEME
)
3198 eResourceType
= FTP
;
3204 // Try to fetch some frequently used property value, e.g. those
3205 // used when loading documents... along with identifying whether
3206 // this is a DAV resource.
3207 std::vector
< DAVResource
> resources
;
3208 std::vector
< OUString
> aPropNames
;
3209 uno::Sequence
< beans::Property
> aProperties( 5 );
3210 aProperties
[ 0 ].Name
= "IsFolder";
3211 aProperties
[ 1 ].Name
= "IsDocument";
3212 aProperties
[ 2 ].Name
= "IsReadOnly";
3213 aProperties
[ 3 ].Name
= "MediaType";
3214 aProperties
[ 4 ].Name
= DAVProperties::SUPPORTEDLOCK
;
3216 ContentProperties::UCBNamesToDAVNames( aProperties
, aPropNames
);
3218 rResAccess
->PROPFIND( DAVZERO
, aPropNames
, resources
, xEnv
);
3220 if ( resources
.size() == 1 )
3222 osl::MutexGuard
g(m_aMutex
);
3223 m_xCachedProps
.reset(
3224 new CachableContentProperties( resources
[ 0 ] ) );
3225 m_xCachedProps
->containsAllNames(
3226 aProperties
, m_aFailedPropNames
);
3229 eResourceType
= DAV
;
3231 catch ( DAVException
const & e
)
3233 rResAccess
->resetUri();
3235 if ( e
.getStatus() == SC_METHOD_NOT_ALLOWED
)
3237 // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the
3238 // resource is NON_DAV
3239 eResourceType
= NON_DAV
;
3241 else if (networkAccessAllowed
!= 0)
3243 *networkAccessAllowed
= *networkAccessAllowed
3244 && shouldAccessNetworkAfterException(e
);
3249 osl::MutexGuard
g(m_aMutex
);
3250 if (m_eResourceType
== UNKNOWN
) {
3251 m_eResourceType
= eResourceType
;
3254 eResourceType
!= m_eResourceType
, "ucb.ucp.webdav",
3255 "different resource types for <" << rURL
<< ">: "
3256 << +eResourceType
<< " vs. " << +m_eResourceType
);
3258 return m_eResourceType
;
3260 SAL_WNODEPRECATED_DECLARATIONS_POP
3263 Content::ResourceType
Content::getResourceType(
3264 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
3265 throw ( uno::Exception
, std::exception
)
3267 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3268 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
3269 SAL_WNODEPRECATED_DECLARATIONS_POP
3271 osl::MutexGuard
aGuard( m_aMutex
);
3272 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
3274 Content::ResourceType
const ret
= getResourceType( xEnv
, xResAccess
);
3276 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3277 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
3282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */