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 u
"com.sun.star.comp.ucb.TransientDocumentsContent"_ustr
;
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 u
"Wrong argument type!"_ustr
,
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 u
"Wrong argument type!"_ustr
,
369 if ( !aProperties
.hasElements() )
371 ucbhelper::cancelCommandExecution(
372 uno::Any( lang::IllegalArgumentException(
373 u
"No properties!"_ustr
,
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 u
"Wrong argument type!"_ustr
,
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 u
"insert command only supported by "
430 "folders and streams!"_ustr
,
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 u
"insert command not supported by "
445 "streams that are direct children "
446 "of document root!"_ustr
,
453 ucb::InsertCommandArgument aArg
;
454 if ( !( aCommand
.Argument
>>= aArg
) )
456 ucbhelper::cancelCommandExecution(
457 uno::Any( lang::IllegalArgumentException(
458 u
"Wrong argument type!"_ustr
,
465 sal_Int32 nNameClash
= aArg
.ReplaceExisting
466 ? ucb::NameClash::OVERWRITE
467 : ucb::NameClash::ERROR
;
468 insert( aArg
.Data
, nNameClash
, Environment
);
470 else if ( aCommand
.Name
== "delete" )
473 // delete ( Supported by folders and streams only )
477 osl::MutexGuard
aGuard( m_aMutex
);
479 ContentType eType
= m_aProps
.getType();
480 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
482 ucbhelper::cancelCommandExecution(
483 uno::Any( ucb::UnsupportedCommandException(
484 u
"delete command only supported by "
485 "folders and streams!"_ustr
,
492 bool bDeletePhysical
= false;
493 aCommand
.Argument
>>= bDeletePhysical
;
494 destroy( bDeletePhysical
, Environment
);
496 // Remove own and all children's persistent data.
499 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
501 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
503 ucbhelper::cancelCommandExecution(
504 ucb::IOErrorCode_CANT_WRITE
,
507 u
"Cannot remove persistent data!"_ustr
,
512 // Remove own and all children's Additional Core Properties.
513 removeAdditionalPropertySet();
515 else if ( aCommand
.Name
== "transfer" )
518 // transfer ( Supported by document and folders only )
522 osl::MutexGuard
aGuard( m_aMutex
);
524 ContentType eType
= m_aProps
.getType();
525 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
527 ucbhelper::cancelCommandExecution(
528 uno::Any( ucb::UnsupportedCommandException(
529 u
"transfer command only supported "
530 "by folders and documents!"_ustr
,
537 ucb::TransferInfo aInfo
;
538 if ( !( aCommand
.Argument
>>= aInfo
) )
540 OSL_FAIL( "Wrong argument type!" );
541 ucbhelper::cancelCommandExecution(
542 uno::Any( lang::IllegalArgumentException(
543 u
"Wrong argument type!"_ustr
,
550 transfer( aInfo
, Environment
);
552 else if ( aCommand
.Name
== "createNewContent" )
555 // createNewContent ( Supported by document and folders only )
559 osl::MutexGuard
aGuard( m_aMutex
);
561 ContentType eType
= m_aProps
.getType();
562 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
564 ucbhelper::cancelCommandExecution(
565 uno::Any( ucb::UnsupportedCommandException(
566 u
"createNewContent command only "
567 "supported by folders and "
575 ucb::ContentInfo aInfo
;
576 if ( !( aCommand
.Argument
>>= aInfo
) )
578 OSL_FAIL( "Wrong argument type!" );
579 ucbhelper::cancelCommandExecution(
580 uno::Any( lang::IllegalArgumentException(
581 u
"Wrong argument type!"_ustr
,
588 aRet
<<= createNewContent( aInfo
);
593 // Unsupported command
596 ucbhelper::cancelCommandExecution(
597 uno::Any( ucb::UnsupportedCommandException(
609 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
614 // XContentCreator methods.
618 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
619 Content::queryCreatableContentsInfo()
621 return m_aProps
.getCreatableContentsInfo();
626 uno::Reference
< ucb::XContent
> SAL_CALL
627 Content::createNewContent( const ucb::ContentInfo
& Info
)
629 if ( m_aProps
.isContentCreator() )
631 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
633 if ( Info
.Type
.isEmpty() )
634 return uno::Reference
< ucb::XContent
>();
636 bool bCreateFolder
= Info
.Type
== TDOC_FOLDER_CONTENT_TYPE
;
638 // streams cannot be created as direct children of document root
639 if ( !bCreateFolder
&& ( m_aProps
.getType() == DOCUMENT
) )
641 OSL_FAIL( "Content::createNewContent - streams cannot be "
642 "created as direct children of document root!" );
643 return uno::Reference
< ucb::XContent
>();
645 if ( !bCreateFolder
&& Info
.Type
!= TDOC_STREAM_CONTENT_TYPE
)
647 OSL_FAIL( "Content::createNewContent - unsupported type!" );
648 return uno::Reference
< ucb::XContent
>();
651 OUString aURL
= m_xIdentifier
->getContentIdentifier();
653 OSL_ENSURE( !aURL
.isEmpty(),
654 "Content::createNewContent - empty identifier!" );
656 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
660 aURL
+= "New_Folder";
662 aURL
+= "New_Stream";
664 uno::Reference
< ucb::XContentIdentifier
> xId
665 = new ::ucbhelper::ContentIdentifier( aURL
);
667 return create( m_xContext
, m_pProvider
, xId
, Info
);
671 OSL_FAIL( "createNewContent called on non-contentcreator object!" );
672 return uno::Reference
< ucb::XContent
>();
678 OUString
Content::getParentURL()
680 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
681 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
682 return aUri
.getParentUri();
686 uno::Reference
< ucb::XContentIdentifier
>
687 Content::makeNewIdentifier( const OUString
& rTitle
)
689 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
691 // Assemble new content identifier...
692 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
693 OUString aNewURL
= aUri
.getParentUri() + ::ucb_impl::urihelper::encodeSegment( rTitle
);
696 uno::Reference
< ucb::XContentIdentifier
>(
697 new ::ucbhelper::ContentIdentifier( aNewURL
) );
701 void Content::queryChildren( ContentRefList
& rChildren
)
703 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
705 // Only folders (root, documents, folders) have children.
706 if ( !m_aProps
.getIsFolder() )
709 // Obtain a list with a snapshot of all currently instantiated contents
710 // from provider and extract the contents which are direct children
713 ::ucbhelper::ContentRefList aAllContents
;
714 m_xProvider
->queryExistingContents( aAllContents
);
716 OUString aURL
= m_xIdentifier
->getContentIdentifier();
717 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
719 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
721 // No trailing slash found. Append.
725 sal_Int32 nLen
= aURL
.getLength();
727 for ( const auto& rContent
: aAllContents
)
729 ::ucbhelper::ContentImplHelperRef xChild
= rContent
;
731 = xChild
->getIdentifier()->getContentIdentifier();
733 // Is aURL a prefix of aChildURL?
734 if ( ( aChildURL
.getLength() > nLen
) &&
735 ( aChildURL
.startsWith( aURL
) ) )
737 sal_Int32 nPos
= aChildURL
.indexOf( '/', nLen
);
739 if ( ( nPos
== -1 ) ||
740 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
742 // No further slashes / only a final slash. It's a child!
743 rChildren
.emplace_back(
744 static_cast< Content
* >( xChild
.get() ) );
751 bool Content::exchangeIdentity(
752 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
757 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
759 uno::Reference
< ucb::XContent
> xThis
= this;
761 // Already persistent?
762 if ( m_eState
!= PERSISTENT
)
764 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
768 // Only folders and streams can be renamed -> exchange identity.
769 ContentType eType
= m_aProps
.getType();
770 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
772 OSL_FAIL( "Content::exchangeIdentity - "
773 "Not supported by root or document!" );
777 // Exchange own identity.
779 // Fail, if a content with given id already exists.
780 if ( !hasData( Uri( xNewId
->getContentIdentifier() ) ) )
782 OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
785 if ( exchange( xNewId
) )
787 if ( eType
== FOLDER
)
789 // Process instantiated children...
791 ContentRefList aChildren
;
792 queryChildren( aChildren
);
794 for ( const auto& rChild
: aChildren
)
796 ContentRef xChild
= rChild
;
798 // Create new content identifier for the child...
799 uno::Reference
< ucb::XContentIdentifier
> xOldChildId
800 = xChild
->getIdentifier();
801 OUString aOldChildURL
802 = xOldChildId
->getContentIdentifier();
803 OUString aNewChildURL
804 = aOldChildURL
.replaceAt(
807 xNewId
->getContentIdentifier() );
808 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
809 = new ::ucbhelper::ContentIdentifier( aNewChildURL
);
811 if ( !xChild
->exchangeIdentity( xNewChildId
) )
819 OSL_FAIL( "Content::exchangeIdentity - "
820 "Panic! Cannot exchange identity!" );
826 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
827 const uno::Reference
< uno::XComponentContext
>& rxContext
,
828 const uno::Sequence
< beans::Property
>& rProperties
,
829 ContentProvider
* pProvider
,
830 const OUString
& rContentId
)
832 ContentProperties aData
;
833 if ( loadData( pProvider
, Uri(rContentId
), aData
) )
835 return getPropertyValues(
836 rxContext
, rProperties
, aData
, pProvider
, rContentId
);
840 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
841 = new ::ucbhelper::PropertyValueSet( rxContext
);
843 for ( const beans::Property
& rProp
: rProperties
)
844 xRow
->appendVoid( rProp
);
852 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
853 const uno::Reference
< uno::XComponentContext
>& rxContext
,
854 const uno::Sequence
< beans::Property
>& rProperties
,
855 const ContentProperties
& rData
,
856 ContentProvider
* pProvider
,
857 const OUString
& rContentId
)
859 // Note: Empty sequence means "get values of all supported properties".
861 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
862 = new ::ucbhelper::PropertyValueSet( rxContext
);
864 if ( rProperties
.hasElements() )
866 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
867 bool bTriedToGetAdditionalPropSet
= false;
869 for ( const beans::Property
& rProp
: rProperties
)
871 // Process Core properties.
873 if ( rProp
.Name
== "ContentType" )
875 xRow
->appendString ( rProp
, rData
.getContentType() );
877 else if ( rProp
.Name
== "Title" )
879 xRow
->appendString ( rProp
, rData
.getTitle() );
881 else if ( rProp
.Name
== "IsDocument" )
883 xRow
->appendBoolean( rProp
, rData
.getIsDocument() );
885 else if ( rProp
.Name
== "IsFolder" )
887 xRow
->appendBoolean( rProp
, rData
.getIsFolder() );
889 else if ( rProp
.Name
== "CreatableContentsInfo" )
892 rProp
, uno::Any( rData
.getCreatableContentsInfo() ) );
894 else if ( rProp
.Name
== "DateModified" )
896 // DateModified is only supported by streams.
897 ContentType eType
= rData
.getType();
898 if ( eType
== STREAM
)
903 pProvider
->queryStreamDateModified( rContentId
) ) );
906 xRow
->appendVoid( rProp
);
908 else if ( rProp
.Name
== "Storage" )
910 // Storage is only supported by folders.
911 ContentType eType
= rData
.getType();
912 if ( eType
== FOLDER
)
916 pProvider
->queryStorageClone( rContentId
) ) );
918 xRow
->appendVoid( rProp
);
920 else if ( rProp
.Name
== "DocumentModel" )
922 // DocumentModel is only supported by documents.
923 ContentType eType
= rData
.getType();
924 if ( eType
== DOCUMENT
)
928 pProvider
->queryDocumentModel( rContentId
) ) );
930 xRow
->appendVoid( rProp
);
934 // Not a Core Property! Maybe it's an Additional Core Property?!
936 if ( !bTriedToGetAdditionalPropSet
&& !xAdditionalPropSet
.is() )
939 pProvider
->getAdditionalPropertySet( rContentId
,
941 bTriedToGetAdditionalPropSet
= true;
944 if ( xAdditionalPropSet
.is() )
946 if ( !xRow
->appendPropertySetValue(
950 // Append empty entry.
951 xRow
->appendVoid( rProp
);
956 // Append empty entry.
957 xRow
->appendVoid( rProp
);
964 // Append all Core Properties.
966 beans::Property( u
"ContentType"_ustr
,
968 cppu::UnoType
<OUString
>::get(),
969 beans::PropertyAttribute::BOUND
970 | beans::PropertyAttribute::READONLY
),
971 rData
.getContentType() );
973 ContentType eType
= rData
.getType();
976 beans::Property( u
"Title"_ustr
,
978 cppu::UnoType
<OUString
>::get(),
979 // Title is read-only for root and documents.
980 beans::PropertyAttribute::BOUND
|
981 ( ( eType
== ROOT
) || ( eType
== DOCUMENT
)
982 ? beans::PropertyAttribute::READONLY
986 beans::Property( u
"IsDocument"_ustr
,
988 cppu::UnoType
<bool>::get(),
989 beans::PropertyAttribute::BOUND
990 | beans::PropertyAttribute::READONLY
),
991 rData
.getIsDocument() );
993 beans::Property( u
"IsFolder"_ustr
,
995 cppu::UnoType
<bool>::get(),
996 beans::PropertyAttribute::BOUND
997 | beans::PropertyAttribute::READONLY
),
998 rData
.getIsFolder() );
1001 u
"CreatableContentsInfo"_ustr
,
1003 cppu::UnoType
<uno::Sequence
< ucb::ContentInfo
>>::get(),
1004 beans::PropertyAttribute::BOUND
1005 | beans::PropertyAttribute::READONLY
),
1006 uno::Any( rData
.getCreatableContentsInfo() ) );
1008 // DateModified is only supported by streams.
1009 if ( eType
== STREAM
)
1012 beans::Property( u
"DateModified"_ustr
,
1014 cppu::UnoType
<css::util::DateTime
>::get(),
1015 beans::PropertyAttribute::BOUND
1016 | beans::PropertyAttribute::READONLY
),
1017 uno::Any( pProvider
->queryStreamDateModified( rContentId
) ) );
1020 // Storage is only supported by folders.
1021 if ( eType
== FOLDER
)
1023 beans::Property( u
"Storage"_ustr
,
1025 cppu::UnoType
<embed::XStorage
>::get(),
1026 beans::PropertyAttribute::BOUND
1027 | beans::PropertyAttribute::READONLY
),
1028 uno::Any( pProvider
->queryStorageClone( rContentId
) ) );
1030 // DocumentModel is only supported by documents.
1031 if ( eType
== DOCUMENT
)
1033 beans::Property( u
"DocumentModel"_ustr
,
1035 cppu::UnoType
<frame::XModel
>::get(),
1036 beans::PropertyAttribute::BOUND
1037 | beans::PropertyAttribute::READONLY
),
1039 pProvider
->queryDocumentModel( rContentId
) ) );
1041 // Append all Additional Core Properties.
1043 uno::Reference
< beans::XPropertySet
> xSet
=
1044 pProvider
->getAdditionalPropertySet( rContentId
, false );
1045 xRow
->appendPropertySet( xSet
);
1052 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1053 const uno::Sequence
< beans::Property
>& rProperties
)
1055 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1056 return getPropertyValues( m_xContext
,
1060 m_xIdentifier
->getContentIdentifier() );
1064 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1065 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1066 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1068 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1070 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1071 auto aRetRange
= asNonConstRange(aRet
);
1072 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1073 sal_Int32 nChanged
= 0;
1075 beans::PropertyChangeEvent aEvent
;
1076 aEvent
.Source
= getXWeak();
1077 aEvent
.Further
= false;
1078 aEvent
.PropertyHandle
= -1;
1080 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1081 sal_Int32 nCount
= rValues
.getLength();
1083 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1084 bool bTriedToGetAdditionalPropSet
= false;
1086 bool bExchange
= false;
1088 sal_Int32 nTitlePos
= -1;
1090 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1092 const beans::PropertyValue
& rValue
= pValues
[ n
];
1094 if ( rValue
.Name
== "ContentType" )
1096 // Read-only property!
1097 aRetRange
[ n
] <<= lang::IllegalAccessException(
1098 u
"Property is read-only!"_ustr
,
1101 else if ( rValue
.Name
== "IsDocument" )
1103 // Read-only property!
1104 aRetRange
[ n
] <<= lang::IllegalAccessException(
1105 u
"Property is read-only!"_ustr
,
1108 else if ( rValue
.Name
== "IsFolder" )
1110 // Read-only property!
1111 aRetRange
[ n
] <<= lang::IllegalAccessException(
1112 u
"Property is read-only!"_ustr
,
1115 else if ( rValue
.Name
== "CreatableContentsInfo" )
1117 // Read-only property!
1118 aRetRange
[ n
] <<= lang::IllegalAccessException(
1119 u
"Property is read-only!"_ustr
,
1122 else if ( rValue
.Name
== "Title" )
1124 // Title is read-only for root and documents.
1125 ContentType eType
= m_aProps
.getType();
1126 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
1128 aRetRange
[ n
] <<= lang::IllegalAccessException(
1129 u
"Property is read-only!"_ustr
,
1135 if ( rValue
.Value
>>= aNewValue
)
1138 if ( !aNewValue
.isEmpty() )
1140 if ( aNewValue
!= m_aProps
.getTitle() )
1142 // modified title -> modified URL -> exchange !
1143 if ( m_eState
== PERSISTENT
)
1146 aOldTitle
= m_aProps
.getTitle();
1147 m_aProps
.setTitle( aNewValue
);
1149 // property change event will be sent later...
1151 // remember position within sequence of values
1152 // (for error handling).
1158 aRetRange
[ n
] <<= lang::IllegalArgumentException(
1159 u
"Empty Title not allowed!"_ustr
,
1166 aRetRange
[ n
] <<= beans::IllegalTypeException(
1167 u
"Title Property value has wrong type!"_ustr
,
1172 else if ( rValue
.Name
== "Storage" )
1174 ContentType eType
= m_aProps
.getType();
1175 if ( eType
== FOLDER
)
1177 aRetRange
[ n
] <<= lang::IllegalAccessException(
1178 u
"Property is read-only!"_ustr
,
1183 // Storage is only supported by folders.
1184 aRetRange
[ n
] <<= beans::UnknownPropertyException(
1185 u
"Storage property only supported by folders"_ustr
,
1189 else if ( rValue
.Name
== "DocumentModel" )
1191 ContentType eType
= m_aProps
.getType();
1192 if ( eType
== DOCUMENT
)
1194 aRetRange
[ n
] <<= lang::IllegalAccessException(
1195 u
"Property is read-only!"_ustr
,
1200 // Storage is only supported by folders.
1201 aRetRange
[ n
] <<= beans::UnknownPropertyException(
1202 u
"DocumentModel property only supported by documents"_ustr
,
1208 // Not a Core Property! Maybe it's an Additional Core Property?!
1210 if ( !bTriedToGetAdditionalPropSet
&& !xAdditionalPropSet
.is() )
1212 xAdditionalPropSet
= getAdditionalPropertySet( false );
1213 bTriedToGetAdditionalPropSet
= true;
1216 if ( xAdditionalPropSet
.is() )
1220 uno::Any aOldValue
= xAdditionalPropSet
->getPropertyValue(
1222 if ( aOldValue
!= rValue
.Value
)
1224 xAdditionalPropSet
->setPropertyValue(
1225 rValue
.Name
, rValue
.Value
);
1227 aEvent
.PropertyName
= rValue
.Name
;
1228 aEvent
.OldValue
= std::move(aOldValue
);
1229 aEvent
.NewValue
= rValue
.Value
;
1231 aChanges
.getArray()[ nChanged
] = aEvent
;
1235 catch ( beans::UnknownPropertyException
const & e
)
1237 aRetRange
[ n
] <<= e
;
1239 catch ( lang::WrappedTargetException
const & e
)
1241 aRetRange
[ n
] <<= e
;
1243 catch ( beans::PropertyVetoException
const & e
)
1245 aRetRange
[ n
] <<= e
;
1247 catch ( lang::IllegalArgumentException
const & e
)
1249 aRetRange
[ n
] <<= e
;
1254 aRetRange
[ n
] <<= uno::Exception(
1255 u
"No property set for storing the value!"_ustr
,
1263 uno::Reference
< ucb::XContentIdentifier
> xOldId
1265 uno::Reference
< ucb::XContentIdentifier
> xNewId
1266 = makeNewIdentifier( m_aProps
.getTitle() );
1269 if ( exchangeIdentity( xNewId
) )
1271 // Adapt persistent data.
1272 renameData( xOldId
, xNewId
);
1274 // Adapt Additional Core Properties.
1275 renameAdditionalPropertySet( xOldId
->getContentIdentifier(),
1276 xNewId
->getContentIdentifier() );
1281 m_aProps
.setTitle( aOldTitle
);
1285 aRetRange
[ nTitlePos
] <<= uno::Exception(
1286 u
"Exchange failed!"_ustr
,
1291 if ( !aOldTitle
.isEmpty() )
1293 aEvent
.PropertyName
= "Title";
1294 aEvent
.OldValue
<<= aOldTitle
;
1295 aEvent
.NewValue
<<= m_aProps
.getTitle();
1297 aChanges
.getArray()[ nChanged
] = std::move(aEvent
);
1303 // Save changes, if content was already made persistent.
1304 if ( !bExchange
&& ( m_eState
== PERSISTENT
) )
1306 if ( !storeData( uno::Reference
< io::XInputStream
>(), xEnv
) )
1308 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1310 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1312 ucbhelper::cancelCommandExecution(
1313 ucb::IOErrorCode_CANT_WRITE
,
1316 u
"Cannot store persistent data!"_ustr
,
1322 aChanges
.realloc( nChanged
);
1325 notifyPropertiesChange( aChanges
);
1332 uno::Any
Content::open(
1333 const ucb::OpenCommandArgument2
& rArg
,
1334 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1336 if ( rArg
.Mode
== ucb::OpenMode::ALL
||
1337 rArg
.Mode
== ucb::OpenMode::FOLDERS
||
1338 rArg
.Mode
== ucb::OpenMode::DOCUMENTS
)
1341 // open command for a folder content
1344 uno::Reference
< ucb::XDynamicResultSet
> xSet
1345 = new DynamicResultSet( m_xContext
, this, rArg
);
1346 return uno::Any( xSet
);
1351 // open command for a document content
1354 if ( ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
1355 ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
1357 // Currently(?) unsupported.
1358 ucbhelper::cancelCommandExecution(
1359 uno::Any( ucb::UnsupportedOpenModeException(
1362 sal_Int16( rArg
.Mode
) ) ),
1367 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1369 uno::Reference
< io::XActiveDataStreamer
> xDataStreamer(
1370 rArg
.Sink
, uno::UNO_QUERY
);
1371 if ( xDataStreamer
.is() )
1373 // May throw CommandFailedException, DocumentPasswordRequest!
1374 uno::Reference
< io::XStream
> xStream
= getStream( xEnv
);
1375 if ( !xStream
.is() )
1377 // No interaction if we are not persistent!
1378 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1380 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1382 ucbhelper::cancelCommandExecution(
1383 ucb::IOErrorCode_CANT_READ
,
1385 m_eState
== PERSISTENT
1387 : uno::Reference
< ucb::XCommandEnvironment
>(),
1388 u
"Got no data stream!"_ustr
,
1394 xDataStreamer
->setStream( xStream
);
1398 uno::Reference
< io::XOutputStream
> xOut( rArg
.Sink
, uno::UNO_QUERY
);
1401 // PUSH: write data into xOut
1403 // May throw CommandFailedException, DocumentPasswordRequest!
1404 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1407 // No interaction if we are not persistent!
1408 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1410 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1412 ucbhelper::cancelCommandExecution(
1413 ucb::IOErrorCode_CANT_READ
,
1415 m_eState
== PERSISTENT
1417 : uno::Reference
< ucb::XCommandEnvironment
>(),
1418 u
"Got no data stream!"_ustr
,
1425 uno::Sequence
< sal_Int8
> aBuffer
;
1429 sal_Int32 nRead
= xIn
->readSomeBytes( aBuffer
, 65536 );
1432 aBuffer
.realloc( nRead
);
1433 xOut
->writeBytes( aBuffer
);
1436 xOut
->closeOutput();
1438 catch ( io::NotConnectedException
const & )
1440 // closeOutput, readSomeBytes, writeBytes
1442 catch ( io::BufferSizeExceededException
const & )
1444 // closeOutput, readSomeBytes, writeBytes
1446 catch ( io::IOException
const & )
1448 // closeOutput, readSomeBytes, writeBytes
1453 uno::Reference
< io::XActiveDataSink
> xDataSink(
1454 rArg
.Sink
, uno::UNO_QUERY
);
1455 if ( xDataSink
.is() )
1457 // PULL: wait for client read
1459 // May throw CommandFailedException, DocumentPasswordRequest!
1460 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1463 // No interaction if we are not persistent!
1464 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1466 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1468 ucbhelper::cancelCommandExecution(
1469 ucb::IOErrorCode_CANT_READ
,
1471 m_eState
== PERSISTENT
1474 ucb::XCommandEnvironment
>(),
1475 u
"Got no data stream!"_ustr
,
1481 xDataSink
->setInputStream( xIn
);
1485 ucbhelper::cancelCommandExecution(
1487 ucb::UnsupportedDataSinkException(
1502 void Content::insert( const uno::Reference
< io::XInputStream
>& xData
,
1503 sal_Int32 nNameClashResolve
,
1504 const uno::Reference
<
1505 ucb::XCommandEnvironment
> & xEnv
)
1507 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1509 ContentType eType
= m_aProps
.getType();
1511 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1512 "insert command only supported by streams and folders!" );
1514 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
1516 #if OSL_DEBUG_LEVEL > 0
1517 if ( eType
== STREAM
)
1519 Uri
aParentUri( aUri
.getParentUri() );
1520 OSL_ENSURE( !aParentUri
.isDocument(),
1521 "insert command not supported by streams that are direct "
1522 "children of document root!" );
1526 // Check, if all required properties were set.
1527 if ( eType
== FOLDER
)
1531 if ( m_aProps
.getTitle().isEmpty() )
1532 m_aProps
.setTitle( aUri
.getDecodedName() );
1540 ucbhelper::cancelCommandExecution(
1541 uno::Any( ucb::MissingInputStreamException(
1550 if ( m_aProps
.getTitle().isEmpty() )
1551 m_aProps
.setTitle( aUri
.getDecodedName() );
1554 Uri
aNewUri( aUri
.getParentUri() + m_aProps
.getTitle() );
1556 // Handle possible name clash...
1557 switch ( nNameClashResolve
)
1560 case ucb::NameClash::ERROR
:
1561 if ( hasData( aNewUri
) )
1563 ucbhelper::cancelCommandExecution(
1564 uno::Any( ucb::NameClashException(
1567 task::InteractionClassification_ERROR
,
1568 m_aProps
.getTitle() ) ),
1574 // replace (possibly) existing object.
1575 case ucb::NameClash::OVERWRITE
:
1578 // "invent" a new valid title.
1579 case ucb::NameClash::RENAME
:
1580 if ( hasData( aNewUri
) )
1586 aNewUri
.setUri( aNewUri
.getUri() + "_" + OUString::number(++nTry
) );
1588 while ( hasData( aNewUri
) && ( nTry
< 1000 ) );
1592 ucbhelper::cancelCommandExecution(
1594 ucb::UnsupportedNameClashException(
1595 u
"Unable to resolve name clash!"_ustr
,
1597 nNameClashResolve
) ),
1603 m_aProps
.setTitle( m_aProps
.getTitle() + "_" + OUString::number( ++nTry
) );
1608 case ucb::NameClash::KEEP
: // deprecated
1609 case ucb::NameClash::ASK
:
1611 if ( hasData( aNewUri
) )
1613 ucbhelper::cancelCommandExecution(
1615 ucb::UnsupportedNameClashException(
1618 nNameClashResolve
) ),
1625 // Identifier changed?
1626 bool bNewId
= ( aUri
!= aNewUri
);
1631 = new ::ucbhelper::ContentIdentifier( aNewUri
.getUri() );
1634 if ( !storeData( xData
, xEnv
) )
1636 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1638 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1640 ucbhelper::cancelCommandExecution(
1641 ucb::IOErrorCode_CANT_WRITE
,
1644 u
"Cannot store persistent data!"_ustr
,
1649 m_eState
= PERSISTENT
;
1653 //loadData( m_pProvider, m_aUri, m_aProps );
1661 void Content::destroy( bool bDeletePhysical
,
1662 const uno::Reference
<
1663 ucb::XCommandEnvironment
> & xEnv
)
1665 // @@@ take care about bDeletePhysical -> trashcan support
1667 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1669 ContentType eType
= m_aProps
.getType();
1671 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1672 "delete command only supported by streams and folders!" );
1674 uno::Reference
< ucb::XContent
> xThis
= this;
1677 if ( m_eState
!= PERSISTENT
)
1679 ucbhelper::cancelCommandExecution(
1680 uno::Any( ucb::UnsupportedCommandException(
1681 u
"Not persistent!"_ustr
,
1692 if ( eType
== FOLDER
)
1694 // Process instantiated children...
1696 ContentRefList aChildren
;
1697 queryChildren( aChildren
);
1699 for ( auto& rChild
: aChildren
)
1701 rChild
->destroy( bDeletePhysical
, xEnv
);
1707 void Content::notifyDocumentClosed()
1709 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1713 // @@@ anything else to reset or such?
1715 // callback follows!
1718 // Propagate destruction to content event listeners
1719 // Remove this from provider's content list.
1724 uno::Reference
< ucb::XContent
>
1725 Content::queryChildContent( std::u16string_view rRelativeChildUri
)
1727 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1729 const OUString aMyId
= getIdentifier()->getContentIdentifier();
1730 OUStringBuffer
aBuf( aMyId
);
1731 if ( !aMyId
.endsWith("/") )
1733 if ( !o3tl::starts_with(rRelativeChildUri
, u
"/") )
1734 aBuf
.append( rRelativeChildUri
);
1736 aBuf
.append( rRelativeChildUri
.substr(1) );
1738 uno::Reference
< ucb::XContentIdentifier
> xChildId
1739 = new ::ucbhelper::ContentIdentifier( aBuf
.makeStringAndClear() );
1741 uno::Reference
< ucb::XContent
> xChild
;
1744 xChild
= m_pProvider
->queryContent( xChildId
);
1746 catch ( ucb::IllegalIdentifierException
const & )
1751 OSL_ENSURE( xChild
.is(),
1752 "Content::queryChildContent - unable to create child content!" );
1757 void Content::notifyChildRemoved( std::u16string_view rRelativeChildUri
)
1759 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1761 // Ugly! Need to create child content object, just to fill event properly.
1762 uno::Reference
< ucb::XContent
> xChild
1763 = queryChildContent( rRelativeChildUri
);
1768 // callback follows!
1771 // Notify "REMOVED" event.
1772 ucb::ContentEvent
aEvt(
1774 ucb::ContentAction::REMOVED
,
1777 notifyContentEvent( aEvt
);
1781 void Content::notifyChildInserted( std::u16string_view rRelativeChildUri
)
1783 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1785 // Ugly! Need to create child content object, just to fill event properly.
1786 uno::Reference
< ucb::XContent
> xChild
1787 = queryChildContent( rRelativeChildUri
);
1792 // callback follows!
1795 // Notify "INSERTED" event.
1796 ucb::ContentEvent
aEvt(
1798 ucb::ContentAction::INSERTED
,
1801 notifyContentEvent( aEvt
);
1805 void Content::transfer(
1806 const ucb::TransferInfo
& rInfo
,
1807 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1809 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1812 if ( m_eState
!= PERSISTENT
)
1814 ucbhelper::cancelCommandExecution(
1815 uno::Any( ucb::UnsupportedCommandException(
1816 u
"Not persistent!"_ustr
,
1822 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
1824 if ( rInfo
.SourceURL
.getLength() < TDOC_URL_SCHEME_LENGTH
+ 2 )
1826 // Invalid length (to short).
1827 ucbhelper::cancelCommandExecution(
1828 uno::Any( ucb::InteractiveBadTransferURLException(
1836 = rInfo
.SourceURL
.copy( 0, TDOC_URL_SCHEME_LENGTH
+ 2 )
1837 .toAsciiLowerCase();
1838 if ( aScheme
!= TDOC_URL_SCHEME
":/" )
1841 ucbhelper::cancelCommandExecution(
1842 uno::Any( ucb::InteractiveBadTransferURLException(
1849 // Does source URI describe a tdoc folder or stream?
1850 Uri
aSourceUri( rInfo
.SourceURL
);
1851 if ( !aSourceUri
.isValid() )
1853 ucbhelper::cancelCommandExecution(
1854 uno::Any( lang::IllegalArgumentException(
1855 u
"Invalid source URI! Syntax!"_ustr
,
1862 if ( aSourceUri
.isRoot() || aSourceUri
.isDocument() )
1864 ucbhelper::cancelCommandExecution(
1865 uno::Any( lang::IllegalArgumentException(
1866 u
"Invalid source URI! Must describe a folder or stream!"_ustr
,
1873 // Is source not a parent of me / not me?
1874 OUString aId
= m_xIdentifier
->getContentIdentifier();
1875 sal_Int32 nPos
= aId
.lastIndexOf( '/' );
1876 if ( nPos
!= ( aId
.getLength() - 1 ) )
1878 // No trailing slash found. Append.
1882 if ( rInfo
.SourceURL
.getLength() <= aId
.getLength() )
1884 if ( aId
.startsWith( rInfo
.SourceURL
) )
1886 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1888 {"Uri", uno::Any(rInfo
.SourceURL
)}
1890 ucbhelper::cancelCommandExecution(
1891 ucb::IOErrorCode_RECURSIVE
,
1894 u
"Target is equal to or is a child of source!"_ustr
,
1900 if ( m_aProps
.getType() == DOCUMENT
)
1904 uno::Reference
< embed::XStorage
> xStorage
1905 = m_pProvider
->queryStorage(
1906 aSourceUri
.getParentUri(), READ_WRITE_NOCREATE
);
1907 if ( xStorage
.is() )
1911 if ( xStorage
->isStreamElement( aSourceUri
.getDecodedName() ) )
1913 ucbhelper::cancelCommandExecution(
1914 uno::Any( lang::IllegalArgumentException(
1915 u
"Invalid source URI! "
1916 "Streams cannot be created as "
1917 "children of document root!"_ustr
,
1925 catch ( container::NoSuchElementException
const & )
1929 catch ( lang::IllegalArgumentException
const & )
1933 catch ( embed::InvalidStorageException
const & )
1941 ucbhelper::cancelCommandExecution(
1942 uno::Any( lang::IllegalArgumentException(
1943 u
"Invalid source URI! Unable to determine source type!"_ustr
,
1955 OUString
aNewName( !rInfo
.NewTitle
.isEmpty()
1957 : aSourceUri
.getDecodedName() );
1959 if ( !copyData( aSourceUri
, aNewName
) )
1961 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1963 {"Uri", uno::Any(rInfo
.SourceURL
)}
1965 ucbhelper::cancelCommandExecution(
1966 ucb::IOErrorCode_CANT_WRITE
,
1969 u
"Cannot copy data!"_ustr
,
1975 // Copy own and all children's Additional Core Properties.
1978 OUString aTargetUri
= m_xIdentifier
->getContentIdentifier();
1979 if ( ( aTargetUri
.lastIndexOf( '/' ) + 1 ) != aTargetUri
.getLength() )
1982 if ( !rInfo
.NewTitle
.isEmpty() )
1983 aTargetUri
+= ::ucb_impl::urihelper::encodeSegment( rInfo
.NewTitle
);
1985 aTargetUri
+= aSourceUri
.getName();
1987 if ( !copyAdditionalPropertySet( aSourceUri
.getUri(), aTargetUri
) )
1989 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1991 {"Uri", uno::Any(rInfo
.SourceURL
)}
1993 ucbhelper::cancelCommandExecution(
1994 ucb::IOErrorCode_CANT_WRITE
,
1997 u
"Cannot copy additional properties!"_ustr
,
2003 // Propagate new content.
2006 rtl::Reference
< Content
> xTarget
;
2009 uno::Reference
< ucb::XContentIdentifier
> xTargetId
2010 = new ::ucbhelper::ContentIdentifier( aTargetUri
);
2012 // Note: The static cast is okay here, because its sure that
2013 // m_xProvider is always the WebDAVContentProvider.
2014 xTarget
= static_cast< Content
* >(
2015 m_pProvider
->queryContent( xTargetId
).get() );
2018 catch ( ucb::IllegalIdentifierException
const & )
2023 if ( !xTarget
.is() )
2025 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2027 {"Uri", uno::Any(aTargetUri
)}
2029 ucbhelper::cancelCommandExecution(
2030 ucb::IOErrorCode_CANT_READ
,
2033 u
"Cannot instantiate target object!"_ustr
,
2038 // Announce transferred content in its new folder.
2039 xTarget
->inserted();
2042 // Remove source, if requested
2045 if ( !rInfo
.MoveData
)
2048 rtl::Reference
< Content
> xSource
;
2051 uno::Reference
< ucb::XContentIdentifier
>
2052 xSourceId
= new ::ucbhelper::ContentIdentifier( rInfo
.SourceURL
);
2054 // Note: The static cast is okay here, because its sure
2055 // that m_xProvider is always the ContentProvider.
2056 xSource
= static_cast< Content
* >(
2057 m_xProvider
->queryContent( xSourceId
).get() );
2059 catch ( ucb::IllegalIdentifierException
const & )
2064 if ( !xSource
.is() )
2066 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2068 {"Uri", uno::Any(rInfo
.SourceURL
)}
2070 ucbhelper::cancelCommandExecution(
2071 ucb::IOErrorCode_CANT_READ
,
2074 u
"Cannot instantiate target object!"_ustr
,
2079 // Propagate destruction (recursively).
2080 xSource
->destroy( true, xEnv
);
2082 // Remove all persistent data of source and its children.
2083 if ( !xSource
->removeData() )
2085 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2087 {"Uri", uno::Any(rInfo
.SourceURL
)}
2089 ucbhelper::cancelCommandExecution(
2090 ucb::IOErrorCode_CANT_WRITE
,
2093 u
"Cannot remove persistent data of source object!"_ustr
,
2098 // Remove own and all children's Additional Core Properties.
2099 if ( xSource
->removeAdditionalPropertySet() )
2102 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2104 {"Uri", uno::Any(rInfo
.SourceURL
)}
2106 ucbhelper::cancelCommandExecution(
2107 ucb::IOErrorCode_CANT_WRITE
,
2110 u
"Cannot remove additional properties of source object!"_ustr
,
2117 bool Content::hasData( ContentProvider
const * pProvider
, const Uri
& rUri
)
2119 if ( rUri
.isRoot() )
2121 return true; // root has no storage
2123 else if ( rUri
.isDocument() )
2125 uno::Reference
< embed::XStorage
> xStorage
2126 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2127 return xStorage
.is();
2133 // Ask parent storage. In case that rUri describes a stream,
2134 // ContentProvider::queryStorage( rUri ) would return null.
2136 uno::Reference
< embed::XStorage
> xStorage
2137 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2139 if ( !xStorage
.is() )
2142 return xStorage
->hasByName( rUri
.getDecodedName() );
2148 bool Content::loadData( ContentProvider
const * pProvider
,
2150 ContentProperties
& rProps
)
2152 if ( rUri
.isRoot() ) // root has no storage, but can always be created
2155 = ContentProperties(
2156 ROOT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2158 else if ( rUri
.isDocument() ) // document must have storage
2160 uno::Reference
< embed::XStorage
> xStorage
2161 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2163 if ( !xStorage
.is() )
2167 = ContentProperties(
2168 DOCUMENT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2170 else // stream or folder; stream has no storage; folder has storage
2172 uno::Reference
< embed::XStorage
> xStorage
2173 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2175 if ( !xStorage
.is() )
2178 // Check whether exists at all, is stream or folder
2181 // return: true -> folder
2182 // return: false -> stream
2183 // NoSuchElementException -> neither folder nor stream
2185 = xStorage
->isStorageElement( rUri
.getDecodedName() );
2188 = ContentProperties(
2189 bIsFolder
? FOLDER
: STREAM
,
2190 pProvider
->queryStorageTitle( rUri
.getUri() ) );
2192 catch ( container::NoSuchElementException
const & )
2194 // there is no element with such name
2195 //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2198 catch ( lang::IllegalArgumentException
const & )
2200 // an illegal argument is provided
2201 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2204 catch ( embed::InvalidStorageException
const & )
2206 // this storage is in invalid state for any reason
2207 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2215 bool Content::storeData( const uno::Reference
< io::XInputStream
>& xData
,
2216 const uno::Reference
<
2217 ucb::XCommandEnvironment
>& xEnv
)
2219 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2221 ContentType eType
= m_aProps
.getType();
2222 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2224 OSL_FAIL( "storeData not supported by root and documents!" );
2228 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2230 if ( eType
== FOLDER
)
2232 uno::Reference
< embed::XStorage
> xStorage
2233 = m_pProvider
->queryStorage( aUri
.getUri(), READ_WRITE_CREATE
);
2235 if ( !xStorage
.is() )
2238 uno::Reference
< beans::XPropertySet
> xPropSet(
2239 xStorage
, uno::UNO_QUERY
);
2240 OSL_ENSURE( xPropSet
.is(),
2241 "Content::storeData - Got no XPropertySet interface!" );
2242 if ( !xPropSet
.is() )
2247 // According to MBA, if no mediatype is set, folder and all
2248 // its contents will be lost on save of the document!!!
2249 xPropSet
->setPropertyValue(
2252 u
"application/binary"_ustr
) );
2254 catch ( beans::UnknownPropertyException
const & )
2256 OSL_FAIL( "Property MediaType not supported!" );
2259 catch ( beans::PropertyVetoException
const & )
2261 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2264 catch ( lang::IllegalArgumentException
const & )
2266 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2269 catch ( lang::WrappedTargetException
const & )
2271 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2275 if ( !commitStorage( xStorage
) )
2278 else if ( eType
== STREAM
)
2282 // Important: Parent storage and output stream must be kept alive until
2283 // changes have been committed!
2284 uno::Reference
< embed::XStorage
> xStorage
2285 = m_pProvider
->queryStorage(
2286 aUri
.getParentUri(), READ_WRITE_CREATE
);
2287 uno::Reference
< io::XOutputStream
> xOut
;
2289 if ( !xStorage
.is() )
2294 // May throw CommandFailedException, DocumentPasswordRequest!
2295 xOut
= getTruncatedOutputStream( xEnv
);
2297 OSL_ENSURE( xOut
.is(), "No target data stream!" );
2301 uno::Sequence
< sal_Int8
> aBuffer
;
2304 sal_Int32 nRead
= xData
->readSomeBytes( aBuffer
, 65536 );
2307 aBuffer
.realloc( nRead
);
2308 xOut
->writeBytes( aBuffer
);
2311 closeOutputStream( xOut
);
2313 catch ( io::NotConnectedException
const & )
2315 // readSomeBytes, writeBytes
2316 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2317 closeOutputStream( xOut
);
2320 catch ( io::BufferSizeExceededException
const & )
2322 // readSomeBytes, writeBytes
2323 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2324 closeOutputStream( xOut
);
2327 catch ( io::IOException
const & )
2329 // readSomeBytes, writeBytes
2330 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2331 closeOutputStream( xOut
);
2336 closeOutputStream( xOut
);
2342 if ( !commitStorage( xStorage
) )
2347 OSL_FAIL( "Unknown content type!" );
2354 void Content::renameData(
2355 const uno::Reference
< ucb::XContentIdentifier
>& xOldId
,
2356 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
2358 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2360 ContentType eType
= m_aProps
.getType();
2361 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2363 OSL_FAIL( "renameData not supported by root and documents!" );
2367 Uri
aOldUri( xOldId
->getContentIdentifier() );
2368 uno::Reference
< embed::XStorage
> xStorage
2369 = m_pProvider
->queryStorage(
2370 aOldUri
.getParentUri(), READ_WRITE_NOCREATE
);
2372 if ( !xStorage
.is() )
2377 Uri
aNewUri( xNewId
->getContentIdentifier() );
2378 xStorage
->renameElement(
2379 aOldUri
.getDecodedName(), aNewUri
.getDecodedName() );
2381 catch ( embed::InvalidStorageException
const & )
2383 // this storage is in invalid state for any reason
2384 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2387 catch ( lang::IllegalArgumentException
const & )
2389 // an illegal argument is provided
2390 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2393 catch ( container::NoSuchElementException
const & )
2395 // there is no element with old name in this storage
2396 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2399 catch ( container::ElementExistException
const & )
2401 // an element with new name already exists in this storage
2402 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2405 catch ( io::IOException
const & )
2407 // in case of io errors during renaming
2408 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2411 catch ( embed::StorageWrappedTargetException
const & )
2413 // wraps other exceptions
2414 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2418 commitStorage( xStorage
);
2422 bool Content::removeData()
2424 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2426 ContentType eType
= m_aProps
.getType();
2427 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2429 OSL_FAIL( "removeData not supported by root and documents!" );
2433 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2434 uno::Reference
< embed::XStorage
> xStorage
2435 = m_pProvider
->queryStorage(
2436 aUri
.getParentUri(), READ_WRITE_NOCREATE
);
2438 if ( !xStorage
.is() )
2443 xStorage
->removeElement( aUri
.getDecodedName() );
2445 catch ( embed::InvalidStorageException
const & )
2447 // this storage is in invalid state for any reason
2448 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2451 catch ( lang::IllegalArgumentException
const & )
2453 // an illegal argument is provided
2454 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2457 catch ( container::NoSuchElementException
const & )
2459 // there is no element with this name in this storage
2460 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2463 catch ( io::IOException
const & )
2465 // in case of io errors during renaming
2466 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2469 catch ( embed::StorageWrappedTargetException
const & )
2471 // wraps other exceptions
2472 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2476 return commitStorage( xStorage
);
2480 bool Content::copyData( const Uri
& rSourceUri
, const OUString
& rNewName
)
2482 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2484 ContentType eType
= m_aProps
.getType();
2485 if ( ( eType
== ROOT
) || ( eType
== STREAM
) )
2487 OSL_FAIL( "copyData not supported by root and streams!" );
2491 Uri
aDestUri( m_xIdentifier
->getContentIdentifier() );
2492 uno::Reference
< embed::XStorage
> xDestStorage
2493 = m_pProvider
->queryStorage( aDestUri
.getUri(), READ_WRITE_NOCREATE
);
2495 if ( !xDestStorage
.is() )
2498 uno::Reference
< embed::XStorage
> xSourceStorage
2499 = m_pProvider
->queryStorage( rSourceUri
.getParentUri(), READ
);
2501 if ( !xSourceStorage
.is() )
2506 xSourceStorage
->copyElementTo( rSourceUri
.getDecodedName(),
2510 catch ( embed::InvalidStorageException
const & )
2512 // this storage is in invalid state for any reason
2513 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2516 catch ( lang::IllegalArgumentException
const & )
2518 // an illegal argument is provided
2519 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2522 catch ( container::NoSuchElementException
const & )
2524 // there is no element with this name in this storage
2525 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2528 catch ( container::ElementExistException
const & )
2530 // there is no element with this name in this storage
2531 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2534 catch ( io::IOException
const & )
2536 // in case of io errors during renaming
2537 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2540 catch ( embed::StorageWrappedTargetException
const & )
2542 // wraps other exceptions
2543 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2547 return commitStorage( xDestStorage
);
2552 bool Content::commitStorage( const uno::Reference
< embed::XStorage
> & xStorage
)
2555 uno::Reference
< embed::XTransactedObject
> xTO( xStorage
, uno::UNO_QUERY
);
2557 OSL_ENSURE( xTO
.is(),
2558 "Required interface css.embed.XTransactedObject missing!" );
2563 catch ( io::IOException
const & )
2565 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2568 catch ( lang::WrappedTargetException
const & )
2570 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2579 bool Content::closeOutputStream(
2580 const uno::Reference
< io::XOutputStream
> & xOut
)
2586 xOut
->closeOutput();
2589 catch ( io::NotConnectedException
const & )
2591 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2593 catch ( io::BufferSizeExceededException
const & )
2595 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2597 catch ( io::IOException
const & )
2599 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2605 /// @throws ucb::CommandFailedException
2606 /// @throws task::DocumentPasswordRequest
2607 static OUString
obtainPassword(
2608 const OUString
& rName
,
2609 task::PasswordRequestMode eMode
,
2610 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2612 rtl::Reference
< DocumentPasswordRequest
> xRequest
2613 = new DocumentPasswordRequest( eMode
, rName
);
2617 uno::Reference
< task::XInteractionHandler
> xIH
2618 = xEnv
->getInteractionHandler();
2621 xIH
->handle( xRequest
);
2623 rtl::Reference
< ucbhelper::InteractionContinuation
> xSelection
2624 = xRequest
->getSelection();
2626 if ( xSelection
.is() )
2628 // Handler handled the request.
2629 uno::Reference
< task::XInteractionAbort
> xAbort(
2630 xSelection
->getXWeak(), uno::UNO_QUERY
);
2633 throw ucb::CommandFailedException(
2634 u
"Abort requested by Interaction Handler."_ustr
,
2635 uno::Reference
< uno::XInterface
>(),
2636 xRequest
->getRequest() );
2639 uno::Reference
< task::XInteractionPassword
> xPassword(
2640 xSelection
->getXWeak(), uno::UNO_QUERY
);
2641 if ( xPassword
.is() )
2643 return xPassword
->getPassword();
2646 // Unknown selection. Should never happen.
2647 throw ucb::CommandFailedException(
2648 u
"Interaction Handler selected unknown continuation!"_ustr
,
2649 uno::Reference
< uno::XInterface
>(),
2650 xRequest
->getRequest() );
2655 // No IH or IH did not handle exception.
2656 task::DocumentPasswordRequest aRequest
;
2657 xRequest
->getRequest() >>= aRequest
;
2662 uno::Reference
< io::XInputStream
> Content::getInputStream(
2663 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2667 bool bPasswordRequested
= false;
2670 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2672 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2673 "Content::getInputStream - content is no stream!" );
2675 aUri
= Uri( m_xIdentifier
->getContentIdentifier() ).getUri();
2682 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2683 return m_pProvider
->queryInputStream( aUri
, aPassword
);
2685 catch ( packages::WrongPasswordException
const & )
2687 // Obtain (new) password.
2689 = obtainPassword( aUri
, /* @@@ find better title */
2691 ? task::PasswordRequestMode_PASSWORD_REENTER
2692 : task::PasswordRequestMode_PASSWORD_ENTER
,
2694 bPasswordRequested
= true;
2699 /// @throws ucb::CommandFailedException
2700 /// @throws task::DocumentPasswordRequest
2701 /// @throws uno::RuntimeException
2702 static uno::Reference
< io::XOutputStream
> lcl_getTruncatedOutputStream(
2703 const OUString
& rUri
,
2704 ContentProvider
const * pProvider
,
2705 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2708 bool bPasswordRequested
= false;
2713 return pProvider
->queryOutputStream(
2714 rUri
, aPassword
, true /* truncate */ );
2716 catch ( packages::WrongPasswordException
const & )
2718 // Obtain (new) password.
2720 = obtainPassword( rUri
, /* @@@ find better title */
2722 ? task::PasswordRequestMode_PASSWORD_REENTER
2723 : task::PasswordRequestMode_PASSWORD_ENTER
,
2725 bPasswordRequested
= true;
2731 uno::Reference
< io::XOutputStream
> Content::getTruncatedOutputStream(
2732 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2734 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2735 "Content::getTruncatedOutputStream - content is no stream!" );
2737 return lcl_getTruncatedOutputStream(
2738 Uri( m_xIdentifier
->getContentIdentifier() ).getUri(),
2744 uno::Reference
< io::XStream
> Content::getStream(
2745 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2747 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2749 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2750 "Content::getStream - content is no stream!" );
2752 OUString
aUri( Uri( m_xIdentifier
->getContentIdentifier() ).getUri() );
2754 bool bPasswordRequested
= false;
2759 return m_pProvider
->queryStream(
2760 aUri
, aPassword
, false /* no truncate */ );
2762 catch ( packages::WrongPasswordException
const & )
2764 // Obtain (new) password.
2766 = obtainPassword( aUri
, /* @@@ find better title */
2768 ? task::PasswordRequestMode_PASSWORD_REENTER
2769 : task::PasswordRequestMode_PASSWORD_ENTER
,
2771 bPasswordRequested
= true;
2777 // ContentProperties Implementation.
2780 uno::Sequence
< ucb::ContentInfo
>
2781 ContentProperties::getCreatableContentsInfo() const
2783 if ( isContentCreator() )
2785 uno::Sequence
< beans::Property
> aProps( 1 );
2786 aProps
.getArray()[ 0 ] = beans::Property(
2789 cppu::UnoType
<OUString
>::get(),
2790 beans::PropertyAttribute::BOUND
);
2792 if ( getType() == DOCUMENT
)
2794 // streams cannot be created as direct children of document root
2795 uno::Sequence
< ucb::ContentInfo
> aSeq( 1 );
2798 aSeq
.getArray()[ 0 ].Type
= TDOC_FOLDER_CONTENT_TYPE
;
2799 aSeq
.getArray()[ 0 ].Attributes
= ucb::ContentInfoAttribute::KIND_FOLDER
;
2800 aSeq
.getArray()[ 0 ].Properties
= std::move(aProps
);
2806 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
2809 aSeq
.getArray()[ 0 ].Type
= TDOC_FOLDER_CONTENT_TYPE
;
2810 aSeq
.getArray()[ 0 ].Attributes
2811 = ucb::ContentInfoAttribute::KIND_FOLDER
;
2812 aSeq
.getArray()[ 0 ].Properties
= aProps
;
2815 aSeq
.getArray()[ 1 ].Type
= TDOC_STREAM_CONTENT_TYPE
;
2816 aSeq
.getArray()[ 1 ].Attributes
2817 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
2818 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
2819 aSeq
.getArray()[ 1 ].Properties
= std::move(aProps
);
2826 OSL_FAIL( "getCreatableContentsInfo called on non-contentcreator "
2829 return uno::Sequence
< ucb::ContentInfo
>( 0 );
2834 bool ContentProperties::isContentCreator() const
2836 return ( getType() == FOLDER
) || ( getType() == DOCUMENT
);
2839 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */