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 <tools/diagnose_ex.h>
32 #include <rtl/ustrbuf.hxx>
33 #include <com/sun/star/beans/IllegalTypeException.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/embed/InvalidStorageException.hpp>
37 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
38 #include <com/sun/star/embed/XTransactedObject.hpp>
39 #include <com/sun/star/io/BufferSizeExceededException.hpp>
40 #include <com/sun/star/io/IOException.hpp>
41 #include <com/sun/star/io/NotConnectedException.hpp>
42 #include <com/sun/star/io/XActiveDataSink.hpp>
43 #include <com/sun/star/io/XActiveDataStreamer.hpp>
44 #include <com/sun/star/lang/IllegalAccessException.hpp>
45 #include <com/sun/star/packages/WrongPasswordException.hpp>
46 #include <com/sun/star/task/DocumentPasswordRequest.hpp>
47 #include <com/sun/star/task/XInteractionPassword.hpp>
48 #include <com/sun/star/ucb/CommandFailedException.hpp>
49 #include <com/sun/star/ucb/ContentAction.hpp>
50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
51 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
52 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
53 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
54 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
55 #include <com/sun/star/ucb/NameClash.hpp>
56 #include <com/sun/star/ucb/NameClashException.hpp>
57 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
58 #include <com/sun/star/ucb/OpenMode.hpp>
59 #include <com/sun/star/ucb/TransferInfo.hpp>
60 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
61 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
62 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
63 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
64 #include <com/sun/star/ucb/XCommandInfo.hpp>
65 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
67 #include <comphelper/propertysequence.hxx>
68 #include <cppuhelper/queryinterface.hxx>
69 #include <ucbhelper/cancelcommandexecution.hxx>
70 #include <ucbhelper/contentidentifier.hxx>
71 #include <ucbhelper/propertyvalueset.hxx>
72 #include <ucbhelper/macros.hxx>
74 #include "tdoc_content.hxx"
75 #include "tdoc_resultset.hxx"
76 #include "tdoc_passwordrequest.hxx"
78 #include "../inc/urihelper.hxx"
80 using namespace com::sun::star
;
81 using namespace tdoc_ucp
;
84 static ContentType
lcl_getContentType( std::u16string_view rType
)
86 if ( rType
== TDOC_ROOT_CONTENT_TYPE
)
88 else if ( rType
== TDOC_DOCUMENT_CONTENT_TYPE
)
90 else if ( rType
== TDOC_FOLDER_CONTENT_TYPE
)
92 else if ( rType
== TDOC_STREAM_CONTENT_TYPE
)
96 OSL_FAIL( "Content::Content - unsupported content type string" );
102 // Content Implementation.
105 // static ( "virtual" ctor )
106 rtl::Reference
<Content
> Content::create(
107 const uno::Reference
< uno::XComponentContext
>& rxContext
,
108 ContentProvider
* pProvider
,
109 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
111 // Fail, if resource does not exist.
112 ContentProperties aProps
;
113 if ( !Content::loadData( pProvider
,
114 Uri( Identifier
->getContentIdentifier() ),
118 return new Content( rxContext
, pProvider
, Identifier
, aProps
);
122 // static ( "virtual" ctor )
123 rtl::Reference
<Content
> Content::create(
124 const uno::Reference
< uno::XComponentContext
>& rxContext
,
125 ContentProvider
* pProvider
,
126 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
127 const ucb::ContentInfo
& Info
)
129 if ( Info
.Type
.isEmpty() )
132 if ( Info
.Type
!= TDOC_FOLDER_CONTENT_TYPE
&& Info
.Type
!= TDOC_STREAM_CONTENT_TYPE
)
134 OSL_FAIL( "Content::create - unsupported content type!" );
138 return new Content( rxContext
, pProvider
, Identifier
, Info
);
143 const uno::Reference
< uno::XComponentContext
> & rxContext
,
144 ContentProvider
* pProvider
,
145 const uno::Reference
< ucb::XContentIdentifier
> & Identifier
,
146 const ContentProperties
& rProps
)
147 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
149 m_eState( PERSISTENT
),
150 m_pProvider( pProvider
)
155 // ctor for a content just created via XContentCreator::createNewContent()
157 const uno::Reference
< uno::XComponentContext
>& rxContext
,
158 ContentProvider
* pProvider
,
159 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
160 const ucb::ContentInfo
& Info
)
161 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
162 m_aProps( lcl_getContentType( Info
.Type
), OUString() ), // no Title (yet)
163 m_eState( TRANSIENT
),
164 m_pProvider( pProvider
)
175 // XInterface methods.
179 void SAL_CALL
Content::acquire()
182 ContentImplHelper::acquire();
187 void SAL_CALL
Content::release()
190 ContentImplHelper::release();
195 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
197 uno::Any aRet
= ContentImplHelper::queryInterface( rType
);
199 if ( !aRet
.hasValue() )
201 aRet
= cppu::queryInterface(
202 rType
, static_cast< ucb::XContentCreator
* >( this ) );
203 if ( aRet
.hasValue() )
205 if ( !m_aProps
.isContentCreator() )
214 // XTypeProvider methods.
217 XTYPEPROVIDER_COMMON_IMPL( Content
);
221 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
223 if ( m_aProps
.isContentCreator() )
225 static cppu::OTypeCollection
s_aFolderTypes(
226 CPPU_TYPE_REF( lang::XTypeProvider
),
227 CPPU_TYPE_REF( lang::XServiceInfo
),
228 CPPU_TYPE_REF( lang::XComponent
),
229 CPPU_TYPE_REF( ucb::XContent
),
230 CPPU_TYPE_REF( ucb::XCommandProcessor
),
231 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
232 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
233 CPPU_TYPE_REF( beans::XPropertyContainer
),
234 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
235 CPPU_TYPE_REF( container::XChild
),
236 CPPU_TYPE_REF( ucb::XContentCreator
) );
238 return s_aFolderTypes
.getTypes();
242 static cppu::OTypeCollection
s_aDocumentTypes(
243 CPPU_TYPE_REF( lang::XTypeProvider
),
244 CPPU_TYPE_REF( lang::XServiceInfo
),
245 CPPU_TYPE_REF( lang::XComponent
),
246 CPPU_TYPE_REF( ucb::XContent
),
247 CPPU_TYPE_REF( ucb::XCommandProcessor
),
248 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
249 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
250 CPPU_TYPE_REF( beans::XPropertyContainer
),
251 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
252 CPPU_TYPE_REF( container::XChild
) );
254 return s_aDocumentTypes
.getTypes();
259 // XServiceInfo methods.
263 OUString SAL_CALL
Content::getImplementationName()
265 return "com.sun.star.comp.ucb.TransientDocumentsContent";
270 uno::Sequence
< OUString
> SAL_CALL
Content::getSupportedServiceNames()
272 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
274 uno::Sequence
< OUString
> aSNS( 1 );
276 if ( m_aProps
.getType() == STREAM
)
277 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsStreamContent";
278 else if ( m_aProps
.getType() == FOLDER
)
279 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsFolderContent";
280 else if ( m_aProps
.getType() == DOCUMENT
)
281 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsDocumentContent";
283 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.TransientDocumentsRootContent";
293 OUString SAL_CALL
Content::getContentType()
295 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
296 return m_aProps
.getContentType();
301 uno::Reference
< ucb::XContentIdentifier
> SAL_CALL
302 Content::getIdentifier()
305 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
308 if ( m_eState
== TRANSIENT
)
310 // Transient contents have no identifier.
311 return uno::Reference
< ucb::XContentIdentifier
>();
314 return ContentImplHelper::getIdentifier();
318 // XCommandProcessor methods.
322 uno::Any SAL_CALL
Content::execute(
323 const ucb::Command
& aCommand
,
324 sal_Int32
/*CommandId*/,
325 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
329 if ( aCommand
.Name
== "getPropertyValues" )
335 uno::Sequence
< beans::Property
> Properties
;
336 if ( !( aCommand
.Argument
>>= Properties
) )
338 ucbhelper::cancelCommandExecution(
339 uno::makeAny( lang::IllegalArgumentException(
340 "Wrong argument type!",
341 static_cast< cppu::OWeakObject
* >( this ),
347 aRet
<<= getPropertyValues( Properties
);
349 else if ( aCommand
.Name
== "setPropertyValues" )
355 uno::Sequence
< beans::PropertyValue
> aProperties
;
356 if ( !( aCommand
.Argument
>>= aProperties
) )
358 ucbhelper::cancelCommandExecution(
359 uno::makeAny( lang::IllegalArgumentException(
360 "Wrong argument type!",
361 static_cast< cppu::OWeakObject
* >( this ),
367 if ( !aProperties
.hasElements() )
369 ucbhelper::cancelCommandExecution(
370 uno::makeAny( lang::IllegalArgumentException(
372 static_cast< cppu::OWeakObject
* >( this ),
378 aRet
<<= setPropertyValues( aProperties
, Environment
);
380 else if ( aCommand
.Name
== "getPropertySetInfo" )
383 // getPropertySetInfo
386 aRet
<<= getPropertySetInfo( Environment
);
388 else if ( aCommand
.Name
== "getCommandInfo" )
394 aRet
<<= getCommandInfo( Environment
);
396 else if ( aCommand
.Name
== "open" )
402 ucb::OpenCommandArgument2 aOpenCommand
;
403 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
405 ucbhelper::cancelCommandExecution(
406 uno::makeAny( lang::IllegalArgumentException(
407 "Wrong argument type!",
408 static_cast< cppu::OWeakObject
* >( this ),
414 aRet
= open( aOpenCommand
, Environment
);
416 else if ( aCommand
.Name
== "insert" )
419 // insert ( Supported by folders and streams only )
422 ContentType eType
= m_aProps
.getType();
423 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
425 ucbhelper::cancelCommandExecution(
426 uno::makeAny( ucb::UnsupportedCommandException(
427 "insert command only supported by "
428 "folders and streams!",
429 static_cast< cppu::OWeakObject
* >( this ) ) ),
434 if ( eType
== STREAM
)
436 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
437 Uri
aParentUri( aUri
.getParentUri() );
438 if ( aParentUri
.isDocument() )
440 ucbhelper::cancelCommandExecution(
441 uno::makeAny( ucb::UnsupportedCommandException(
442 "insert command not supported by "
443 "streams that are direct children "
445 static_cast< cppu::OWeakObject
* >(
452 ucb::InsertCommandArgument aArg
;
453 if ( !( aCommand
.Argument
>>= aArg
) )
455 ucbhelper::cancelCommandExecution(
456 uno::makeAny( lang::IllegalArgumentException(
457 "Wrong argument type!",
458 static_cast< cppu::OWeakObject
* >( this ),
464 sal_Int32 nNameClash
= aArg
.ReplaceExisting
465 ? ucb::NameClash::OVERWRITE
466 : ucb::NameClash::ERROR
;
467 insert( aArg
.Data
, nNameClash
, Environment
);
469 else if ( aCommand
.Name
== "delete" )
472 // delete ( Supported by folders and streams only )
476 osl::MutexGuard
aGuard( m_aMutex
);
478 ContentType eType
= m_aProps
.getType();
479 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
481 ucbhelper::cancelCommandExecution(
482 uno::makeAny( ucb::UnsupportedCommandException(
483 "delete command only supported by "
484 "folders and streams!",
485 static_cast< cppu::OWeakObject
* >(
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 "Cannot remove persistent data!",
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::makeAny( ucb::UnsupportedCommandException(
529 "transfer command only supported "
530 "by folders and documents!",
531 static_cast< cppu::OWeakObject
* >(
538 ucb::TransferInfo aInfo
;
539 if ( !( aCommand
.Argument
>>= aInfo
) )
541 OSL_FAIL( "Wrong argument type!" );
542 ucbhelper::cancelCommandExecution(
543 uno::makeAny( lang::IllegalArgumentException(
544 "Wrong argument type!",
545 static_cast< cppu::OWeakObject
* >( this ),
551 transfer( aInfo
, Environment
);
553 else if ( aCommand
.Name
== "createNewContent" )
556 // createNewContent ( Supported by document and folders only )
560 osl::MutexGuard
aGuard( m_aMutex
);
562 ContentType eType
= m_aProps
.getType();
563 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
565 ucbhelper::cancelCommandExecution(
566 uno::makeAny( ucb::UnsupportedCommandException(
567 "createNewContent command only "
568 "supported by folders and "
570 static_cast< cppu::OWeakObject
* >(
577 ucb::ContentInfo aInfo
;
578 if ( !( aCommand
.Argument
>>= aInfo
) )
580 OSL_FAIL( "Wrong argument type!" );
581 ucbhelper::cancelCommandExecution(
582 uno::makeAny( lang::IllegalArgumentException(
583 "Wrong argument type!",
584 static_cast< cppu::OWeakObject
* >( this ),
590 aRet
<<= createNewContent( aInfo
);
595 // Unsupported command
598 ucbhelper::cancelCommandExecution(
599 uno::makeAny( ucb::UnsupportedCommandException(
601 static_cast< cppu::OWeakObject
* >( this ) ) ),
611 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
616 // XContentCreator methods.
620 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
621 Content::queryCreatableContentsInfo()
623 return m_aProps
.getCreatableContentsInfo();
628 uno::Reference
< ucb::XContent
> SAL_CALL
629 Content::createNewContent( const ucb::ContentInfo
& Info
)
631 if ( m_aProps
.isContentCreator() )
633 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
635 if ( Info
.Type
.isEmpty() )
636 return uno::Reference
< ucb::XContent
>();
638 bool bCreateFolder
= Info
.Type
== TDOC_FOLDER_CONTENT_TYPE
;
640 // streams cannot be created as direct children of document root
641 if ( !bCreateFolder
&& ( m_aProps
.getType() == DOCUMENT
) )
643 OSL_FAIL( "Content::createNewContent - streams cannot be "
644 "created as direct children of document root!" );
645 return uno::Reference
< ucb::XContent
>();
647 if ( !bCreateFolder
&& Info
.Type
!= TDOC_STREAM_CONTENT_TYPE
)
649 OSL_FAIL( "Content::createNewContent - unsupported type!" );
650 return uno::Reference
< ucb::XContent
>();
653 OUString aURL
= m_xIdentifier
->getContentIdentifier();
655 OSL_ENSURE( !aURL
.isEmpty(),
656 "Content::createNewContent - empty identifier!" );
658 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
662 aURL
+= "New_Folder";
664 aURL
+= "New_Stream";
666 uno::Reference
< ucb::XContentIdentifier
> xId
667 = new ::ucbhelper::ContentIdentifier( aURL
);
669 return create( m_xContext
, m_pProvider
, xId
, Info
);
673 OSL_FAIL( "createNewContent called on non-contentcreator object!" );
674 return uno::Reference
< ucb::XContent
>();
680 OUString
Content::getParentURL()
682 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
683 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
684 return aUri
.getParentUri();
688 uno::Reference
< ucb::XContentIdentifier
>
689 Content::makeNewIdentifier( const OUString
& rTitle
)
691 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
693 // Assemble new content identifier...
694 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
695 OUStringBuffer aNewURL
= aUri
.getParentUri();
696 aNewURL
.append( ::ucb_impl::urihelper::encodeSegment( rTitle
) );
699 uno::Reference
< ucb::XContentIdentifier
>(
700 new ::ucbhelper::ContentIdentifier( aNewURL
.makeStringAndClear() ) );
704 void Content::queryChildren( ContentRefList
& rChildren
)
706 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
708 // Only folders (root, documents, folders) have children.
709 if ( !m_aProps
.getIsFolder() )
712 // Obtain a list with a snapshot of all currently instantiated contents
713 // from provider and extract the contents which are direct children
716 ::ucbhelper::ContentRefList aAllContents
;
717 m_xProvider
->queryExistingContents( aAllContents
);
719 OUString aURL
= m_xIdentifier
->getContentIdentifier();
720 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
722 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
724 // No trailing slash found. Append.
728 sal_Int32 nLen
= aURL
.getLength();
730 for ( const auto& rContent
: aAllContents
)
732 ::ucbhelper::ContentImplHelperRef xChild
= rContent
;
734 = xChild
->getIdentifier()->getContentIdentifier();
736 // Is aURL a prefix of aChildURL?
737 if ( ( aChildURL
.getLength() > nLen
) &&
738 ( aChildURL
.startsWith( aURL
) ) )
740 sal_Int32 nPos
= aChildURL
.indexOf( '/', nLen
);
742 if ( ( nPos
== -1 ) ||
743 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
745 // No further slashes / only a final slash. It's a child!
746 rChildren
.emplace_back(
747 static_cast< Content
* >( xChild
.get() ) );
754 bool Content::exchangeIdentity(
755 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
760 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
762 uno::Reference
< ucb::XContent
> xThis
= this;
764 // Already persistent?
765 if ( m_eState
!= PERSISTENT
)
767 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
771 // Only folders and streams can be renamed -> exchange identity.
772 ContentType eType
= m_aProps
.getType();
773 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
775 OSL_FAIL( "Content::exchangeIdentity - "
776 "Not supported by root or document!" );
780 // Exchange own identity.
782 // Fail, if a content with given id already exists.
783 if ( !hasData( Uri( xNewId
->getContentIdentifier() ) ) )
785 OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
788 if ( exchange( xNewId
) )
790 if ( eType
== FOLDER
)
792 // Process instantiated children...
794 ContentRefList aChildren
;
795 queryChildren( aChildren
);
797 for ( const auto& rChild
: aChildren
)
799 ContentRef xChild
= rChild
;
801 // Create new content identifier for the child...
802 uno::Reference
< ucb::XContentIdentifier
> xOldChildId
803 = xChild
->getIdentifier();
804 OUString aOldChildURL
805 = xOldChildId
->getContentIdentifier();
806 OUString aNewChildURL
807 = aOldChildURL
.replaceAt(
810 xNewId
->getContentIdentifier() );
811 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
812 = new ::ucbhelper::ContentIdentifier( aNewChildURL
);
814 if ( !xChild
->exchangeIdentity( xNewChildId
) )
822 OSL_FAIL( "Content::exchangeIdentity - "
823 "Panic! Cannot exchange identity!" );
829 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
830 const uno::Reference
< uno::XComponentContext
>& rxContext
,
831 const uno::Sequence
< beans::Property
>& rProperties
,
832 ContentProvider
* pProvider
,
833 const OUString
& rContentId
)
835 ContentProperties aData
;
836 if ( loadData( pProvider
, Uri(rContentId
), aData
) )
838 return getPropertyValues(
839 rxContext
, rProperties
, aData
, pProvider
, rContentId
);
843 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
844 = new ::ucbhelper::PropertyValueSet( rxContext
);
846 for ( const beans::Property
& rProp
: rProperties
)
847 xRow
->appendVoid( rProp
);
855 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
856 const uno::Reference
< uno::XComponentContext
>& rxContext
,
857 const uno::Sequence
< beans::Property
>& rProperties
,
858 const ContentProperties
& rData
,
859 ContentProvider
* pProvider
,
860 const OUString
& rContentId
)
862 // Note: Empty sequence means "get values of all supported properties".
864 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
865 = new ::ucbhelper::PropertyValueSet( rxContext
);
867 if ( rProperties
.hasElements() )
869 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
870 bool bTriedToGetAdditionalPropSet
= false;
872 for ( const beans::Property
& rProp
: rProperties
)
874 // Process Core properties.
876 if ( rProp
.Name
== "ContentType" )
878 xRow
->appendString ( rProp
, rData
.getContentType() );
880 else if ( rProp
.Name
== "Title" )
882 xRow
->appendString ( rProp
, rData
.getTitle() );
884 else if ( rProp
.Name
== "IsDocument" )
886 xRow
->appendBoolean( rProp
, rData
.getIsDocument() );
888 else if ( rProp
.Name
== "IsFolder" )
890 xRow
->appendBoolean( rProp
, rData
.getIsFolder() );
892 else if ( rProp
.Name
== "CreatableContentsInfo" )
895 rProp
, uno::makeAny( rData
.getCreatableContentsInfo() ) );
897 else if ( rProp
.Name
== "Storage" )
899 // Storage is only supported by folders.
900 ContentType eType
= rData
.getType();
901 if ( eType
== FOLDER
)
905 pProvider
->queryStorageClone( rContentId
) ) );
907 xRow
->appendVoid( rProp
);
909 else if ( rProp
.Name
== "DocumentModel" )
911 // DocumentModel is only supported by documents.
912 ContentType eType
= rData
.getType();
913 if ( eType
== DOCUMENT
)
917 pProvider
->queryDocumentModel( rContentId
) ) );
919 xRow
->appendVoid( rProp
);
923 // Not a Core Property! Maybe it's an Additional Core Property?!
925 if ( !bTriedToGetAdditionalPropSet
&& !xAdditionalPropSet
.is() )
928 pProvider
->getAdditionalPropertySet( rContentId
,
930 bTriedToGetAdditionalPropSet
= true;
933 if ( xAdditionalPropSet
.is() )
935 if ( !xRow
->appendPropertySetValue(
939 // Append empty entry.
940 xRow
->appendVoid( rProp
);
945 // Append empty entry.
946 xRow
->appendVoid( rProp
);
953 // Append all Core Properties.
955 beans::Property( "ContentType",
957 cppu::UnoType
<OUString
>::get(),
958 beans::PropertyAttribute::BOUND
959 | beans::PropertyAttribute::READONLY
),
960 rData
.getContentType() );
962 ContentType eType
= rData
.getType();
965 beans::Property( "Title",
967 cppu::UnoType
<OUString
>::get(),
968 // Title is read-only for root and documents.
969 beans::PropertyAttribute::BOUND
|
970 ( ( eType
== ROOT
) || ( eType
== DOCUMENT
)
971 ? beans::PropertyAttribute::READONLY
975 beans::Property( "IsDocument",
977 cppu::UnoType
<bool>::get(),
978 beans::PropertyAttribute::BOUND
979 | beans::PropertyAttribute::READONLY
),
980 rData
.getIsDocument() );
982 beans::Property( "IsFolder",
984 cppu::UnoType
<bool>::get(),
985 beans::PropertyAttribute::BOUND
986 | beans::PropertyAttribute::READONLY
),
987 rData
.getIsFolder() );
990 "CreatableContentsInfo",
992 cppu::UnoType
<uno::Sequence
< ucb::ContentInfo
>>::get(),
993 beans::PropertyAttribute::BOUND
994 | beans::PropertyAttribute::READONLY
),
995 uno::makeAny( rData
.getCreatableContentsInfo() ) );
997 // Storage is only supported by folders.
998 if ( eType
== FOLDER
)
1000 beans::Property( "Storage",
1002 cppu::UnoType
<embed::XStorage
>::get(),
1003 beans::PropertyAttribute::BOUND
1004 | beans::PropertyAttribute::READONLY
),
1005 uno::makeAny( pProvider
->queryStorageClone( rContentId
) ) );
1007 // DocumentModel is only supported by documents.
1008 if ( eType
== DOCUMENT
)
1010 beans::Property( "DocumentModel",
1012 cppu::UnoType
<frame::XModel
>::get(),
1013 beans::PropertyAttribute::BOUND
1014 | beans::PropertyAttribute::READONLY
),
1016 pProvider
->queryDocumentModel( rContentId
) ) );
1018 // Append all Additional Core Properties.
1020 uno::Reference
< beans::XPropertySet
> xSet
=
1021 pProvider
->getAdditionalPropertySet( rContentId
, false );
1022 xRow
->appendPropertySet( xSet
);
1029 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1030 const uno::Sequence
< beans::Property
>& rProperties
)
1032 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1033 return getPropertyValues( m_xContext
,
1037 m_xIdentifier
->getContentIdentifier() );
1041 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1042 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1043 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1045 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1047 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1048 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1049 sal_Int32 nChanged
= 0;
1051 beans::PropertyChangeEvent aEvent
;
1052 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1053 aEvent
.Further
= false;
1054 // aEvent.PropertyName =
1055 aEvent
.PropertyHandle
= -1;
1056 // aEvent.OldValue =
1057 // aEvent.NewValue =
1059 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1060 sal_Int32 nCount
= rValues
.getLength();
1062 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1063 bool bTriedToGetAdditionalPropSet
= false;
1065 bool bExchange
= false;
1067 sal_Int32 nTitlePos
= -1;
1069 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1071 const beans::PropertyValue
& rValue
= pValues
[ n
];
1073 if ( rValue
.Name
== "ContentType" )
1075 // Read-only property!
1076 aRet
[ n
] <<= lang::IllegalAccessException(
1077 "Property is read-only!",
1078 static_cast< cppu::OWeakObject
* >( this ) );
1080 else if ( rValue
.Name
== "IsDocument" )
1082 // Read-only property!
1083 aRet
[ n
] <<= lang::IllegalAccessException(
1084 "Property is read-only!",
1085 static_cast< cppu::OWeakObject
* >( this ) );
1087 else if ( rValue
.Name
== "IsFolder" )
1089 // Read-only property!
1090 aRet
[ n
] <<= lang::IllegalAccessException(
1091 "Property is read-only!",
1092 static_cast< cppu::OWeakObject
* >( this ) );
1094 else if ( rValue
.Name
== "CreatableContentsInfo" )
1096 // Read-only property!
1097 aRet
[ n
] <<= lang::IllegalAccessException(
1098 "Property is read-only!",
1099 static_cast< cppu::OWeakObject
* >( this ) );
1101 else if ( rValue
.Name
== "Title" )
1103 // Title is read-only for root and documents.
1104 ContentType eType
= m_aProps
.getType();
1105 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
1107 aRet
[ n
] <<= lang::IllegalAccessException(
1108 "Property is read-only!",
1109 static_cast< cppu::OWeakObject
* >( this ) );
1114 if ( rValue
.Value
>>= aNewValue
)
1117 if ( !aNewValue
.isEmpty() )
1119 if ( aNewValue
!= m_aProps
.getTitle() )
1121 // modified title -> modified URL -> exchange !
1122 if ( m_eState
== PERSISTENT
)
1125 aOldTitle
= m_aProps
.getTitle();
1126 m_aProps
.setTitle( aNewValue
);
1128 // property change event will be sent later...
1130 // remember position within sequence of values
1131 // (for error handling).
1137 aRet
[ n
] <<= lang::IllegalArgumentException(
1138 "Empty Title not allowed!",
1139 static_cast< cppu::OWeakObject
* >( this ),
1145 aRet
[ n
] <<= beans::IllegalTypeException(
1146 "Title Property value has wrong type!",
1147 static_cast< cppu::OWeakObject
* >( this ) );
1151 else if ( rValue
.Name
== "Storage" )
1153 ContentType eType
= m_aProps
.getType();
1154 if ( eType
== FOLDER
)
1156 aRet
[ n
] <<= lang::IllegalAccessException(
1157 "Property is read-only!",
1158 static_cast< cppu::OWeakObject
* >( this ) );
1162 // Storage is only supported by folders.
1163 aRet
[ n
] <<= beans::UnknownPropertyException(
1164 "Storage property only supported by folders",
1165 static_cast< cppu::OWeakObject
* >( this ) );
1168 else if ( rValue
.Name
== "DocumentModel" )
1170 ContentType eType
= m_aProps
.getType();
1171 if ( eType
== DOCUMENT
)
1173 aRet
[ n
] <<= lang::IllegalAccessException(
1174 "Property is read-only!",
1175 static_cast< cppu::OWeakObject
* >( this ) );
1179 // Storage is only supported by folders.
1180 aRet
[ n
] <<= beans::UnknownPropertyException(
1181 "DocumentModel property only supported by documents",
1182 static_cast< cppu::OWeakObject
* >( this ) );
1187 // Not a Core Property! Maybe it's an Additional Core Property?!
1189 if ( !bTriedToGetAdditionalPropSet
&& !xAdditionalPropSet
.is() )
1191 xAdditionalPropSet
= getAdditionalPropertySet( false );
1192 bTriedToGetAdditionalPropSet
= true;
1195 if ( xAdditionalPropSet
.is() )
1199 uno::Any aOldValue
= xAdditionalPropSet
->getPropertyValue(
1201 if ( aOldValue
!= rValue
.Value
)
1203 xAdditionalPropSet
->setPropertyValue(
1204 rValue
.Name
, rValue
.Value
);
1206 aEvent
.PropertyName
= rValue
.Name
;
1207 aEvent
.OldValue
= aOldValue
;
1208 aEvent
.NewValue
= rValue
.Value
;
1210 aChanges
.getArray()[ nChanged
] = aEvent
;
1214 catch ( beans::UnknownPropertyException
const & e
)
1218 catch ( lang::WrappedTargetException
const & e
)
1222 catch ( beans::PropertyVetoException
const & e
)
1226 catch ( lang::IllegalArgumentException
const & e
)
1233 aRet
[ n
] <<= uno::Exception(
1234 "No property set for storing the value!",
1235 static_cast< cppu::OWeakObject
* >( this ) );
1242 uno::Reference
< ucb::XContentIdentifier
> xOldId
1244 uno::Reference
< ucb::XContentIdentifier
> xNewId
1245 = makeNewIdentifier( m_aProps
.getTitle() );
1248 if ( exchangeIdentity( xNewId
) )
1250 // Adapt persistent data.
1251 renameData( xOldId
, xNewId
);
1253 // Adapt Additional Core Properties.
1254 renameAdditionalPropertySet( xOldId
->getContentIdentifier(),
1255 xNewId
->getContentIdentifier() );
1260 m_aProps
.setTitle( aOldTitle
);
1264 aRet
[ nTitlePos
] <<= uno::Exception(
1266 static_cast< cppu::OWeakObject
* >( this ) );
1270 if ( !aOldTitle
.isEmpty() )
1272 aEvent
.PropertyName
= "Title";
1273 aEvent
.OldValue
<<= aOldTitle
;
1274 aEvent
.NewValue
<<= m_aProps
.getTitle();
1276 aChanges
.getArray()[ nChanged
] = aEvent
;
1282 // Save changes, if content was already made persistent.
1283 if ( !bExchange
&& ( m_eState
== PERSISTENT
) )
1285 if ( !storeData( uno::Reference
< io::XInputStream
>(), xEnv
) )
1287 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1289 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1291 ucbhelper::cancelCommandExecution(
1292 ucb::IOErrorCode_CANT_WRITE
,
1295 "Cannot store persistent data!",
1301 aChanges
.realloc( nChanged
);
1304 notifyPropertiesChange( aChanges
);
1311 uno::Any
Content::open(
1312 const ucb::OpenCommandArgument2
& rArg
,
1313 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1315 if ( rArg
.Mode
== ucb::OpenMode::ALL
||
1316 rArg
.Mode
== ucb::OpenMode::FOLDERS
||
1317 rArg
.Mode
== ucb::OpenMode::DOCUMENTS
)
1320 // open command for a folder content
1323 uno::Reference
< ucb::XDynamicResultSet
> xSet
1324 = new DynamicResultSet( m_xContext
, this, rArg
);
1325 return uno::makeAny( xSet
);
1330 // open command for a document content
1333 if ( ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
1334 ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
1336 // Currently(?) unsupported.
1337 ucbhelper::cancelCommandExecution(
1338 uno::makeAny( ucb::UnsupportedOpenModeException(
1340 static_cast< cppu::OWeakObject
* >( this ),
1341 sal_Int16( rArg
.Mode
) ) ),
1346 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1348 uno::Reference
< io::XActiveDataStreamer
> xDataStreamer(
1349 rArg
.Sink
, uno::UNO_QUERY
);
1350 if ( xDataStreamer
.is() )
1352 // May throw CommandFailedException, DocumentPasswordRequest!
1353 uno::Reference
< io::XStream
> xStream
= getStream( xEnv
);
1354 if ( !xStream
.is() )
1356 // No interaction if we are not persistent!
1357 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1359 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1361 ucbhelper::cancelCommandExecution(
1362 ucb::IOErrorCode_CANT_READ
,
1364 m_eState
== PERSISTENT
1366 : uno::Reference
< ucb::XCommandEnvironment
>(),
1367 "Got no data stream!",
1373 xDataStreamer
->setStream( xStream
);
1377 uno::Reference
< io::XOutputStream
> xOut( rArg
.Sink
, uno::UNO_QUERY
);
1380 // PUSH: write data into xOut
1382 // May throw CommandFailedException, DocumentPasswordRequest!
1383 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1386 // No interaction if we are not persistent!
1387 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1389 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1391 ucbhelper::cancelCommandExecution(
1392 ucb::IOErrorCode_CANT_READ
,
1394 m_eState
== PERSISTENT
1396 : uno::Reference
< ucb::XCommandEnvironment
>(),
1397 "Got no data stream!",
1404 uno::Sequence
< sal_Int8
> aBuffer
;
1408 sal_Int32 nRead
= xIn
->readSomeBytes( aBuffer
, 65536 );
1411 aBuffer
.realloc( nRead
);
1412 xOut
->writeBytes( aBuffer
);
1415 xOut
->closeOutput();
1417 catch ( io::NotConnectedException
const & )
1419 // closeOutput, readSomeBytes, writeBytes
1421 catch ( io::BufferSizeExceededException
const & )
1423 // closeOutput, readSomeBytes, writeBytes
1425 catch ( io::IOException
const & )
1427 // closeOutput, readSomeBytes, writeBytes
1432 uno::Reference
< io::XActiveDataSink
> xDataSink(
1433 rArg
.Sink
, uno::UNO_QUERY
);
1434 if ( xDataSink
.is() )
1436 // PULL: wait for client read
1438 // May throw CommandFailedException, DocumentPasswordRequest!
1439 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1442 // No interaction if we are not persistent!
1443 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1445 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1447 ucbhelper::cancelCommandExecution(
1448 ucb::IOErrorCode_CANT_READ
,
1450 m_eState
== PERSISTENT
1453 ucb::XCommandEnvironment
>(),
1454 "Got no data stream!",
1460 xDataSink
->setInputStream( xIn
);
1464 ucbhelper::cancelCommandExecution(
1466 ucb::UnsupportedDataSinkException(
1468 static_cast< cppu::OWeakObject
* >( this ),
1481 void Content::insert( const uno::Reference
< io::XInputStream
>& xData
,
1482 sal_Int32 nNameClashResolve
,
1483 const uno::Reference
<
1484 ucb::XCommandEnvironment
> & xEnv
)
1486 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1488 ContentType eType
= m_aProps
.getType();
1490 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1491 "insert command only supported by streams and folders!" );
1493 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
1495 #if OSL_DEBUG_LEVEL > 0
1496 if ( eType
== STREAM
)
1498 Uri
aParentUri( aUri
.getParentUri() );
1499 OSL_ENSURE( !aParentUri
.isDocument(),
1500 "insert command not supported by streams that are direct "
1501 "children of document root!" );
1505 // Check, if all required properties were set.
1506 if ( eType
== FOLDER
)
1510 if ( m_aProps
.getTitle().isEmpty() )
1511 m_aProps
.setTitle( aUri
.getDecodedName() );
1519 ucbhelper::cancelCommandExecution(
1520 uno::makeAny( ucb::MissingInputStreamException(
1522 static_cast< cppu::OWeakObject
* >( this ) ) ),
1529 if ( m_aProps
.getTitle().isEmpty() )
1530 m_aProps
.setTitle( aUri
.getDecodedName() );
1533 OUStringBuffer aNewURL
= aUri
.getParentUri();
1534 aNewURL
.append( m_aProps
.getTitle() );
1535 Uri
aNewUri( aNewURL
.makeStringAndClear() );
1537 // Handle possible name clash...
1538 switch ( nNameClashResolve
)
1541 case ucb::NameClash::ERROR
:
1542 if ( hasData( aNewUri
) )
1544 ucbhelper::cancelCommandExecution(
1545 uno::makeAny( ucb::NameClashException(
1547 static_cast< cppu::OWeakObject
* >( this ),
1548 task::InteractionClassification_ERROR
,
1549 m_aProps
.getTitle() ) ),
1555 // replace (possibly) existing object.
1556 case ucb::NameClash::OVERWRITE
:
1559 // "invent" a new valid title.
1560 case ucb::NameClash::RENAME
:
1561 if ( hasData( aNewUri
) )
1567 OUStringBuffer aNew
= aNewUri
.getUri();
1569 aNew
.append( ++nTry
);
1570 aNewUri
.setUri( aNew
.makeStringAndClear() );
1572 while ( hasData( aNewUri
) && ( nTry
< 1000 ) );
1576 ucbhelper::cancelCommandExecution(
1578 ucb::UnsupportedNameClashException(
1579 "Unable to resolve name clash!",
1580 static_cast< cppu::OWeakObject
* >( this ),
1581 nNameClashResolve
) ),
1587 OUStringBuffer aNewTitle
= m_aProps
.getTitle();
1588 aNewTitle
.append( "_" );
1589 aNewTitle
.append( ++nTry
);
1590 m_aProps
.setTitle( aNewTitle
.makeStringAndClear() );
1595 case ucb::NameClash::KEEP
: // deprecated
1596 case ucb::NameClash::ASK
:
1598 if ( hasData( aNewUri
) )
1600 ucbhelper::cancelCommandExecution(
1602 ucb::UnsupportedNameClashException(
1604 static_cast< cppu::OWeakObject
* >( this ),
1605 nNameClashResolve
) ),
1612 // Identifier changed?
1613 bool bNewId
= ( aUri
!= aNewUri
);
1618 = new ::ucbhelper::ContentIdentifier( aNewUri
.getUri() );
1621 if ( !storeData( xData
, xEnv
) )
1623 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1625 {"Uri", uno::Any(m_xIdentifier
->getContentIdentifier())}
1627 ucbhelper::cancelCommandExecution(
1628 ucb::IOErrorCode_CANT_WRITE
,
1631 "Cannot store persistent data!",
1636 m_eState
= PERSISTENT
;
1640 //loadData( m_pProvider, m_aUri, m_aProps );
1648 void Content::destroy( bool bDeletePhysical
,
1649 const uno::Reference
<
1650 ucb::XCommandEnvironment
> & xEnv
)
1652 // @@@ take care about bDeletePhysical -> trashcan support
1654 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1656 ContentType eType
= m_aProps
.getType();
1658 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1659 "delete command only supported by streams and folders!" );
1661 uno::Reference
< ucb::XContent
> xThis
= this;
1664 if ( m_eState
!= PERSISTENT
)
1666 ucbhelper::cancelCommandExecution(
1667 uno::makeAny( ucb::UnsupportedCommandException(
1669 static_cast< cppu::OWeakObject
* >( this ) ) ),
1679 if ( eType
== FOLDER
)
1681 // Process instantiated children...
1683 ContentRefList aChildren
;
1684 queryChildren( aChildren
);
1686 for ( auto& rChild
: aChildren
)
1688 rChild
->destroy( bDeletePhysical
, xEnv
);
1694 void Content::notifyDocumentClosed()
1696 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1700 // @@@ anything else to reset or such?
1702 // callback follows!
1705 // Propagate destruction to content event listeners
1706 // Remove this from provider's content list.
1711 uno::Reference
< ucb::XContent
>
1712 Content::queryChildContent( const OUString
& rRelativeChildUri
)
1714 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1716 const OUString aMyId
= getIdentifier()->getContentIdentifier();
1717 OUStringBuffer
aBuf( aMyId
);
1718 if ( !aMyId
.endsWith("/") )
1720 if ( !rRelativeChildUri
.startsWith("/") )
1721 aBuf
.append( rRelativeChildUri
);
1723 aBuf
.append( rRelativeChildUri
.subView(1) );
1725 uno::Reference
< ucb::XContentIdentifier
> xChildId
1726 = new ::ucbhelper::ContentIdentifier( aBuf
.makeStringAndClear() );
1728 uno::Reference
< ucb::XContent
> xChild
;
1731 xChild
= m_pProvider
->queryContent( xChildId
);
1733 catch ( ucb::IllegalIdentifierException
const & )
1738 OSL_ENSURE( xChild
.is(),
1739 "Content::queryChildContent - unable to create child content!" );
1744 void Content::notifyChildRemoved( const OUString
& rRelativeChildUri
)
1746 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1748 // Ugly! Need to create child content object, just to fill event properly.
1749 uno::Reference
< ucb::XContent
> xChild
1750 = queryChildContent( rRelativeChildUri
);
1755 // callback follows!
1758 // Notify "REMOVED" event.
1759 ucb::ContentEvent
aEvt(
1760 static_cast< cppu::OWeakObject
* >( this ),
1761 ucb::ContentAction::REMOVED
,
1764 notifyContentEvent( aEvt
);
1768 void Content::notifyChildInserted( const OUString
& rRelativeChildUri
)
1770 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1772 // Ugly! Need to create child content object, just to fill event properly.
1773 uno::Reference
< ucb::XContent
> xChild
1774 = queryChildContent( rRelativeChildUri
);
1779 // callback follows!
1782 // Notify "INSERTED" event.
1783 ucb::ContentEvent
aEvt(
1784 static_cast< cppu::OWeakObject
* >( this ),
1785 ucb::ContentAction::INSERTED
,
1788 notifyContentEvent( aEvt
);
1792 void Content::transfer(
1793 const ucb::TransferInfo
& rInfo
,
1794 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1796 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1799 if ( m_eState
!= PERSISTENT
)
1801 ucbhelper::cancelCommandExecution(
1802 uno::makeAny( ucb::UnsupportedCommandException(
1804 static_cast< cppu::OWeakObject
* >( this ) ) ),
1809 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
1811 if ( rInfo
.SourceURL
.getLength() < TDOC_URL_SCHEME_LENGTH
+ 2 )
1813 // Invalid length (to short).
1814 ucbhelper::cancelCommandExecution(
1815 uno::makeAny( ucb::InteractiveBadTransferURLException(
1817 static_cast< cppu::OWeakObject
* >( this ) ) ),
1823 = rInfo
.SourceURL
.copy( 0, TDOC_URL_SCHEME_LENGTH
+ 2 )
1824 .toAsciiLowerCase();
1825 if ( aScheme
!= TDOC_URL_SCHEME
":/" )
1828 ucbhelper::cancelCommandExecution(
1829 uno::makeAny( ucb::InteractiveBadTransferURLException(
1831 static_cast< cppu::OWeakObject
* >( this ) ) ),
1836 // Does source URI describe a tdoc folder or stream?
1837 Uri
aSourceUri( rInfo
.SourceURL
);
1838 if ( !aSourceUri
.isValid() )
1840 ucbhelper::cancelCommandExecution(
1841 uno::makeAny( lang::IllegalArgumentException(
1842 "Invalid source URI! Syntax!",
1843 static_cast< cppu::OWeakObject
* >( this ),
1849 if ( aSourceUri
.isRoot() || aSourceUri
.isDocument() )
1851 ucbhelper::cancelCommandExecution(
1852 uno::makeAny( lang::IllegalArgumentException(
1853 "Invalid source URI! Must describe a folder or stream!",
1854 static_cast< cppu::OWeakObject
* >( this ),
1860 // Is source not a parent of me / not me?
1861 OUString aId
= m_xIdentifier
->getContentIdentifier();
1862 sal_Int32 nPos
= aId
.lastIndexOf( '/' );
1863 if ( nPos
!= ( aId
.getLength() - 1 ) )
1865 // No trailing slash found. Append.
1869 if ( rInfo
.SourceURL
.getLength() <= aId
.getLength() )
1871 if ( aId
.startsWith( rInfo
.SourceURL
) )
1873 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1875 {"Uri", uno::Any(rInfo
.SourceURL
)}
1877 ucbhelper::cancelCommandExecution(
1878 ucb::IOErrorCode_RECURSIVE
,
1881 "Target is equal to or is a child of source!",
1887 if ( m_aProps
.getType() == DOCUMENT
)
1891 uno::Reference
< embed::XStorage
> xStorage
1892 = m_pProvider
->queryStorage(
1893 aSourceUri
.getParentUri(), READ_WRITE_NOCREATE
);
1894 if ( xStorage
.is() )
1898 if ( xStorage
->isStreamElement( aSourceUri
.getDecodedName() ) )
1900 ucbhelper::cancelCommandExecution(
1901 uno::makeAny( lang::IllegalArgumentException(
1902 "Invalid source URI! "
1903 "Streams cannot be created as "
1904 "children of document root!",
1905 static_cast< cppu::OWeakObject
* >(
1913 catch ( container::NoSuchElementException
const & )
1917 catch ( lang::IllegalArgumentException
const & )
1921 catch ( embed::InvalidStorageException
const & )
1929 ucbhelper::cancelCommandExecution(
1930 uno::makeAny( lang::IllegalArgumentException(
1931 "Invalid source URI! Unable to determine source type!",
1932 static_cast< cppu::OWeakObject
* >( this ),
1943 OUString
aNewName( !rInfo
.NewTitle
.isEmpty()
1945 : aSourceUri
.getDecodedName() );
1947 if ( !copyData( aSourceUri
, aNewName
) )
1949 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1951 {"Uri", uno::Any(rInfo
.SourceURL
)}
1953 ucbhelper::cancelCommandExecution(
1954 ucb::IOErrorCode_CANT_WRITE
,
1957 "Cannot copy data!",
1963 // Copy own and all children's Additional Core Properties.
1966 OUString aTargetUri
= m_xIdentifier
->getContentIdentifier();
1967 if ( ( aTargetUri
.lastIndexOf( '/' ) + 1 ) != aTargetUri
.getLength() )
1970 if ( !rInfo
.NewTitle
.isEmpty() )
1971 aTargetUri
+= ::ucb_impl::urihelper::encodeSegment( rInfo
.NewTitle
);
1973 aTargetUri
+= aSourceUri
.getName();
1975 if ( !copyAdditionalPropertySet( aSourceUri
.getUri(), aTargetUri
) )
1977 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
1979 {"Uri", uno::Any(rInfo
.SourceURL
)}
1981 ucbhelper::cancelCommandExecution(
1982 ucb::IOErrorCode_CANT_WRITE
,
1985 "Cannot copy additional properties!",
1991 // Propagate new content.
1994 rtl::Reference
< Content
> xTarget
;
1997 uno::Reference
< ucb::XContentIdentifier
> xTargetId
1998 = new ::ucbhelper::ContentIdentifier( aTargetUri
);
2000 // Note: The static cast is okay here, because its sure that
2001 // m_xProvider is always the WebDAVContentProvider.
2002 xTarget
= static_cast< Content
* >(
2003 m_pProvider
->queryContent( xTargetId
).get() );
2006 catch ( ucb::IllegalIdentifierException
const & )
2011 if ( !xTarget
.is() )
2013 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2015 {"Uri", uno::Any(aTargetUri
)}
2017 ucbhelper::cancelCommandExecution(
2018 ucb::IOErrorCode_CANT_READ
,
2021 "Cannot instantiate target object!",
2026 // Announce transferred content in its new folder.
2027 xTarget
->inserted();
2030 // Remove source, if requested
2033 if ( !rInfo
.MoveData
)
2036 rtl::Reference
< Content
> xSource
;
2039 uno::Reference
< ucb::XContentIdentifier
>
2040 xSourceId
= new ::ucbhelper::ContentIdentifier( rInfo
.SourceURL
);
2042 // Note: The static cast is okay here, because its sure
2043 // that m_xProvider is always the ContentProvider.
2044 xSource
= static_cast< Content
* >(
2045 m_xProvider
->queryContent( xSourceId
).get() );
2047 catch ( ucb::IllegalIdentifierException
const & )
2052 if ( !xSource
.is() )
2054 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2056 {"Uri", uno::Any(rInfo
.SourceURL
)}
2058 ucbhelper::cancelCommandExecution(
2059 ucb::IOErrorCode_CANT_READ
,
2062 "Cannot instantiate target object!",
2067 // Propagate destruction (recursively).
2068 xSource
->destroy( true, xEnv
);
2070 // Remove all persistent data of source and its children.
2071 if ( !xSource
->removeData() )
2073 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2075 {"Uri", uno::Any(rInfo
.SourceURL
)}
2077 ucbhelper::cancelCommandExecution(
2078 ucb::IOErrorCode_CANT_WRITE
,
2081 "Cannot remove persistent data of source object!",
2086 // Remove own and all children's Additional Core Properties.
2087 if ( xSource
->removeAdditionalPropertySet() )
2090 uno::Sequence
<uno::Any
> aArgs(comphelper::InitAnyPropertySequence(
2092 {"Uri", uno::Any(rInfo
.SourceURL
)}
2094 ucbhelper::cancelCommandExecution(
2095 ucb::IOErrorCode_CANT_WRITE
,
2098 "Cannot remove additional properties of source object!",
2105 bool Content::hasData( ContentProvider
const * pProvider
, const Uri
& rUri
)
2107 if ( rUri
.isRoot() )
2109 return true; // root has no storage
2111 else if ( rUri
.isDocument() )
2113 uno::Reference
< embed::XStorage
> xStorage
2114 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2115 return xStorage
.is();
2121 // Ask parent storage. In case that rUri describes a stream,
2122 // ContentProvider::queryStorage( rUri ) would return null.
2124 uno::Reference
< embed::XStorage
> xStorage
2125 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2127 if ( !xStorage
.is() )
2130 return xStorage
->hasByName( rUri
.getDecodedName() );
2136 bool Content::loadData( ContentProvider
const * pProvider
,
2138 ContentProperties
& rProps
)
2140 if ( rUri
.isRoot() ) // root has no storage, but can always be created
2143 = ContentProperties(
2144 ROOT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2146 else if ( rUri
.isDocument() ) // document must have storage
2148 uno::Reference
< embed::XStorage
> xStorage
2149 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2151 if ( !xStorage
.is() )
2155 = ContentProperties(
2156 DOCUMENT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2158 else // stream or folder; stream has no storage; folder has storage
2160 uno::Reference
< embed::XStorage
> xStorage
2161 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2163 if ( !xStorage
.is() )
2166 // Check whether exists at all, is stream or folder
2169 // return: true -> folder
2170 // return: false -> stream
2171 // NoSuchElementException -> neither folder nor stream
2173 = xStorage
->isStorageElement( rUri
.getDecodedName() );
2176 = ContentProperties(
2177 bIsFolder
? FOLDER
: STREAM
,
2178 pProvider
->queryStorageTitle( rUri
.getUri() ) );
2180 catch ( container::NoSuchElementException
const & )
2182 // there is no element with such name
2183 //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2186 catch ( lang::IllegalArgumentException
const & )
2188 // an illegal argument is provided
2189 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2192 catch ( embed::InvalidStorageException
const & )
2194 // this storage is in invalid state for any reason
2195 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2203 bool Content::storeData( const uno::Reference
< io::XInputStream
>& xData
,
2204 const uno::Reference
<
2205 ucb::XCommandEnvironment
>& xEnv
)
2207 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2209 ContentType eType
= m_aProps
.getType();
2210 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2212 OSL_FAIL( "storeData not supported by root and documents!" );
2216 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2218 if ( eType
== FOLDER
)
2220 uno::Reference
< embed::XStorage
> xStorage
2221 = m_pProvider
->queryStorage( aUri
.getUri(), READ_WRITE_CREATE
);
2223 if ( !xStorage
.is() )
2226 uno::Reference
< beans::XPropertySet
> xPropSet(
2227 xStorage
, uno::UNO_QUERY
);
2228 OSL_ENSURE( xPropSet
.is(),
2229 "Content::storeData - Got no XPropertySet interface!" );
2230 if ( !xPropSet
.is() )
2235 // According to MBA, if no mediatype is set, folder and all
2236 // its contents will be lost on save of the document!!!
2237 xPropSet
->setPropertyValue(
2240 OUString( // @@@ better mediatype
2241 "application/binary" ) ) );
2243 catch ( beans::UnknownPropertyException
const & )
2245 OSL_FAIL( "Property MediaType not supported!" );
2248 catch ( beans::PropertyVetoException
const & )
2250 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2253 catch ( lang::IllegalArgumentException
const & )
2255 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2258 catch ( lang::WrappedTargetException
const & )
2260 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2264 if ( !commitStorage( xStorage
) )
2267 else if ( eType
== STREAM
)
2271 // Important: Parent storage and output stream must be kept alive until
2272 // changes have been committed!
2273 uno::Reference
< embed::XStorage
> xStorage
2274 = m_pProvider
->queryStorage(
2275 aUri
.getParentUri(), READ_WRITE_CREATE
);
2276 uno::Reference
< io::XOutputStream
> xOut
;
2278 if ( !xStorage
.is() )
2283 // May throw CommandFailedException, DocumentPasswordRequest!
2284 xOut
= getTruncatedOutputStream( xEnv
);
2286 OSL_ENSURE( xOut
.is(), "No target data stream!" );
2290 uno::Sequence
< sal_Int8
> aBuffer
;
2293 sal_Int32 nRead
= xData
->readSomeBytes( aBuffer
, 65536 );
2296 aBuffer
.realloc( nRead
);
2297 xOut
->writeBytes( aBuffer
);
2300 closeOutputStream( xOut
);
2302 catch ( io::NotConnectedException
const & )
2304 // readSomeBytes, writeBytes
2305 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2306 closeOutputStream( xOut
);
2309 catch ( io::BufferSizeExceededException
const & )
2311 // readSomeBytes, writeBytes
2312 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2313 closeOutputStream( xOut
);
2316 catch ( io::IOException
const & )
2318 // readSomeBytes, writeBytes
2319 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2320 closeOutputStream( xOut
);
2325 closeOutputStream( xOut
);
2331 if ( !commitStorage( xStorage
) )
2336 OSL_FAIL( "Unknown content type!" );
2343 void Content::renameData(
2344 const uno::Reference
< ucb::XContentIdentifier
>& xOldId
,
2345 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
2347 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2349 ContentType eType
= m_aProps
.getType();
2350 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2352 OSL_FAIL( "renameData not supported by root and documents!" );
2356 Uri
aOldUri( xOldId
->getContentIdentifier() );
2357 uno::Reference
< embed::XStorage
> xStorage
2358 = m_pProvider
->queryStorage(
2359 aOldUri
.getParentUri(), READ_WRITE_NOCREATE
);
2361 if ( !xStorage
.is() )
2366 Uri
aNewUri( xNewId
->getContentIdentifier() );
2367 xStorage
->renameElement(
2368 aOldUri
.getDecodedName(), aNewUri
.getDecodedName() );
2370 catch ( embed::InvalidStorageException
const & )
2372 // this storage is in invalid state for any reason
2373 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2376 catch ( lang::IllegalArgumentException
const & )
2378 // an illegal argument is provided
2379 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2382 catch ( container::NoSuchElementException
const & )
2384 // there is no element with old name in this storage
2385 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2388 catch ( container::ElementExistException
const & )
2390 // an element with new name already exists in this storage
2391 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2394 catch ( io::IOException
const & )
2396 // in case of io errors during renaming
2397 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2400 catch ( embed::StorageWrappedTargetException
const & )
2402 // wraps other exceptions
2403 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2407 commitStorage( xStorage
);
2411 bool Content::removeData()
2413 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2415 ContentType eType
= m_aProps
.getType();
2416 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2418 OSL_FAIL( "removeData not supported by root and documents!" );
2422 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2423 uno::Reference
< embed::XStorage
> xStorage
2424 = m_pProvider
->queryStorage(
2425 aUri
.getParentUri(), READ_WRITE_NOCREATE
);
2427 if ( !xStorage
.is() )
2432 xStorage
->removeElement( aUri
.getDecodedName() );
2434 catch ( embed::InvalidStorageException
const & )
2436 // this storage is in invalid state for any reason
2437 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2440 catch ( lang::IllegalArgumentException
const & )
2442 // an illegal argument is provided
2443 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2446 catch ( container::NoSuchElementException
const & )
2448 // there is no element with this name in this storage
2449 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2452 catch ( io::IOException
const & )
2454 // in case of io errors during renaming
2455 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2458 catch ( embed::StorageWrappedTargetException
const & )
2460 // wraps other exceptions
2461 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2465 return commitStorage( xStorage
);
2469 bool Content::copyData( const Uri
& rSourceUri
, const OUString
& rNewName
)
2471 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2473 ContentType eType
= m_aProps
.getType();
2474 if ( ( eType
== ROOT
) || ( eType
== STREAM
) )
2476 OSL_FAIL( "copyData not supported by root and streams!" );
2480 Uri
aDestUri( m_xIdentifier
->getContentIdentifier() );
2481 uno::Reference
< embed::XStorage
> xDestStorage
2482 = m_pProvider
->queryStorage( aDestUri
.getUri(), READ_WRITE_NOCREATE
);
2484 if ( !xDestStorage
.is() )
2487 uno::Reference
< embed::XStorage
> xSourceStorage
2488 = m_pProvider
->queryStorage( rSourceUri
.getParentUri(), READ
);
2490 if ( !xSourceStorage
.is() )
2495 xSourceStorage
->copyElementTo( rSourceUri
.getDecodedName(),
2499 catch ( embed::InvalidStorageException
const & )
2501 // this storage is in invalid state for any reason
2502 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2505 catch ( lang::IllegalArgumentException
const & )
2507 // an illegal argument is provided
2508 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2511 catch ( container::NoSuchElementException
const & )
2513 // there is no element with this name in this storage
2514 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2517 catch ( container::ElementExistException
const & )
2519 // there is no element with this name in this storage
2520 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2523 catch ( io::IOException
const & )
2525 // in case of io errors during renaming
2526 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2529 catch ( embed::StorageWrappedTargetException
const & )
2531 // wraps other exceptions
2532 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2536 return commitStorage( xDestStorage
);
2541 bool Content::commitStorage( const uno::Reference
< embed::XStorage
> & xStorage
)
2544 uno::Reference
< embed::XTransactedObject
> xTO( xStorage
, uno::UNO_QUERY
);
2546 OSL_ENSURE( xTO
.is(),
2547 "Required interface css.embed.XTransactedObject missing!" );
2552 catch ( io::IOException
const & )
2554 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2557 catch ( lang::WrappedTargetException
const & )
2559 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2568 bool Content::closeOutputStream(
2569 const uno::Reference
< io::XOutputStream
> & xOut
)
2575 xOut
->closeOutput();
2578 catch ( io::NotConnectedException
const & )
2580 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2582 catch ( io::BufferSizeExceededException
const & )
2584 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2586 catch ( io::IOException
const & )
2588 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
2594 /// @throws ucb::CommandFailedException
2595 /// @throws task::DocumentPasswordRequest
2596 static OUString
obtainPassword(
2597 const OUString
& rName
,
2598 task::PasswordRequestMode eMode
,
2599 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2601 rtl::Reference
< DocumentPasswordRequest
> xRequest
2602 = new DocumentPasswordRequest( eMode
, rName
);
2606 uno::Reference
< task::XInteractionHandler
> xIH
2607 = xEnv
->getInteractionHandler();
2610 xIH
->handle( xRequest
);
2612 rtl::Reference
< ucbhelper::InteractionContinuation
> xSelection
2613 = xRequest
->getSelection();
2615 if ( xSelection
.is() )
2617 // Handler handled the request.
2618 uno::Reference
< task::XInteractionAbort
> xAbort(
2619 xSelection
.get(), uno::UNO_QUERY
);
2622 throw ucb::CommandFailedException(
2623 "Abort requested by Interaction Handler.",
2624 uno::Reference
< uno::XInterface
>(),
2625 xRequest
->getRequest() );
2628 uno::Reference
< task::XInteractionPassword
> xPassword(
2629 xSelection
.get(), uno::UNO_QUERY
);
2630 if ( xPassword
.is() )
2632 return xPassword
->getPassword();
2635 // Unknown selection. Should never happen.
2636 throw ucb::CommandFailedException(
2637 "Interaction Handler selected unknown continuation!",
2638 uno::Reference
< uno::XInterface
>(),
2639 xRequest
->getRequest() );
2644 // No IH or IH did not handle exception.
2645 task::DocumentPasswordRequest aRequest
;
2646 xRequest
->getRequest() >>= aRequest
;
2651 uno::Reference
< io::XInputStream
> Content::getInputStream(
2652 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2656 bool bPasswordRequested
= false;
2659 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2661 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2662 "Content::getInputStream - content is no stream!" );
2664 aUri
= Uri( m_xIdentifier
->getContentIdentifier() ).getUri();
2671 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2672 return m_pProvider
->queryInputStream( aUri
, aPassword
);
2674 catch ( packages::WrongPasswordException
const & )
2676 // Obtain (new) password.
2678 = obtainPassword( aUri
, /* @@@ find better title */
2680 ? task::PasswordRequestMode_PASSWORD_REENTER
2681 : task::PasswordRequestMode_PASSWORD_ENTER
,
2683 bPasswordRequested
= true;
2688 /// @throws ucb::CommandFailedException
2689 /// @throws task::DocumentPasswordRequest
2690 /// @throws uno::RuntimeException
2691 static uno::Reference
< io::XOutputStream
> lcl_getTruncatedOutputStream(
2692 const OUString
& rUri
,
2693 ContentProvider
const * pProvider
,
2694 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2697 bool bPasswordRequested
= false;
2702 return pProvider
->queryOutputStream(
2703 rUri
, aPassword
, true /* truncate */ );
2705 catch ( packages::WrongPasswordException
const & )
2707 // Obtain (new) password.
2709 = obtainPassword( rUri
, /* @@@ find better title */
2711 ? task::PasswordRequestMode_PASSWORD_REENTER
2712 : task::PasswordRequestMode_PASSWORD_ENTER
,
2714 bPasswordRequested
= true;
2720 uno::Reference
< io::XOutputStream
> Content::getTruncatedOutputStream(
2721 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2723 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2724 "Content::getTruncatedOutputStream - content is no stream!" );
2726 return lcl_getTruncatedOutputStream(
2727 Uri( m_xIdentifier
->getContentIdentifier() ).getUri(),
2733 uno::Reference
< io::XStream
> Content::getStream(
2734 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2736 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2738 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2739 "Content::getStream - content is no stream!" );
2741 OUString
aUri( Uri( m_xIdentifier
->getContentIdentifier() ).getUri() );
2743 bool bPasswordRequested
= false;
2748 return m_pProvider
->queryStream(
2749 aUri
, aPassword
, false /* no truncate */ );
2751 catch ( packages::WrongPasswordException
const & )
2753 // Obtain (new) password.
2755 = obtainPassword( aUri
, /* @@@ find better title */
2757 ? task::PasswordRequestMode_PASSWORD_REENTER
2758 : task::PasswordRequestMode_PASSWORD_ENTER
,
2760 bPasswordRequested
= true;
2766 // ContentProperties Implementation.
2769 uno::Sequence
< ucb::ContentInfo
>
2770 ContentProperties::getCreatableContentsInfo() const
2772 if ( isContentCreator() )
2774 uno::Sequence
< beans::Property
> aProps( 1 );
2775 aProps
.getArray()[ 0 ] = beans::Property(
2778 cppu::UnoType
<OUString
>::get(),
2779 beans::PropertyAttribute::BOUND
);
2781 if ( getType() == DOCUMENT
)
2783 // streams cannot be created as direct children of document root
2784 uno::Sequence
< ucb::ContentInfo
> aSeq( 1 );
2787 aSeq
.getArray()[ 0 ].Type
= TDOC_FOLDER_CONTENT_TYPE
;
2788 aSeq
.getArray()[ 0 ].Attributes
= ucb::ContentInfoAttribute::KIND_FOLDER
;
2789 aSeq
.getArray()[ 0 ].Properties
= aProps
;
2795 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
2798 aSeq
.getArray()[ 0 ].Type
= TDOC_FOLDER_CONTENT_TYPE
;
2799 aSeq
.getArray()[ 0 ].Attributes
2800 = ucb::ContentInfoAttribute::KIND_FOLDER
;
2801 aSeq
.getArray()[ 0 ].Properties
= aProps
;
2804 aSeq
.getArray()[ 1 ].Type
= TDOC_STREAM_CONTENT_TYPE
;
2805 aSeq
.getArray()[ 1 ].Attributes
2806 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
2807 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
2808 aSeq
.getArray()[ 1 ].Properties
= aProps
;
2815 OSL_FAIL( "getCreatableContentsInfo called on non-contentcreator "
2818 return uno::Sequence
< ucb::ContentInfo
>( 0 );
2823 bool ContentProperties::isContentCreator() const
2825 return ( getType() == FOLDER
) || ( getType() == DOCUMENT
);
2828 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */