1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
23 **************************************************************************
25 *************************************************************************/
27 #include <sal/config.h>
29 #include <string_view>
31 #include <o3tl/string_view.hxx>
32 #include <comphelper/diagnose_ex.hxx>
33 #include <rtl/ustrbuf.hxx>
34 #include <com/sun/star/beans/IllegalTypeException.hpp>
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/embed/InvalidStorageException.hpp>
38 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
39 #include <com/sun/star/embed/XTransactedObject.hpp>
40 #include <com/sun/star/io/BufferSizeExceededException.hpp>
41 #include <com/sun/star/io/IOException.hpp>
42 #include <com/sun/star/io/NotConnectedException.hpp>
43 #include <com/sun/star/io/XActiveDataSink.hpp>
44 #include <com/sun/star/io/XActiveDataStreamer.hpp>
45 #include <com/sun/star/lang/IllegalAccessException.hpp>
46 #include <com/sun/star/packages/WrongPasswordException.hpp>
47 #include <com/sun/star/task/DocumentPasswordRequest.hpp>
48 #include <com/sun/star/task/XInteractionPassword.hpp>
49 #include <com/sun/star/ucb/CommandFailedException.hpp>
50 #include <com/sun/star/ucb/ContentAction.hpp>
51 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
52 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
53 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
54 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
55 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
56 #include <com/sun/star/ucb/NameClash.hpp>
57 #include <com/sun/star/ucb/NameClashException.hpp>
58 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
59 #include <com/sun/star/ucb/OpenMode.hpp>
60 #include <com/sun/star/ucb/TransferInfo.hpp>
61 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
62 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
63 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
64 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
65 #include <com/sun/star/ucb/XCommandInfo.hpp>
66 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
68 #include <comphelper/propertysequence.hxx>
69 #include <cppuhelper/queryinterface.hxx>
70 #include <ucbhelper/cancelcommandexecution.hxx>
71 #include <ucbhelper/contentidentifier.hxx>
72 #include <ucbhelper/propertyvalueset.hxx>
73 #include <ucbhelper/macros.hxx>
76 #include "tdoc_content.hxx"
77 #include "tdoc_resultset.hxx"
78 #include "tdoc_passwordrequest.hxx"
80 #include "../inc/urihelper.hxx"
82 using namespace com::sun::star
;
83 using namespace tdoc_ucp
;
86 static ContentType
lcl_getContentType( std::u16string_view rType
)
88 if ( rType
== TDOC_ROOT_CONTENT_TYPE
)
90 else if ( rType
== TDOC_DOCUMENT_CONTENT_TYPE
)
92 else if ( rType
== TDOC_FOLDER_CONTENT_TYPE
)
94 else if ( rType
== TDOC_STREAM_CONTENT_TYPE
)
98 OSL_FAIL( "Content::Content - unsupported content type string" );
104 // Content Implementation.
107 // static ( "virtual" ctor )
108 rtl::Reference
<Content
> Content::create(
109 const uno::Reference
< uno::XComponentContext
>& rxContext
,
110 ContentProvider
* pProvider
,
111 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
113 // Fail, if resource does not exist.
114 ContentProperties aProps
;
115 if ( !Content::loadData( pProvider
,
116 Uri( Identifier
->getContentIdentifier() ),
120 return new Content( rxContext
, pProvider
, Identifier
, std::move(aProps
) );
124 // static ( "virtual" ctor )
125 rtl::Reference
<Content
> Content::create(
126 const uno::Reference
< uno::XComponentContext
>& rxContext
,
127 ContentProvider
* pProvider
,
128 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
129 const ucb::ContentInfo
& Info
)
131 if ( Info
.Type
.isEmpty() )
134 if ( Info
.Type
!= TDOC_FOLDER_CONTENT_TYPE
&& Info
.Type
!= TDOC_STREAM_CONTENT_TYPE
)
136 OSL_FAIL( "Content::create - unsupported content type!" );
140 return new Content( rxContext
, pProvider
, Identifier
, Info
);
145 const uno::Reference
< uno::XComponentContext
> & rxContext
,
146 ContentProvider
* pProvider
,
147 const uno::Reference
< ucb::XContentIdentifier
> & Identifier
,
148 ContentProperties aProps
)
149 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
150 m_aProps(std::move( aProps
)),
151 m_eState( PERSISTENT
),
152 m_pProvider( pProvider
)
157 // ctor for a content just created via XContentCreator::createNewContent()
159 const uno::Reference
< uno::XComponentContext
>& rxContext
,
160 ContentProvider
* pProvider
,
161 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
162 const ucb::ContentInfo
& Info
)
163 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
164 m_aProps( lcl_getContentType( Info
.Type
), OUString() ), // no Title (yet)
165 m_eState( TRANSIENT
),
166 m_pProvider( pProvider
)
177 // XInterface methods.
181 void SAL_CALL
Content::acquire()
184 ContentImplHelper::acquire();
189 void SAL_CALL
Content::release()
192 ContentImplHelper::release();
197 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
199 uno::Any aRet
= ContentImplHelper::queryInterface( rType
);
201 if ( !aRet
.hasValue() )
203 aRet
= cppu::queryInterface(
204 rType
, static_cast< ucb::XContentCreator
* >( this ) );
205 if ( aRet
.hasValue() )
207 if ( !m_aProps
.isContentCreator() )
216 // XTypeProvider methods.
219 XTYPEPROVIDER_COMMON_IMPL( Content
);
223 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
225 if ( m_aProps
.isContentCreator() )
227 static cppu::OTypeCollection
s_aFolderTypes(
228 CPPU_TYPE_REF( lang::XTypeProvider
),
229 CPPU_TYPE_REF( lang::XServiceInfo
),
230 CPPU_TYPE_REF( lang::XComponent
),
231 CPPU_TYPE_REF( ucb::XContent
),
232 CPPU_TYPE_REF( ucb::XCommandProcessor
),
233 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
234 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
235 CPPU_TYPE_REF( beans::XPropertyContainer
),
236 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
237 CPPU_TYPE_REF( container::XChild
),
238 CPPU_TYPE_REF( ucb::XContentCreator
) );
240 return s_aFolderTypes
.getTypes();
244 static cppu::OTypeCollection
s_aDocumentTypes(
245 CPPU_TYPE_REF( lang::XTypeProvider
),
246 CPPU_TYPE_REF( lang::XServiceInfo
),
247 CPPU_TYPE_REF( lang::XComponent
),
248 CPPU_TYPE_REF( ucb::XContent
),
249 CPPU_TYPE_REF( ucb::XCommandProcessor
),
250 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
251 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
252 CPPU_TYPE_REF( beans::XPropertyContainer
),
253 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
254 CPPU_TYPE_REF( container::XChild
) );
256 return s_aDocumentTypes
.getTypes();
261 // XServiceInfo methods.
265 OUString SAL_CALL
Content::getImplementationName()
267 return "com.sun.star.comp.ucb.TransientDocumentsContent";
272 uno::Sequence
< OUString
> SAL_CALL
Content::getSupportedServiceNames()
274 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
276 uno::Sequence
< OUString
> aSNS( 1 );
278 if ( m_aProps
.getType() == STREAM
)
279 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsStreamContent";
280 else if ( m_aProps
.getType() == FOLDER
)
281 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsFolderContent";
282 else if ( m_aProps
.getType() == DOCUMENT
)
283 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsDocumentContent";
285 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsRootContent";
295 OUString SAL_CALL
Content::getContentType()
297 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
298 return m_aProps
.getContentType();
303 uno::Reference
< ucb::XContentIdentifier
> SAL_CALL
304 Content::getIdentifier()
307 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
310 if ( m_eState
== TRANSIENT
)
312 // Transient contents have no identifier.
313 return uno::Reference
< ucb::XContentIdentifier
>();
316 return ContentImplHelper::getIdentifier();
320 // XCommandProcessor methods.
324 uno::Any SAL_CALL
Content::execute(
325 const ucb::Command
& aCommand
,
326 sal_Int32
/*CommandId*/,
327 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
331 if ( aCommand
.Name
== "getPropertyValues" )
337 uno::Sequence
< beans::Property
> Properties
;
338 if ( !( aCommand
.Argument
>>= Properties
) )
340 ucbhelper::cancelCommandExecution(
341 uno::Any( lang::IllegalArgumentException(
342 "Wrong argument type!",
343 static_cast< cppu::OWeakObject
* >( this ),
349 aRet
<<= getPropertyValues( Properties
);
351 else if ( aCommand
.Name
== "setPropertyValues" )
357 uno::Sequence
< beans::PropertyValue
> aProperties
;
358 if ( !( aCommand
.Argument
>>= aProperties
) )
360 ucbhelper::cancelCommandExecution(
361 uno::Any( lang::IllegalArgumentException(
362 "Wrong argument type!",
363 static_cast< cppu::OWeakObject
* >( this ),
369 if ( !aProperties
.hasElements() )
371 ucbhelper::cancelCommandExecution(
372 uno::Any( lang::IllegalArgumentException(
374 static_cast< cppu::OWeakObject
* >( this ),
380 aRet
<<= setPropertyValues( aProperties
, Environment
);
382 else if ( aCommand
.Name
== "getPropertySetInfo" )
385 // getPropertySetInfo
388 aRet
<<= getPropertySetInfo( Environment
);
390 else if ( aCommand
.Name
== "getCommandInfo" )
396 aRet
<<= getCommandInfo( Environment
);
398 else if ( aCommand
.Name
== "open" )
404 ucb::OpenCommandArgument2 aOpenCommand
;
405 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
407 ucbhelper::cancelCommandExecution(
408 uno::Any( lang::IllegalArgumentException(
409 "Wrong argument type!",
410 static_cast< cppu::OWeakObject
* >( this ),
416 aRet
= open( aOpenCommand
, Environment
);
418 else if ( aCommand
.Name
== "insert" )
421 // insert ( Supported by folders and streams only )
424 ContentType eType
= m_aProps
.getType();
425 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
427 ucbhelper::cancelCommandExecution(
428 uno::Any( ucb::UnsupportedCommandException(
429 "insert command only supported by "
430 "folders and streams!",
431 static_cast< cppu::OWeakObject
* >( this ) ) ),
436 if ( eType
== STREAM
)
438 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
439 Uri
aParentUri( aUri
.getParentUri() );
440 if ( aParentUri
.isDocument() )
442 ucbhelper::cancelCommandExecution(
443 uno::Any( ucb::UnsupportedCommandException(
444 "insert command not supported by "
445 "streams that are direct children "
447 static_cast< cppu::OWeakObject
* >(
454 ucb::InsertCommandArgument aArg
;
455 if ( !( aCommand
.Argument
>>= aArg
) )
457 ucbhelper::cancelCommandExecution(
458 uno::Any( lang::IllegalArgumentException(
459 "Wrong argument type!",
460 static_cast< cppu::OWeakObject
* >( this ),
466 sal_Int32 nNameClash
= aArg
.ReplaceExisting
467 ? ucb::NameClash::OVERWRITE
468 : ucb::NameClash::ERROR
;
469 insert( aArg
.Data
, nNameClash
, Environment
);
471 else if ( aCommand
.Name
== "delete" )
474 // delete ( Supported by folders and streams only )
478 osl::MutexGuard
aGuard( m_aMutex
);
480 ContentType eType
= m_aProps
.getType();
481 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
483 ucbhelper::cancelCommandExecution(
484 uno::Any( ucb::UnsupportedCommandException(
485 "delete command only supported by "
486 "folders and streams!",
487 static_cast< cppu::OWeakObject
* >(
494 bool bDeletePhysical
= false;
495 aCommand
.Argument
>>= bDeletePhysical
;
496 destroy( bDeletePhysical
, Environment
);
498 // Remove own and all children's persistent data.
501 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
503 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
505 ucbhelper::cancelCommandExecution(
506 ucb::IOErrorCode_CANT_WRITE
,
509 "Cannot remove persistent data!",
514 // Remove own and all children's Additional Core Properties.
515 removeAdditionalPropertySet();
517 else if ( aCommand
.Name
== "transfer" )
520 // transfer ( Supported by document and folders only )
524 osl::MutexGuard
aGuard( m_aMutex
);
526 ContentType eType
= m_aProps
.getType();
527 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
529 ucbhelper::cancelCommandExecution(
530 uno::Any( ucb::UnsupportedCommandException(
531 "transfer command only supported "
532 "by folders and documents!",
533 static_cast< cppu::OWeakObject
* >(
540 ucb::TransferInfo aInfo
;
541 if ( !( aCommand
.Argument
>>= aInfo
) )
543 OSL_FAIL( "Wrong argument type!" );
544 ucbhelper::cancelCommandExecution(
545 uno::Any( lang::IllegalArgumentException(
546 "Wrong argument type!",
547 static_cast< cppu::OWeakObject
* >( this ),
553 transfer( aInfo
, Environment
);
555 else if ( aCommand
.Name
== "createNewContent" )
558 // createNewContent ( Supported by document and folders only )
562 osl::MutexGuard
aGuard( m_aMutex
);
564 ContentType eType
= m_aProps
.getType();
565 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
567 ucbhelper::cancelCommandExecution(
568 uno::Any( ucb::UnsupportedCommandException(
569 "createNewContent command only "
570 "supported by folders and "
572 static_cast< cppu::OWeakObject
* >(
579 ucb::ContentInfo aInfo
;
580 if ( !( aCommand
.Argument
>>= aInfo
) )
582 OSL_FAIL( "Wrong argument type!" );
583 ucbhelper::cancelCommandExecution(
584 uno::Any( lang::IllegalArgumentException(
585 "Wrong argument type!",
586 static_cast< cppu::OWeakObject
* >( this ),
592 aRet
<<= createNewContent( aInfo
);
597 // Unsupported command
600 ucbhelper::cancelCommandExecution(
601 uno::Any( ucb::UnsupportedCommandException(
603 static_cast< cppu::OWeakObject
* >( this ) ) ),
613 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
618 // XContentCreator methods.
622 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
623 Content::queryCreatableContentsInfo()
625 return m_aProps
.getCreatableContentsInfo();
630 uno::Reference
< ucb::XContent
> SAL_CALL
631 Content::createNewContent( const ucb::ContentInfo
& Info
)
633 if ( m_aProps
.isContentCreator() )
635 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
637 if ( Info
.Type
.isEmpty() )
638 return uno::Reference
< ucb::XContent
>();
640 bool bCreateFolder
= Info
.Type
== TDOC_FOLDER_CONTENT_TYPE
;
642 // streams cannot be created as direct children of document root
643 if ( !bCreateFolder
&& ( m_aProps
.getType() == DOCUMENT
) )
645 OSL_FAIL( "Content::createNewContent - streams cannot be "
646 "created as direct children of document root!" );
647 return uno::Reference
< ucb::XContent
>();
649 if ( !bCreateFolder
&& Info
.Type
!= TDOC_STREAM_CONTENT_TYPE
)
651 OSL_FAIL( "Content::createNewContent - unsupported type!" );
652 return uno::Reference
< ucb::XContent
>();
655 OUString aURL
= m_xIdentifier
->getContentIdentifier();
657 OSL_ENSURE( !aURL
.isEmpty(),
658 "Content::createNewContent - empty identifier!" );
660 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
664 aURL
+= "New_Folder";
666 aURL
+= "New_Stream";
668 uno::Reference
< ucb::XContentIdentifier
> xId
669 = new ::ucbhelper::ContentIdentifier( aURL
);
671 return create( m_xContext
, m_pProvider
, xId
, Info
);
675 OSL_FAIL( "createNewContent called on non-contentcreator object!" );
676 return uno::Reference
< ucb::XContent
>();
682 OUString
Content::getParentURL()
684 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
685 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
686 return aUri
.getParentUri();
690 uno::Reference
< ucb::XContentIdentifier
>
691 Content::makeNewIdentifier( const OUString
& rTitle
)
693 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
695 // Assemble new content identifier...
696 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
697 OUString aNewURL
= aUri
.getParentUri() + ::ucb_impl::urihelper::encodeSegment( rTitle
);
700 uno::Reference
< ucb::XContentIdentifier
>(
701 new ::ucbhelper::ContentIdentifier( aNewURL
) );
705 void Content::queryChildren( ContentRefList
& rChildren
)
707 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
709 // Only folders (root, documents, folders) have children.
710 if ( !m_aProps
.getIsFolder() )
713 // Obtain a list with a snapshot of all currently instantiated contents
714 // from provider and extract the contents which are direct children
717 ::ucbhelper::ContentRefList aAllContents
;
718 m_xProvider
->queryExistingContents( aAllContents
);
720 OUString aURL
= m_xIdentifier
->getContentIdentifier();
721 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
723 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
725 // No trailing slash found. Append.
729 sal_Int32 nLen
= aURL
.getLength();
731 for ( const auto& rContent
: aAllContents
)
733 ::ucbhelper::ContentImplHelperRef xChild
= rContent
;
735 = xChild
->getIdentifier()->getContentIdentifier();
737 // Is aURL a prefix of aChildURL?
738 if ( ( aChildURL
.getLength() > nLen
) &&
739 ( aChildURL
.startsWith( aURL
) ) )
741 sal_Int32 nPos
= aChildURL
.indexOf( '/', nLen
);
743 if ( ( nPos
== -1 ) ||
744 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
746 // No further slashes / only a final slash. It's a child!
747 rChildren
.emplace_back(
748 static_cast< Content
* >( xChild
.get() ) );
755 bool Content::exchangeIdentity(
756 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
761 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
763 uno::Reference
< ucb::XContent
> xThis
= this;
765 // Already persistent?
766 if ( m_eState
!= PERSISTENT
)
768 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
772 // Only folders and streams can be renamed -> exchange identity.
773 ContentType eType
= m_aProps
.getType();
774 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
776 OSL_FAIL( "Content::exchangeIdentity - "
777 "Not supported by root or document!" );
781 // Exchange own identity.
783 // Fail, if a content with given id already exists.
784 if ( !hasData( Uri( xNewId
->getContentIdentifier() ) ) )
786 OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
789 if ( exchange( xNewId
) )
791 if ( eType
== FOLDER
)
793 // Process instantiated children...
795 ContentRefList aChildren
;
796 queryChildren( aChildren
);
798 for ( const auto& rChild
: aChildren
)
800 ContentRef xChild
= rChild
;
802 // Create new content identifier for the child...
803 uno::Reference
< ucb::XContentIdentifier
> xOldChildId
804 = xChild
->getIdentifier();
805 OUString aOldChildURL
806 = xOldChildId
->getContentIdentifier();
807 OUString aNewChildURL
808 = aOldChildURL
.replaceAt(
811 xNewId
->getContentIdentifier() );
812 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
813 = new ::ucbhelper::ContentIdentifier( aNewChildURL
);
815 if ( !xChild
->exchangeIdentity( xNewChildId
) )
823 OSL_FAIL( "Content::exchangeIdentity - "
824 "Panic! Cannot exchange identity!" );
830 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
831 const uno::Reference
< uno::XComponentContext
>& rxContext
,
832 const uno::Sequence
< beans::Property
>& rProperties
,
833 ContentProvider
* pProvider
,
834 const OUString
& rContentId
)
836 ContentProperties aData
;
837 if ( loadData( pProvider
, Uri(rContentId
), aData
) )
839 return getPropertyValues(
840 rxContext
, rProperties
, aData
, pProvider
, rContentId
);
844 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
845 = new ::ucbhelper::PropertyValueSet( rxContext
);
847 for ( const beans::Property
& rProp
: rProperties
)
848 xRow
->appendVoid( rProp
);
856 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
857 const uno::Reference
< uno::XComponentContext
>& rxContext
,
858 const uno::Sequence
< beans::Property
>& rProperties
,
859 const ContentProperties
& rData
,
860 ContentProvider
* pProvider
,
861 const OUString
& rContentId
)
863 // Note: Empty sequence means "get values of all supported properties".
865 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
866 = new ::ucbhelper::PropertyValueSet( rxContext
);
868 if ( rProperties
.hasElements() )
870 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
871 bool bTriedToGetAdditionalPropSet
= false;
873 for ( const beans::Property
& rProp
: rProperties
)
875 // Process Core properties.
877 if ( rProp
.Name
== "ContentType" )
879 xRow
->appendString ( rProp
, rData
.getContentType() );
881 else if ( rProp
.Name
== "Title" )
883 xRow
->appendString ( rProp
, rData
.getTitle() );
885 else if ( rProp
.Name
== "IsDocument" )
887 xRow
->appendBoolean( rProp
, rData
.getIsDocument() );
889 else if ( rProp
.Name
== "IsFolder" )
891 xRow
->appendBoolean( rProp
, rData
.getIsFolder() );
893 else if ( rProp
.Name
== "CreatableContentsInfo" )
896 rProp
, uno::Any( rData
.getCreatableContentsInfo() ) );
898 else if ( rProp
.Name
== "DateModified" )
900 // DateModified is only supported by streams.
901 ContentType eType
= rData
.getType();
902 if ( eType
== STREAM
)
907 pProvider
->queryStreamDateModified( rContentId
) ) );
910 xRow
->appendVoid( rProp
);
912 else if ( rProp
.Name
== "Storage" )
914 // Storage is only supported by folders.
915 ContentType eType
= rData
.getType();
916 if ( eType
== FOLDER
)
920 pProvider
->queryStorageClone( rContentId
) ) );
922 xRow
->appendVoid( rProp
);
924 else if ( rProp
.Name
== "DocumentModel" )
926 // DocumentModel is only supported by documents.
927 ContentType eType
= rData
.getType();
928 if ( eType
== DOCUMENT
)
932 pProvider
->queryDocumentModel( rContentId
) ) );
934 xRow
->appendVoid( rProp
);
938 // Not a Core Property! Maybe it's an Additional Core Property?!
940 if ( !bTriedToGetAdditionalPropSet
&& !xAdditionalPropSet
.is() )
943 pProvider
->getAdditionalPropertySet( rContentId
,
945 bTriedToGetAdditionalPropSet
= true;
948 if ( xAdditionalPropSet
.is() )
950 if ( !xRow
->appendPropertySetValue(
954 // Append empty entry.
955 xRow
->appendVoid( rProp
);
960 // Append empty entry.
961 xRow
->appendVoid( rProp
);
968 // Append all Core Properties.
970 beans::Property( "ContentType",
972 cppu::UnoType
<OUString
>::get(),
973 beans::PropertyAttribute::BOUND
974 | beans::PropertyAttribute::READONLY
),
975 rData
.getContentType() );
977 ContentType eType
= rData
.getType();
980 beans::Property( "Title",
982 cppu::UnoType
<OUString
>::get(),
983 // Title is read-only for root and documents.
984 beans::PropertyAttribute::BOUND
|
985 ( ( eType
== ROOT
) || ( eType
== DOCUMENT
)
986 ? beans::PropertyAttribute::READONLY
990 beans::Property( "IsDocument",
992 cppu::UnoType
<bool>::get(),
993 beans::PropertyAttribute::BOUND
994 | beans::PropertyAttribute::READONLY
),
995 rData
.getIsDocument() );
997 beans::Property( "IsFolder",
999 cppu::UnoType
<bool>::get(),
1000 beans::PropertyAttribute::BOUND
1001 | beans::PropertyAttribute::READONLY
),
1002 rData
.getIsFolder() );
1005 "CreatableContentsInfo",
1007 cppu::UnoType
<uno::Sequence
< ucb::ContentInfo
>>::get(),
1008 beans::PropertyAttribute::BOUND
1009 | beans::PropertyAttribute::READONLY
),
1010 uno::Any( rData
.getCreatableContentsInfo() ) );
1012 // DateModified is only supported by streams.
1013 if ( eType
== STREAM
)
1016 beans::Property( "DateModified",
1018 cppu::UnoType
<css::util::DateTime
>::get(),
1019 beans::PropertyAttribute::BOUND
1020 | beans::PropertyAttribute::READONLY
),
1021 uno::Any( pProvider
->queryStreamDateModified( rContentId
) ) );
1024 // Storage is only supported by folders.
1025 if ( eType
== FOLDER
)
1027 beans::Property( "Storage",
1029 cppu::UnoType
<embed::XStorage
>::get(),
1030 beans::PropertyAttribute::BOUND
1031 | beans::PropertyAttribute::READONLY
),
1032 uno::Any( pProvider
->queryStorageClone( rContentId
) ) );
1034 // DocumentModel is only supported by documents.
1035 if ( eType
== DOCUMENT
)
1037 beans::Property( "DocumentModel",
1039 cppu::UnoType
<frame::XModel
>::get(),
1040 beans::PropertyAttribute::BOUND
1041 | beans::PropertyAttribute::READONLY
),
1043 pProvider
->queryDocumentModel( rContentId
) ) );
1045 // Append all Additional Core Properties.
1047 uno::Reference
< beans::XPropertySet
> xSet
=
1048 pProvider
->getAdditionalPropertySet( rContentId
, false );
1049 xRow
->appendPropertySet( xSet
);
1056 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1057 const uno::Sequence
< beans::Property
>& rProperties
)
1059 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1060 return getPropertyValues( m_xContext
,
1064 m_xIdentifier
->getContentIdentifier() );
1068 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1069 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1070 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1072 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1074 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1075 auto aRetRange
= asNonConstRange(aRet
);
1076 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1077 sal_Int32 nChanged
= 0;
1079 beans::PropertyChangeEvent aEvent
;
1080 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1081 aEvent
.Further
= false;
1082 // aEvent.PropertyName =
1083 aEvent
.PropertyHandle
= -1;
1084 // aEvent.OldValue =
1085 // aEvent.NewValue =
1087 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1088 sal_Int32 nCount
= rValues
.getLength();
1090 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1091 bool bTriedToGetAdditionalPropSet
= false;
1093 bool bExchange
= false;
1095 sal_Int32 nTitlePos
= -1;
1097 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1099 const beans::PropertyValue
& rValue
= pValues
[ n
];
1101 if ( rValue
.Name
== "ContentType" )
1103 // Read-only property!
1104 aRetRange
[ n
] <<= lang::IllegalAccessException(
1105 "Property is read-only!",
1106 static_cast< cppu::OWeakObject
* >( this ) );
1108 else if ( rValue
.Name
== "IsDocument" )
1110 // Read-only property!
1111 aRetRange
[ n
] <<= lang::IllegalAccessException(
1112 "Property is read-only!",
1113 static_cast< cppu::OWeakObject
* >( this ) );
1115 else if ( rValue
.Name
== "IsFolder" )
1117 // Read-only property!
1118 aRetRange
[ n
] <<= lang::IllegalAccessException(
1119 "Property is read-only!",
1120 static_cast< cppu::OWeakObject
* >( this ) );
1122 else if ( rValue
.Name
== "CreatableContentsInfo" )
1124 // Read-only property!
1125 aRetRange
[ n
] <<= lang::IllegalAccessException(
1126 "Property is read-only!",
1127 static_cast< cppu::OWeakObject
* >( this ) );
1129 else if ( rValue
.Name
== "Title" )
1131 // Title is read-only for root and documents.
1132 ContentType eType
= m_aProps
.getType();
1133 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
1135 aRetRange
[ n
] <<= lang::IllegalAccessException(
1136 "Property is read-only!",
1137 static_cast< cppu::OWeakObject
* >( this ) );
1142 if ( rValue
.Value
>>= aNewValue
)
1145 if ( !aNewValue
.isEmpty() )
1147 if ( aNewValue
!= m_aProps
.getTitle() )
1149 // modified title -> modified URL -> exchange !
1150 if ( m_eState
== PERSISTENT
)
1153 aOldTitle
= m_aProps
.getTitle();
1154 m_aProps
.setTitle( aNewValue
);
1156 // property change event will be sent later...
1158 // remember position within sequence of values
1159 // (for error handling).
1165 aRetRange
[ n
] <<= lang::IllegalArgumentException(
1166 "Empty Title not allowed!",
1167 static_cast< cppu::OWeakObject
* >( this ),
1173 aRetRange
[ n
] <<= beans::IllegalTypeException(
1174 "Title Property value has wrong type!",
1175 static_cast< cppu::OWeakObject
* >( this ) );
1179 else if ( rValue
.Name
== "Storage" )
1181 ContentType eType
= m_aProps
.getType();
1182 if ( eType
== FOLDER
)
1184 aRetRange
[ n
] <<= lang::IllegalAccessException(
1185 "Property is read-only!",
1186 static_cast< cppu::OWeakObject
* >( this ) );
1190 // Storage is only supported by folders.
1191 aRetRange
[ n
] <<= beans::UnknownPropertyException(
1192 "Storage property only supported by folders",
1193 static_cast< cppu::OWeakObject
* >( this ) );
1196 else if ( rValue
.Name
== "DocumentModel" )
1198 ContentType eType
= m_aProps
.getType();
1199 if ( eType
== DOCUMENT
)
1201 aRetRange
[ n
] <<= lang::IllegalAccessException(
1202 "Property is read-only!",
1203 static_cast< cppu::OWeakObject
* >( this ) );
1207 // Storage is only supported by folders.
1208 aRetRange
[ n
] <<= beans::UnknownPropertyException(
1209 "DocumentModel property only supported by documents",
1210 static_cast< cppu::OWeakObject
* >( this ) );
1215 // Not a Core Property! Maybe it's an Additional Core Property?!
1217 if ( !bTriedToGetAdditionalPropSet
&& !xAdditionalPropSet
.is() )
1219 xAdditionalPropSet
= getAdditionalPropertySet( false );
1220 bTriedToGetAdditionalPropSet
= true;
1223 if ( xAdditionalPropSet
.is() )
1227 uno::Any aOldValue
= xAdditionalPropSet
->getPropertyValue(
1229 if ( aOldValue
!= rValue
.Value
)
1231 xAdditionalPropSet
->setPropertyValue(
1232 rValue
.Name
, rValue
.Value
);
1234 aEvent
.PropertyName
= rValue
.Name
;
1235 aEvent
.OldValue
= aOldValue
;
1236 aEvent
.NewValue
= rValue
.Value
;
1238 aChanges
.getArray()[ nChanged
] = aEvent
;
1242 catch ( beans::UnknownPropertyException
const & e
)
1244 aRetRange
[ n
] <<= e
;
1246 catch ( lang::WrappedTargetException
const & e
)
1248 aRetRange
[ n
] <<= e
;
1250 catch ( beans::PropertyVetoException
const & e
)
1252 aRetRange
[ n
] <<= e
;
1254 catch ( lang::IllegalArgumentException
const & e
)
1256 aRetRange
[ n
] <<= e
;
1261 aRetRange
[ n
] <<= uno::Exception(
1262 "No property set for storing the value!",
1263 static_cast< cppu::OWeakObject
* >( this ) );
1270 uno::Reference
< ucb::XContentIdentifier
> xOldId
1272 uno::Reference
< ucb::XContentIdentifier
> xNewId
1273 = makeNewIdentifier( m_aProps
.getTitle() );
1276 if ( exchangeIdentity( xNewId
) )
1278 // Adapt persistent data.
1279 renameData( xOldId
, xNewId
);
1281 // Adapt Additional Core Properties.
1282 renameAdditionalPropertySet( xOldId
->getContentIdentifier(),
1283 xNewId
->getContentIdentifier() );
1288 m_aProps
.setTitle( aOldTitle
);
1292 aRetRange
[ nTitlePos
] <<= uno::Exception(
1294 static_cast< cppu::OWeakObject
* >( this ) );
1298 if ( !aOldTitle
.isEmpty() )
1300 aEvent
.PropertyName
= "Title";
1301 aEvent
.OldValue
<<= aOldTitle
;
1302 aEvent
.NewValue
<<= m_aProps
.getTitle();
1304 aChanges
.getArray()[ nChanged
] = aEvent
;
1310 // Save changes, if content was already made persistent.
1311 if ( !bExchange
&& ( m_eState
== PERSISTENT
) )
1313 if ( !storeData( uno::Reference
< io::XInputStream
>(), xEnv
) )
1315 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1317 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1319 ucbhelper::cancelCommandExecution(
1320 ucb::IOErrorCode_CANT_WRITE
,
1323 "Cannot store persistent data!",
1329 aChanges
.realloc( nChanged
);
1332 notifyPropertiesChange( aChanges
);
1339 uno::Any
Content::open(
1340 const ucb::OpenCommandArgument2
& rArg
,
1341 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1343 if ( rArg
.Mode
== ucb::OpenMode::ALL
||
1344 rArg
.Mode
== ucb::OpenMode::FOLDERS
||
1345 rArg
.Mode
== ucb::OpenMode::DOCUMENTS
)
1348 // open command for a folder content
1351 uno::Reference
< ucb::XDynamicResultSet
> xSet
1352 = new DynamicResultSet( m_xContext
, this, rArg
);
1353 return uno::Any( xSet
);
1358 // open command for a document content
1361 if ( ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
1362 ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
1364 // Currently(?) unsupported.
1365 ucbhelper::cancelCommandExecution(
1366 uno::Any( ucb::UnsupportedOpenModeException(
1368 static_cast< cppu::OWeakObject
* >( this ),
1369 sal_Int16( rArg
.Mode
) ) ),
1374 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1376 uno::Reference
< io::XActiveDataStreamer
> xDataStreamer(
1377 rArg
.Sink
, uno::UNO_QUERY
);
1378 if ( xDataStreamer
.is() )
1380 // May throw CommandFailedException, DocumentPasswordRequest!
1381 uno::Reference
< io::XStream
> xStream
= getStream( xEnv
);
1382 if ( !xStream
.is() )
1384 // No interaction if we are not persistent!
1385 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1387 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1389 ucbhelper::cancelCommandExecution(
1390 ucb::IOErrorCode_CANT_READ
,
1392 m_eState
== PERSISTENT
1394 : uno::Reference
< ucb::XCommandEnvironment
>(),
1395 "Got no data stream!",
1401 xDataStreamer
->setStream( xStream
);
1405 uno::Reference
< io::XOutputStream
> xOut( rArg
.Sink
, uno::UNO_QUERY
);
1408 // PUSH: write data into xOut
1410 // May throw CommandFailedException, DocumentPasswordRequest!
1411 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1414 // No interaction if we are not persistent!
1415 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1417 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1419 ucbhelper::cancelCommandExecution(
1420 ucb::IOErrorCode_CANT_READ
,
1422 m_eState
== PERSISTENT
1424 : uno::Reference
< ucb::XCommandEnvironment
>(),
1425 "Got no data stream!",
1432 uno::Sequence
< sal_Int8
> aBuffer
;
1436 sal_Int32 nRead
= xIn
->readSomeBytes( aBuffer
, 65536 );
1439 aBuffer
.realloc( nRead
);
1440 xOut
->writeBytes( aBuffer
);
1443 xOut
->closeOutput();
1445 catch ( io::NotConnectedException
const & )
1447 // closeOutput, readSomeBytes, writeBytes
1449 catch ( io::BufferSizeExceededException
const & )
1451 // closeOutput, readSomeBytes, writeBytes
1453 catch ( io::IOException
const & )
1455 // closeOutput, readSomeBytes, writeBytes
1460 uno::Reference
< io::XActiveDataSink
> xDataSink(
1461 rArg
.Sink
, uno::UNO_QUERY
);
1462 if ( xDataSink
.is() )
1464 // PULL: wait for client read
1466 // May throw CommandFailedException, DocumentPasswordRequest!
1467 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1470 // No interaction if we are not persistent!
1471 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1473 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1475 ucbhelper::cancelCommandExecution(
1476 ucb::IOErrorCode_CANT_READ
,
1478 m_eState
== PERSISTENT
1481 ucb::XCommandEnvironment
>(),
1482 "Got no data stream!",
1488 xDataSink
->setInputStream( xIn
);
1492 ucbhelper::cancelCommandExecution(
1494 ucb::UnsupportedDataSinkException(
1496 static_cast< cppu::OWeakObject
* >( this ),
1509 void Content::insert( const uno::Reference
< io::XInputStream
>& xData
,
1510 sal_Int32 nNameClashResolve
,
1511 const uno::Reference
<
1512 ucb::XCommandEnvironment
> & xEnv
)
1514 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1516 ContentType eType
= m_aProps
.getType();
1518 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1519 "insert command only supported by streams and folders!" );
1521 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
1523 #if OSL_DEBUG_LEVEL > 0
1524 if ( eType
== STREAM
)
1526 Uri
aParentUri( aUri
.getParentUri() );
1527 OSL_ENSURE( !aParentUri
.isDocument(),
1528 "insert command not supported by streams that are direct "
1529 "children of document root!" );
1533 // Check, if all required properties were set.
1534 if ( eType
== FOLDER
)
1538 if ( m_aProps
.getTitle().isEmpty() )
1539 m_aProps
.setTitle( aUri
.getDecodedName() );
1547 ucbhelper::cancelCommandExecution(
1548 uno::Any( ucb::MissingInputStreamException(
1550 static_cast< cppu::OWeakObject
* >( this ) ) ),
1557 if ( m_aProps
.getTitle().isEmpty() )
1558 m_aProps
.setTitle( aUri
.getDecodedName() );
1561 Uri
aNewUri( aUri
.getParentUri() + m_aProps
.getTitle() );
1563 // Handle possible name clash...
1564 switch ( nNameClashResolve
)
1567 case ucb::NameClash::ERROR
:
1568 if ( hasData( aNewUri
) )
1570 ucbhelper::cancelCommandExecution(
1571 uno::Any( ucb::NameClashException(
1573 static_cast< cppu::OWeakObject
* >( this ),
1574 task::InteractionClassification_ERROR
,
1575 m_aProps
.getTitle() ) ),
1581 // replace (possibly) existing object.
1582 case ucb::NameClash::OVERWRITE
:
1585 // "invent" a new valid title.
1586 case ucb::NameClash::RENAME
:
1587 if ( hasData( aNewUri
) )
1593 aNewUri
.setUri( aNewUri
.getUri() + "_" + OUString::number(++nTry
) );
1595 while ( hasData( aNewUri
) && ( nTry
< 1000 ) );
1599 ucbhelper::cancelCommandExecution(
1601 ucb::UnsupportedNameClashException(
1602 "Unable to resolve name clash!",
1603 static_cast< cppu::OWeakObject
* >( this ),
1604 nNameClashResolve
) ),
1610 m_aProps
.setTitle( m_aProps
.getTitle() + "_" + OUString::number( ++nTry
) );
1615 case ucb::NameClash::KEEP
: // deprecated
1616 case ucb::NameClash::ASK
:
1618 if ( hasData( aNewUri
) )
1620 ucbhelper::cancelCommandExecution(
1622 ucb::UnsupportedNameClashException(
1624 static_cast< cppu::OWeakObject
* >( this ),
1625 nNameClashResolve
) ),
1632 // Identifier changed?
1633 bool bNewId
= ( aUri
!= aNewUri
);
1638 = new ::ucbhelper::ContentIdentifier( aNewUri
.getUri() );
1641 if ( !storeData( xData
, xEnv
) )
1643 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1645 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1647 ucbhelper::cancelCommandExecution(
1648 ucb::IOErrorCode_CANT_WRITE
,
1651 "Cannot store persistent data!",
1656 m_eState
= PERSISTENT
;
1660 //loadData( m_pProvider, m_aUri, m_aProps );
1668 void Content::destroy( bool bDeletePhysical
,
1669 const uno::Reference
<
1670 ucb::XCommandEnvironment
> & xEnv
)
1672 // @@@ take care about bDeletePhysical -> trashcan support
1674 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1676 ContentType eType
= m_aProps
.getType();
1678 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1679 "delete command only supported by streams and folders!" );
1681 uno::Reference
< ucb::XContent
> xThis
= this;
1684 if ( m_eState
!= PERSISTENT
)
1686 ucbhelper::cancelCommandExecution(
1687 uno::Any( ucb::UnsupportedCommandException(
1689 static_cast< cppu::OWeakObject
* >( this ) ) ),
1699 if ( eType
== FOLDER
)
1701 // Process instantiated children...
1703 ContentRefList aChildren
;
1704 queryChildren( aChildren
);
1706 for ( auto& rChild
: aChildren
)
1708 rChild
->destroy( bDeletePhysical
, xEnv
);
1714 void Content::notifyDocumentClosed()
1716 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1720 // @@@ anything else to reset or such?
1722 // callback follows!
1725 // Propagate destruction to content event listeners
1726 // Remove this from provider's content list.
1731 uno::Reference
< ucb::XContent
>
1732 Content::queryChildContent( std::u16string_view rRelativeChildUri
)
1734 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1736 const OUString aMyId
= getIdentifier()->getContentIdentifier();
1737 OUStringBuffer
aBuf( aMyId
);
1738 if ( !aMyId
.endsWith("/") )
1740 if ( !o3tl::starts_with(rRelativeChildUri
, u
"/") )
1741 aBuf
.append( rRelativeChildUri
);
1743 aBuf
.append( rRelativeChildUri
.substr(1) );
1745 uno::Reference
< ucb::XContentIdentifier
> xChildId
1746 = new ::ucbhelper::ContentIdentifier( aBuf
.makeStringAndClear() );
1748 uno::Reference
< ucb::XContent
> xChild
;
1751 xChild
= m_pProvider
->queryContent( xChildId
);
1753 catch ( ucb::IllegalIdentifierException
const & )
1758 OSL_ENSURE( xChild
.is(),
1759 "Content::queryChildContent - unable to create child content!" );
1764 void Content::notifyChildRemoved( std::u16string_view rRelativeChildUri
)
1766 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1768 // Ugly! Need to create child content object, just to fill event properly.
1769 uno::Reference
< ucb::XContent
> xChild
1770 = queryChildContent( rRelativeChildUri
);
1775 // callback follows!
1778 // Notify "REMOVED" event.
1779 ucb::ContentEvent
aEvt(
1780 static_cast< cppu::OWeakObject
* >( this ),
1781 ucb::ContentAction::REMOVED
,
1784 notifyContentEvent( aEvt
);
1788 void Content::notifyChildInserted( std::u16string_view rRelativeChildUri
)
1790 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1792 // Ugly! Need to create child content object, just to fill event properly.
1793 uno::Reference
< ucb::XContent
> xChild
1794 = queryChildContent( rRelativeChildUri
);
1799 // callback follows!
1802 // Notify "INSERTED" event.
1803 ucb::ContentEvent
aEvt(
1804 static_cast< cppu::OWeakObject
* >( this ),
1805 ucb::ContentAction::INSERTED
,
1808 notifyContentEvent( aEvt
);
1812 void Content::transfer(
1813 const ucb::TransferInfo
& rInfo
,
1814 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1816 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1819 if ( m_eState
!= PERSISTENT
)
1821 ucbhelper::cancelCommandExecution(
1822 uno::Any( ucb::UnsupportedCommandException(
1824 static_cast< cppu::OWeakObject
* >( this ) ) ),
1829 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
1831 if ( rInfo
.SourceURL
.getLength() < TDOC_URL_SCHEME_LENGTH
+ 2 )
1833 // Invalid length (to short).
1834 ucbhelper::cancelCommandExecution(
1835 uno::Any( ucb::InteractiveBadTransferURLException(
1837 static_cast< cppu::OWeakObject
* >( this ) ) ),
1843 = rInfo
.SourceURL
.copy( 0, TDOC_URL_SCHEME_LENGTH
+ 2 )
1844 .toAsciiLowerCase();
1845 if ( aScheme
!= TDOC_URL_SCHEME
":/" )
1848 ucbhelper::cancelCommandExecution(
1849 uno::Any( ucb::InteractiveBadTransferURLException(
1851 static_cast< cppu::OWeakObject
* >( this ) ) ),
1856 // Does source URI describe a tdoc folder or stream?
1857 Uri
aSourceUri( rInfo
.SourceURL
);
1858 if ( !aSourceUri
.isValid() )
1860 ucbhelper::cancelCommandExecution(
1861 uno::Any( lang::IllegalArgumentException(
1862 "Invalid source URI! Syntax!",
1863 static_cast< cppu::OWeakObject
* >( this ),
1869 if ( aSourceUri
.isRoot() || aSourceUri
.isDocument() )
1871 ucbhelper::cancelCommandExecution(
1872 uno::Any( lang::IllegalArgumentException(
1873 "Invalid source URI! Must describe a folder or stream!",
1874 static_cast< cppu::OWeakObject
* >( this ),
1880 // Is source not a parent of me / not me?
1881 OUString aId
= m_xIdentifier
->getContentIdentifier();
1882 sal_Int32 nPos
= aId
.lastIndexOf( '/' );
1883 if ( nPos
!= ( aId
.getLength() - 1 ) )
1885 // No trailing slash found. Append.
1889 if ( rInfo
.SourceURL
.getLength() <= aId
.getLength() )
1891 if ( aId
.startsWith( rInfo
.SourceURL
) )
1893 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1895 {"Uri", uno::Any(rInfo
.SourceURL
)}
1897 ucbhelper::cancelCommandExecution(
1898 ucb::IOErrorCode_RECURSIVE
,
1901 "Target is equal to or is a child of source!",
1907 if ( m_aProps
.getType() == DOCUMENT
)
1911 uno::Reference
< embed::XStorage
> xStorage
1912 = m_pProvider
->queryStorage(
1913 aSourceUri
.getParentUri(), READ_WRITE_NOCREATE
);
1914 if ( xStorage
.is() )
1918 if ( xStorage
->isStreamElement( aSourceUri
.getDecodedName() ) )
1920 ucbhelper::cancelCommandExecution(
1921 uno::Any( lang::IllegalArgumentException(
1922 "Invalid source URI! "
1923 "Streams cannot be created as "
1924 "children of document root!",
1925 static_cast< cppu::OWeakObject
* >(
1933 catch ( container::NoSuchElementException
const & )
1937 catch ( lang::IllegalArgumentException
const & )
1941 catch ( embed::InvalidStorageException
const & )
1949 ucbhelper::cancelCommandExecution(
1950 uno::Any( lang::IllegalArgumentException(
1951 "Invalid source URI! Unable to determine source type!",
1952 static_cast< cppu::OWeakObject
* >( this ),
1963 OUString
aNewName( !rInfo
.NewTitle
.isEmpty()
1965 : aSourceUri
.getDecodedName() );
1967 if ( !copyData( aSourceUri
, aNewName
) )
1969 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1971 {"Uri", uno::Any(rInfo
.SourceURL
)}
1973 ucbhelper::cancelCommandExecution(
1974 ucb::IOErrorCode_CANT_WRITE
,
1977 "Cannot copy data!",
1983 // Copy own and all children's Additional Core Properties.
1986 OUString aTargetUri
= m_xIdentifier
->getContentIdentifier();
1987 if ( ( aTargetUri
.lastIndexOf( '/' ) + 1 ) != aTargetUri
.getLength() )
1990 if ( !rInfo
.NewTitle
.isEmpty() )
1991 aTargetUri
+= ::ucb_impl::urihelper::encodeSegment( rInfo
.NewTitle
);
1993 aTargetUri
+= aSourceUri
.getName();
1995 if ( !copyAdditionalPropertySet( aSourceUri
.getUri(), aTargetUri
) )
1997 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1999 {"Uri", uno::Any(rInfo
.SourceURL
)}
2001 ucbhelper::cancelCommandExecution(
2002 ucb::IOErrorCode_CANT_WRITE
,
2005 "Cannot copy additional properties!",
2011 // Propagate new content.
2014 rtl::Reference
< Content
> xTarget
;
2017 uno::Reference
< ucb::XContentIdentifier
> xTargetId
2018 = new ::ucbhelper::ContentIdentifier( aTargetUri
);
2020 // Note: The static cast is okay here, because its sure that
2021 // m_xProvider is always the WebDAVContentProvider.
2022 xTarget
= static_cast< Content
* >(
2023 m_pProvider
->queryContent( xTargetId
).get() );
2026 catch ( ucb::IllegalIdentifierException
const & )
2031 if ( !xTarget
.is() )
2033 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2035 {"Uri", uno::Any(aTargetUri
)}
2037 ucbhelper::cancelCommandExecution(
2038 ucb::IOErrorCode_CANT_READ
,
2041 "Cannot instantiate target object!",
2046 // Announce transferred content in its new folder.
2047 xTarget
->inserted();
2050 // Remove source, if requested
2053 if ( !rInfo
.MoveData
)
2056 rtl::Reference
< Content
> xSource
;
2059 uno::Reference
< ucb::XContentIdentifier
>
2060 xSourceId
= new ::ucbhelper::ContentIdentifier( rInfo
.SourceURL
);
2062 // Note: The static cast is okay here, because its sure
2063 // that m_xProvider is always the ContentProvider.
2064 xSource
= static_cast< Content
* >(
2065 m_xProvider
->queryContent( xSourceId
).get() );
2067 catch ( ucb::IllegalIdentifierException
const & )
2072 if ( !xSource
.is() )
2074 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2076 {"Uri", uno::Any(rInfo
.SourceURL
)}
2078 ucbhelper::cancelCommandExecution(
2079 ucb::IOErrorCode_CANT_READ
,
2082 "Cannot instantiate target object!",
2087 // Propagate destruction (recursively).
2088 xSource
->destroy( true, xEnv
);
2090 // Remove all persistent data of source and its children.
2091 if ( !xSource
->removeData() )
2093 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2095 {"Uri", uno::Any(rInfo
.SourceURL
)}
2097 ucbhelper::cancelCommandExecution(
2098 ucb::IOErrorCode_CANT_WRITE
,
2101 "Cannot remove persistent data of source object!",
2106 // Remove own and all children's Additional Core Properties.
2107 if ( xSource
->removeAdditionalPropertySet() )
2110 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2112 {"Uri", uno::Any(rInfo
.SourceURL
)}
2114 ucbhelper::cancelCommandExecution(
2115 ucb::IOErrorCode_CANT_WRITE
,
2118 "Cannot remove additional properties of source object!",
2125 bool Content::hasData( ContentProvider
const * pProvider
, const Uri
& rUri
)
2127 if ( rUri
.isRoot() )
2129 return true; // root has no storage
2131 else if ( rUri
.isDocument() )
2133 uno::Reference
< embed::XStorage
> xStorage
2134 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2135 return xStorage
.is();
2141 // Ask parent storage. In case that rUri describes a stream,
2142 // ContentProvider::queryStorage( rUri ) would return null.
2144 uno::Reference
< embed::XStorage
> xStorage
2145 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2147 if ( !xStorage
.is() )
2150 return xStorage
->hasByName( rUri
.getDecodedName() );
2156 bool Content::loadData( ContentProvider
const * pProvider
,
2158 ContentProperties
& rProps
)
2160 if ( rUri
.isRoot() ) // root has no storage, but can always be created
2163 = ContentProperties(
2164 ROOT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2166 else if ( rUri
.isDocument() ) // document must have storage
2168 uno::Reference
< embed::XStorage
> xStorage
2169 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2171 if ( !xStorage
.is() )
2175 = ContentProperties(
2176 DOCUMENT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2178 else // stream or folder; stream has no storage; folder has storage
2180 uno::Reference
< embed::XStorage
> xStorage
2181 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2183 if ( !xStorage
.is() )
2186 // Check whether exists at all, is stream or folder
2189 // return: true -> folder
2190 // return: false -> stream
2191 // NoSuchElementException -> neither folder nor stream
2193 = xStorage
->isStorageElement( rUri
.getDecodedName() );
2196 = ContentProperties(
2197 bIsFolder
? FOLDER
: STREAM
,
2198 pProvider
->queryStorageTitle( rUri
.getUri() ) );
2200 catch ( container::NoSuchElementException
const & )
2202 // there is no element with such name
2203 //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2206 catch ( lang::IllegalArgumentException
const & )
2208 // an illegal argument is provided
2209 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2212 catch ( embed::InvalidStorageException
const & )
2214 // this storage is in invalid state for any reason
2215 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2223 bool Content::storeData( const uno::Reference
< io::XInputStream
>& xData
,
2224 const uno::Reference
<
2225 ucb::XCommandEnvironment
>& xEnv
)
2227 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2229 ContentType eType
= m_aProps
.getType();
2230 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2232 OSL_FAIL( "storeData not supported by root and documents!" );
2236 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2238 if ( eType
== FOLDER
)
2240 uno::Reference
< embed::XStorage
> xStorage
2241 = m_pProvider
->queryStorage( aUri
.getUri(), READ_WRITE_CREATE
);
2243 if ( !xStorage
.is() )
2246 uno::Reference
< beans::XPropertySet
> xPropSet(
2247 xStorage
, uno::UNO_QUERY
);
2248 OSL_ENSURE( xPropSet
.is(),
2249 "Content::storeData - Got no XPropertySet interface!" );
2250 if ( !xPropSet
.is() )
2255 // According to MBA, if no mediatype is set, folder and all
2256 // its contents will be lost on save of the document!!!
2257 xPropSet
->setPropertyValue(
2260 OUString( // @@@ better mediatype
2261 "application/binary" ) ) );
2263 catch ( beans::UnknownPropertyException
const & )
2265 OSL_FAIL( "Property MediaType not supported!" );
2268 catch ( beans::PropertyVetoException
const & )
2270 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2273 catch ( lang::IllegalArgumentException
const & )
2275 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2278 catch ( lang::WrappedTargetException
const & )
2280 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2284 if ( !commitStorage( xStorage
) )
2287 else if ( eType
== STREAM
)
2291 // Important: Parent storage and output stream must be kept alive until
2292 // changes have been committed!
2293 uno::Reference
< embed::XStorage
> xStorage
2294 = m_pProvider
->queryStorage(
2295 aUri
.getParentUri(), READ_WRITE_CREATE
);
2296 uno::Reference
< io::XOutputStream
> xOut
;
2298 if ( !xStorage
.is() )
2303 // May throw CommandFailedException, DocumentPasswordRequest!
2304 xOut
= getTruncatedOutputStream( xEnv
);
2306 OSL_ENSURE( xOut
.is(), "No target data stream!" );
2310 uno::Sequence
< sal_Int8
> aBuffer
;
2313 sal_Int32 nRead
= xData
->readSomeBytes( aBuffer
, 65536 );
2316 aBuffer
.realloc( nRead
);
2317 xOut
->writeBytes( aBuffer
);
2320 closeOutputStream( xOut
);
2322 catch ( io::NotConnectedException
const & )
2324 // readSomeBytes, writeBytes
2325 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2326 closeOutputStream( xOut
);
2329 catch ( io::BufferSizeExceededException
const & )
2331 // readSomeBytes, writeBytes
2332 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2333 closeOutputStream( xOut
);
2336 catch ( io::IOException
const & )
2338 // readSomeBytes, writeBytes
2339 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2340 closeOutputStream( xOut
);
2345 closeOutputStream( xOut
);
2351 if ( !commitStorage( xStorage
) )
2356 OSL_FAIL( "Unknown content type!" );
2363 void Content::renameData(
2364 const uno::Reference
< ucb::XContentIdentifier
>& xOldId
,
2365 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
2367 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2369 ContentType eType
= m_aProps
.getType();
2370 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2372 OSL_FAIL( "renameData not supported by root and documents!" );
2376 Uri
aOldUri( xOldId
->getContentIdentifier() );
2377 uno::Reference
< embed::XStorage
> xStorage
2378 = m_pProvider
->queryStorage(
2379 aOldUri
.getParentUri(), READ_WRITE_NOCREATE
);
2381 if ( !xStorage
.is() )
2386 Uri
aNewUri( xNewId
->getContentIdentifier() );
2387 xStorage
->renameElement(
2388 aOldUri
.getDecodedName(), aNewUri
.getDecodedName() );
2390 catch ( embed::InvalidStorageException
const & )
2392 // this storage is in invalid state for any reason
2393 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2396 catch ( lang::IllegalArgumentException
const & )
2398 // an illegal argument is provided
2399 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2402 catch ( container::NoSuchElementException
const & )
2404 // there is no element with old name in this storage
2405 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2408 catch ( container::ElementExistException
const & )
2410 // an element with new name already exists in this storage
2411 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2414 catch ( io::IOException
const & )
2416 // in case of io errors during renaming
2417 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2420 catch ( embed::StorageWrappedTargetException
const & )
2422 // wraps other exceptions
2423 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2427 commitStorage( xStorage
);
2431 bool Content::removeData()
2433 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2435 ContentType eType
= m_aProps
.getType();
2436 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2438 OSL_FAIL( "removeData not supported by root and documents!" );
2442 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2443 uno::Reference
< embed::XStorage
> xStorage
2444 = m_pProvider
->queryStorage(
2445 aUri
.getParentUri(), READ_WRITE_NOCREATE
);
2447 if ( !xStorage
.is() )
2452 xStorage
->removeElement( aUri
.getDecodedName() );
2454 catch ( embed::InvalidStorageException
const & )
2456 // this storage is in invalid state for any reason
2457 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2460 catch ( lang::IllegalArgumentException
const & )
2462 // an illegal argument is provided
2463 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2466 catch ( container::NoSuchElementException
const & )
2468 // there is no element with this name in this storage
2469 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2472 catch ( io::IOException
const & )
2474 // in case of io errors during renaming
2475 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2478 catch ( embed::StorageWrappedTargetException
const & )
2480 // wraps other exceptions
2481 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2485 return commitStorage( xStorage
);
2489 bool Content::copyData( const Uri
& rSourceUri
, const OUString
& rNewName
)
2491 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2493 ContentType eType
= m_aProps
.getType();
2494 if ( ( eType
== ROOT
) || ( eType
== STREAM
) )
2496 OSL_FAIL( "copyData not supported by root and streams!" );
2500 Uri
aDestUri( m_xIdentifier
->getContentIdentifier() );
2501 uno::Reference
< embed::XStorage
> xDestStorage
2502 = m_pProvider
->queryStorage( aDestUri
.getUri(), READ_WRITE_NOCREATE
);
2504 if ( !xDestStorage
.is() )
2507 uno::Reference
< embed::XStorage
> xSourceStorage
2508 = m_pProvider
->queryStorage( rSourceUri
.getParentUri(), READ
);
2510 if ( !xSourceStorage
.is() )
2515 xSourceStorage
->copyElementTo( rSourceUri
.getDecodedName(),
2519 catch ( embed::InvalidStorageException
const & )
2521 // this storage is in invalid state for any reason
2522 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2525 catch ( lang::IllegalArgumentException
const & )
2527 // an illegal argument is provided
2528 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2531 catch ( container::NoSuchElementException
const & )
2533 // there is no element with this name in this storage
2534 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2537 catch ( container::ElementExistException
const & )
2539 // there is no element with this name in this storage
2540 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2543 catch ( io::IOException
const & )
2545 // in case of io errors during renaming
2546 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2549 catch ( embed::StorageWrappedTargetException
const & )
2551 // wraps other exceptions
2552 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2556 return commitStorage( xDestStorage
);
2561 bool Content::commitStorage( const uno::Reference
< embed::XStorage
> & xStorage
)
2564 uno::Reference
< embed::XTransactedObject
> xTO( xStorage
, uno::UNO_QUERY
);
2566 OSL_ENSURE( xTO
.is(),
2567 "Required interface css.embed.XTransactedObject missing!" );
2572 catch ( io::IOException
const & )
2574 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2577 catch ( lang::WrappedTargetException
const & )
2579 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2588 bool Content::closeOutputStream(
2589 const uno::Reference
< io::XOutputStream
> & xOut
)
2595 xOut
->closeOutput();
2598 catch ( io::NotConnectedException
const & )
2600 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2602 catch ( io::BufferSizeExceededException
const & )
2604 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2606 catch ( io::IOException
const & )
2608 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2614 /// @throws ucb::CommandFailedException
2615 /// @throws task::DocumentPasswordRequest
2616 static OUString
obtainPassword(
2617 const OUString
& rName
,
2618 task::PasswordRequestMode eMode
,
2619 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2621 rtl::Reference
< DocumentPasswordRequest
> xRequest
2622 = new DocumentPasswordRequest( eMode
, rName
);
2626 uno::Reference
< task::XInteractionHandler
> xIH
2627 = xEnv
->getInteractionHandler();
2630 xIH
->handle( xRequest
);
2632 rtl::Reference
< ucbhelper::InteractionContinuation
> xSelection
2633 = xRequest
->getSelection();
2635 if ( xSelection
.is() )
2637 // Handler handled the request.
2638 uno::Reference
< task::XInteractionAbort
> xAbort(
2639 xSelection
.get(), uno::UNO_QUERY
);
2642 throw ucb::CommandFailedException(
2643 "Abort requested by Interaction Handler.",
2644 uno::Reference
< uno::XInterface
>(),
2645 xRequest
->getRequest() );
2648 uno::Reference
< task::XInteractionPassword
> xPassword(
2649 xSelection
.get(), uno::UNO_QUERY
);
2650 if ( xPassword
.is() )
2652 return xPassword
->getPassword();
2655 // Unknown selection. Should never happen.
2656 throw ucb::CommandFailedException(
2657 "Interaction Handler selected unknown continuation!",
2658 uno::Reference
< uno::XInterface
>(),
2659 xRequest
->getRequest() );
2664 // No IH or IH did not handle exception.
2665 task::DocumentPasswordRequest aRequest
;
2666 xRequest
->getRequest() >>= aRequest
;
2671 uno::Reference
< io::XInputStream
> Content::getInputStream(
2672 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2676 bool bPasswordRequested
= false;
2679 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2681 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2682 "Content::getInputStream - content is no stream!" );
2684 aUri
= Uri( m_xIdentifier
->getContentIdentifier() ).getUri();
2691 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2692 return m_pProvider
->queryInputStream( aUri
, aPassword
);
2694 catch ( packages::WrongPasswordException
const & )
2696 // Obtain (new) password.
2698 = obtainPassword( aUri
, /* @@@ find better title */
2700 ? task::PasswordRequestMode_PASSWORD_REENTER
2701 : task::PasswordRequestMode_PASSWORD_ENTER
,
2703 bPasswordRequested
= true;
2708 /// @throws ucb::CommandFailedException
2709 /// @throws task::DocumentPasswordRequest
2710 /// @throws uno::RuntimeException
2711 static uno::Reference
< io::XOutputStream
> lcl_getTruncatedOutputStream(
2712 const OUString
& rUri
,
2713 ContentProvider
const * pProvider
,
2714 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2717 bool bPasswordRequested
= false;
2722 return pProvider
->queryOutputStream(
2723 rUri
, aPassword
, true /* truncate */ );
2725 catch ( packages::WrongPasswordException
const & )
2727 // Obtain (new) password.
2729 = obtainPassword( rUri
, /* @@@ find better title */
2731 ? task::PasswordRequestMode_PASSWORD_REENTER
2732 : task::PasswordRequestMode_PASSWORD_ENTER
,
2734 bPasswordRequested
= true;
2740 uno::Reference
< io::XOutputStream
> Content::getTruncatedOutputStream(
2741 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2743 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2744 "Content::getTruncatedOutputStream - content is no stream!" );
2746 return lcl_getTruncatedOutputStream(
2747 Uri( m_xIdentifier
->getContentIdentifier() ).getUri(),
2753 uno::Reference
< io::XStream
> Content::getStream(
2754 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2756 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2758 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2759 "Content::getStream - content is no stream!" );
2761 OUString
aUri( Uri( m_xIdentifier
->getContentIdentifier() ).getUri() );
2763 bool bPasswordRequested
= false;
2768 return m_pProvider
->queryStream(
2769 aUri
, aPassword
, false /* no truncate */ );
2771 catch ( packages::WrongPasswordException
const & )
2773 // Obtain (new) password.
2775 = obtainPassword( aUri
, /* @@@ find better title */
2777 ? task::PasswordRequestMode_PASSWORD_REENTER
2778 : task::PasswordRequestMode_PASSWORD_ENTER
,
2780 bPasswordRequested
= true;
2786 // ContentProperties Implementation.
2789 uno::Sequence
< ucb::ContentInfo
>
2790 ContentProperties::getCreatableContentsInfo() const
2792 if ( isContentCreator() )
2794 uno::Sequence
< beans::Property
> aProps( 1 );
2795 aProps
.getArray()[ 0 ] = beans::Property(
2798 cppu::UnoType
<OUString
>::get(),
2799 beans::PropertyAttribute::BOUND
);
2801 if ( getType() == DOCUMENT
)
2803 // streams cannot be created as direct children of document root
2804 uno::Sequence
< ucb::ContentInfo
> aSeq( 1 );
2807 aSeq
.getArray()[ 0 ].Type
= TDOC_FOLDER_CONTENT_TYPE
;
2808 aSeq
.getArray()[ 0 ].Attributes
= ucb::ContentInfoAttribute::KIND_FOLDER
;
2809 aSeq
.getArray()[ 0 ].Properties
= aProps
;
2815 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
2818 aSeq
.getArray()[ 0 ].Type
= TDOC_FOLDER_CONTENT_TYPE
;
2819 aSeq
.getArray()[ 0 ].Attributes
2820 = ucb::ContentInfoAttribute::KIND_FOLDER
;
2821 aSeq
.getArray()[ 0 ].Properties
= aProps
;
2824 aSeq
.getArray()[ 1 ].Type
= TDOC_STREAM_CONTENT_TYPE
;
2825 aSeq
.getArray()[ 1 ].Attributes
2826 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
2827 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
2828 aSeq
.getArray()[ 1 ].Properties
= aProps
;
2835 OSL_FAIL( "getCreatableContentsInfo called on non-contentcreator "
2838 return uno::Sequence
< ucb::ContentInfo
>( 0 );
2843 bool ContentProperties::isContentCreator() const
2845 return ( getType() == FOLDER
) || ( getType() == DOCUMENT
);
2848 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */