Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / webdav / webdavcontent.cxx
blobcf966668a28589d64fa95e9b87324f537879d6f4
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 /**************************************************************************
31 TODO
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
103 Content::Content(
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(
119 rxSMgr,
120 rSessionFactory,
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
134 Content::Content(
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 //=========================================================================
162 // virtual
163 Content::~Content()
167 //=========================================================================
169 // XInterface methods.
171 //=========================================================================
173 // virtual
174 void SAL_CALL Content::acquire()
175 throw( )
177 ContentImplHelper::acquire();
180 //=========================================================================
181 // virtual
182 void SAL_CALL Content::release()
183 throw( )
185 ContentImplHelper::release();
188 //=========================================================================
189 // virtual
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(
196 rType,
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(
218 xCtx,
219 xIH,
220 uno::Reference< ucb::XProgressHandler >() ) );
222 return isFolder( xCmdEnv ) ? aRet : uno::Any();
224 catch ( uno::RuntimeException const & )
226 throw;
228 catch ( uno::Exception const & )
230 return uno::Any();
233 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
236 //=========================================================================
238 // XTypeProvider methods.
240 //=========================================================================
242 XTYPEPROVIDER_COMMON_IMPL( Content );
244 //=========================================================================
245 // virtual
246 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
247 throw( uno::RuntimeException )
249 sal_Bool bFolder = sal_False;
252 bFolder
253 = isFolder( uno::Reference< ucb::XCommandEnvironment >() );
255 catch ( uno::RuntimeException const & )
257 throw;
259 catch ( uno::Exception const & )
263 cppu::OTypeCollection * pCollection = 0;
265 if ( bFolder )
267 static cppu::OTypeCollection* pFolderTypes = 0;
269 pCollection = pFolderTypes;
270 if ( !pCollection )
272 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
274 pCollection = pFolderTypes;
275 if ( !pCollection )
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;
294 else {
295 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
298 else
300 static cppu::OTypeCollection* pDocumentTypes = 0;
302 pCollection = pDocumentTypes;
303 if ( !pCollection )
305 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
307 pCollection = pDocumentTypes;
308 if ( !pCollection )
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;
326 else {
327 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
331 return (*pCollection).getTypes();
334 //=========================================================================
336 // XServiceInfo methods.
338 //=========================================================================
340 // virtual
341 rtl::OUString SAL_CALL Content::getImplementationName()
342 throw( uno::RuntimeException )
344 return rtl::OUString( "com.sun.star.comp.ucb.WebDAVContent" );
347 //=========================================================================
348 // virtual
349 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
350 throw( uno::RuntimeException )
352 uno::Sequence< rtl::OUString > aSNS( 1 );
353 aSNS.getArray()[ 0 ]
354 = rtl::OUString( WEBDAV_CONTENT_SERVICE_NAME );
355 return aSNS;
358 //=========================================================================
360 // XContent methods.
362 //=========================================================================
364 // virtual
365 rtl::OUString SAL_CALL Content::getContentType()
366 throw( uno::RuntimeException )
368 sal_Bool bFolder = sal_False;
371 bFolder
372 = isFolder( uno::Reference< ucb::XCommandEnvironment >() );
374 catch ( uno::RuntimeException const & )
376 throw;
378 catch ( uno::Exception const & )
382 if ( bFolder )
383 return rtl::OUString( WEBDAV_COLLECTION_TYPE );
385 return rtl::OUString( WEBDAV_CONTENT_TYPE );
388 //=========================================================================
390 // XCommandProcessor methods.
392 //=========================================================================
394 // virtual
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" );
408 uno::Any aRet;
410 if ( aCommand.Name == "getPropertyValues" )
412 //////////////////////////////////////////////////////////////////
413 // getPropertyValues
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 ),
423 -1 ) ),
424 Environment );
425 // Unreachable
428 aRet <<= getPropertyValues( Properties, Environment );
430 else if ( aCommand.Name == "setPropertyValues" )
432 //////////////////////////////////////////////////////////////////
433 // setPropertyValues
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 ),
443 -1 ) ),
444 Environment );
445 // Unreachable
448 if ( !aProperties.getLength() )
450 ucbhelper::cancelCommandExecution(
451 uno::makeAny( lang::IllegalArgumentException(
452 rtl::OUString( "No properties!" ),
453 static_cast< cppu::OWeakObject * >( this ),
454 -1 ) ),
455 Environment );
456 // Unreachable
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 //////////////////////////////////////////////////////////////////
474 // getCommandInfo
475 //////////////////////////////////////////////////////////////////
477 // Note: Implemented by base class.
478 aRet <<= getCommandInfo( Environment, sal_False );
480 else if ( aCommand.Name == "open" )
482 //////////////////////////////////////////////////////////////////
483 // open
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 ),
494 -1 ) ),
495 Environment );
496 // Unreachable
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 );
509 #if 1
510 if ( (aOpenCommand.Mode == ucb::OpenMode::DOCUMENT ||
511 aOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE) &&
512 supportsExclusiveWriteLock( Environment ) )
513 lock( Environment );
514 #endif
516 else if ( aCommand.Name == "insert" )
518 //////////////////////////////////////////////////////////////////
519 // insert
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 ),
529 -1 ) ),
530 Environment );
531 // Unreachable
534 insert( arg.Data, arg.ReplaceExisting, Environment );
536 else if ( aCommand.Name == "delete" )
538 //////////////////////////////////////////////////////////////////
539 // delete
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 )
549 // {
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 );
568 // Unreachable
570 // }
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 //////////////////////////////////////////////////////////////////
581 // transfer
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 ),
592 -1 ) ),
593 Environment );
594 // Unreachable
597 transfer( transferArgs, Environment );
599 else if ( aCommand.Name == "post" )
601 //////////////////////////////////////////////////////////////////
602 // post
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 ),
612 -1 ) ),
613 Environment );
614 // Unreachable
617 post( aArg, Environment );
619 else if ( aCommand.Name == "lock" && supportsExclusiveWriteLock( Environment ) )
621 //////////////////////////////////////////////////////////////////
622 // lock
623 //////////////////////////////////////////////////////////////////
625 lock( Environment );
627 else if ( aCommand.Name == "unlock" && supportsExclusiveWriteLock( Environment ) )
629 //////////////////////////////////////////////////////////////////
630 // unlock
631 //////////////////////////////////////////////////////////////////
633 unlock( Environment );
635 else if ( aCommand.Name == "createNewContent" && isFolder( Environment ) )
637 //////////////////////////////////////////////////////////////////
638 // createNewContent
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 ),
648 -1 ) ),
649 Environment );
650 // Unreachable
653 aRet = uno::makeAny( createNewContent( aArg ) );
655 else
657 //////////////////////////////////////////////////////////////////
658 // Unsupported command
659 //////////////////////////////////////////////////////////////////
661 ucbhelper::cancelCommandExecution(
662 uno::makeAny( ucb::UnsupportedCommandException(
663 aCommand.Name,
664 static_cast< cppu::OWeakObject * >( this ) ) ),
665 Environment );
666 // Unreachable
669 OSL_TRACE( "<<<<< Content::execute: end: command: %s",
670 rtl::OUStringToOString( aCommand.Name,
671 RTL_TEXTENCODING_UTF8 ).getStr() );
673 return aRet;
676 //=========================================================================
677 // virtual
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() ) );
690 xResAccess->abort();
692 osl::Guard< osl::Mutex > aGuard( m_aMutex );
693 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
696 catch ( DAVException const & )
698 // abort failed!
702 //=========================================================================
704 // XPropertyContainer methods.
706 //=========================================================================
708 // virtual
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 )
718 // @@@ ???
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 ),
776 Name,
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 );
791 else
793 if ( shouldAccessNetworkAfterException( e ) )
797 const ResourceType & rType = getResourceType( xEnv );
798 switch ( rType )
800 case UNKNOWN:
801 case DAV:
802 throw lang::IllegalArgumentException();
804 case FTP:
805 case NON_DAV:
806 // Store property locally.
807 ContentImplHelper::addProperty( Name,
808 Attributes,
809 DefaultValue );
810 break;
812 default:
813 OSL_FAIL( "Content::addProperty - "
814 "Unsupported resource type!" );
815 break;
818 catch ( uno::Exception const & )
820 OSL_FAIL( "Content::addProperty - "
821 "Unable to determine resource type!" );
824 else
826 OSL_FAIL( "Content::addProperty - "
827 "Unable to determine resource type!" );
833 //=========================================================================
834 // virtual
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 ),
872 Name,
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 );
886 else
888 if ( shouldAccessNetworkAfterException( e ) )
892 const ResourceType & rType = getResourceType( xEnv );
893 switch ( rType )
895 case UNKNOWN:
896 case DAV:
897 throw beans::UnknownPropertyException();
899 case FTP:
900 case NON_DAV:
901 // Try to remove property from local store.
902 ContentImplHelper::removeProperty( Name );
903 break;
905 default:
906 OSL_FAIL( "Content::removeProperty - "
907 "Unsupported resource type!" );
908 break;
911 catch ( uno::Exception const & )
913 OSL_FAIL( "Content::removeProperty - "
914 "Unable to determine resource type!" );
917 else
919 OSL_FAIL( "Content::removeProperty - "
920 "Unable to determine resource type!" );
921 // throw beans::UnknownPropertyException();
927 //=========================================================================
929 // XContentCreator methods.
931 //=========================================================================
933 // virtual
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 );
942 // document.
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;
957 // folder.
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;
966 return aSeq;
969 //=========================================================================
970 // virtual
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;
997 else
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,
1010 m_pProvider,
1011 xId,
1012 m_xResAccess->getSessionFactory(),
1013 isCollection );
1015 catch ( ucb::ContentCreationException & )
1017 return uno::Reference< ucb::XContent >();
1021 //=========================================================================
1022 // virtual
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 );
1042 if ( nPos1 != -1 )
1043 nPos1 = aURL.lastIndexOf( '/', nPos1 );
1045 if ( nPos1 == -1 )
1046 return rtl::OUString();
1048 return rtl::OUString( aURL.copy( 0, nPos + 1 ) );
1051 //=========================================================================
1053 // Non-interface methods.
1055 //=========================================================================
1057 // static
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();
1071 if ( nCount )
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 );
1087 else
1089 // Process local Additional Properties.
1090 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1092 xAdditionalPropSet
1093 = uno::Reference< beans::XPropertySet >(
1094 rProvider->getAdditionalPropertySet( rContentId,
1095 sal_False ),
1096 uno::UNO_QUERY );
1097 bTriedToGetAdditonalPropSet = sal_True;
1100 if ( !xAdditionalPropSet.is() ||
1101 !xRow->appendPropertySetValue(
1102 xAdditionalPropSet, rProp ) )
1104 // Append empty entry.
1105 xRow->appendVoid( rProp );
1110 else
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;
1124 while ( it != end )
1126 if ( pProvider->getProperty( (*it).first, aProp ) )
1127 xRow->appendObject( aProp, (*it).second.value() );
1129 ++it;
1132 // Append all local Additional Properties.
1133 uno::Reference< beans::XPropertySet > xSet(
1134 rProvider->getAdditionalPropertySet( rContentId, sal_False ),
1135 uno::UNO_QUERY );
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.
1177 bHasAll = true;
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;
1196 if ( DAV == rType )
1198 // cache lookup... getResourceType may fill the props cache via
1199 // PROPFIND!
1200 if ( m_xCachedProps.get() )
1202 xCachedProps.reset(
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
1210 // needed.
1211 bHasAll = true;
1214 // use the cached ContentProperties instance
1215 xProps.reset( new ContentProperties( *xCachedProps.get() ) );
1218 if ( !bHasAll )
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();
1239 while ( it != end )
1241 if ( *it == rName )
1242 break;
1244 ++it;
1247 if ( it == end )
1249 aProperties[ nProps ] = rProperties[ n ];
1250 nProps++;
1254 aProperties.realloc( nProps );
1256 else
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() )
1275 if ( xProps.get())
1276 xProps->addProperties(
1277 aPropNames,
1278 ContentProperties( resources[ 0 ] ));
1279 else
1280 xProps.reset(
1281 new ContentProperties( resources[ 0 ] ) );
1284 catch ( DAVException const & e )
1286 bNetworkAccessAllowed
1287 = shouldAccessNetworkAfterException( e );
1289 if ( !bNetworkAccessAllowed )
1291 cancelCommandExecution( e, xEnv );
1292 // unreachable
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
1309 // request.
1311 std::vector< rtl::OUString > aHeaderNames;
1312 ContentProperties::UCBNamesToHTTPNames(
1313 rProperties,
1314 aHeaderNames,
1315 true /* bIncludeUnmatched */ );
1317 if ( !aHeaderNames.empty() )
1321 DAVResource resource;
1322 xResAccess->HEAD( aHeaderNames, resource, xEnv );
1323 m_bDidGetOrHead = true;
1325 if ( xProps.get() )
1326 xProps->addProperties(
1327 aMissingProps,
1328 ContentProperties( resource ) );
1329 else
1330 xProps.reset ( new ContentProperties( resource ) );
1332 if ( m_eResourceType == NON_DAV )
1333 xProps->addProperties( aMissingProps,
1334 ContentProperties(
1335 aUnescapedTitle,
1336 false ) );
1338 catch ( DAVException const & e )
1340 bNetworkAccessAllowed
1341 = shouldAccessNetworkAfterException( e );
1343 if ( !bNetworkAccessAllowed )
1345 cancelCommandExecution( e, xEnv );
1346 // unreachable
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.
1366 if ( rType == DAV )
1368 //xProps.reset(
1369 // new ContentProperties( aUnescapedTitle ) );
1370 xProps->addProperty(
1371 rtl::OUString( "Title" ),
1372 uno::makeAny( aUnescapedTitle ),
1373 true );
1375 else
1377 if ( !xProps.get() )
1378 xProps.reset( new ContentProperties( aUnescapedTitle, false ) );
1379 else
1380 xProps->addProperty(
1381 rtl::OUString( "Title" ),
1382 uno::makeAny( aUnescapedTitle ),
1383 true );
1385 xProps->addProperty(
1386 rtl::OUString( "IsFolder" ),
1387 uno::makeAny( false ),
1388 true );
1389 xProps->addProperty(
1390 rtl::OUString( "IsDocument" ),
1391 uno::makeAny( true ),
1392 true );
1395 else
1397 // No server access for just created (not yet committed) objects.
1398 // Only a minimal set of properties supported at this stage.
1399 if (m_bTransient)
1400 xProps.reset( new ContentProperties( aUnescapedTitle,
1401 m_bCollection ) );
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 ) ),
1414 true );
1416 else if ( rName == "CreatableContentsInfo" )
1418 // Add CreatableContentsInfo property, if requested.
1419 sal_Bool bFolder = sal_False;
1420 xProps->getValue(
1421 rtl::OUString( "IsFolder" ) )
1422 >>= bFolder;
1423 xProps->addProperty(
1424 rtl::OUString( "CreatableContentsInfo" ),
1425 uno::makeAny( bFolder
1426 ? queryCreatableContentsInfo()
1427 : uno::Sequence< ucb::ContentInfo >() ),
1428 true );
1432 uno::Reference< sdbc::XRow > xResultRow
1433 = getPropertyValues( xSMgr,
1434 rProperties,
1435 *xProps,
1436 xProvider,
1437 xIdentifier->getContentIdentifier() );
1440 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1442 if ( !m_xCachedProps.get() )
1443 m_xCachedProps.reset( new CachableContentProperties( *xProps.get() ) );
1444 else
1445 m_xCachedProps->addProperties( *xProps.get() );
1447 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
1448 m_aEscapedTitle = NeonUri::escapeSegment( aUnescapedTitle );
1451 return xResultRow;
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 ) );
1519 continue;
1522 //////////////////////////////////////////////////////////////////
1523 // Mandatory props.
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 )
1552 // No empty titles!
1553 if ( !aNewValue.isEmpty() )
1557 NeonUri aURI( xIdentifier->getContentIdentifier() );
1558 aOldTitle = aURI.GetPathBaseNameUnescaped();
1560 if ( aNewValue != aOldTitle )
1562 // modified title -> modified URL -> exchange !
1563 if ( !bTransient )
1564 bExchange = sal_True;
1566 // new value will be set later...
1567 aNewTitle = aNewValue;
1569 // remember position within sequence of values (for
1570 // error handling).
1571 nTitlePos = n;
1574 catch ( DAVException const & )
1576 aRet[ n ] <<= lang::IllegalArgumentException(
1577 rtl::OUString( "Invalid content identifier!" ),
1578 static_cast< cppu::OWeakObject * >( this ),
1579 -1 );
1582 else
1584 aRet[ n ] <<= lang::IllegalArgumentException(
1585 rtl::OUString( "Empty title not allowed!" ),
1586 static_cast< cppu::OWeakObject * >( this ),
1587 -1 );
1590 else
1592 aRet[ n ] <<= beans::IllegalTypeException(
1593 rtl::OUString( "Property value has wrong type!" ),
1594 static_cast< cppu::OWeakObject * >( this ) );
1597 else
1599 //////////////////////////////////////////////////////////////
1600 // Optional props.
1601 //////////////////////////////////////////////////////////////
1603 if ( !xInfo.is() )
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 ) );
1615 continue;
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 ) );
1654 else
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
1663 // error handling).
1664 aProppatchPropsPositions.push_back( n );
1666 else
1668 // Property value will be stored in local property store.
1669 if ( !bTriedToGetAdditonalPropSet &&
1670 !xAdditionalPropSet.is() )
1672 xAdditionalPropSet
1673 = getAdditionalPropertySet( sal_False );
1674 bTriedToGetAdditonalPropSet = sal_True;
1677 if ( xAdditionalPropSet.is() )
1681 uno::Any aOldValue
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;
1693 nChanged++;
1696 catch ( beans::UnknownPropertyException const & e )
1698 aRet[ n ] <<= e;
1700 catch ( lang::WrappedTargetException const & e )
1702 aRet[ n ] <<= e;
1704 catch ( beans::PropertyVetoException const & e )
1706 aRet[ n ] <<= e;
1708 catch ( lang::IllegalArgumentException const & e )
1710 aRet[ n ] <<= e;
1713 else
1715 aRet[ n ] <<= uno::Exception(
1716 rtl::OUString( "No property set for storing the value!" ),
1717 static_cast< cppu::OWeakObject * >( this ) );
1722 } // for
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();
1736 while ( it != 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;
1743 nChanged++;
1745 ++it;
1748 catch ( DAVException const & e )
1750 // OSL_FAIL( // "Content::setPropertyValues - PROPPATCH failed!" );
1752 cancelCommandExecution( e, xEnv );
1753 // unreachable
1757 if ( bExchange )
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() );
1777 xResAccess->MOVE(
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(),
1797 // sal_True );
1799 else
1801 // Do not set new title!
1802 aNewTitle = rtl::OUString();
1804 // Set error .
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();
1815 // Set error .
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;
1831 nChanged++;
1834 if ( nChanged > 0 )
1836 aChanges.realloc( nChanged );
1837 notifyPropertiesChange( aChanges );
1841 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1842 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
1845 return aRet;
1848 //=========================================================================
1849 uno::Any Content::open(
1850 const ucb::OpenCommandArgument3 & rArg,
1851 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1852 throw( uno::Exception )
1854 uno::Any aRet;
1856 sal_Bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) ||
1857 ( rArg.Mode == ucb::OpenMode::FOLDERS ) ||
1858 ( rArg.Mode == ucb::OpenMode::DOCUMENTS ) );
1859 if ( bOpenFolder )
1861 if ( isFolder( xEnv ) )
1863 // Open collection.
1865 uno::Reference< ucb::XDynamicResultSet > xSet
1866 = new DynamicResultSet( m_xSMgr, this, rArg, xEnv );
1867 aRet <<= xSet;
1869 else
1871 // Error: Not a folder!
1873 rtl::OUStringBuffer aMsg;
1874 if ( getResourceType( xEnv ) == FTP )
1876 // #114653#
1877 aMsg.appendAscii( "FTP over HTTP proxy: resource cannot "
1878 "be opened as folder! Wrong Open Mode!" );
1880 else
1882 aMsg.appendAscii( "Non-folder resource cannot be "
1883 "opened as folder! Wrong Open Mode!" );
1886 ucbhelper::cancelCommandExecution(
1887 uno::makeAny(
1888 lang::IllegalArgumentException(
1889 aMsg.makeStringAndClear(),
1890 static_cast< cppu::OWeakObject * >( this ),
1891 -1 ) ),
1892 xEnv );
1893 // Unreachable
1897 if ( rArg.Sink.is() )
1899 // Open document.
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(
1906 uno::makeAny(
1907 ucb::UnsupportedOpenModeException(
1908 rtl::OUString(),
1909 static_cast< cppu::OWeakObject * >( this ),
1910 sal_Int16( rArg.Mode ) ) ),
1911 xEnv );
1912 // Unreachable
1915 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
1916 uno::Reference< io::XOutputStream > xOut
1917 = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY );
1918 if ( xOut.is() )
1920 // PUSH: write data
1923 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1924 std::auto_ptr< DAVResourceAccess > xResAccess;
1925 SAL_WNODEPRECATED_DECLARATIONS_POP
1928 osl::MutexGuard aGuard( m_aMutex );
1930 xResAccess.reset(
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 );
1944 // cache headers.
1945 if ( !m_xCachedProps.get())
1946 m_xCachedProps.reset(
1947 new CachableContentProperties( aResource ) );
1948 else
1949 m_xCachedProps->addProperties( aResource );
1951 m_xResAccess.reset(
1952 new DAVResourceAccess( *xResAccess.get() ) );
1955 catch ( DAVException const & e )
1957 cancelCommandExecution( e, xEnv );
1958 // Unreachable
1961 else
1963 uno::Reference< io::XActiveDataSink > xDataSink
1964 = uno::Reference< io::XActiveDataSink >( rArg.Sink,
1965 uno::UNO_QUERY );
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 );
1977 xResAccess.reset(
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 );
1994 // cache headers.
1995 if ( !m_xCachedProps.get())
1996 m_xCachedProps.reset(
1997 new CachableContentProperties( aResource ) );
1998 else
1999 m_xCachedProps->addProperties(
2000 aResource.properties );
2002 m_xResAccess.reset(
2003 new DAVResourceAccess( *xResAccess.get() ) );
2006 xDataSink->setInputStream( xIn );
2008 catch ( DAVException const & e )
2010 cancelCommandExecution( e, xEnv );
2011 // Unreachable
2014 else
2016 // Note: aOpenCommand.Sink may contain an XStream
2017 // implementation. Support for this type of
2018 // sink is optional...
2019 ucbhelper::cancelCommandExecution(
2020 uno::makeAny(
2021 ucb::UnsupportedDataSinkException(
2022 rtl::OUString(),
2023 static_cast< cppu::OWeakObject * >( this ),
2024 rArg.Sink ) ),
2025 xEnv );
2026 // Unreachable
2031 return aRet;
2034 //=========================================================================
2035 void Content::post(
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 );
2041 if ( xSink.is() )
2045 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2046 std::auto_ptr< DAVResourceAccess > xResAccess;
2047 SAL_WNODEPRECATED_DECLARATIONS_POP
2049 osl::MutexGuard aGuard( m_aMutex );
2050 xResAccess.reset(
2051 new DAVResourceAccess( *m_xResAccess.get() ) );
2054 uno::Reference< io::XInputStream > xResult
2055 = xResAccess->POST( rArg.MediaType,
2056 rArg.Referer,
2057 rArg.Source,
2058 xEnv );
2061 osl::MutexGuard aGuard( m_aMutex );
2062 m_xResAccess.reset(
2063 new DAVResourceAccess( *xResAccess.get() ) );
2066 xSink->setInputStream( xResult );
2068 catch ( DAVException const & e )
2070 cancelCommandExecution( e, xEnv, sal_True );
2071 // Unreachable
2074 else
2076 uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY );
2077 if ( xResult.is() )
2081 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2082 std::auto_ptr< DAVResourceAccess > xResAccess;
2083 SAL_WNODEPRECATED_DECLARATIONS_POP
2085 osl::MutexGuard aGuard( m_aMutex );
2086 xResAccess.reset(
2087 new DAVResourceAccess( *m_xResAccess.get() ) );
2090 xResAccess->POST( rArg.MediaType,
2091 rArg.Referer,
2092 rArg.Source,
2093 xResult,
2094 xEnv );
2097 osl::MutexGuard aGuard( m_aMutex );
2098 m_xResAccess.reset(
2099 new DAVResourceAccess( *xResAccess.get() ) );
2102 catch ( DAVException const & e )
2104 cancelCommandExecution( e, xEnv, sal_True );
2105 // Unreachable
2108 else
2110 ucbhelper::cancelCommandExecution(
2111 uno::makeAny(
2112 ucb::UnsupportedDataSinkException(
2113 rtl::OUString(),
2114 static_cast< cppu::OWeakObject * >( this ),
2115 rArg.Sink ) ),
2116 xEnv );
2117 // Unreachable
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
2127 // of this content.
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();
2146 while ( it != 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 * >(
2166 xChild.get() ) ) );
2169 ++it;
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(
2205 rtl::OUString(),
2206 static_cast< cppu::OWeakObject * >( this ),
2207 aProps ) ),
2208 Environment );
2209 // Unreachable
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();
2242 if ( xIH.is() )
2244 uno::Any aExAsAny( uno::makeAny( aEx ) );
2246 rtl::Reference< ucbhelper::SimpleInteractionRequest > xRequest
2247 = new ucbhelper::SimpleInteractionRequest(
2248 aExAsAny,
2249 ucbhelper::CONTINUATION_APPROVE
2250 | ucbhelper::CONTINUATION_DISAPPROVE );
2251 xIH->handle( xRequest.get() );
2253 const sal_Int32 nResp = xRequest->getResponse();
2255 switch ( nResp )
2257 case ucbhelper::CONTINUATION_UNKNOWN:
2258 // Not handled; throw.
2259 throw aEx;
2260 // break;
2262 case ucbhelper::CONTINUATION_APPROVE:
2263 // Continue -> Overwrite.
2264 bReplaceExisting = sal_True;
2265 break;
2267 case ucbhelper::CONTINUATION_DISAPPROVE:
2268 // Abort.
2269 throw ucb::CommandFailedException(
2270 rtl::OUString(),
2271 uno::Reference< uno::XInterface >(),
2272 aExAsAny );
2273 // break;
2275 default:
2276 OSL_FAIL( "Content::insert - "
2277 "Unknown interaction selection!" );
2278 throw ucb::CommandFailedException(
2279 rtl::OUString( "Unknown interaction selection!" ),
2280 uno::Reference< uno::XInterface >(),
2281 aExAsAny );
2282 // break;
2285 else
2287 // No IH; throw.
2288 throw aEx;
2293 if ( bTransient )
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 );
2306 if ( bCollection )
2307 xResAccess->MKCOL( Environment );
2308 else
2309 xResAccess->PUT( xInputStream, Environment );
2311 catch ( DAVException const & except )
2313 if ( bCollection )
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 );
2331 // Unreachable
2334 // Insert (recursion!).
2335 insert( xInputStream, bReplaceExisting, Environment );
2338 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2339 m_xResAccess.reset(
2340 new DAVResourceAccess( *xResAccess.get() ) );
2343 // Success!
2344 return;
2346 else
2348 rtl::OUString aTitle;
2351 NeonUri aURI( aURL );
2352 aTitle = aURI.GetPathBaseNameUnescaped();
2354 catch ( DAVException const & )
2358 ucbhelper::cancelCommandExecution(
2359 uno::makeAny(
2360 ucb::NameClashException(
2361 rtl::OUString(),
2362 static_cast< cppu::OWeakObject * >( this ),
2363 task::InteractionClassification_ERROR,
2364 aTitle ) ),
2365 Environment );
2366 // Unreachable
2371 cancelCommandExecution( except, Environment, sal_True );
2372 // Unreachable
2376 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2377 m_xIdentifier
2378 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
2381 inserted();
2384 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2385 m_bTransient = sal_False;
2388 else
2390 if ( !xInputStream.is() )
2392 ucbhelper::cancelCommandExecution(
2393 uno::makeAny(
2394 ucb::MissingInputStreamException(
2395 rtl::OUString(),
2396 static_cast< cppu::OWeakObject * >( this ) ) ),
2397 Environment );
2398 // Unreachable
2403 xResAccess->PUT( xInputStream, Environment );
2405 catch ( DAVException const & e )
2407 cancelCommandExecution( e, Environment, sal_True );
2408 // Unreachable
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 ) );
2465 else
2467 if ( aScheme != HTTP_URL_SCHEME && aScheme != HTTPS_URL_SCHEME )
2469 ucbhelper::cancelCommandExecution(
2470 uno::makeAny(
2471 ucb::InteractiveBadTransferURLException(
2472 rtl::OUString( "Unsupported URL scheme!" ),
2473 static_cast< cppu::OWeakObject * >( this ) ) ),
2474 Environment );
2475 // Unreachable
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 ) ) ),
2499 Environment );
2500 // Unreachable
2503 rtl::OUString aTitle = rArgs.NewTitle;
2505 if ( aTitle.isEmpty() )
2506 aTitle = sourceURI.GetPathBaseNameUnescaped();
2508 if ( aTitle == "/" )
2510 // kso: ???
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(),
2549 targetURI.GetURI(),
2550 rArgs.NameClash
2551 == ucb::NameClash::OVERWRITE,
2552 Environment );
2554 if ( xSource.is() )
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(),
2564 // sal_True );
2566 else
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(),
2576 targetURI.GetURI(),
2577 rArgs.NameClash
2578 == ucb::NameClash::OVERWRITE,
2579 Environment );
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(),
2585 // sal_True );
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 & )
2599 // queryContent
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(
2616 uno::makeAny(
2617 ucb::NameClashException(
2618 rtl::OUString(),
2619 static_cast< cppu::OWeakObject * >( this ),
2620 task::InteractionClassification_ERROR,
2621 aTargetURI ) ),
2622 Environment );
2623 // Unreachable
2626 case ucb::NameClash::OVERWRITE:
2627 break;
2629 case ucb::NameClash::KEEP: // deprecated
2630 case ucb::NameClash::RENAME:
2631 case ucb::NameClash::ASK:
2632 default:
2634 ucbhelper::cancelCommandExecution(
2635 uno::makeAny(
2636 ucb::UnsupportedNameClashException(
2637 rtl::OUString(),
2638 static_cast< cppu::OWeakObject * >( this ),
2639 rArgs.NameClash ) ),
2640 Environment );
2641 // Unreachable
2646 cancelCommandExecution( e, Environment, sal_True );
2647 // Unreachable
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;
2665 deleted();
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();
2677 while ( it != end )
2679 (*it)->destroy( bDeletePhysical );
2680 ++it;
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 )
2702 return true;
2707 return false;
2710 //=========================================================================
2711 void Content::lock(
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() ) );
2725 uno::Any aOwnerAny;
2726 aOwnerAny
2727 <<= rtl::OUString("http://ucb.openoffice.org");
2729 ucb::Lock aLock(
2730 ucb::LockScope_EXCLUSIVE,
2731 ucb::LockType_WRITE,
2732 ucb::LockDepth_ZERO,
2733 aOwnerAny,
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 );
2748 // Unreachable
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 );
2777 // Unreachable
2781 //=========================================================================
2782 sal_Bool Content::exchangeIdentity(
2783 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2785 if ( !xNewId.is() )
2786 return sal_False;
2788 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
2790 uno::Reference< ucb::XContent > xThis = this;
2792 // Already persistent?
2793 if ( m_bTransient )
2795 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
2796 return sal_False;
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();
2806 aGuard.clear();
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();
2817 while ( it != 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 ) )
2836 return sal_False;
2838 ++it;
2840 return sal_True;
2844 OSL_FAIL( "Content::exchangeIdentity - "
2845 "Panic! Cannot exchange identity!" );
2846 return sal_False;
2849 //=========================================================================
2850 sal_Bool Content::isFolder(
2851 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
2852 throw( uno::Exception )
2855 osl::MutexGuard aGuard( m_aMutex );
2857 if ( m_bTransient )
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 ) );
2865 if ( xRow.is() )
2869 return xRow->getBoolean( 1 );
2871 catch ( sdbc::SQLException const & )
2876 return sal_False;
2879 //=========================================================================
2880 uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite )
2882 // Map DAVException...
2883 uno::Any aException;
2885 rtl::OUString aURL;
2886 if ( m_bTransient )
2888 aURL = getParentURL();
2889 if ( aURL.lastIndexOf('/') != ( aURL.getLength() - 1 ) )
2890 aURL += rtl::OUString(static_cast<sal_Unicode>('/'));
2892 aURL += m_aEscapedTitle;
2894 else
2896 aURL = m_xIdentifier->getContentIdentifier();
2899 switch ( e.getStatus() )
2901 case SC_NOT_FOUND:
2903 uno::Sequence< uno::Any > aArgs( 1 );
2904 aArgs[ 0 ] <<= beans::PropertyValue(
2905 rtl::OUString("Uri"), -1,
2906 uno::makeAny(aURL),
2907 beans::PropertyState_DIRECT_VALUE);
2909 aException <<=
2910 ucb::InteractiveAugmentedIOException(
2911 rtl::OUString("Not found!"),
2912 static_cast< cppu::OWeakObject * >( this ),
2913 task::InteractionClassification_ERROR,
2914 ucb::IOErrorCode_NOT_EXISTING,
2915 aArgs );
2916 return aException;
2918 default:
2919 break;
2922 switch ( e.getError() )
2924 case DAVException::DAV_HTTP_ERROR:
2926 if ( bWrite )
2927 aException <<=
2928 ucb::InteractiveNetworkWriteException(
2929 e.getData(),
2930 static_cast< cppu::OWeakObject * >( this ),
2931 task::InteractionClassification_ERROR,
2932 e.getData() );
2933 else
2934 aException <<=
2935 ucb::InteractiveNetworkReadException(
2936 e.getData(),
2937 static_cast< cppu::OWeakObject * >( this ),
2938 task::InteractionClassification_ERROR,
2939 e.getData() );
2940 break;
2943 case DAVException::DAV_HTTP_LOOKUP:
2944 aException <<=
2945 ucb::InteractiveNetworkResolveNameException(
2946 rtl::OUString(),
2947 static_cast< cppu::OWeakObject * >( this ),
2948 task::InteractionClassification_ERROR,
2949 e.getData() );
2950 break;
2952 // @@@ No matching InteractiveNetwork*Exception
2953 // case DAVException::DAV_HTTP_AUTH:
2954 // break;
2956 // @@@ No matching InteractiveNetwork*Exception
2957 // case DAVException::DAV_HTTP_AUTHPROXY:
2958 // break;
2960 case DAVException::DAV_HTTP_CONNECT:
2961 aException <<=
2962 ucb::InteractiveNetworkConnectException(
2963 rtl::OUString(),
2964 static_cast< cppu::OWeakObject * >( this ),
2965 task::InteractionClassification_ERROR,
2966 e.getData() );
2967 break;
2969 // @@@ No matching InteractiveNetwork*Exception
2970 // case DAVException::DAV_HTTP_TIMEOUT:
2971 // break;
2973 // @@@ No matching InteractiveNetwork*Exception
2974 // case DAVException::DAV_HTTP_REDIRECT:
2975 // break;
2977 // @@@ No matching InteractiveNetwork*Exception
2978 // case DAVException::DAV_SESSION_CREATE:
2979 // break;
2981 case DAVException::DAV_INVALID_ARG:
2982 aException <<=
2983 lang::IllegalArgumentException(
2984 rtl::OUString(),
2985 static_cast< cppu::OWeakObject * >( this ),
2986 -1 );
2987 break;
2989 case DAVException::DAV_LOCKED:
2990 aException <<=
2991 ucb::InteractiveLockingLockedException(
2992 rtl::OUString("Locked!"),
2993 static_cast< cppu::OWeakObject * >( this ),
2994 task::InteractionClassification_ERROR,
2995 aURL,
2996 sal_False ); // not SelfOwned
2997 break;
2999 case DAVException::DAV_LOCKED_SELF:
3000 aException <<=
3001 ucb::InteractiveLockingLockedException(
3002 rtl::OUString("Locked (self!)"),
3003 static_cast< cppu::OWeakObject * >( this ),
3004 task::InteractionClassification_ERROR,
3005 aURL,
3006 sal_True ); // SelfOwned
3007 break;
3009 case DAVException::DAV_NOT_LOCKED:
3010 aException <<=
3011 ucb::InteractiveLockingNotLockedException(
3012 rtl::OUString("Not locked!"),
3013 static_cast< cppu::OWeakObject * >( this ),
3014 task::InteractionClassification_ERROR,
3015 aURL );
3016 break;
3018 case DAVException::DAV_LOCK_EXPIRED:
3019 aException <<=
3020 ucb::InteractiveLockingLockExpiredException(
3021 rtl::OUString("Lock expired!"),
3022 static_cast< cppu::OWeakObject * >( this ),
3023 task::InteractionClassification_ERROR,
3024 aURL );
3025 break;
3027 default:
3028 aException <<=
3029 ucb::InteractiveNetworkGeneralException(
3030 rtl::OUString(),
3031 static_cast< cppu::OWeakObject * >( this ),
3032 task::InteractionClassification_ERROR );
3033 break;
3036 return aException;
3039 //=========================================================================
3040 // static
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 ) )
3048 return false;
3050 return true;
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 );
3061 // Unreachable
3064 //=========================================================================
3065 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3066 const rtl::OUString
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(),
3084 aLocation );
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;
3116 else
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: */