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 <osl/diagnose.h>
37 #include "osl/doublecheckedlocking.h"
38 #include <rtl/uri.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <ucbhelper/contentidentifier.hxx>
41 #include <ucbhelper/propertyvalueset.hxx>
42 #include <ucbhelper/simpleinteractionrequest.hxx>
43 #include <ucbhelper/cancelcommandexecution.hxx>
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
47 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/io/XActiveDataSink.hpp>
50 #include <com/sun/star/io/XOutputStream.hpp>
51 #include <com/sun/star/lang/IllegalAccessException.hpp>
52 #include <com/sun/star/task/PasswordContainerInteractionHandler.hpp>
53 #include <com/sun/star/ucb/CommandEnvironment.hpp>
54 #include <com/sun/star/ucb/CommandFailedException.hpp>
55 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
56 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
57 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
58 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
59 #include "com/sun/star/ucb/InteractiveLockingLockedException.hpp"
60 #include "com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp"
61 #include "com/sun/star/ucb/InteractiveLockingNotLockedException.hpp"
62 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
63 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
64 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
65 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
66 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
67 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
68 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
69 #include <com/sun/star/ucb/NameClash.hpp>
70 #include <com/sun/star/ucb/NameClashException.hpp>
71 #include <com/sun/star/ucb/OpenCommandArgument3.hpp>
72 #include <com/sun/star/ucb/OpenMode.hpp>
73 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
74 #include <com/sun/star/ucb/TransferInfo.hpp>
75 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
76 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
77 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
78 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
79 #include <com/sun/star/ucb/XCommandInfo.hpp>
80 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
81 #include <com/sun/star/uno/XComponentContext.hpp>
83 #include "webdavcontent.hxx"
84 #include "webdavprovider.hxx"
85 #include "webdavresultset.hxx"
86 #include "ContentProperties.hxx"
87 #include "NeonUri.hxx"
88 #include "UCBDeadPropertyValue.hxx"
90 using namespace com::sun::star
;
91 using namespace webdav_ucp
;
93 //=========================================================================
94 //=========================================================================
96 // Content Implementation.
98 //=========================================================================
99 //=========================================================================
101 //=========================================================================
102 // ctr for content on an existing webdav resource
104 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
105 ContentProvider
* pProvider
,
106 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
107 rtl::Reference
< DAVSessionFactory
> const & rSessionFactory
)
108 throw ( ucb::ContentCreationException
)
109 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
110 m_eResourceType( UNKNOWN
),
111 m_pProvider( pProvider
),
112 m_bTransient( false ),
113 m_bCollection( false ),
114 m_bDidGetOrHead( false )
118 m_xResAccess
.reset( new DAVResourceAccess(
121 Identifier
->getContentIdentifier() ) );
123 NeonUri
aURI( Identifier
->getContentIdentifier() );
124 m_aEscapedTitle
= aURI
.GetPathBaseName();
126 catch ( DAVException
const & )
128 throw ucb::ContentCreationException();
132 //=========================================================================
133 // ctr for content on an non-existing webdav resource
135 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
136 ContentProvider
* pProvider
,
137 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
138 rtl::Reference
< DAVSessionFactory
> const & rSessionFactory
,
139 sal_Bool isCollection
)
140 throw ( ucb::ContentCreationException
)
141 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
142 m_eResourceType( UNKNOWN
),
143 m_pProvider( pProvider
),
144 m_bTransient( true ),
145 m_bCollection( isCollection
),
146 m_bDidGetOrHead( false )
150 m_xResAccess
.reset( new DAVResourceAccess(
151 rxSMgr
, rSessionFactory
, Identifier
->getContentIdentifier() ) );
153 catch ( DAVException
const & )
155 throw ucb::ContentCreationException();
158 // Do not set m_aEscapedTitle here! Content::insert relays on this!!!
161 //=========================================================================
167 //=========================================================================
169 // XInterface methods.
171 //=========================================================================
174 void SAL_CALL
Content::acquire()
177 ContentImplHelper::acquire();
180 //=========================================================================
182 void SAL_CALL
Content::release()
185 ContentImplHelper::release();
188 //=========================================================================
190 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
191 throw ( uno::RuntimeException
)
193 // Note: isFolder may require network activities! So call it only
194 // if it is really necessary!!!
195 uno::Any aRet
= cppu::queryInterface(
197 static_cast< ucb::XContentCreator
* >( this ) );
198 if ( aRet
.hasValue() )
202 uno::Reference
< beans::XPropertySet
> const xProps(
203 m_xSMgr
, uno::UNO_QUERY_THROW
);
204 uno::Reference
< uno::XComponentContext
> xCtx
;
205 xCtx
.set( xProps
->getPropertyValue(
206 rtl::OUString( "DefaultContext" ) ),
207 uno::UNO_QUERY_THROW
);
209 uno::Reference
< task::XInteractionHandler
> xIH(
210 task::PasswordContainerInteractionHandler::create( xCtx
) );
212 // Supply a command env to isFolder() that contains an interaction
213 // handler that uses the password container service to obtain
214 // credentials without displaying a password gui.
216 uno::Reference
< ucb::XCommandEnvironment
> xCmdEnv(
217 ucb::CommandEnvironment::create(
220 uno::Reference
< ucb::XProgressHandler
>() ) );
222 return isFolder( xCmdEnv
) ? aRet
: uno::Any();
224 catch ( uno::RuntimeException
const & )
228 catch ( uno::Exception
const & )
233 return aRet
.hasValue() ? aRet
: ContentImplHelper::queryInterface( rType
);
236 //=========================================================================
238 // XTypeProvider methods.
240 //=========================================================================
242 XTYPEPROVIDER_COMMON_IMPL( Content
);
244 //=========================================================================
246 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
247 throw( uno::RuntimeException
)
249 sal_Bool bFolder
= sal_False
;
253 = isFolder( uno::Reference
< ucb::XCommandEnvironment
>() );
255 catch ( uno::RuntimeException
const & )
259 catch ( uno::Exception
const & )
263 cppu::OTypeCollection
* pCollection
= 0;
267 static cppu::OTypeCollection
* pFolderTypes
= 0;
269 pCollection
= pFolderTypes
;
272 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
274 pCollection
= pFolderTypes
;
277 static cppu::OTypeCollection
aCollection(
278 CPPU_TYPE_REF( lang::XTypeProvider
),
279 CPPU_TYPE_REF( lang::XServiceInfo
),
280 CPPU_TYPE_REF( lang::XComponent
),
281 CPPU_TYPE_REF( ucb::XContent
),
282 CPPU_TYPE_REF( ucb::XCommandProcessor
),
283 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
284 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
285 CPPU_TYPE_REF( beans::XPropertyContainer
),
286 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
287 CPPU_TYPE_REF( container::XChild
),
288 CPPU_TYPE_REF( ucb::XContentCreator
) ); // !!
289 pCollection
= &aCollection
;
290 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
291 pFolderTypes
= pCollection
;
295 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
300 static cppu::OTypeCollection
* pDocumentTypes
= 0;
302 pCollection
= pDocumentTypes
;
305 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
307 pCollection
= pDocumentTypes
;
310 static cppu::OTypeCollection
aCollection(
311 CPPU_TYPE_REF( lang::XTypeProvider
),
312 CPPU_TYPE_REF( lang::XServiceInfo
),
313 CPPU_TYPE_REF( lang::XComponent
),
314 CPPU_TYPE_REF( ucb::XContent
),
315 CPPU_TYPE_REF( ucb::XCommandProcessor
),
316 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
317 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
318 CPPU_TYPE_REF( beans::XPropertyContainer
),
319 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
320 CPPU_TYPE_REF( container::XChild
) );
321 pCollection
= &aCollection
;
322 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
323 pDocumentTypes
= pCollection
;
327 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
331 return (*pCollection
).getTypes();
334 //=========================================================================
336 // XServiceInfo methods.
338 //=========================================================================
341 rtl::OUString SAL_CALL
Content::getImplementationName()
342 throw( uno::RuntimeException
)
344 return rtl::OUString( "com.sun.star.comp.ucb.WebDAVContent" );
347 //=========================================================================
349 uno::Sequence
< rtl::OUString
> SAL_CALL
Content::getSupportedServiceNames()
350 throw( uno::RuntimeException
)
352 uno::Sequence
< rtl::OUString
> aSNS( 1 );
354 = rtl::OUString( WEBDAV_CONTENT_SERVICE_NAME
);
358 //=========================================================================
362 //=========================================================================
365 rtl::OUString SAL_CALL
Content::getContentType()
366 throw( uno::RuntimeException
)
368 sal_Bool bFolder
= sal_False
;
372 = isFolder( uno::Reference
< ucb::XCommandEnvironment
>() );
374 catch ( uno::RuntimeException
const & )
378 catch ( uno::Exception
const & )
383 return rtl::OUString( WEBDAV_COLLECTION_TYPE
);
385 return rtl::OUString( WEBDAV_CONTENT_TYPE
);
388 //=========================================================================
390 // XCommandProcessor methods.
392 //=========================================================================
395 uno::Any SAL_CALL
Content::execute(
396 const ucb::Command
& aCommand
,
397 sal_Int32
/*CommandId*/,
398 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
399 throw( uno::Exception
,
400 ucb::CommandAbortedException
,
401 uno::RuntimeException
)
403 OSL_TRACE( ">>>>> Content::execute: start: command: %s, env: %s",
404 rtl::OUStringToOString( aCommand
.Name
,
405 RTL_TEXTENCODING_UTF8
).getStr(),
406 Environment
.is() ? "present" : "missing" );
410 if ( aCommand
.Name
== "getPropertyValues" )
412 //////////////////////////////////////////////////////////////////
414 //////////////////////////////////////////////////////////////////
416 uno::Sequence
< beans::Property
> Properties
;
417 if ( !( aCommand
.Argument
>>= Properties
) )
419 ucbhelper::cancelCommandExecution(
420 uno::makeAny( lang::IllegalArgumentException(
421 rtl::OUString( "Wrong argument type!" ),
422 static_cast< cppu::OWeakObject
* >( this ),
428 aRet
<<= getPropertyValues( Properties
, Environment
);
430 else if ( aCommand
.Name
== "setPropertyValues" )
432 //////////////////////////////////////////////////////////////////
434 //////////////////////////////////////////////////////////////////
436 uno::Sequence
< beans::PropertyValue
> aProperties
;
437 if ( !( aCommand
.Argument
>>= aProperties
) )
439 ucbhelper::cancelCommandExecution(
440 uno::makeAny( lang::IllegalArgumentException(
441 rtl::OUString( "Wrong argument type!" ),
442 static_cast< cppu::OWeakObject
* >( this ),
448 if ( !aProperties
.getLength() )
450 ucbhelper::cancelCommandExecution(
451 uno::makeAny( lang::IllegalArgumentException(
452 rtl::OUString( "No properties!" ),
453 static_cast< cppu::OWeakObject
* >( this ),
459 aRet
<<= setPropertyValues( aProperties
, Environment
);
461 else if ( aCommand
.Name
== "getPropertySetInfo" )
463 //////////////////////////////////////////////////////////////////
464 // getPropertySetInfo
465 //////////////////////////////////////////////////////////////////
467 // Note: Implemented by base class.
468 aRet
<<= getPropertySetInfo( Environment
,
469 sal_False
/* don't cache data */ );
471 else if ( aCommand
.Name
== "getCommandInfo" )
473 //////////////////////////////////////////////////////////////////
475 //////////////////////////////////////////////////////////////////
477 // Note: Implemented by base class.
478 aRet
<<= getCommandInfo( Environment
, sal_False
);
480 else if ( aCommand
.Name
== "open" )
482 //////////////////////////////////////////////////////////////////
484 //////////////////////////////////////////////////////////////////
486 ucb::OpenCommandArgument3 aOpenCommand
;
487 ucb::OpenCommandArgument2 aTmp
;
488 if ( !( aCommand
.Argument
>>= aTmp
) )
490 ucbhelper::cancelCommandExecution(
491 uno::makeAny( lang::IllegalArgumentException(
492 rtl::OUString( "Wrong argument type!" ),
493 static_cast< cppu::OWeakObject
* >( this ),
498 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
500 // compat mode, extract Arg2 info into newer structure
501 aOpenCommand
.Mode
= aTmp
.Mode
;
502 aOpenCommand
.Priority
= aTmp
.Priority
;
503 aOpenCommand
.Sink
= aTmp
.Sink
;
504 aOpenCommand
.Properties
= aTmp
.Properties
;
505 aOpenCommand
.SortingInfo
= aTmp
.SortingInfo
;
508 aRet
= open( aOpenCommand
, Environment
);
510 if ( (aOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT
||
511 aOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) &&
512 supportsExclusiveWriteLock( Environment
) )
516 else if ( aCommand
.Name
== "insert" )
518 //////////////////////////////////////////////////////////////////
520 //////////////////////////////////////////////////////////////////
522 ucb::InsertCommandArgument arg
;
523 if ( !( aCommand
.Argument
>>= arg
) )
525 ucbhelper::cancelCommandExecution(
526 uno::makeAny( lang::IllegalArgumentException(
527 rtl::OUString( "Wrong argument type!" ),
528 static_cast< cppu::OWeakObject
* >( this ),
534 insert( arg
.Data
, arg
.ReplaceExisting
, Environment
);
536 else if ( aCommand
.Name
== "delete" )
538 //////////////////////////////////////////////////////////////////
540 //////////////////////////////////////////////////////////////////
542 sal_Bool bDeletePhysical
= sal_False
;
543 aCommand
.Argument
>>= bDeletePhysical
;
545 // KSO: Ignore parameter and destroy the content, if you don't support
546 // putting objects into trashcan. ( Since we do not have a trash can
547 // service yet (src603), you actually have no other choice. )
548 // if ( bDeletePhysical )
552 SAL_WNODEPRECATED_DECLARATIONS_PUSH
553 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
554 SAL_WNODEPRECATED_DECLARATIONS_POP
556 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
557 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
559 xResAccess
->DESTROY( Environment
);
561 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
562 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
565 catch ( DAVException
const & e
)
567 cancelCommandExecution( e
, Environment
, sal_True
);
572 // Propagate destruction.
573 destroy( bDeletePhysical
);
575 // Remove own and all children's Additional Core Properties.
576 removeAdditionalPropertySet( sal_True
);
578 else if ( aCommand
.Name
== "transfer" && isFolder( Environment
) )
580 //////////////////////////////////////////////////////////////////
582 // ( Not available at documents )
583 //////////////////////////////////////////////////////////////////
585 ucb::TransferInfo transferArgs
;
586 if ( !( aCommand
.Argument
>>= transferArgs
) )
588 ucbhelper::cancelCommandExecution(
589 uno::makeAny( lang::IllegalArgumentException(
590 rtl::OUString( "Wrong argument type!" ),
591 static_cast< cppu::OWeakObject
* >( this ),
597 transfer( transferArgs
, Environment
);
599 else if ( aCommand
.Name
== "post" )
601 //////////////////////////////////////////////////////////////////
603 //////////////////////////////////////////////////////////////////
605 ucb::PostCommandArgument2 aArg
;
606 if ( !( aCommand
.Argument
>>= aArg
) )
608 ucbhelper::cancelCommandExecution(
609 uno::makeAny( lang::IllegalArgumentException(
610 rtl::OUString( "Wrong argument type!" ),
611 static_cast< cppu::OWeakObject
* >( this ),
617 post( aArg
, Environment
);
619 else if ( aCommand
.Name
== "lock" && supportsExclusiveWriteLock( Environment
) )
621 //////////////////////////////////////////////////////////////////
623 //////////////////////////////////////////////////////////////////
627 else if ( aCommand
.Name
== "unlock" && supportsExclusiveWriteLock( Environment
) )
629 //////////////////////////////////////////////////////////////////
631 //////////////////////////////////////////////////////////////////
633 unlock( Environment
);
635 else if ( aCommand
.Name
== "createNewContent" && isFolder( Environment
) )
637 //////////////////////////////////////////////////////////////////
639 //////////////////////////////////////////////////////////////////
641 ucb::ContentInfo aArg
;
642 if ( !( aCommand
.Argument
>>= aArg
) )
644 ucbhelper::cancelCommandExecution(
645 uno::makeAny( lang::IllegalArgumentException(
646 rtl::OUString( "Wrong argument type!" ),
647 static_cast< cppu::OWeakObject
* >( this ),
653 aRet
= uno::makeAny( createNewContent( aArg
) );
657 //////////////////////////////////////////////////////////////////
658 // Unsupported command
659 //////////////////////////////////////////////////////////////////
661 ucbhelper::cancelCommandExecution(
662 uno::makeAny( ucb::UnsupportedCommandException(
664 static_cast< cppu::OWeakObject
* >( this ) ) ),
669 OSL_TRACE( "<<<<< Content::execute: end: command: %s",
670 rtl::OUStringToOString( aCommand
.Name
,
671 RTL_TEXTENCODING_UTF8
).getStr() );
676 //=========================================================================
678 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
679 throw( uno::RuntimeException
)
683 SAL_WNODEPRECATED_DECLARATIONS_PUSH
684 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
685 SAL_WNODEPRECATED_DECLARATIONS_POP
687 osl::MutexGuard
aGuard( m_aMutex
);
688 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
692 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
693 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
696 catch ( DAVException
const & )
702 //=========================================================================
704 // XPropertyContainer methods.
706 //=========================================================================
709 void SAL_CALL
Content::addProperty( const rtl::OUString
& Name
,
710 sal_Int16 Attributes
,
711 const uno::Any
& DefaultValue
)
712 throw( beans::PropertyExistException
,
713 beans::IllegalTypeException
,
714 lang::IllegalArgumentException
,
715 uno::RuntimeException
)
717 // if ( m_bTransient )
720 if ( Name
.isEmpty() )
721 throw lang::IllegalArgumentException();
723 // Check property type.
724 if ( !UCBDeadPropertyValue::supportsType( DefaultValue
.getValueType() ) )
726 OSL_FAIL( "Content::addProperty - Unsupported property type!" );
727 throw beans::IllegalTypeException();
730 //////////////////////////////////////////////////////////////////////
731 // Make sure a property with the requested name does not already
732 // exist in dynamic and static(!) properties.
733 //////////////////////////////////////////////////////////////////////
735 // @@@ Need real command environment here, but where to get it from?
736 // XPropertyContainer interface should be replaced by
737 // XCommandProcessor commands!
738 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
740 // Note: This requires network access!
741 if ( getPropertySetInfo( xEnv
, sal_False
/* don't cache data */ )
742 ->hasPropertyByName( Name
) )
744 // Property does already exist.
745 throw beans::PropertyExistException();
748 //////////////////////////////////////////////////////////////////////
749 // Add a new dynamic property.
750 //////////////////////////////////////////////////////////////////////
752 ProppatchValue
aValue( PROPSET
, Name
, DefaultValue
);
754 std::vector
< ProppatchValue
> aProppatchValues
;
755 aProppatchValues
.push_back( aValue
);
759 // Set property value at server.
760 SAL_WNODEPRECATED_DECLARATIONS_PUSH
761 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
762 SAL_WNODEPRECATED_DECLARATIONS_POP
764 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
765 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
767 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
769 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
770 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
773 // Notify propertyset info change listeners.
774 beans::PropertySetInfoChangeEvent
evt(
775 static_cast< cppu::OWeakObject
* >( this ),
777 -1, // No handle available
778 beans::PropertySetInfoChange::PROPERTY_INSERTED
);
779 notifyPropertySetInfoChange( evt
);
781 catch ( DAVException
const & e
)
783 if ( e
.getStatus() == SC_FORBIDDEN
)
785 // Support for setting arbitrary dead properties is optional!
787 // Store property locally.
788 ContentImplHelper::addProperty(
789 Name
, Attributes
, DefaultValue
);
793 if ( shouldAccessNetworkAfterException( e
) )
797 const ResourceType
& rType
= getResourceType( xEnv
);
802 throw lang::IllegalArgumentException();
806 // Store property locally.
807 ContentImplHelper::addProperty( Name
,
813 OSL_FAIL( "Content::addProperty - "
814 "Unsupported resource type!" );
818 catch ( uno::Exception
const & )
820 OSL_FAIL( "Content::addProperty - "
821 "Unable to determine resource type!" );
826 OSL_FAIL( "Content::addProperty - "
827 "Unable to determine resource type!" );
833 //=========================================================================
835 void SAL_CALL
Content::removeProperty( const rtl::OUString
& Name
)
836 throw( beans::UnknownPropertyException
,
837 beans::NotRemoveableException
,
838 uno::RuntimeException
)
840 // @@@ Need real command environment here, but where to get it from?
841 // XPropertyContainer interface should be replaced by
842 // XCommandProcessor commands!
843 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
845 //////////////////////////////////////////////////////////////////////
846 // Try to remove property from server.
847 //////////////////////////////////////////////////////////////////////
851 std::vector
< ProppatchValue
> aProppatchValues
;
852 ProppatchValue
aValue( PROPREMOVE
, Name
, uno::Any() );
853 aProppatchValues
.push_back( aValue
);
855 // Remove property value from server.
856 SAL_WNODEPRECATED_DECLARATIONS_PUSH
857 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
858 SAL_WNODEPRECATED_DECLARATIONS_POP
860 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
861 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
863 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
865 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
866 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
869 // Notify propertyset info change listeners.
870 beans::PropertySetInfoChangeEvent
evt(
871 static_cast< cppu::OWeakObject
* >( this ),
873 -1, // No handle available
874 beans::PropertySetInfoChange::PROPERTY_REMOVED
);
875 notifyPropertySetInfoChange( evt
);
877 catch ( DAVException
const & e
)
879 if ( e
.getStatus() == SC_FORBIDDEN
)
881 // Support for setting arbitrary dead properties is optional!
883 // Try to remove property from local store.
884 ContentImplHelper::removeProperty( Name
);
888 if ( shouldAccessNetworkAfterException( e
) )
892 const ResourceType
& rType
= getResourceType( xEnv
);
897 throw beans::UnknownPropertyException();
901 // Try to remove property from local store.
902 ContentImplHelper::removeProperty( Name
);
906 OSL_FAIL( "Content::removeProperty - "
907 "Unsupported resource type!" );
911 catch ( uno::Exception
const & )
913 OSL_FAIL( "Content::removeProperty - "
914 "Unable to determine resource type!" );
919 OSL_FAIL( "Content::removeProperty - "
920 "Unable to determine resource type!" );
921 // throw beans::UnknownPropertyException();
927 //=========================================================================
929 // XContentCreator methods.
931 //=========================================================================
934 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
935 Content::queryCreatableContentsInfo()
936 throw( uno::RuntimeException
)
938 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
940 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
943 aSeq
.getArray()[ 0 ].Type
944 = rtl::OUString( WEBDAV_CONTENT_TYPE
);
945 aSeq
.getArray()[ 0 ].Attributes
946 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
947 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
949 beans::Property aProp
;
950 m_pProvider
->getProperty(
951 rtl::OUString( "Title" ), aProp
);
953 uno::Sequence
< beans::Property
> aDocProps( 1 );
954 aDocProps
.getArray()[ 0 ] = aProp
;
955 aSeq
.getArray()[ 0 ].Properties
= aDocProps
;
958 aSeq
.getArray()[ 1 ].Type
959 = rtl::OUString( WEBDAV_COLLECTION_TYPE
);
960 aSeq
.getArray()[ 1 ].Attributes
961 = ucb::ContentInfoAttribute::KIND_FOLDER
;
963 uno::Sequence
< beans::Property
> aFolderProps( 1 );
964 aFolderProps
.getArray()[ 0 ] = aProp
;
965 aSeq
.getArray()[ 1 ].Properties
= aFolderProps
;
969 //=========================================================================
971 uno::Reference
< ucb::XContent
> SAL_CALL
972 Content::createNewContent( const ucb::ContentInfo
& Info
)
973 throw( uno::RuntimeException
)
975 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
977 if ( Info
.Type
.isEmpty() )
978 return uno::Reference
< ucb::XContent
>();
980 if ( ( Info
.Type
!= WEBDAV_COLLECTION_TYPE
) && ( Info
.Type
!= WEBDAV_CONTENT_TYPE
) )
981 return uno::Reference
< ucb::XContent
>();
983 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
985 OSL_ENSURE( !aURL
.isEmpty(),
986 "WebdavContent::createNewContent - empty identifier!" );
988 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
989 aURL
+= rtl::OUString("/");
991 sal_Bool isCollection
;
992 if ( Info
.Type
== WEBDAV_COLLECTION_TYPE
)
994 aURL
+= rtl::OUString("New_Collection");
995 isCollection
= sal_True
;
999 aURL
+= rtl::OUString("New_Content");
1000 isCollection
= sal_False
;
1003 uno::Reference
< ucb::XContentIdentifier
> xId(
1004 new ::ucbhelper::ContentIdentifier( m_xSMgr
, aURL
) );
1006 // create the local content
1009 return new ::webdav_ucp::Content( m_xSMgr
,
1012 m_xResAccess
->getSessionFactory(),
1015 catch ( ucb::ContentCreationException
& )
1017 return uno::Reference
< ucb::XContent
>();
1021 //=========================================================================
1023 rtl::OUString
Content::getParentURL()
1025 // <scheme>:// -> ""
1026 // <scheme>://foo -> ""
1027 // <scheme>://foo/ -> ""
1028 // <scheme>://foo/bar -> <scheme>://foo/
1029 // <scheme>://foo/bar/ -> <scheme>://foo/
1030 // <scheme>://foo/bar/abc -> <scheme>://foo/bar/
1032 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
1034 sal_Int32 nPos
= aURL
.lastIndexOf( '/' );
1035 if ( nPos
== ( aURL
.getLength() - 1 ) )
1037 // Trailing slash found. Skip.
1038 nPos
= aURL
.lastIndexOf( '/', nPos
);
1041 sal_Int32 nPos1
= aURL
.lastIndexOf( '/', nPos
);
1043 nPos1
= aURL
.lastIndexOf( '/', nPos1
);
1046 return rtl::OUString();
1048 return rtl::OUString( aURL
.copy( 0, nPos
+ 1 ) );
1051 //=========================================================================
1053 // Non-interface methods.
1055 //=========================================================================
1058 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1059 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
1060 const uno::Sequence
< beans::Property
>& rProperties
,
1061 const ContentProperties
& rData
,
1062 const rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
>& rProvider
,
1063 const rtl::OUString
& rContentId
)
1065 // Note: Empty sequence means "get values of all supported properties".
1067 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
1068 = new ::ucbhelper::PropertyValueSet( rSMgr
);
1070 sal_Int32 nCount
= rProperties
.getLength();
1073 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
1074 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1076 const beans::Property
* pProps
= rProperties
.getConstArray();
1077 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1079 const beans::Property
& rProp
= pProps
[ n
];
1081 // Process standard UCB, DAV and HTTP properties.
1082 const uno::Any
& rValue
= rData
.getValue( rProp
.Name
);
1083 if ( rValue
.hasValue() )
1085 xRow
->appendObject( rProp
, rValue
);
1089 // Process local Additional Properties.
1090 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1093 = uno::Reference
< beans::XPropertySet
>(
1094 rProvider
->getAdditionalPropertySet( rContentId
,
1097 bTriedToGetAdditonalPropSet
= sal_True
;
1100 if ( !xAdditionalPropSet
.is() ||
1101 !xRow
->appendPropertySetValue(
1102 xAdditionalPropSet
, rProp
) )
1104 // Append empty entry.
1105 xRow
->appendVoid( rProp
);
1112 // Append all standard UCB, DAV and HTTP properties.
1113 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1114 const std::auto_ptr
< PropertyValueMap
> & xProps
= rData
.getProperties();
1115 SAL_WNODEPRECATED_DECLARATIONS_POP
1117 PropertyValueMap::const_iterator it
= xProps
->begin();
1118 PropertyValueMap::const_iterator end
= xProps
->end();
1120 ContentProvider
* pProvider
1121 = static_cast< ContentProvider
* >( rProvider
.get() );
1122 beans::Property aProp
;
1126 if ( pProvider
->getProperty( (*it
).first
, aProp
) )
1127 xRow
->appendObject( aProp
, (*it
).second
.value() );
1132 // Append all local Additional Properties.
1133 uno::Reference
< beans::XPropertySet
> xSet(
1134 rProvider
->getAdditionalPropertySet( rContentId
, sal_False
),
1136 xRow
->appendPropertySet( xSet
);
1139 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1142 //=========================================================================
1143 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1144 const uno::Sequence
< beans::Property
>& rProperties
,
1145 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1146 throw ( uno::Exception
)
1148 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1149 std::auto_ptr
< ContentProperties
> xProps
;
1150 std::auto_ptr
< ContentProperties
> xCachedProps
;
1151 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1152 SAL_WNODEPRECATED_DECLARATIONS_POP
1153 rtl::OUString aUnescapedTitle
;
1154 bool bHasAll
= false;
1155 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
1156 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
1157 rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
> xProvider
;
1160 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1162 aUnescapedTitle
= NeonUri::unescape( m_aEscapedTitle
);
1163 xSMgr
.set( m_xSMgr
);
1164 xIdentifier
.set( m_xIdentifier
);
1165 xProvider
.set( m_xProvider
.get() );
1166 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1168 // First, ask cache...
1169 if ( m_xCachedProps
.get() )
1171 xCachedProps
.reset( new ContentProperties( *m_xCachedProps
.get() ) );
1173 std::vector
< rtl::OUString
> aMissingProps
;
1174 if ( xCachedProps
->containsAllNames( rProperties
, aMissingProps
) )
1176 // All properties are already in cache! No server access needed.
1180 // use the cached ContentProperties instance
1181 xProps
.reset( new ContentProperties( *xCachedProps
.get() ) );
1185 if ( !m_bTransient
&& !bHasAll
)
1187 /////////////////////////////////////////////////////////////////////
1188 // Obtain values from server...
1189 /////////////////////////////////////////////////////////////////////
1191 // First, identify whether resource is DAV or not
1192 const ResourceType
& rType
= getResourceType( xEnv
, xResAccess
);
1194 bool bNetworkAccessAllowed
= true;
1198 // cache lookup... getResourceType may fill the props cache via
1200 if ( m_xCachedProps
.get() )
1203 new ContentProperties( *m_xCachedProps
.get() ) );
1205 std::vector
< rtl::OUString
> aMissingProps
;
1206 if ( xCachedProps
->containsAllNames(
1207 rProperties
, aMissingProps
) )
1209 // All properties are already in cache! No server access
1214 // use the cached ContentProperties instance
1215 xProps
.reset( new ContentProperties( *xCachedProps
.get() ) );
1220 // Only DAV resources support PROPFIND
1221 std::vector
< rtl::OUString
> aPropNames
;
1223 uno::Sequence
< beans::Property
> aProperties(
1224 rProperties
.getLength() );
1226 if ( !m_aFailedPropNames
.empty() )
1228 sal_Int32 nProps
= 0;
1229 sal_Int32 nCount
= rProperties
.getLength();
1230 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1232 const rtl::OUString
& rName
= rProperties
[ n
].Name
;
1234 std::vector
< rtl::OUString
>::const_iterator it
1235 = m_aFailedPropNames
.begin();
1236 std::vector
< rtl::OUString
>::const_iterator end
1237 = m_aFailedPropNames
.end();
1249 aProperties
[ nProps
] = rProperties
[ n
];
1254 aProperties
.realloc( nProps
);
1258 aProperties
= rProperties
;
1261 if ( aProperties
.getLength() > 0 )
1262 ContentProperties::UCBNamesToDAVNames(
1263 aProperties
, aPropNames
);
1265 if ( !aPropNames
.empty() )
1267 std::vector
< DAVResource
> resources
;
1270 xResAccess
->PROPFIND(
1271 DAVZERO
, aPropNames
, resources
, xEnv
);
1273 if ( 1 == resources
.size() )
1276 xProps
->addProperties(
1278 ContentProperties( resources
[ 0 ] ));
1281 new ContentProperties( resources
[ 0 ] ) );
1284 catch ( DAVException
const & e
)
1286 bNetworkAccessAllowed
1287 = shouldAccessNetworkAfterException( e
);
1289 if ( !bNetworkAccessAllowed
)
1291 cancelCommandExecution( e
, xEnv
);
1299 if ( bNetworkAccessAllowed
)
1301 // All properties obtained already?
1302 std::vector
< rtl::OUString
> aMissingProps
;
1303 if ( !( xProps
.get()
1304 && xProps
->containsAllNames(
1305 rProperties
, aMissingProps
) )
1306 && !m_bDidGetOrHead
)
1308 // Possibly the missing props can be obtained using a HEAD
1311 std::vector
< rtl::OUString
> aHeaderNames
;
1312 ContentProperties::UCBNamesToHTTPNames(
1315 true /* bIncludeUnmatched */ );
1317 if ( !aHeaderNames
.empty() )
1321 DAVResource resource
;
1322 xResAccess
->HEAD( aHeaderNames
, resource
, xEnv
);
1323 m_bDidGetOrHead
= true;
1326 xProps
->addProperties(
1328 ContentProperties( resource
) );
1330 xProps
.reset ( new ContentProperties( resource
) );
1332 if ( m_eResourceType
== NON_DAV
)
1333 xProps
->addProperties( aMissingProps
,
1338 catch ( DAVException
const & e
)
1340 bNetworkAccessAllowed
1341 = shouldAccessNetworkAfterException( e
);
1343 if ( !bNetworkAccessAllowed
)
1345 cancelCommandExecution( e
, xEnv
);
1353 // might trigger HTTP redirect.
1354 // Therefore, title must be updated here.
1355 NeonUri
aUri( xResAccess
->getURL() );
1356 aUnescapedTitle
= aUri
.GetPathBaseNameUnescaped();
1358 if ( rType
== UNKNOWN
)
1360 xProps
.reset( new ContentProperties( aUnescapedTitle
) );
1363 // For DAV resources we only know the Title, for non-DAV
1364 // resources we additionally know that it is a document.
1369 // new ContentProperties( aUnescapedTitle ) );
1370 xProps
->addProperty(
1371 rtl::OUString( "Title" ),
1372 uno::makeAny( aUnescapedTitle
),
1377 if ( !xProps
.get() )
1378 xProps
.reset( new ContentProperties( aUnescapedTitle
, false ) );
1380 xProps
->addProperty(
1381 rtl::OUString( "Title" ),
1382 uno::makeAny( aUnescapedTitle
),
1385 xProps
->addProperty(
1386 rtl::OUString( "IsFolder" ),
1387 uno::makeAny( false ),
1389 xProps
->addProperty(
1390 rtl::OUString( "IsDocument" ),
1391 uno::makeAny( true ),
1397 // No server access for just created (not yet committed) objects.
1398 // Only a minimal set of properties supported at this stage.
1400 xProps
.reset( new ContentProperties( aUnescapedTitle
,
1404 sal_Int32 nCount
= rProperties
.getLength();
1405 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1407 const rtl::OUString rName
= rProperties
[ n
].Name
;
1408 if ( rName
== "BaseURI" )
1410 // Add BaseURI property, if requested.
1411 xProps
->addProperty(
1412 rtl::OUString( "BaseURI" ),
1413 uno::makeAny( getBaseURI( xResAccess
) ),
1416 else if ( rName
== "CreatableContentsInfo" )
1418 // Add CreatableContentsInfo property, if requested.
1419 sal_Bool bFolder
= sal_False
;
1421 rtl::OUString( "IsFolder" ) )
1423 xProps
->addProperty(
1424 rtl::OUString( "CreatableContentsInfo" ),
1425 uno::makeAny( bFolder
1426 ? queryCreatableContentsInfo()
1427 : uno::Sequence
< ucb::ContentInfo
>() ),
1432 uno::Reference
< sdbc::XRow
> xResultRow
1433 = getPropertyValues( xSMgr
,
1437 xIdentifier
->getContentIdentifier() );
1440 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1442 if ( !m_xCachedProps
.get() )
1443 m_xCachedProps
.reset( new CachableContentProperties( *xProps
.get() ) );
1445 m_xCachedProps
->addProperties( *xProps
.get() );
1447 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
1448 m_aEscapedTitle
= NeonUri::escapeSegment( aUnescapedTitle
);
1454 //=========================================================================
1455 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1456 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1457 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1458 throw ( uno::Exception
)
1460 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
1461 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
1462 rtl::Reference
< ContentProvider
> xProvider
;
1463 sal_Bool bTransient
;
1464 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1465 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1466 SAL_WNODEPRECATED_DECLARATIONS_POP
1469 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1471 xProvider
.set( m_pProvider
);
1472 xIdentifier
.set( m_xIdentifier
);
1473 bTransient
= m_bTransient
;
1474 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
1475 xSMgr
.set( m_xSMgr
);
1478 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1479 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1480 sal_Int32 nChanged
= 0;
1482 beans::PropertyChangeEvent aEvent
;
1483 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1484 aEvent
.Further
= sal_False
;
1485 // aEvent.PropertyName =
1486 aEvent
.PropertyHandle
= -1;
1487 // aEvent.OldValue =
1488 // aEvent.NewValue =
1490 std::vector
< ProppatchValue
> aProppatchValues
;
1491 std::vector
< sal_Int32
> aProppatchPropsPositions
;
1493 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1494 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1496 sal_Bool bExchange
= sal_False
;
1497 rtl::OUString aNewTitle
;
1498 rtl::OUString aOldTitle
;
1499 sal_Int32 nTitlePos
= -1;
1501 uno::Reference
< beans::XPropertySetInfo
> xInfo
;
1503 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1504 sal_Int32 nCount
= rValues
.getLength();
1505 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1507 const beans::PropertyValue
& rValue
= pValues
[ n
];
1508 const rtl::OUString
& rName
= rValue
.Name
;
1510 beans::Property aTmpProp
;
1511 xProvider
->getProperty( rName
, aTmpProp
);
1513 if ( aTmpProp
.Attributes
& beans::PropertyAttribute::READONLY
)
1515 // Read-only property!
1516 aRet
[ n
] <<= lang::IllegalAccessException(
1517 rtl::OUString( "Property is read-only!" ),
1518 static_cast< cppu::OWeakObject
* >( this ) );
1522 //////////////////////////////////////////////////////////////////
1524 //////////////////////////////////////////////////////////////////
1526 if ( rName
== "ContentType" )
1528 // Read-only property!
1529 aRet
[ n
] <<= lang::IllegalAccessException(
1530 rtl::OUString( "Property is read-only!" ),
1531 static_cast< cppu::OWeakObject
* >( this ) );
1533 else if ( rName
== "IsDocument" )
1535 // Read-only property!
1536 aRet
[ n
] <<= lang::IllegalAccessException(
1537 rtl::OUString( "Property is read-only!" ),
1538 static_cast< cppu::OWeakObject
* >( this ) );
1540 else if ( rName
== "IsFolder" )
1542 // Read-only property!
1543 aRet
[ n
] <<= lang::IllegalAccessException(
1544 rtl::OUString( "Property is read-only!" ),
1545 static_cast< cppu::OWeakObject
* >( this ) );
1547 else if ( rName
== "Title" )
1549 rtl::OUString aNewValue
;
1550 if ( rValue
.Value
>>= aNewValue
)
1553 if ( !aNewValue
.isEmpty() )
1557 NeonUri
aURI( xIdentifier
->getContentIdentifier() );
1558 aOldTitle
= aURI
.GetPathBaseNameUnescaped();
1560 if ( aNewValue
!= aOldTitle
)
1562 // modified title -> modified URL -> exchange !
1564 bExchange
= sal_True
;
1566 // new value will be set later...
1567 aNewTitle
= aNewValue
;
1569 // remember position within sequence of values (for
1574 catch ( DAVException
const & )
1576 aRet
[ n
] <<= lang::IllegalArgumentException(
1577 rtl::OUString( "Invalid content identifier!" ),
1578 static_cast< cppu::OWeakObject
* >( this ),
1584 aRet
[ n
] <<= lang::IllegalArgumentException(
1585 rtl::OUString( "Empty title not allowed!" ),
1586 static_cast< cppu::OWeakObject
* >( this ),
1592 aRet
[ n
] <<= beans::IllegalTypeException(
1593 rtl::OUString( "Property value has wrong type!" ),
1594 static_cast< cppu::OWeakObject
* >( this ) );
1599 //////////////////////////////////////////////////////////////
1601 //////////////////////////////////////////////////////////////
1604 xInfo
= getPropertySetInfo( xEnv
,
1605 sal_False
/* don't cache data */ );
1607 if ( !xInfo
->hasPropertyByName( rName
) )
1609 // Check, whether property exists. Skip otherwise.
1610 // PROPPATCH::set would add the property automatically, which
1611 // is not allowed for "setPropertyValues" command!
1612 aRet
[ n
] <<= beans::UnknownPropertyException(
1613 rtl::OUString( "Property is unknown!" ),
1614 static_cast< cppu::OWeakObject
* >( this ) );
1618 if ( rName
== "Size" )
1620 // Read-only property!
1621 aRet
[ n
] <<= lang::IllegalAccessException(
1622 rtl::OUString( "Property is read-only!" ),
1623 static_cast< cppu::OWeakObject
* >( this ) );
1625 else if ( rName
== "DateCreated" )
1627 // Read-only property!
1628 aRet
[ n
] <<= lang::IllegalAccessException(
1629 rtl::OUString( "Property is read-only!" ),
1630 static_cast< cppu::OWeakObject
* >( this ) );
1632 else if ( rName
== "DateModified" )
1634 // Read-only property!
1635 aRet
[ n
] <<= lang::IllegalAccessException(
1636 rtl::OUString( "Property is read-only!" ),
1637 static_cast< cppu::OWeakObject
* >( this ) );
1639 else if ( rName
== "MediaType" )
1641 // Read-only property!
1642 // (but could be writable, if 'getcontenttype' would be)
1643 aRet
[ n
] <<= lang::IllegalAccessException(
1644 rtl::OUString( "Property is read-only!" ),
1645 static_cast< cppu::OWeakObject
* >( this ) );
1647 if ( rName
== "CreatableContentsInfo" )
1649 // Read-only property!
1650 aRet
[ n
] <<= lang::IllegalAccessException(
1651 rtl::OUString( "Property is read-only!" ),
1652 static_cast< cppu::OWeakObject
* >( this ) );
1656 if ( getResourceType( xEnv
, xResAccess
) == DAV
)
1658 // Property value will be set on server.
1659 ProppatchValue
aValue( PROPSET
, rName
, rValue
.Value
);
1660 aProppatchValues
.push_back( aValue
);
1662 // remember position within sequence of values (for
1664 aProppatchPropsPositions
.push_back( n
);
1668 // Property value will be stored in local property store.
1669 if ( !bTriedToGetAdditonalPropSet
&&
1670 !xAdditionalPropSet
.is() )
1673 = getAdditionalPropertySet( sal_False
);
1674 bTriedToGetAdditonalPropSet
= sal_True
;
1677 if ( xAdditionalPropSet
.is() )
1682 = xAdditionalPropSet
->getPropertyValue( rName
);
1683 if ( aOldValue
!= rValue
.Value
)
1685 xAdditionalPropSet
->setPropertyValue(
1686 rName
, rValue
.Value
);
1688 aEvent
.PropertyName
= rName
;
1689 aEvent
.OldValue
= aOldValue
;
1690 aEvent
.NewValue
= rValue
.Value
;
1692 aChanges
.getArray()[ nChanged
] = aEvent
;
1696 catch ( beans::UnknownPropertyException
const & e
)
1700 catch ( lang::WrappedTargetException
const & e
)
1704 catch ( beans::PropertyVetoException
const & e
)
1708 catch ( lang::IllegalArgumentException
const & e
)
1715 aRet
[ n
] <<= uno::Exception(
1716 rtl::OUString( "No property set for storing the value!" ),
1717 static_cast< cppu::OWeakObject
* >( this ) );
1724 if ( !bTransient
&& aProppatchValues
.size() )
1728 // Set property values at server.
1729 xResAccess
->PROPPATCH( aProppatchValues
, xEnv
);
1731 std::vector
< ProppatchValue
>::const_iterator it
1732 = aProppatchValues
.begin();
1733 std::vector
< ProppatchValue
>::const_iterator end
1734 = aProppatchValues
.end();
1738 aEvent
.PropertyName
= (*it
).name
;
1739 aEvent
.OldValue
= uno::Any(); // @@@ to expensive to obtain!
1740 aEvent
.NewValue
= (*it
).value
;
1742 aChanges
.getArray()[ nChanged
] = aEvent
;
1748 catch ( DAVException
const & e
)
1750 // OSL_FAIL( // "Content::setPropertyValues - PROPPATCH failed!" );
1752 cancelCommandExecution( e
, xEnv
);
1759 // Assemble new content identifier...
1761 rtl::OUString aNewURL
= getParentURL();
1762 if ( aNewURL
.lastIndexOf( '/' ) != ( aNewURL
.getLength() - 1 ) )
1763 aNewURL
+= rtl::OUString("/");
1765 aNewURL
+= NeonUri::escapeSegment( aNewTitle
);
1767 uno::Reference
< ucb::XContentIdentifier
> xNewId
1768 = new ::ucbhelper::ContentIdentifier( xSMgr
, aNewURL
);
1769 uno::Reference
< ucb::XContentIdentifier
> xOldId
= xIdentifier
;
1773 NeonUri
sourceURI( xOldId
->getContentIdentifier() );
1774 NeonUri
targetURI( xNewId
->getContentIdentifier() );
1775 targetURI
.SetScheme( sourceURI
.GetScheme() );
1778 sourceURI
.GetPath(), targetURI
.GetURI(), sal_False
, xEnv
);
1779 // @@@ Should check for resources that could not be moved
1780 // (due to source access or target overwrite) and send
1781 // this information through the interaction handler.
1783 // @@@ Existing content should be checked to see if it needs
1784 // to be deleted at the source
1786 // @@@ Existing content should be checked to see if it has
1787 // been overwritten at the target
1789 if ( exchangeIdentity( xNewId
) )
1791 xResAccess
->setURL( aNewURL
);
1793 // DAV resources store all additional props on server!
1794 // // Adapt Additional Core Properties.
1795 // renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1796 // xNewId->getContentIdentifier(),
1801 // Do not set new title!
1802 aNewTitle
= rtl::OUString();
1805 aRet
[ nTitlePos
] <<= uno::Exception(
1806 rtl::OUString("Exchange failed!"),
1807 static_cast< cppu::OWeakObject
* >( this ) );
1810 catch ( DAVException
const & e
)
1812 // Do not set new title!
1813 aNewTitle
= rtl::OUString();
1816 aRet
[ nTitlePos
] <<= MapDAVException( e
, sal_True
);
1820 if ( !aNewTitle
.isEmpty() )
1822 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1824 aEvent
.PropertyName
= rtl::OUString("Title");
1825 aEvent
.OldValue
= uno::makeAny( aOldTitle
);
1826 aEvent
.NewValue
= uno::makeAny( aNewTitle
);
1828 m_aEscapedTitle
= NeonUri::escapeSegment( aNewTitle
);
1830 aChanges
.getArray()[ nChanged
] = aEvent
;
1836 aChanges
.realloc( nChanged
);
1837 notifyPropertiesChange( aChanges
);
1841 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1842 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
1848 //=========================================================================
1849 uno::Any
Content::open(
1850 const ucb::OpenCommandArgument3
& rArg
,
1851 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1852 throw( uno::Exception
)
1856 sal_Bool bOpenFolder
= ( ( rArg
.Mode
== ucb::OpenMode::ALL
) ||
1857 ( rArg
.Mode
== ucb::OpenMode::FOLDERS
) ||
1858 ( rArg
.Mode
== ucb::OpenMode::DOCUMENTS
) );
1861 if ( isFolder( xEnv
) )
1865 uno::Reference
< ucb::XDynamicResultSet
> xSet
1866 = new DynamicResultSet( m_xSMgr
, this, rArg
, xEnv
);
1871 // Error: Not a folder!
1873 rtl::OUStringBuffer aMsg
;
1874 if ( getResourceType( xEnv
) == FTP
)
1877 aMsg
.appendAscii( "FTP over HTTP proxy: resource cannot "
1878 "be opened as folder! Wrong Open Mode!" );
1882 aMsg
.appendAscii( "Non-folder resource cannot be "
1883 "opened as folder! Wrong Open Mode!" );
1886 ucbhelper::cancelCommandExecution(
1888 lang::IllegalArgumentException(
1889 aMsg
.makeStringAndClear(),
1890 static_cast< cppu::OWeakObject
* >( this ),
1897 if ( rArg
.Sink
.is() )
1901 if ( ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
1902 ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
1904 // Currently(?) unsupported.
1905 ucbhelper::cancelCommandExecution(
1907 ucb::UnsupportedOpenModeException(
1909 static_cast< cppu::OWeakObject
* >( this ),
1910 sal_Int16( rArg
.Mode
) ) ),
1915 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
1916 uno::Reference
< io::XOutputStream
> xOut
1917 = uno::Reference
< io::XOutputStream
>( rArg
.Sink
, uno::UNO_QUERY
);
1923 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1924 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1925 SAL_WNODEPRECATED_DECLARATIONS_POP
1928 osl::MutexGuard
aGuard( m_aMutex
);
1931 new DAVResourceAccess( *m_xResAccess
.get() ) );
1934 xResAccess
->setFlags( rArg
.OpeningFlags
);
1935 DAVResource aResource
;
1936 std::vector
< rtl::OUString
> aHeaders
;
1938 xResAccess
->GET( xOut
, aHeaders
, aResource
, xEnv
);
1939 m_bDidGetOrHead
= true;
1942 osl::MutexGuard
aGuard( m_aMutex
);
1945 if ( !m_xCachedProps
.get())
1946 m_xCachedProps
.reset(
1947 new CachableContentProperties( aResource
) );
1949 m_xCachedProps
->addProperties( aResource
);
1952 new DAVResourceAccess( *xResAccess
.get() ) );
1955 catch ( DAVException
const & e
)
1957 cancelCommandExecution( e
, xEnv
);
1963 uno::Reference
< io::XActiveDataSink
> xDataSink
1964 = uno::Reference
< io::XActiveDataSink
>( rArg
.Sink
,
1966 if ( xDataSink
.is() )
1968 // PULL: wait for client read
1971 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1972 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
1973 SAL_WNODEPRECATED_DECLARATIONS_POP
1975 osl::MutexGuard
aGuard( m_aMutex
);
1978 new DAVResourceAccess( *m_xResAccess
.get() ) );
1981 xResAccess
->setFlags( rArg
.OpeningFlags
);
1983 // fill inputsream sync; return if all data present
1984 DAVResource aResource
;
1985 std::vector
< rtl::OUString
> aHeaders
;
1987 uno::Reference
< io::XInputStream
> xIn
1988 = xResAccess
->GET( aHeaders
, aResource
, xEnv
);
1989 m_bDidGetOrHead
= true;
1992 osl::MutexGuard
aGuard( m_aMutex
);
1995 if ( !m_xCachedProps
.get())
1996 m_xCachedProps
.reset(
1997 new CachableContentProperties( aResource
) );
1999 m_xCachedProps
->addProperties(
2000 aResource
.properties
);
2003 new DAVResourceAccess( *xResAccess
.get() ) );
2006 xDataSink
->setInputStream( xIn
);
2008 catch ( DAVException
const & e
)
2010 cancelCommandExecution( e
, xEnv
);
2016 // Note: aOpenCommand.Sink may contain an XStream
2017 // implementation. Support for this type of
2018 // sink is optional...
2019 ucbhelper::cancelCommandExecution(
2021 ucb::UnsupportedDataSinkException(
2023 static_cast< cppu::OWeakObject
* >( this ),
2034 //=========================================================================
2036 const ucb::PostCommandArgument2
& rArg
,
2037 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2038 throw( uno::Exception
)
2040 uno::Reference
< io::XActiveDataSink
> xSink( rArg
.Sink
, uno::UNO_QUERY
);
2045 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2046 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2047 SAL_WNODEPRECATED_DECLARATIONS_POP
2049 osl::MutexGuard
aGuard( m_aMutex
);
2051 new DAVResourceAccess( *m_xResAccess
.get() ) );
2054 uno::Reference
< io::XInputStream
> xResult
2055 = xResAccess
->POST( rArg
.MediaType
,
2061 osl::MutexGuard
aGuard( m_aMutex
);
2063 new DAVResourceAccess( *xResAccess
.get() ) );
2066 xSink
->setInputStream( xResult
);
2068 catch ( DAVException
const & e
)
2070 cancelCommandExecution( e
, xEnv
, sal_True
);
2076 uno::Reference
< io::XOutputStream
> xResult( rArg
.Sink
, uno::UNO_QUERY
);
2081 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2082 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2083 SAL_WNODEPRECATED_DECLARATIONS_POP
2085 osl::MutexGuard
aGuard( m_aMutex
);
2087 new DAVResourceAccess( *m_xResAccess
.get() ) );
2090 xResAccess
->POST( rArg
.MediaType
,
2097 osl::MutexGuard
aGuard( m_aMutex
);
2099 new DAVResourceAccess( *xResAccess
.get() ) );
2102 catch ( DAVException
const & e
)
2104 cancelCommandExecution( e
, xEnv
, sal_True
);
2110 ucbhelper::cancelCommandExecution(
2112 ucb::UnsupportedDataSinkException(
2114 static_cast< cppu::OWeakObject
* >( this ),
2122 //=========================================================================
2123 void Content::queryChildren( ContentRefList
& rChildren
)
2125 // Obtain a list with a snapshot of all currently instanciated contents
2126 // from provider and extract the contents which are direct children
2129 ::ucbhelper::ContentRefList aAllContents
;
2130 m_xProvider
->queryExistingContents( aAllContents
);
2132 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
2133 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
2135 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
2137 // No trailing slash found. Append.
2138 aURL
+= rtl::OUString("/");
2141 sal_Int32 nLen
= aURL
.getLength();
2143 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
2144 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
2148 ::ucbhelper::ContentImplHelperRef xChild
= (*it
);
2149 rtl::OUString aChildURL
2150 = xChild
->getIdentifier()->getContentIdentifier();
2152 // Is aURL a prefix of aChildURL?
2153 if ( ( aChildURL
.getLength() > nLen
) &&
2154 ( aChildURL
.compareTo( aURL
, nLen
) == 0 ) )
2156 sal_Int32 nPos
= nLen
;
2157 nPos
= aChildURL
.indexOf( '/', nPos
);
2159 if ( ( nPos
== -1 ) ||
2160 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
2162 // No further slashes / only a final slash. It's a child!
2163 rChildren
.push_back(
2164 ::webdav_ucp::Content::ContentRef(
2165 static_cast< ::webdav_ucp::Content
* >(
2173 //=========================================================================
2174 void Content::insert(
2175 const uno::Reference
< io::XInputStream
> & xInputStream
,
2176 sal_Bool bReplaceExisting
,
2177 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2178 throw( uno::Exception
)
2180 sal_Bool bTransient
, bCollection
;
2181 rtl::OUString aEscapedTitle
;
2182 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2183 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2184 SAL_WNODEPRECATED_DECLARATIONS_POP
2187 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2189 bTransient
= m_bTransient
;
2190 bCollection
= m_bCollection
;
2191 aEscapedTitle
= m_aEscapedTitle
;
2192 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2195 // Check, if all required properties are present.
2197 if ( aEscapedTitle
.isEmpty() )
2199 OSL_FAIL( "Content::insert - Title missing!" );
2201 uno::Sequence
< rtl::OUString
> aProps( 1 );
2202 aProps
[ 0 ] = rtl::OUString("Title");
2203 ucbhelper::cancelCommandExecution(
2204 uno::makeAny( ucb::MissingPropertiesException(
2206 static_cast< cppu::OWeakObject
* >( this ),
2212 if ( !bReplaceExisting
)
2214 /* [RFC 2616] - HTTP
2216 The PUT method requests that the enclosed entity be stored under the
2217 supplied Request-URI. If the Request-URI refers to an already
2218 existing resource, the enclosed entity SHOULD be considered as a
2219 modified version of the one residing on the origin server.
2222 /* [RFC 2518] - WebDAV
2224 MKCOL creates a new collection resource at the location specified by
2225 the Request-URI. If the resource identified by the Request-URI is
2226 non-null then the MKCOL MUST fail.
2229 // ==> Complain on PUT, continue on MKCOL.
2230 if ( !bTransient
|| ( bTransient
&& !bCollection
) )
2232 ucb::UnsupportedNameClashException
aEx(
2233 rtl::OUString( "Unable to write without overwrite!" ),
2234 static_cast< cppu::OWeakObject
* >( this ),
2235 ucb::NameClash::ERROR
);
2237 uno::Reference
< task::XInteractionHandler
> xIH
;
2239 if ( Environment
.is() )
2240 xIH
= Environment
->getInteractionHandler();
2244 uno::Any
aExAsAny( uno::makeAny( aEx
) );
2246 rtl::Reference
< ucbhelper::SimpleInteractionRequest
> xRequest
2247 = new ucbhelper::SimpleInteractionRequest(
2249 ucbhelper::CONTINUATION_APPROVE
2250 | ucbhelper::CONTINUATION_DISAPPROVE
);
2251 xIH
->handle( xRequest
.get() );
2253 const sal_Int32 nResp
= xRequest
->getResponse();
2257 case ucbhelper::CONTINUATION_UNKNOWN
:
2258 // Not handled; throw.
2262 case ucbhelper::CONTINUATION_APPROVE
:
2263 // Continue -> Overwrite.
2264 bReplaceExisting
= sal_True
;
2267 case ucbhelper::CONTINUATION_DISAPPROVE
:
2269 throw ucb::CommandFailedException(
2271 uno::Reference
< uno::XInterface
>(),
2276 OSL_FAIL( "Content::insert - "
2277 "Unknown interaction selection!" );
2278 throw ucb::CommandFailedException(
2279 rtl::OUString( "Unknown interaction selection!" ),
2280 uno::Reference
< uno::XInterface
>(),
2295 // Assemble new content identifier...
2296 rtl::OUString aURL
= getParentURL();
2297 if ( aURL
.lastIndexOf( '/' ) != ( aURL
.getLength() - 1 ) )
2298 aURL
+= rtl::OUString("/");
2300 aURL
+= aEscapedTitle
;
2304 xResAccess
->setURL( aURL
);
2307 xResAccess
->MKCOL( Environment
);
2309 xResAccess
->PUT( xInputStream
, Environment
);
2311 catch ( DAVException
const & except
)
2315 if ( except
.getStatus() == SC_METHOD_NOT_ALLOWED
)
2317 // [RFC 2518] - WebDAV
2318 // 405 (Method Not Allowed) - MKCOL can only be
2319 // executed on a deleted/non-existent resource.
2321 if ( bReplaceExisting
)
2323 // Destroy old resource.
2326 xResAccess
->DESTROY( Environment
);
2328 catch ( DAVException
const & e
)
2330 cancelCommandExecution( e
, Environment
, sal_True
);
2334 // Insert (recursion!).
2335 insert( xInputStream
, bReplaceExisting
, Environment
);
2338 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2340 new DAVResourceAccess( *xResAccess
.get() ) );
2348 rtl::OUString aTitle
;
2351 NeonUri
aURI( aURL
);
2352 aTitle
= aURI
.GetPathBaseNameUnescaped();
2354 catch ( DAVException
const & )
2358 ucbhelper::cancelCommandExecution(
2360 ucb::NameClashException(
2362 static_cast< cppu::OWeakObject
* >( this ),
2363 task::InteractionClassification_ERROR
,
2371 cancelCommandExecution( except
, Environment
, sal_True
);
2376 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2378 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aURL
);
2384 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2385 m_bTransient
= sal_False
;
2390 if ( !xInputStream
.is() )
2392 ucbhelper::cancelCommandExecution(
2394 ucb::MissingInputStreamException(
2396 static_cast< cppu::OWeakObject
* >( this ) ) ),
2403 xResAccess
->PUT( xInputStream
, Environment
);
2405 catch ( DAVException
const & e
)
2407 cancelCommandExecution( e
, Environment
, sal_True
);
2413 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2414 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2418 //=========================================================================
2419 void Content::transfer(
2420 const ucb::TransferInfo
& rArgs
,
2421 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2422 throw( uno::Exception
)
2424 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
2425 uno::Reference
< ucb::XContentIdentifier
> xIdentifier
;
2426 uno::Reference
< ucb::XContentProvider
> xProvider
;
2427 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2428 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2429 SAL_WNODEPRECATED_DECLARATIONS_POP
2432 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2434 xSMgr
.set( m_xSMgr
);
2435 xIdentifier
.set( m_xIdentifier
);
2436 xProvider
.set( m_xProvider
.get() );
2437 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2440 rtl::OUString aTargetURI
;
2443 NeonUri
sourceURI( rArgs
.SourceURL
);
2444 NeonUri
targetURI( xIdentifier
->getContentIdentifier() );
2445 aTargetURI
= targetURI
.GetPathBaseNameUnescaped();
2447 // Check source's and target's URL scheme
2449 const rtl::OUString aScheme
= sourceURI
.GetScheme().toAsciiLowerCase();
2450 if ( aScheme
== WEBDAV_URL_SCHEME
)
2452 sourceURI
.SetScheme(
2453 rtl::OUString( HTTP_URL_SCHEME
) );
2455 else if ( aScheme
== DAV_URL_SCHEME
)
2457 sourceURI
.SetScheme(
2458 rtl::OUString( HTTP_URL_SCHEME
) );
2460 else if ( aScheme
== DAVS_URL_SCHEME
)
2462 sourceURI
.SetScheme(
2463 rtl::OUString( HTTPS_URL_SCHEME
) );
2467 if ( aScheme
!= HTTP_URL_SCHEME
&& aScheme
!= HTTPS_URL_SCHEME
)
2469 ucbhelper::cancelCommandExecution(
2471 ucb::InteractiveBadTransferURLException(
2472 rtl::OUString( "Unsupported URL scheme!" ),
2473 static_cast< cppu::OWeakObject
* >( this ) ) ),
2479 if ( targetURI
.GetScheme().toAsciiLowerCase() == WEBDAV_URL_SCHEME
)
2480 targetURI
.SetScheme(
2481 rtl::OUString( HTTP_URL_SCHEME
) );
2482 else if ( targetURI
.GetScheme().toAsciiLowerCase() == DAV_URL_SCHEME
)
2483 targetURI
.SetScheme(
2484 rtl::OUString( HTTP_URL_SCHEME
) );
2486 // @@@ This implementation of 'transfer' only works
2487 // if the source and target are located at same host.
2488 // (Neon does not support cross-server copy/move)
2490 // Check for same host
2492 if ( !sourceURI
.GetHost().isEmpty() &&
2493 ( sourceURI
.GetHost() != targetURI
.GetHost() ) )
2495 ucbhelper::cancelCommandExecution(
2496 uno::makeAny( ucb::InteractiveBadTransferURLException(
2497 rtl::OUString( "Different hosts!" ),
2498 static_cast< cppu::OWeakObject
* >( this ) ) ),
2503 rtl::OUString aTitle
= rArgs
.NewTitle
;
2505 if ( aTitle
.isEmpty() )
2506 aTitle
= sourceURI
.GetPathBaseNameUnescaped();
2508 if ( aTitle
== "/" )
2511 aTitle
= rtl::OUString();
2514 targetURI
.AppendPath( aTitle
);
2516 rtl::OUString aTargetURL
= xIdentifier
->getContentIdentifier();
2517 if ( ( aTargetURL
.lastIndexOf( '/' ) + 1 )
2518 != aTargetURL
.getLength() )
2519 aTargetURL
+= rtl::OUString("/");
2521 aTargetURL
+= aTitle
;
2523 uno::Reference
< ucb::XContentIdentifier
> xTargetId
2524 = new ::ucbhelper::ContentIdentifier( xSMgr
, aTargetURL
);
2526 DAVResourceAccess
aSourceAccess( xSMgr
,
2527 xResAccess
->getSessionFactory(),
2528 sourceURI
.GetURI() );
2530 if ( rArgs
.MoveData
== sal_True
)
2532 uno::Reference
< ucb::XContentIdentifier
> xId
2533 = new ::ucbhelper::ContentIdentifier( xSMgr
, rArgs
.SourceURL
);
2535 // Note: The static cast is okay here, because its sure that
2536 // xProvider is always the WebDAVContentProvider.
2537 rtl::Reference
< Content
> xSource
2538 = static_cast< Content
* >(
2539 xProvider
->queryContent( xId
).get() );
2541 // [RFC 2518] - WebDAV
2542 // If a resource exists at the destination and the Overwrite
2543 // header is "T" then prior to performing the move the server
2544 // MUST perform a DELETE with "Depth: infinity" on the
2545 // destination resource. If the Overwrite header is set to
2546 // "F" then the operation will fail.
2548 aSourceAccess
.MOVE( sourceURI
.GetPath(),
2551 == ucb::NameClash::OVERWRITE
,
2556 // Propagate destruction to listeners.
2557 xSource
->destroy( sal_True
);
2560 // DAV resources store all additional props on server!
2561 // // Rename own and all children's Additional Core Properties.
2562 // renameAdditionalPropertySet( xId->getContentIdentifier(),
2563 // xTargetId->getContentIdentifier(),
2568 // [RFC 2518] - WebDAV
2569 // If a resource exists at the destination and the Overwrite
2570 // header is "T" then prior to performing the copy the server
2571 // MUST perform a DELETE with "Depth: infinity" on the
2572 // destination resource. If the Overwrite header is set to
2573 // "F" then the operation will fail.
2575 aSourceAccess
.COPY( sourceURI
.GetPath(),
2578 == ucb::NameClash::OVERWRITE
,
2581 // DAV resources store all additional props on server!
2582 // // Copy own and all children's Additional Core Properties.
2583 // copyAdditionalPropertySet( xId->getContentIdentifier(),
2584 // xTargetId->getContentIdentifier(),
2588 // Note: The static cast is okay here, because its sure that
2589 // xProvider is always the WebDAVContentProvider.
2590 rtl::Reference
< Content
> xTarget
2591 = static_cast< Content
* >(
2592 xProvider
->queryContent( xTargetId
).get() );
2594 // Announce transfered content in its new folder.
2595 xTarget
->inserted();
2597 catch ( ucb::IllegalIdentifierException
const & )
2601 catch ( DAVException
const & e
)
2603 // [RFC 2518] - WebDAV
2604 // 412 (Precondition Failed) - The server was unable to maintain
2605 // the liveness of the properties listed in the propertybehavior
2606 // XML element or the Overwrite header is "F" and the state of
2607 // the destination resource is non-null.
2609 if ( e
.getStatus() == SC_PRECONDITION_FAILED
)
2611 switch ( rArgs
.NameClash
)
2613 case ucb::NameClash::ERROR
:
2615 ucbhelper::cancelCommandExecution(
2617 ucb::NameClashException(
2619 static_cast< cppu::OWeakObject
* >( this ),
2620 task::InteractionClassification_ERROR
,
2626 case ucb::NameClash::OVERWRITE
:
2629 case ucb::NameClash::KEEP
: // deprecated
2630 case ucb::NameClash::RENAME
:
2631 case ucb::NameClash::ASK
:
2634 ucbhelper::cancelCommandExecution(
2636 ucb::UnsupportedNameClashException(
2638 static_cast< cppu::OWeakObject
* >( this ),
2639 rArgs
.NameClash
) ),
2646 cancelCommandExecution( e
, Environment
, sal_True
);
2651 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2652 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2656 //=========================================================================
2657 void Content::destroy( sal_Bool bDeletePhysical
)
2658 throw( uno::Exception
)
2660 // @@@ take care about bDeletePhysical -> trashcan support
2661 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
2663 uno::Reference
< ucb::XContent
> xThis
= this;
2667 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2669 // Process instanciated children...
2671 ::webdav_ucp::Content::ContentRefList aChildren
;
2672 queryChildren( aChildren
);
2674 ContentRefList::const_iterator it
= aChildren
.begin();
2675 ContentRefList::const_iterator end
= aChildren
.end();
2679 (*it
)->destroy( bDeletePhysical
);
2684 //=========================================================================
2685 bool Content::supportsExclusiveWriteLock(
2686 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2688 if ( getResourceType( Environment
) == DAV
)
2690 if ( m_xCachedProps
.get() )
2692 uno::Sequence
< ucb::LockEntry
> aSupportedLocks
;
2693 if ( m_xCachedProps
->getValue( DAVProperties::SUPPORTEDLOCK
)
2694 >>= aSupportedLocks
)
2696 for ( sal_Int32 n
= 0; n
< aSupportedLocks
.getLength(); ++n
)
2698 if ( aSupportedLocks
[ n
].Scope
2699 == ucb::LockScope_EXCLUSIVE
&&
2700 aSupportedLocks
[ n
].Type
2701 == ucb::LockType_WRITE
)
2710 //=========================================================================
2712 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2713 throw( uno::Exception
)
2717 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2718 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2719 SAL_WNODEPRECATED_DECLARATIONS_POP
2721 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2722 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2727 <<= rtl::OUString("http://ucb.openoffice.org");
2730 ucb::LockScope_EXCLUSIVE
,
2731 ucb::LockType_WRITE
,
2732 ucb::LockDepth_ZERO
,
2734 180, // lock timeout in secs
2735 //-1, // infinite lock
2736 uno::Sequence
< ::rtl::OUString
>() );
2738 xResAccess
->LOCK( aLock
, Environment
);
2741 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2742 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2745 catch ( DAVException
const & e
)
2747 cancelCommandExecution( e
, Environment
, sal_False
);
2752 //=========================================================================
2753 void Content::unlock(
2754 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
2755 throw( uno::Exception
)
2759 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2760 std::auto_ptr
< DAVResourceAccess
> xResAccess
;
2761 SAL_WNODEPRECATED_DECLARATIONS_POP
2763 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2764 xResAccess
.reset( new DAVResourceAccess( *m_xResAccess
.get() ) );
2767 xResAccess
->UNLOCK( Environment
);
2770 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2771 m_xResAccess
.reset( new DAVResourceAccess( *xResAccess
.get() ) );
2774 catch ( DAVException
const & e
)
2776 cancelCommandExecution( e
, Environment
, sal_False
);
2781 //=========================================================================
2782 sal_Bool
Content::exchangeIdentity(
2783 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
2788 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
2790 uno::Reference
< ucb::XContent
> xThis
= this;
2792 // Already persistent?
2795 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
2799 // Exchange own identitity.
2801 // Fail, if a content with given id already exists.
2802 // if ( !hasData( xNewId ) )
2804 rtl::OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
2807 if ( exchange( xNewId
) )
2809 // Process instanciated children...
2811 ContentRefList aChildren
;
2812 queryChildren( aChildren
);
2814 ContentRefList::const_iterator it
= aChildren
.begin();
2815 ContentRefList::const_iterator end
= aChildren
.end();
2819 ContentRef xChild
= (*it
);
2821 // Create new content identifier for the child...
2822 uno::Reference
< ucb::XContentIdentifier
>
2823 xOldChildId
= xChild
->getIdentifier();
2824 rtl::OUString aOldChildURL
2825 = xOldChildId
->getContentIdentifier();
2826 rtl::OUString aNewChildURL
2827 = aOldChildURL
.replaceAt(
2829 aOldURL
.getLength(),
2830 xNewId
->getContentIdentifier() );
2831 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
2832 = new ::ucbhelper::ContentIdentifier(
2833 m_xSMgr
, aNewChildURL
);
2835 if ( !xChild
->exchangeIdentity( xNewChildId
) )
2844 OSL_FAIL( "Content::exchangeIdentity - "
2845 "Panic! Cannot exchange identity!" );
2849 //=========================================================================
2850 sal_Bool
Content::isFolder(
2851 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
2852 throw( uno::Exception
)
2855 osl::MutexGuard
aGuard( m_aMutex
);
2858 return m_bCollection
;
2861 uno::Sequence
< beans::Property
> aProperties( 1 );
2862 aProperties
[ 0 ].Name
= rtl::OUString("IsFolder");
2863 aProperties
[ 0 ].Handle
= -1;
2864 uno::Reference
< sdbc::XRow
> xRow( getPropertyValues( aProperties
, xEnv
) );
2869 return xRow
->getBoolean( 1 );
2871 catch ( sdbc::SQLException
const & )
2879 //=========================================================================
2880 uno::Any
Content::MapDAVException( const DAVException
& e
, sal_Bool bWrite
)
2882 // Map DAVException...
2883 uno::Any aException
;
2888 aURL
= getParentURL();
2889 if ( aURL
.lastIndexOf('/') != ( aURL
.getLength() - 1 ) )
2890 aURL
+= rtl::OUString(static_cast<sal_Unicode
>('/'));
2892 aURL
+= m_aEscapedTitle
;
2896 aURL
= m_xIdentifier
->getContentIdentifier();
2899 switch ( e
.getStatus() )
2903 uno::Sequence
< uno::Any
> aArgs( 1 );
2904 aArgs
[ 0 ] <<= beans::PropertyValue(
2905 rtl::OUString("Uri"), -1,
2907 beans::PropertyState_DIRECT_VALUE
);
2910 ucb::InteractiveAugmentedIOException(
2911 rtl::OUString("Not found!"),
2912 static_cast< cppu::OWeakObject
* >( this ),
2913 task::InteractionClassification_ERROR
,
2914 ucb::IOErrorCode_NOT_EXISTING
,
2922 switch ( e
.getError() )
2924 case DAVException::DAV_HTTP_ERROR
:
2928 ucb::InteractiveNetworkWriteException(
2930 static_cast< cppu::OWeakObject
* >( this ),
2931 task::InteractionClassification_ERROR
,
2935 ucb::InteractiveNetworkReadException(
2937 static_cast< cppu::OWeakObject
* >( this ),
2938 task::InteractionClassification_ERROR
,
2943 case DAVException::DAV_HTTP_LOOKUP
:
2945 ucb::InteractiveNetworkResolveNameException(
2947 static_cast< cppu::OWeakObject
* >( this ),
2948 task::InteractionClassification_ERROR
,
2952 // @@@ No matching InteractiveNetwork*Exception
2953 // case DAVException::DAV_HTTP_AUTH:
2956 // @@@ No matching InteractiveNetwork*Exception
2957 // case DAVException::DAV_HTTP_AUTHPROXY:
2960 case DAVException::DAV_HTTP_CONNECT
:
2962 ucb::InteractiveNetworkConnectException(
2964 static_cast< cppu::OWeakObject
* >( this ),
2965 task::InteractionClassification_ERROR
,
2969 // @@@ No matching InteractiveNetwork*Exception
2970 // case DAVException::DAV_HTTP_TIMEOUT:
2973 // @@@ No matching InteractiveNetwork*Exception
2974 // case DAVException::DAV_HTTP_REDIRECT:
2977 // @@@ No matching InteractiveNetwork*Exception
2978 // case DAVException::DAV_SESSION_CREATE:
2981 case DAVException::DAV_INVALID_ARG
:
2983 lang::IllegalArgumentException(
2985 static_cast< cppu::OWeakObject
* >( this ),
2989 case DAVException::DAV_LOCKED
:
2991 ucb::InteractiveLockingLockedException(
2992 rtl::OUString("Locked!"),
2993 static_cast< cppu::OWeakObject
* >( this ),
2994 task::InteractionClassification_ERROR
,
2996 sal_False
); // not SelfOwned
2999 case DAVException::DAV_LOCKED_SELF
:
3001 ucb::InteractiveLockingLockedException(
3002 rtl::OUString("Locked (self!)"),
3003 static_cast< cppu::OWeakObject
* >( this ),
3004 task::InteractionClassification_ERROR
,
3006 sal_True
); // SelfOwned
3009 case DAVException::DAV_NOT_LOCKED
:
3011 ucb::InteractiveLockingNotLockedException(
3012 rtl::OUString("Not locked!"),
3013 static_cast< cppu::OWeakObject
* >( this ),
3014 task::InteractionClassification_ERROR
,
3018 case DAVException::DAV_LOCK_EXPIRED
:
3020 ucb::InteractiveLockingLockExpiredException(
3021 rtl::OUString("Lock expired!"),
3022 static_cast< cppu::OWeakObject
* >( this ),
3023 task::InteractionClassification_ERROR
,
3029 ucb::InteractiveNetworkGeneralException(
3031 static_cast< cppu::OWeakObject
* >( this ),
3032 task::InteractionClassification_ERROR
);
3039 //=========================================================================
3041 bool Content::shouldAccessNetworkAfterException( const DAVException
& e
)
3043 if ( ( e
.getStatus() == SC_NOT_FOUND
) ||
3044 ( e
.getError() == DAVException::DAV_HTTP_LOOKUP
) ||
3045 ( e
.getError() == DAVException::DAV_HTTP_CONNECT
) ||
3046 ( e
.getError() == DAVException::DAV_HTTP_AUTH
) ||
3047 ( e
.getError() == DAVException::DAV_HTTP_AUTHPROXY
) )
3053 //=========================================================================
3054 void Content::cancelCommandExecution(
3055 const DAVException
& e
,
3056 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
3057 sal_Bool bWrite
/* = sal_False */ )
3058 throw ( uno::Exception
)
3060 ucbhelper::cancelCommandExecution( MapDAVException( e
, bWrite
), xEnv
);
3064 //=========================================================================
3065 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3067 Content::getBaseURI( const std::auto_ptr
< DAVResourceAccess
> & rResAccess
)
3069 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3071 // First, try to obtain value of response header "Content-Location".
3072 if ( m_xCachedProps
.get() )
3074 rtl::OUString aLocation
;
3075 m_xCachedProps
->getValue( rtl::OUString( "Content-Location" ) ) >>= aLocation
;
3076 if ( !aLocation
.isEmpty() )
3080 // Do not use m_xIdentifier->getContentIdentifier() because it
3081 // for example does not reflect redirects applied to requests
3082 // done using the original URI but m_xResAccess' URI does.
3083 return rtl::Uri::convertRelToAbs( rResAccess
->getURL(),
3086 catch ( rtl::MalformedUriException
const & )
3092 return rtl::OUString( rResAccess
->getURL() );
3095 //=========================================================================
3096 const Content::ResourceType
& Content::getResourceType(
3097 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
,
3098 const std::auto_ptr
< DAVResourceAccess
> & rResAccess
)
3099 throw ( uno::Exception
)
3101 if ( m_eResourceType
== UNKNOWN
)
3103 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3105 ResourceType eResourceType
;
3106 eResourceType
= m_eResourceType
;
3108 const rtl::OUString
& rURL
= rResAccess
->getURL();
3109 const rtl::OUString
aScheme(
3110 rURL
.copy( 0, rURL
.indexOf( ':' ) ).toAsciiLowerCase() );
3112 if ( aScheme
== FTP_URL_SCHEME
)
3114 eResourceType
= FTP
;
3120 // Try to fetch some frequently used property value, e.g. those
3121 // used when loading documents... along with identifying whether
3122 // this is a DAV resource.
3123 std::vector
< DAVResource
> resources
;
3124 std::vector
< rtl::OUString
> aPropNames
;
3125 uno::Sequence
< beans::Property
> aProperties( 5 );
3126 aProperties
[ 0 ].Name
3127 = rtl::OUString("IsFolder");
3128 aProperties
[ 1 ].Name
3129 = rtl::OUString("IsDocument");
3130 aProperties
[ 2 ].Name
3131 = rtl::OUString("IsReadOnly");
3132 aProperties
[ 3 ].Name
3133 = rtl::OUString("MediaType");
3134 aProperties
[ 4 ].Name
3135 = DAVProperties::SUPPORTEDLOCK
;
3137 ContentProperties::UCBNamesToDAVNames(
3138 aProperties
, aPropNames
);
3140 rResAccess
->PROPFIND(
3141 DAVZERO
, aPropNames
, resources
, xEnv
);
3143 if ( resources
.size() == 1 )
3145 m_xCachedProps
.reset(
3146 new CachableContentProperties( resources
[ 0 ] ) );
3147 m_xCachedProps
->containsAllNames(
3148 aProperties
, m_aFailedPropNames
);
3151 eResourceType
= DAV
;
3153 catch ( DAVException
const & e
)
3155 rResAccess
->resetUri();
3157 if ( e
.getStatus() == SC_METHOD_NOT_ALLOWED
)
3159 // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the
3160 // resource is NON_DAV
3161 eResourceType
= NON_DAV
;
3165 m_eResourceType
= eResourceType
;
3167 return m_eResourceType
;
3169 SAL_WNODEPRECATED_DECLARATIONS_POP
3171 //=========================================================================
3172 const Content::ResourceType
& Content::getResourceType(
3173 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
3174 throw ( uno::Exception
)
3176 return getResourceType( xEnv
, m_xResAccess
);
3179 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */