1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tdoc_content.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
36 **************************************************************************
38 *************************************************************************/
40 #include "osl/diagnose.h"
41 #include "osl/doublecheckedlocking.h"
42 #include "rtl/ustrbuf.hxx"
44 #include "com/sun/star/beans/PropertyAttribute.hpp"
45 #include "com/sun/star/beans/PropertyValue.hpp"
46 #include "com/sun/star/beans/XPropertySet.hpp"
47 #include "com/sun/star/embed/ElementModes.hpp"
48 #include "com/sun/star/embed/XStorage.hpp"
49 #include "com/sun/star/embed/XTransactedObject.hpp"
50 #include "com/sun/star/io/XActiveDataSink.hpp"
51 #include "com/sun/star/io/XActiveDataStreamer.hpp"
52 #include "com/sun/star/lang/IllegalAccessException.hpp"
53 #include "com/sun/star/sdbc/XRow.hpp"
54 #include "com/sun/star/ucb/ContentAction.hpp"
55 #include "com/sun/star/ucb/ContentInfoAttribute.hpp"
56 #include "com/sun/star/ucb/InsertCommandArgument.hpp"
57 #include "com/sun/star/ucb/InteractiveBadTransferURLException.hpp"
58 #include "com/sun/star/ucb/MissingInputStreamException.hpp"
59 #include "com/sun/star/ucb/MissingPropertiesException.hpp"
60 #include "com/sun/star/ucb/NameClash.hpp"
61 #include "com/sun/star/ucb/NameClashException.hpp"
62 #include "com/sun/star/ucb/OpenCommandArgument2.hpp"
63 #include "com/sun/star/ucb/OpenMode.hpp"
64 #include "com/sun/star/ucb/TransferInfo.hpp"
65 #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
66 #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp"
67 #include "com/sun/star/ucb/UnsupportedNameClashException.hpp"
68 #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp"
69 #include "com/sun/star/ucb/XCommandInfo.hpp"
70 #include "com/sun/star/ucb/XPersistentPropertySet.hpp"
72 #include "ucbhelper/cancelcommandexecution.hxx"
73 #include "ucbhelper/contentidentifier.hxx"
74 #include "ucbhelper/propertyvalueset.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
;
85 //=========================================================================
86 static ContentType
lcl_getContentType( const rtl::OUString
& rType
)
88 if ( rType
.equalsAsciiL(
89 RTL_CONSTASCII_STRINGPARAM( TDOC_ROOT_CONTENT_TYPE
) ) )
91 else if ( rType
.equalsAsciiL(
92 RTL_CONSTASCII_STRINGPARAM( TDOC_DOCUMENT_CONTENT_TYPE
) ) )
94 else if ( rType
.equalsAsciiL(
95 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE
) ) )
97 else if ( rType
.equalsAsciiL(
98 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE
) ) )
102 OSL_ENSURE( sal_False
,
103 "Content::Content - unsupported content type string" );
108 //=========================================================================
109 //=========================================================================
111 // Content Implementation.
113 //=========================================================================
114 //=========================================================================
116 // static ( "virtual" ctor )
117 Content
* Content::create(
118 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
119 ContentProvider
* pProvider
,
120 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
122 // Fail, if resource does not exist.
123 ContentProperties aProps
;
124 if ( !Content::loadData( pProvider
,
125 Uri( Identifier
->getContentIdentifier() ),
129 return new Content( rxSMgr
, pProvider
, Identifier
, aProps
);
132 //=========================================================================
133 // static ( "virtual" ctor )
134 Content
* Content::create(
135 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
136 ContentProvider
* pProvider
,
137 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
138 const ucb::ContentInfo
& Info
)
140 if ( !Info
.Type
.getLength() )
143 if ( !Info
.Type
.equalsAsciiL(
144 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE
) ) &&
145 !Info
.Type
.equalsAsciiL(
146 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE
) ) )
148 OSL_ENSURE( sal_False
, "Content::create - unsupported content type!" );
153 // Fail, if content does exist.
154 if ( Content::hasData( pProvider
,
155 Uri( Identifier
->getContentIdentifier() ) ) )
159 return new Content( rxSMgr
, pProvider
, Identifier
, Info
);
162 //=========================================================================
164 const uno::Reference
< lang::XMultiServiceFactory
> & rxSMgr
,
165 ContentProvider
* pProvider
,
166 const uno::Reference
< ucb::XContentIdentifier
> & Identifier
,
167 const ContentProperties
& rProps
)
168 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
170 m_eState( PERSISTENT
),
171 m_pProvider( pProvider
)
175 //=========================================================================
176 // ctor for a content just created via XContentCreator::createNewContent()
178 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
179 ContentProvider
* pProvider
,
180 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
181 const ucb::ContentInfo
& Info
)
182 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
183 m_aProps( lcl_getContentType( Info
.Type
), rtl::OUString() ), // no Title (yet)
184 m_eState( TRANSIENT
),
185 m_pProvider( pProvider
)
189 //=========================================================================
195 //=========================================================================
197 // XInterface methods.
199 //=========================================================================
202 void SAL_CALL
Content::acquire()
205 ContentImplHelper::acquire();
208 //=========================================================================
210 void SAL_CALL
Content::release()
213 ContentImplHelper::release();
216 //=========================================================================
218 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
219 throw ( uno::RuntimeException
)
221 uno::Any aRet
= ContentImplHelper::queryInterface( rType
);
223 if ( !aRet
.hasValue() )
225 aRet
= cppu::queryInterface(
226 rType
, static_cast< ucb::XContentCreator
* >( this ) );
227 if ( aRet
.hasValue() )
229 if ( !isContentCreator() )
237 //=========================================================================
239 // XTypeProvider methods.
241 //=========================================================================
243 XTYPEPROVIDER_COMMON_IMPL( Content
);
245 //=========================================================================
247 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
248 throw( uno::RuntimeException
)
250 cppu::OTypeCollection
* pCollection
= 0;
252 if ( isContentCreator() )
254 static cppu::OTypeCollection
* pFolderTypes
= 0;
256 pCollection
= pFolderTypes
;
259 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
261 pCollection
= pFolderTypes
;
264 static cppu::OTypeCollection
aCollection(
265 CPPU_TYPE_REF( lang::XTypeProvider
),
266 CPPU_TYPE_REF( lang::XServiceInfo
),
267 CPPU_TYPE_REF( lang::XComponent
),
268 CPPU_TYPE_REF( ucb::XContent
),
269 CPPU_TYPE_REF( ucb::XCommandProcessor
),
270 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
271 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
272 CPPU_TYPE_REF( beans::XPropertyContainer
),
273 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
274 CPPU_TYPE_REF( container::XChild
),
275 CPPU_TYPE_REF( ucb::XContentCreator
) ); // !!
276 pCollection
= &aCollection
;
277 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
278 pFolderTypes
= pCollection
;
282 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
287 static cppu::OTypeCollection
* pDocumentTypes
= 0;
289 pCollection
= pDocumentTypes
;
292 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
294 pCollection
= pDocumentTypes
;
297 static cppu::OTypeCollection
aCollection(
298 CPPU_TYPE_REF( lang::XTypeProvider
),
299 CPPU_TYPE_REF( lang::XServiceInfo
),
300 CPPU_TYPE_REF( lang::XComponent
),
301 CPPU_TYPE_REF( ucb::XContent
),
302 CPPU_TYPE_REF( ucb::XCommandProcessor
),
303 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
304 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
305 CPPU_TYPE_REF( beans::XPropertyContainer
),
306 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
307 CPPU_TYPE_REF( container::XChild
) );
308 pCollection
= &aCollection
;
309 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
310 pDocumentTypes
= pCollection
;
314 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
318 return (*pCollection
).getTypes();
321 //=========================================================================
323 // XServiceInfo methods.
325 //=========================================================================
328 rtl::OUString SAL_CALL
Content::getImplementationName()
329 throw( uno::RuntimeException
)
331 return rtl::OUString::createFromAscii(
332 "com.sun.star.comp.ucb.TransientDocumentsContent" );
335 //=========================================================================
337 uno::Sequence
< rtl::OUString
> SAL_CALL
Content::getSupportedServiceNames()
338 throw( uno::RuntimeException
)
340 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
342 uno::Sequence
< rtl::OUString
> aSNS( 1 );
344 if ( m_aProps
.getType() == STREAM
)
345 aSNS
.getArray()[ 0 ] = rtl::OUString::createFromAscii(
346 TDOC_STREAM_CONTENT_SERVICE_NAME
);
347 else if ( m_aProps
.getType() == FOLDER
)
348 aSNS
.getArray()[ 0 ] = rtl::OUString::createFromAscii(
349 TDOC_FOLDER_CONTENT_SERVICE_NAME
);
350 else if ( m_aProps
.getType() == DOCUMENT
)
351 aSNS
.getArray()[ 0 ] = rtl::OUString::createFromAscii(
352 TDOC_DOCUMENT_CONTENT_SERVICE_NAME
);
354 aSNS
.getArray()[ 0 ] = rtl::OUString::createFromAscii(
355 TDOC_ROOT_CONTENT_SERVICE_NAME
);
360 //=========================================================================
364 //=========================================================================
367 rtl::OUString SAL_CALL
Content::getContentType()
368 throw( uno::RuntimeException
)
370 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
371 return m_aProps
.getContentType();
374 //=========================================================================
376 uno::Reference
< ucb::XContentIdentifier
> SAL_CALL
377 Content::getIdentifier()
378 throw( uno::RuntimeException
)
381 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
384 if ( m_eState
== TRANSIENT
)
386 // Transient contents have no identifier.
387 return uno::Reference
< ucb::XContentIdentifier
>();
390 return ContentImplHelper::getIdentifier();
393 //=========================================================================
395 // XCommandProcessor methods.
397 //=========================================================================
400 uno::Any SAL_CALL
Content::execute(
401 const ucb::Command
& aCommand
,
402 sal_Int32
/*CommandId*/,
403 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
404 throw( uno::Exception
,
405 ucb::CommandAbortedException
,
406 uno::RuntimeException
)
410 if ( aCommand
.Name
.equalsAsciiL(
411 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
413 //////////////////////////////////////////////////////////////////
415 //////////////////////////////////////////////////////////////////
417 uno::Sequence
< beans::Property
> Properties
;
418 if ( !( aCommand
.Argument
>>= Properties
) )
420 ucbhelper::cancelCommandExecution(
421 uno::makeAny( lang::IllegalArgumentException(
422 rtl::OUString::createFromAscii(
423 "Wrong argument type!" ),
424 static_cast< cppu::OWeakObject
* >( this ),
430 aRet
<<= getPropertyValues( Properties
);
432 else if ( aCommand
.Name
.equalsAsciiL(
433 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
435 //////////////////////////////////////////////////////////////////
437 //////////////////////////////////////////////////////////////////
439 uno::Sequence
< beans::PropertyValue
> aProperties
;
440 if ( !( aCommand
.Argument
>>= aProperties
) )
442 ucbhelper::cancelCommandExecution(
443 uno::makeAny( lang::IllegalArgumentException(
444 rtl::OUString::createFromAscii(
445 "Wrong argument type!" ),
446 static_cast< cppu::OWeakObject
* >( this ),
452 if ( !aProperties
.getLength() )
454 ucbhelper::cancelCommandExecution(
455 uno::makeAny( lang::IllegalArgumentException(
456 rtl::OUString::createFromAscii(
458 static_cast< cppu::OWeakObject
* >( this ),
464 aRet
<<= setPropertyValues( aProperties
, Environment
);
466 else if ( aCommand
.Name
.equalsAsciiL(
467 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
469 //////////////////////////////////////////////////////////////////
470 // getPropertySetInfo
471 //////////////////////////////////////////////////////////////////
473 aRet
<<= getPropertySetInfo( Environment
);
475 else if ( aCommand
.Name
.equalsAsciiL(
476 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
478 //////////////////////////////////////////////////////////////////
480 //////////////////////////////////////////////////////////////////
482 aRet
<<= getCommandInfo( Environment
);
484 else if ( aCommand
.Name
.equalsAsciiL(
485 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
487 //////////////////////////////////////////////////////////////////
489 //////////////////////////////////////////////////////////////////
491 ucb::OpenCommandArgument2 aOpenCommand
;
492 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
494 ucbhelper::cancelCommandExecution(
495 uno::makeAny( lang::IllegalArgumentException(
496 rtl::OUString::createFromAscii(
497 "Wrong argument type!" ),
498 static_cast< cppu::OWeakObject
* >( this ),
504 aRet
= open( aOpenCommand
, Environment
);
506 else if ( aCommand
.Name
.equalsAsciiL(
507 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
509 //////////////////////////////////////////////////////////////////
510 // insert ( Supported by folders and streams only )
511 //////////////////////////////////////////////////////////////////
513 ContentType eType
= m_aProps
.getType();
514 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
516 ucbhelper::cancelCommandExecution(
517 uno::makeAny( ucb::UnsupportedCommandException(
519 RTL_CONSTASCII_USTRINGPARAM(
520 "insert command only supported by "
521 "folders and streams!" ) ),
522 static_cast< cppu::OWeakObject
* >( this ) ) ),
527 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
528 if ( eType
== STREAM
)
530 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
531 Uri
aParentUri( aUri
.getParentUri() );
532 if ( aParentUri
.isDocument() )
534 ucbhelper::cancelCommandExecution(
535 uno::makeAny( ucb::UnsupportedCommandException(
537 RTL_CONSTASCII_USTRINGPARAM(
538 "insert command not supported by "
539 "streams that are direct children "
540 "of document root!" ) ),
541 static_cast< cppu::OWeakObject
* >(
548 ucb::InsertCommandArgument aArg
;
549 if ( !( aCommand
.Argument
>>= aArg
) )
551 ucbhelper::cancelCommandExecution(
552 uno::makeAny( lang::IllegalArgumentException(
553 rtl::OUString::createFromAscii(
554 "Wrong argument type!" ),
555 static_cast< cppu::OWeakObject
* >( this ),
561 sal_Int32 nNameClash
= aArg
.ReplaceExisting
562 ? ucb::NameClash::OVERWRITE
563 : ucb::NameClash::ERROR
;
564 insert( aArg
.Data
, nNameClash
, Environment
);
566 else if ( aCommand
.Name
.equalsAsciiL(
567 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
569 //////////////////////////////////////////////////////////////////
570 // delete ( Supported by folders and streams only )
571 //////////////////////////////////////////////////////////////////
574 osl::MutexGuard
aGuard( m_aMutex
);
576 ContentType eType
= m_aProps
.getType();
577 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
579 ucbhelper::cancelCommandExecution(
580 uno::makeAny( ucb::UnsupportedCommandException(
582 RTL_CONSTASCII_USTRINGPARAM(
583 "delete command only supported by "
584 "folders and streams!" ) ),
585 static_cast< cppu::OWeakObject
* >(
592 sal_Bool bDeletePhysical
= sal_False
;
593 aCommand
.Argument
>>= bDeletePhysical
;
594 destroy( bDeletePhysical
, Environment
);
596 // Remove own and all children's persistent data.
601 beans::PropertyValue(
602 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
605 uno::makeAny(m_xIdentifier
->
606 getContentIdentifier()),
607 beans::PropertyState_DIRECT_VALUE
));
608 ucbhelper::cancelCommandExecution(
609 ucb::IOErrorCode_CANT_WRITE
,
610 uno::Sequence
< uno::Any
>(&aProps
, 1),
612 rtl::OUString::createFromAscii(
613 "Cannot remove persistent data!" ),
618 // Remove own and all children's Additional Core Properties.
619 removeAdditionalPropertySet( sal_True
);
621 else if ( aCommand
.Name
.equalsAsciiL(
622 RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) )
624 //////////////////////////////////////////////////////////////////
625 // transfer ( Supported by document and folders only )
626 //////////////////////////////////////////////////////////////////
629 osl::MutexGuard
aGuard( m_aMutex
);
631 ContentType eType
= m_aProps
.getType();
632 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
634 ucbhelper::cancelCommandExecution(
635 uno::makeAny( ucb::UnsupportedCommandException(
637 RTL_CONSTASCII_USTRINGPARAM(
638 "transfer command only supported "
639 "by folders and documents!" ) ),
640 static_cast< cppu::OWeakObject
* >(
647 ucb::TransferInfo aInfo
;
648 if ( !( aCommand
.Argument
>>= aInfo
) )
650 OSL_ENSURE( sal_False
, "Wrong argument type!" );
651 ucbhelper::cancelCommandExecution(
652 uno::makeAny( lang::IllegalArgumentException(
653 rtl::OUString::createFromAscii(
654 "Wrong argument type!" ),
655 static_cast< cppu::OWeakObject
* >( this ),
661 transfer( aInfo
, Environment
);
665 //////////////////////////////////////////////////////////////////
666 // Unsupported command
667 //////////////////////////////////////////////////////////////////
669 ucbhelper::cancelCommandExecution(
670 uno::makeAny( ucb::UnsupportedCommandException(
672 static_cast< cppu::OWeakObject
* >( this ) ) ),
680 //=========================================================================
682 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
683 throw( uno::RuntimeException
)
687 //=========================================================================
689 // XContentCreator methods.
691 //=========================================================================
694 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
695 Content::queryCreatableContentsInfo()
696 throw( uno::RuntimeException
)
698 if ( isContentCreator() )
700 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
702 uno::Sequence
< beans::Property
> aProps( 1 );
703 aProps
.getArray()[ 0 ] = beans::Property(
704 rtl::OUString::createFromAscii( "Title" ),
706 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
707 beans::PropertyAttribute::BOUND
);
709 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
710 if ( m_aProps
.getType() == DOCUMENT
)
712 // streams cannot be created as direct children of document root
713 uno::Sequence
< ucb::ContentInfo
> aSeq( 1 );
716 aSeq
.getArray()[ 0 ].Type
717 = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE
);
718 aSeq
.getArray()[ 0 ].Attributes
719 = ucb::ContentInfoAttribute::KIND_FOLDER
;
720 aSeq
.getArray()[ 0 ].Properties
= aProps
;
727 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
730 aSeq
.getArray()[ 0 ].Type
731 = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE
);
732 aSeq
.getArray()[ 0 ].Attributes
733 = ucb::ContentInfoAttribute::KIND_FOLDER
;
734 aSeq
.getArray()[ 0 ].Properties
= aProps
;
737 aSeq
.getArray()[ 1 ].Type
738 = rtl::OUString::createFromAscii( TDOC_STREAM_CONTENT_TYPE
);
739 aSeq
.getArray()[ 1 ].Attributes
740 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
741 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
742 aSeq
.getArray()[ 1 ].Properties
= aProps
;
745 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
751 OSL_ENSURE( sal_False
,
752 "queryCreatableContentsInfo called on non-contentcreator "
755 return uno::Sequence
< ucb::ContentInfo
>( 0 );
759 //=========================================================================
761 uno::Reference
< ucb::XContent
> SAL_CALL
762 Content::createNewContent( const ucb::ContentInfo
& Info
)
763 throw( uno::RuntimeException
)
765 if ( isContentCreator() )
767 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
769 if ( !Info
.Type
.getLength() )
770 return uno::Reference
< ucb::XContent
>();
772 sal_Bool bCreateFolder
=
773 Info
.Type
.equalsAsciiL(
774 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE
) );
776 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
777 // streams cannot be created as direct children of document root
778 if ( !bCreateFolder
&& ( m_aProps
.getType() == DOCUMENT
) )
780 OSL_ENSURE( sal_False
,
781 "Content::createNewContent - streams cannot be "
782 "created as direct children of document root!" );
783 return uno::Reference
< ucb::XContent
>();
786 if ( !bCreateFolder
&&
787 !Info
.Type
.equalsAsciiL(
788 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE
) ) )
790 OSL_ENSURE( sal_False
,
791 "Content::createNewContent - unsupported type!" );
792 return uno::Reference
< ucb::XContent
>();
795 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
797 OSL_ENSURE( aURL
.getLength() > 0,
798 "Content::createNewContent - empty identifier!" );
800 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
801 aURL
+= rtl::OUString::createFromAscii( "/" );
804 aURL
+= rtl::OUString::createFromAscii( "New_Folder" );
806 aURL
+= rtl::OUString::createFromAscii( "New_Stream" );
808 uno::Reference
< ucb::XContentIdentifier
> xId
809 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aURL
);
811 return create( m_xSMgr
, m_pProvider
, xId
, Info
);
815 OSL_ENSURE( sal_False
,
816 "createNewContent called on non-contentcreator object!" );
817 return uno::Reference
< ucb::XContent
>();
821 //=========================================================================
823 rtl::OUString
Content::getParentURL()
825 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
826 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
827 return aUri
.getParentUri();
830 //=========================================================================
831 uno::Reference
< ucb::XContentIdentifier
>
832 Content::makeNewIdentifier( const rtl::OUString
& rTitle
)
834 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
836 // Assemble new content identifier...
837 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
838 rtl::OUStringBuffer aNewURL
= aUri
.getParentUri();
839 aNewURL
.append( ::ucb_impl::urihelper::encodeSegment( rTitle
) );
842 uno::Reference
< ucb::XContentIdentifier
>(
843 new ::ucbhelper::ContentIdentifier(
844 m_xSMgr
, aNewURL
.makeStringAndClear() ) );
847 //=========================================================================
848 void Content::queryChildren( ContentRefList
& rChildren
)
850 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
852 // Only folders (root, documents, folders) have children.
853 if ( !m_aProps
.getIsFolder() )
856 // Obtain a list with a snapshot of all currently instanciated contents
857 // from provider and extract the contents which are direct children
860 ::ucbhelper::ContentRefList aAllContents
;
861 m_xProvider
->queryExistingContents( aAllContents
);
863 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
864 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
866 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
868 // No trailing slash found. Append.
869 aURL
+= rtl::OUString::createFromAscii( "/" );
872 sal_Int32 nLen
= aURL
.getLength();
874 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
875 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
879 ::ucbhelper::ContentImplHelperRef xChild
= (*it
);
880 rtl::OUString aChildURL
881 = xChild
->getIdentifier()->getContentIdentifier();
883 // Is aURL a prefix of aChildURL?
884 if ( ( aChildURL
.getLength() > nLen
) &&
885 ( aChildURL
.compareTo( aURL
, nLen
) == 0 ) )
887 sal_Int32 nPos
= nLen
;
888 nPos
= aChildURL
.indexOf( '/', nPos
);
890 if ( ( nPos
== -1 ) ||
891 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
893 // No further slashes / only a final slash. It's a child!
896 static_cast< Content
* >( xChild
.get() ) ) );
903 //=========================================================================
904 sal_Bool
Content::exchangeIdentity(
905 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
910 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
912 uno::Reference
< ucb::XContent
> xThis
= this;
914 // Already persistent?
915 if ( m_eState
!= PERSISTENT
)
917 OSL_ENSURE( sal_False
,
918 "Content::exchangeIdentity - Not persistent!" );
922 // Only folders and streams can be renamed -> exchange identity.
923 ContentType eType
= m_aProps
.getType();
924 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
926 OSL_ENSURE( sal_False
, "Content::exchangeIdentity - "
927 "Not supported by root or document!" );
931 // Exchange own identitity.
933 // Fail, if a content with given id already exists.
934 if ( !hasData( Uri( xNewId
->getContentIdentifier() ) ) )
936 rtl::OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
939 if ( exchange( xNewId
) )
941 if ( eType
== FOLDER
)
943 // Process instanciated children...
945 ContentRefList aChildren
;
946 queryChildren( aChildren
);
948 ContentRefList::const_iterator it
= aChildren
.begin();
949 ContentRefList::const_iterator end
= aChildren
.end();
953 ContentRef xChild
= (*it
);
955 // Create new content identifier for the child...
956 uno::Reference
< ucb::XContentIdentifier
> xOldChildId
957 = xChild
->getIdentifier();
958 rtl::OUString aOldChildURL
959 = xOldChildId
->getContentIdentifier();
960 rtl::OUString aNewChildURL
961 = aOldChildURL
.replaceAt(
964 xNewId
->getContentIdentifier() );
965 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
966 = new ::ucbhelper::ContentIdentifier(
967 m_xSMgr
, aNewChildURL
);
969 if ( !xChild
->exchangeIdentity( xNewChildId
) )
979 OSL_ENSURE( sal_False
,
980 "Content::exchangeIdentity - "
981 "Panic! Cannot exchange identity!" );
985 //=========================================================================
987 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
988 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
989 const uno::Sequence
< beans::Property
>& rProperties
,
990 ContentProvider
* pProvider
,
991 const rtl::OUString
& rContentId
)
993 ContentProperties aData
;
994 if ( loadData( pProvider
, rContentId
, aData
) )
996 return getPropertyValues(
997 rSMgr
, rProperties
, aData
, pProvider
, rContentId
);
1001 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
1002 = new ::ucbhelper::PropertyValueSet( rSMgr
);
1004 sal_Int32 nCount
= rProperties
.getLength();
1007 const beans::Property
* pProps
= rProperties
.getConstArray();
1008 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1009 xRow
->appendVoid( pProps
[ n
] );
1012 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1016 //=========================================================================
1018 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1019 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
1020 const uno::Sequence
< beans::Property
>& rProperties
,
1021 const ContentProperties
& rData
,
1022 ContentProvider
* pProvider
,
1023 const rtl::OUString
& rContentId
)
1025 // Note: Empty sequence means "get values of all supported properties".
1027 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
1028 = new ::ucbhelper::PropertyValueSet( rSMgr
);
1030 sal_Int32 nCount
= rProperties
.getLength();
1033 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
1034 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1036 const beans::Property
* pProps
= rProperties
.getConstArray();
1037 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1039 const beans::Property
& rProp
= pProps
[ n
];
1041 // Process Core properties.
1043 if ( rProp
.Name
.equalsAsciiL(
1044 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1046 xRow
->appendString ( rProp
, rData
.getContentType() );
1048 else if ( rProp
.Name
.equalsAsciiL(
1049 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1051 xRow
->appendString ( rProp
, rData
.getTitle() );
1053 else if ( rProp
.Name
.equalsAsciiL(
1054 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1056 xRow
->appendBoolean( rProp
, rData
.getIsDocument() );
1058 else if ( rProp
.Name
.equalsAsciiL(
1059 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1061 xRow
->appendBoolean( rProp
, rData
.getIsFolder() );
1063 else if ( rProp
.Name
.equalsAsciiL(
1064 RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) )
1066 // Storage is only supported by folders.
1067 ContentType eType
= rData
.getType();
1068 if ( eType
== FOLDER
)
1072 pProvider
->queryStorageClone( rContentId
) ) );
1074 xRow
->appendVoid( rProp
);
1076 else if ( rProp
.Name
.equalsAsciiL(
1077 RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) )
1079 // DocumentModel is only supported by documents.
1080 ContentType eType
= rData
.getType();
1081 if ( eType
== DOCUMENT
)
1085 pProvider
->queryDocumentModel( rContentId
) ) );
1087 xRow
->appendVoid( rProp
);
1091 // Not a Core Property! Maybe it's an Additional Core Property?!
1093 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1096 = uno::Reference
< beans::XPropertySet
>(
1097 pProvider
->getAdditionalPropertySet( rContentId
,
1100 bTriedToGetAdditonalPropSet
= sal_True
;
1103 if ( xAdditionalPropSet
.is() )
1105 if ( !xRow
->appendPropertySetValue(
1109 // Append empty entry.
1110 xRow
->appendVoid( rProp
);
1115 // Append empty entry.
1116 xRow
->appendVoid( rProp
);
1123 // Append all Core Properties.
1124 xRow
->appendString (
1125 beans::Property( rtl::OUString::createFromAscii( "ContentType" ),
1127 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1128 beans::PropertyAttribute::BOUND
1129 | beans::PropertyAttribute::READONLY
),
1130 rData
.getContentType() );
1132 ContentType eType
= rData
.getType();
1134 xRow
->appendString (
1135 beans::Property( rtl::OUString::createFromAscii( "Title" ),
1137 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1138 // Title is read-only for root and documents.
1139 beans::PropertyAttribute::BOUND
||
1140 ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
1141 ? beans::PropertyAttribute::READONLY
1144 xRow
->appendBoolean(
1145 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
1147 getCppuBooleanType(),
1148 beans::PropertyAttribute::BOUND
1149 | beans::PropertyAttribute::READONLY
),
1150 rData
.getIsDocument() );
1151 xRow
->appendBoolean(
1152 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ),
1154 getCppuBooleanType(),
1155 beans::PropertyAttribute::BOUND
1156 | beans::PropertyAttribute::READONLY
),
1157 rData
.getIsFolder() );
1159 // Storage is only supported by folders.
1160 if ( eType
== FOLDER
)
1162 beans::Property( rtl::OUString::createFromAscii( "Storage" ),
1166 const uno::Reference
< embed::XStorage
> * >( 0 ) ),
1167 beans::PropertyAttribute::BOUND
1168 | beans::PropertyAttribute::READONLY
),
1169 uno::makeAny( pProvider
->queryStorageClone( rContentId
) ) );
1171 // DocumentModel is only supported by documents.
1172 if ( eType
== DOCUMENT
)
1174 beans::Property( rtl::OUString::createFromAscii( "DocumentModel" ),
1178 const uno::Reference
< frame::XModel
> * >( 0 ) ),
1179 beans::PropertyAttribute::BOUND
1180 | beans::PropertyAttribute::READONLY
),
1182 pProvider
->queryDocumentModel( rContentId
) ) );
1184 // Append all Additional Core Properties.
1186 uno::Reference
< beans::XPropertySet
> xSet(
1187 pProvider
->getAdditionalPropertySet( rContentId
, sal_False
),
1189 xRow
->appendPropertySet( xSet
);
1192 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1195 //=========================================================================
1196 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1197 const uno::Sequence
< beans::Property
>& rProperties
)
1199 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1200 return getPropertyValues( m_xSMgr
,
1204 m_xIdentifier
->getContentIdentifier() );
1207 //=========================================================================
1208 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1209 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1210 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1211 throw( uno::Exception
)
1213 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1215 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1216 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1217 sal_Int32 nChanged
= 0;
1219 beans::PropertyChangeEvent aEvent
;
1220 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1221 aEvent
.Further
= sal_False
;
1222 // aEvent.PropertyName =
1223 aEvent
.PropertyHandle
= -1;
1224 // aEvent.OldValue =
1225 // aEvent.NewValue =
1227 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1228 sal_Int32 nCount
= rValues
.getLength();
1230 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1231 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1233 sal_Bool bExchange
= sal_False
;
1234 rtl::OUString aOldTitle
;
1235 sal_Int32 nTitlePos
= -1;
1237 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1239 const beans::PropertyValue
& rValue
= pValues
[ n
];
1241 if ( rValue
.Name
.equalsAsciiL(
1242 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1244 // Read-only property!
1245 aRet
[ n
] <<= lang::IllegalAccessException(
1246 rtl::OUString::createFromAscii(
1247 "Property is read-only!" ),
1248 static_cast< cppu::OWeakObject
* >( this ) );
1250 else if ( rValue
.Name
.equalsAsciiL(
1251 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1253 // Read-only property!
1254 aRet
[ n
] <<= lang::IllegalAccessException(
1255 rtl::OUString::createFromAscii(
1256 "Property is read-only!" ),
1257 static_cast< cppu::OWeakObject
* >( this ) );
1259 else if ( rValue
.Name
.equalsAsciiL(
1260 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1262 // Read-only property!
1263 aRet
[ n
] <<= lang::IllegalAccessException(
1264 rtl::OUString::createFromAscii(
1265 "Property is read-only!" ),
1266 static_cast< cppu::OWeakObject
* >( this ) );
1268 else if ( rValue
.Name
.equalsAsciiL(
1269 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1271 // Title is read-only for root and documents.
1272 ContentType eType
= m_aProps
.getType();
1273 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
1275 aRet
[ n
] <<= lang::IllegalAccessException(
1276 rtl::OUString::createFromAscii(
1277 "Property is read-only!" ),
1278 static_cast< cppu::OWeakObject
* >( this ) );
1282 rtl::OUString aNewValue
;
1283 if ( rValue
.Value
>>= aNewValue
)
1286 if ( aNewValue
.getLength() > 0 )
1288 if ( aNewValue
!= m_aProps
.getTitle() )
1290 // modified title -> modified URL -> exchange !
1291 if ( m_eState
== PERSISTENT
)
1292 bExchange
= sal_True
;
1294 aOldTitle
= m_aProps
.getTitle();
1295 m_aProps
.setTitle( aNewValue
);
1297 // property change event will be sent later...
1299 // remember position within sequence of values
1300 // (for error handling).
1306 aRet
[ n
] <<= lang::IllegalArgumentException(
1307 rtl::OUString::createFromAscii(
1308 "Empty Title not allowed!" ),
1309 static_cast< cppu::OWeakObject
* >( this ),
1315 aRet
[ n
] <<= beans::IllegalTypeException(
1316 rtl::OUString::createFromAscii(
1317 "Title Property value has wrong type!" ),
1318 static_cast< cppu::OWeakObject
* >( this ) );
1322 else if ( rValue
.Name
.equalsAsciiL(
1323 RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) )
1325 ContentType eType
= m_aProps
.getType();
1326 if ( eType
== FOLDER
)
1328 aRet
[ n
] <<= lang::IllegalAccessException(
1329 rtl::OUString::createFromAscii(
1330 "Property is read-only!" ),
1331 static_cast< cppu::OWeakObject
* >( this ) );
1335 // Storage is only supported by folders.
1336 aRet
[ n
] <<= beans::UnknownPropertyException(
1337 rtl::OUString::createFromAscii(
1338 "Storage property only supported by folders" ),
1339 static_cast< cppu::OWeakObject
* >( this ) );
1342 else if ( rValue
.Name
.equalsAsciiL(
1343 RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) )
1345 ContentType eType
= m_aProps
.getType();
1346 if ( eType
== DOCUMENT
)
1348 aRet
[ n
] <<= lang::IllegalAccessException(
1349 rtl::OUString::createFromAscii(
1350 "Property is read-only!" ),
1351 static_cast< cppu::OWeakObject
* >( this ) );
1355 // Storage is only supported by folders.
1356 aRet
[ n
] <<= beans::UnknownPropertyException(
1357 rtl::OUString::createFromAscii(
1358 "DocumentModel property only supported by "
1360 static_cast< cppu::OWeakObject
* >( this ) );
1365 // Not a Core Property! Maybe it's an Additional Core Property?!
1367 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1369 xAdditionalPropSet
= getAdditionalPropertySet( sal_False
);
1370 bTriedToGetAdditonalPropSet
= sal_True
;
1373 if ( xAdditionalPropSet
.is() )
1377 uno::Any aOldValue
= xAdditionalPropSet
->getPropertyValue(
1379 if ( aOldValue
!= rValue
.Value
)
1381 xAdditionalPropSet
->setPropertyValue(
1382 rValue
.Name
, rValue
.Value
);
1384 aEvent
.PropertyName
= rValue
.Name
;
1385 aEvent
.OldValue
= aOldValue
;
1386 aEvent
.NewValue
= rValue
.Value
;
1388 aChanges
.getArray()[ nChanged
] = aEvent
;
1392 catch ( beans::UnknownPropertyException
const & e
)
1396 catch ( lang::WrappedTargetException
const & e
)
1400 catch ( beans::PropertyVetoException
const & e
)
1404 catch ( lang::IllegalArgumentException
const & e
)
1411 aRet
[ n
] <<= uno::Exception(
1412 rtl::OUString::createFromAscii(
1413 "No property set for storing the value!" ),
1414 static_cast< cppu::OWeakObject
* >( this ) );
1421 uno::Reference
< ucb::XContentIdentifier
> xOldId
1423 uno::Reference
< ucb::XContentIdentifier
> xNewId
1424 = makeNewIdentifier( m_aProps
.getTitle() );
1427 if ( exchangeIdentity( xNewId
) )
1429 // Adapt persistent data.
1430 renameData( xOldId
, xNewId
);
1432 // Adapt Additional Core Properties.
1433 renameAdditionalPropertySet( xOldId
->getContentIdentifier(),
1434 xNewId
->getContentIdentifier(),
1440 m_aProps
.setTitle( aOldTitle
);
1441 aOldTitle
= rtl::OUString();
1444 aRet
[ nTitlePos
] <<= uno::Exception(
1445 rtl::OUString::createFromAscii( "Exchange failed!" ),
1446 static_cast< cppu::OWeakObject
* >( this ) );
1450 if ( aOldTitle
.getLength() )
1452 aEvent
.PropertyName
= rtl::OUString::createFromAscii( "Title" );
1453 aEvent
.OldValue
= uno::makeAny( aOldTitle
);
1454 aEvent
.NewValue
= uno::makeAny( m_aProps
.getTitle() );
1456 aChanges
.getArray()[ nChanged
] = aEvent
;
1462 // Save changes, if content was already made persistent.
1463 if ( !bExchange
&& ( m_eState
== PERSISTENT
) )
1465 if ( !storeData( uno::Reference
< io::XInputStream
>(), xEnv
) )
1469 beans::PropertyValue(
1470 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1473 uno::makeAny(m_xIdentifier
->
1474 getContentIdentifier()),
1475 beans::PropertyState_DIRECT_VALUE
));
1476 ucbhelper::cancelCommandExecution(
1477 ucb::IOErrorCode_CANT_WRITE
,
1478 uno::Sequence
< uno::Any
>(&aProps
, 1),
1480 rtl::OUString::createFromAscii(
1481 "Cannot store persistent data!" ),
1487 aChanges
.realloc( nChanged
);
1490 notifyPropertiesChange( aChanges
);
1496 //=========================================================================
1497 uno::Any
Content::open(
1498 const ucb::OpenCommandArgument2
& rArg
,
1499 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1500 throw( uno::Exception
)
1502 if ( rArg
.Mode
== ucb::OpenMode::ALL
||
1503 rArg
.Mode
== ucb::OpenMode::FOLDERS
||
1504 rArg
.Mode
== ucb::OpenMode::DOCUMENTS
)
1506 //////////////////////////////////////////////////////////////////
1507 // open command for a folder content
1508 //////////////////////////////////////////////////////////////////
1510 uno::Reference
< ucb::XDynamicResultSet
> xSet
1511 = new DynamicResultSet( m_xSMgr
, this, rArg
);
1512 return uno::makeAny( xSet
);
1516 //////////////////////////////////////////////////////////////////
1517 // open command for a document content
1518 //////////////////////////////////////////////////////////////////
1520 if ( ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
1521 ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
1523 // Currently(?) unsupported.
1524 ucbhelper::cancelCommandExecution(
1525 uno::makeAny( ucb::UnsupportedOpenModeException(
1527 static_cast< cppu::OWeakObject
* >( this ),
1528 sal_Int16( rArg
.Mode
) ) ),
1533 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1535 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
1537 uno::Reference
< io::XActiveDataStreamer
> xDataStreamer(
1538 rArg
.Sink
, uno::UNO_QUERY
);
1539 if ( xDataStreamer
.is() )
1541 // May throw CommandFailedException, DocumentPasswordRequest!
1542 uno::Reference
< io::XStream
> xStream
= getStream( xEnv
);
1543 if ( !xStream
.is() )
1545 // No interaction if we are not persistent!
1548 beans::PropertyValue(
1550 RTL_CONSTASCII_USTRINGPARAM("Uri")),
1552 uno::makeAny(m_xIdentifier
->
1553 getContentIdentifier()),
1554 beans::PropertyState_DIRECT_VALUE
));
1555 ucbhelper::cancelCommandExecution(
1556 ucb::IOErrorCode_CANT_READ
,
1557 uno::Sequence
< uno::Any
>(&aProps
, 1),
1558 m_eState
== PERSISTENT
1560 : uno::Reference
< ucb::XCommandEnvironment
>(),
1561 rtl::OUString::createFromAscii(
1562 "Got no data stream!" ),
1568 xDataStreamer
->setStream( xStream
);
1572 uno::Reference
< io::XOutputStream
> xOut( rArg
.Sink
, uno::UNO_QUERY
);
1575 // PUSH: write data into xOut
1577 // May throw CommandFailedException, DocumentPasswordRequest!
1578 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1581 // No interaction if we are not persistent!
1584 beans::PropertyValue(
1585 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1588 uno::makeAny(m_xIdentifier
->
1589 getContentIdentifier()),
1590 beans::PropertyState_DIRECT_VALUE
));
1591 ucbhelper::cancelCommandExecution(
1592 ucb::IOErrorCode_CANT_READ
,
1593 uno::Sequence
< uno::Any
>(&aProps
, 1),
1594 m_eState
== PERSISTENT
1596 : uno::Reference
< ucb::XCommandEnvironment
>(),
1597 rtl::OUString::createFromAscii( "Got no data stream!" ),
1604 uno::Sequence
< sal_Int8
> aBuffer
;
1605 sal_Int32 nRead
= xIn
->readSomeBytes( aBuffer
, 65536 );
1609 aBuffer
.realloc( nRead
);
1610 xOut
->writeBytes( aBuffer
);
1611 aBuffer
.realloc( 0 );
1612 nRead
= xIn
->readSomeBytes( aBuffer
, 65536 );
1615 xOut
->closeOutput();
1617 catch ( io::NotConnectedException
const & )
1619 // closeOutput, readSomeBytes, writeBytes
1621 catch ( io::BufferSizeExceededException
const & )
1623 // closeOutput, readSomeBytes, writeBytes
1625 catch ( io::IOException
const & )
1627 // closeOutput, readSomeBytes, writeBytes
1632 uno::Reference
< io::XActiveDataSink
> xDataSink(
1633 rArg
.Sink
, uno::UNO_QUERY
);
1634 if ( xDataSink
.is() )
1636 // PULL: wait for client read
1638 // May throw CommandFailedException, DocumentPasswordRequest!
1639 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1642 // No interaction if we are not persistent!
1645 beans::PropertyValue(
1647 RTL_CONSTASCII_USTRINGPARAM("Uri")),
1649 uno::makeAny(m_xIdentifier
->
1650 getContentIdentifier()),
1651 beans::PropertyState_DIRECT_VALUE
));
1652 ucbhelper::cancelCommandExecution(
1653 ucb::IOErrorCode_CANT_READ
,
1654 uno::Sequence
< uno::Any
>(&aProps
, 1),
1655 m_eState
== PERSISTENT
1658 ucb::XCommandEnvironment
>(),
1659 rtl::OUString::createFromAscii(
1660 "Got no data stream!" ),
1666 xDataSink
->setInputStream( xIn
);
1670 ucbhelper::cancelCommandExecution(
1672 ucb::UnsupportedDataSinkException(
1674 static_cast< cppu::OWeakObject
* >( this ),
1686 //=========================================================================
1687 void Content::insert( const uno::Reference
< io::XInputStream
>& xData
,
1688 sal_Int32 nNameClashResolve
,
1689 const uno::Reference
<
1690 ucb::XCommandEnvironment
> & xEnv
)
1691 throw( uno::Exception
)
1693 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1695 ContentType eType
= m_aProps
.getType();
1697 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1698 "insert command only supported by streams and folders!" );
1700 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
1702 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
1703 #if OSL_DEBUG_LEVEL > 0
1704 if ( eType
== STREAM
)
1706 Uri
aParentUri( aUri
.getParentUri() );
1707 OSL_ENSURE( !aParentUri
.isDocument(),
1708 "insert command not supported by streams that are direct "
1709 "children of document root!" );
1714 // Check, if all required properties were set.
1715 if ( eType
== FOLDER
)
1719 if ( m_aProps
.getTitle().getLength() == 0 )
1720 m_aProps
.setTitle( aUri
.getDecodedName() );
1728 ucbhelper::cancelCommandExecution(
1729 uno::makeAny( ucb::MissingInputStreamException(
1731 static_cast< cppu::OWeakObject
* >( this ) ) ),
1738 if ( m_aProps
.getTitle().getLength() == 0 )
1739 m_aProps
.setTitle( aUri
.getDecodedName() );
1742 rtl::OUStringBuffer aNewURL
= aUri
.getParentUri();
1743 aNewURL
.append( m_aProps
.getTitle() );
1744 Uri
aNewUri( aNewURL
.makeStringAndClear() );
1746 // Handle possible name clash...
1747 switch ( nNameClashResolve
)
1750 case ucb::NameClash::ERROR
:
1751 if ( hasData( aNewUri
) )
1753 ucbhelper::cancelCommandExecution(
1754 uno::makeAny( ucb::NameClashException(
1756 static_cast< cppu::OWeakObject
* >( this ),
1757 task::InteractionClassification_ERROR
,
1758 m_aProps
.getTitle() ) ),
1764 // replace (possibly) existing object.
1765 case ucb::NameClash::OVERWRITE
:
1768 // "invent" a new valid title.
1769 case ucb::NameClash::RENAME
:
1770 if ( hasData( aNewUri
) )
1776 rtl::OUStringBuffer aNew
= aNewUri
.getUri();
1777 aNew
.appendAscii( "_" );
1778 aNew
.append( rtl::OUString::valueOf( ++nTry
) );
1779 aNewUri
.setUri( aNew
.makeStringAndClear() );
1781 while ( hasData( aNewUri
) && ( nTry
< 1000 ) );
1785 ucbhelper::cancelCommandExecution(
1787 ucb::UnsupportedNameClashException(
1788 rtl::OUString::createFromAscii(
1789 "Unable to resolve name clash!" ),
1790 static_cast< cppu::OWeakObject
* >( this ),
1791 nNameClashResolve
) ),
1797 rtl::OUStringBuffer aNewTitle
= m_aProps
.getTitle();
1798 aNewTitle
.appendAscii( "_" );
1799 aNewTitle
.append( rtl::OUString::valueOf( ++nTry
) );
1800 m_aProps
.setTitle( aNewTitle
.makeStringAndClear() );
1805 case ucb::NameClash::KEEP
: // deprecated
1806 case ucb::NameClash::ASK
:
1808 if ( hasData( aNewUri
) )
1810 ucbhelper::cancelCommandExecution(
1812 ucb::UnsupportedNameClashException(
1814 static_cast< cppu::OWeakObject
* >( this ),
1815 nNameClashResolve
) ),
1822 // Identifier changed?
1823 sal_Bool bNewId
= ( aUri
!= aNewUri
);
1828 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aNewUri
.getUri() );
1831 if ( !storeData( xData
, xEnv
) )
1834 = uno::makeAny(beans::PropertyValue(
1835 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1838 uno::makeAny(m_xIdentifier
->
1839 getContentIdentifier()),
1840 beans::PropertyState_DIRECT_VALUE
));
1841 ucbhelper::cancelCommandExecution(
1842 ucb::IOErrorCode_CANT_WRITE
,
1843 uno::Sequence
< uno::Any
>(&aProps
, 1),
1845 rtl::OUString::createFromAscii( "Cannot store persistent data!" ),
1850 m_eState
= PERSISTENT
;
1854 //loadData( m_pProvider, m_aUri, m_aProps );
1861 //=========================================================================
1862 void Content::destroy( sal_Bool bDeletePhysical
,
1863 const uno::Reference
<
1864 ucb::XCommandEnvironment
> & xEnv
)
1865 throw( uno::Exception
)
1867 // @@@ take care about bDeletePhysical -> trashcan support
1869 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1871 ContentType eType
= m_aProps
.getType();
1873 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1874 "delete command only supported by streams and folders!" );
1876 uno::Reference
< ucb::XContent
> xThis
= this;
1879 if ( m_eState
!= PERSISTENT
)
1881 ucbhelper::cancelCommandExecution(
1882 uno::makeAny( ucb::UnsupportedCommandException(
1883 rtl::OUString::createFromAscii(
1884 "Not persistent!" ),
1885 static_cast< cppu::OWeakObject
* >( this ) ) ),
1895 if ( eType
== FOLDER
)
1897 // Process instanciated children...
1899 ContentRefList aChildren
;
1900 queryChildren( aChildren
);
1902 ContentRefList::const_iterator it
= aChildren
.begin();
1903 ContentRefList::const_iterator end
= aChildren
.end();
1907 (*it
)->destroy( bDeletePhysical
, xEnv
);
1913 //=========================================================================
1914 void Content::notifyDocumentClosed()
1916 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1920 // @@@ anything else to reset or such?
1922 // callback follows!
1925 // Propagate destruction to content event listeners
1926 // Remove this from provider's content list.
1930 //=========================================================================
1931 uno::Reference
< ucb::XContent
>
1932 Content::queryChildContent( const rtl::OUString
& rRelativeChildUri
)
1934 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1936 const rtl::OUString aMyId
= getIdentifier()->getContentIdentifier();
1937 rtl::OUStringBuffer
aBuf( aMyId
);
1938 if ( aMyId
.getStr()[ aMyId
.getLength() - 1 ] != sal_Unicode( '/' ) )
1939 aBuf
.appendAscii( "/" );
1940 if ( rRelativeChildUri
.getStr()[ 0 ] != sal_Unicode( '/' ) )
1941 aBuf
.append( rRelativeChildUri
);
1943 aBuf
.append( rRelativeChildUri
.copy( 1 ) );
1945 uno::Reference
< ucb::XContentIdentifier
> xChildId
1946 = new ::ucbhelper::ContentIdentifier(
1947 m_xSMgr
, aBuf
.makeStringAndClear() );
1949 uno::Reference
< ucb::XContent
> xChild
;
1952 xChild
= m_pProvider
->queryContent( xChildId
);
1954 catch ( ucb::IllegalIdentifierException
const & )
1959 OSL_ENSURE( xChild
.is(),
1960 "Content::queryChildContent - unable to create child content!" );
1964 //=========================================================================
1965 void Content::notifyChildRemoved( const rtl::OUString
& rRelativeChildUri
)
1967 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1969 // Ugly! Need to create child content object, just to fill event properly.
1970 uno::Reference
< ucb::XContent
> xChild
1971 = queryChildContent( rRelativeChildUri
);
1975 // callback follows!
1978 // Notify "REMOVED" event.
1979 ucb::ContentEvent
aEvt(
1980 static_cast< cppu::OWeakObject
* >( this ),
1981 ucb::ContentAction::REMOVED
,
1984 notifyContentEvent( aEvt
);
1988 //=========================================================================
1989 void Content::notifyChildInserted( const rtl::OUString
& rRelativeChildUri
)
1991 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1993 // Ugly! Need to create child content object, just to fill event properly.
1994 uno::Reference
< ucb::XContent
> xChild
1995 = queryChildContent( rRelativeChildUri
);
1999 // callback follows!
2002 // Notify "INSERTED" event.
2003 ucb::ContentEvent
aEvt(
2004 static_cast< cppu::OWeakObject
* >( this ),
2005 ucb::ContentAction::INSERTED
,
2008 notifyContentEvent( aEvt
);
2012 //=========================================================================
2013 void Content::transfer(
2014 const ucb::TransferInfo
& rInfo
,
2015 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2016 throw( uno::Exception
)
2018 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
2021 if ( m_eState
!= PERSISTENT
)
2023 ucbhelper::cancelCommandExecution(
2024 uno::makeAny( ucb::UnsupportedCommandException(
2025 rtl::OUString::createFromAscii(
2026 "Not persistent!" ),
2027 static_cast< cppu::OWeakObject
* >( this ) ) ),
2032 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
2034 if ( ( rInfo
.SourceURL
.getLength() < TDOC_URL_SCHEME_LENGTH
+ 2 ) )
2036 // Invaild length (to short).
2037 ucbhelper::cancelCommandExecution(
2038 uno::makeAny( ucb::InteractiveBadTransferURLException(
2040 static_cast< cppu::OWeakObject
* >( this ) ) ),
2045 rtl::OUString aScheme
2046 = rInfo
.SourceURL
.copy( 0, TDOC_URL_SCHEME_LENGTH
+ 2 )
2047 .toAsciiLowerCase();
2048 if ( !aScheme
.equalsAsciiL(
2049 RTL_CONSTASCII_STRINGPARAM( TDOC_URL_SCHEME
":/" ) ) )
2052 ucbhelper::cancelCommandExecution(
2053 uno::makeAny( ucb::InteractiveBadTransferURLException(
2055 static_cast< cppu::OWeakObject
* >( this ) ) ),
2060 // Does source URI describe a tdoc folder or stream?
2061 Uri
aSourceUri( rInfo
.SourceURL
);
2062 if ( !aSourceUri
.isValid() )
2064 ucbhelper::cancelCommandExecution(
2065 uno::makeAny( lang::IllegalArgumentException(
2066 rtl::OUString::createFromAscii(
2067 "Invalid source URI! Syntax!" ),
2068 static_cast< cppu::OWeakObject
* >( this ),
2074 if ( aSourceUri
.isRoot() || aSourceUri
.isDocument() )
2076 ucbhelper::cancelCommandExecution(
2077 uno::makeAny( lang::IllegalArgumentException(
2078 rtl::OUString::createFromAscii(
2079 "Invalid source URI! "
2080 "Must describe a folder or stream!" ),
2081 static_cast< cppu::OWeakObject
* >( this ),
2087 // Is source not a parent of me / not me?
2088 rtl::OUString aId
= m_xIdentifier
->getContentIdentifier();
2089 sal_Int32 nPos
= aId
.lastIndexOf( '/' );
2090 if ( nPos
!= ( aId
.getLength() - 1 ) )
2092 // No trailing slash found. Append.
2093 aId
+= rtl::OUString::createFromAscii( "/" );
2096 if ( rInfo
.SourceURL
.getLength() <= aId
.getLength() )
2099 rInfo
.SourceURL
, rInfo
.SourceURL
.getLength() ) == 0 )
2102 = uno::makeAny(beans::PropertyValue(
2104 RTL_CONSTASCII_USTRINGPARAM("Uri")),
2106 uno::makeAny( rInfo
.SourceURL
),
2107 beans::PropertyState_DIRECT_VALUE
));
2108 ucbhelper::cancelCommandExecution(
2109 ucb::IOErrorCode_RECURSIVE
,
2110 uno::Sequence
< uno::Any
>(&aProps
, 1),
2112 rtl::OUString::createFromAscii(
2113 "Target is equal to or is a child of source!" ),
2119 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2120 if ( m_aProps
.getType() == DOCUMENT
)
2124 uno::Reference
< embed::XStorage
> xStorage
2125 = m_pProvider
->queryStorage(
2126 aSourceUri
.getParentUri(), READ_WRITE_NOCREATE
);
2127 if ( xStorage
.is() )
2131 if ( xStorage
->isStreamElement( aSourceUri
.getDecodedName() ) )
2133 ucbhelper::cancelCommandExecution(
2134 uno::makeAny( lang::IllegalArgumentException(
2135 rtl::OUString::createFromAscii(
2136 "Invalid source URI! "
2137 "Streams cannot be created as "
2138 "children of document root!" ),
2139 static_cast< cppu::OWeakObject
* >(
2147 catch ( container::NoSuchElementException
const & )
2151 catch ( lang::IllegalArgumentException
const & )
2155 catch ( embed::InvalidStorageException
const & )
2163 ucbhelper::cancelCommandExecution(
2164 uno::makeAny( lang::IllegalArgumentException(
2165 rtl::OUString::createFromAscii(
2166 "Invalid source URI! "
2167 "Unabale to determine source type!" ),
2168 static_cast< cppu::OWeakObject
* >( this ),
2176 /////////////////////////////////////////////////////////////////////////
2178 /////////////////////////////////////////////////////////////////////////
2180 rtl::OUString
aNewName( rInfo
.NewTitle
.getLength() > 0
2182 : aSourceUri
.getDecodedName() );
2184 if ( !copyData( aSourceUri
, aNewName
) )
2188 beans::PropertyValue(
2189 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2192 uno::makeAny( rInfo
.SourceURL
),
2193 beans::PropertyState_DIRECT_VALUE
));
2194 ucbhelper::cancelCommandExecution(
2195 ucb::IOErrorCode_CANT_WRITE
,
2196 uno::Sequence
< uno::Any
>(&aProps
, 1),
2199 RTL_CONSTASCII_USTRINGPARAM( "Cannot copy data!" ) ),
2204 /////////////////////////////////////////////////////////////////////////
2205 // Copy own and all children's Additional Core Properties.
2206 /////////////////////////////////////////////////////////////////////////
2208 rtl::OUString aTargetUri
= m_xIdentifier
->getContentIdentifier();
2209 if ( ( aTargetUri
.lastIndexOf( '/' ) + 1 ) != aTargetUri
.getLength() )
2210 aTargetUri
+= rtl::OUString::createFromAscii( "/" );
2212 if ( rInfo
.NewTitle
.getLength() > 0 )
2213 aTargetUri
+= ::ucb_impl::urihelper::encodeSegment( rInfo
.NewTitle
);
2215 aTargetUri
+= aSourceUri
.getName();
2217 if ( !copyAdditionalPropertySet(
2218 aSourceUri
.getUri(), aTargetUri
, sal_True
) )
2222 beans::PropertyValue(
2223 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2226 uno::makeAny( rInfo
.SourceURL
),
2227 beans::PropertyState_DIRECT_VALUE
));
2228 ucbhelper::cancelCommandExecution(
2229 ucb::IOErrorCode_CANT_WRITE
,
2230 uno::Sequence
< uno::Any
>(&aProps
, 1),
2233 RTL_CONSTASCII_USTRINGPARAM(
2234 "Cannot copy additional properties!" ) ),
2239 /////////////////////////////////////////////////////////////////////////
2240 // Propagate new content.
2241 /////////////////////////////////////////////////////////////////////////
2243 rtl::Reference
< Content
> xTarget
;
2246 uno::Reference
< ucb::XContentIdentifier
> xTargetId
2247 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aTargetUri
);
2249 // Note: The static cast is okay here, because its sure that
2250 // m_xProvider is always the WebDAVContentProvider.
2251 xTarget
= static_cast< Content
* >(
2252 m_pProvider
->queryContent( xTargetId
).get() );
2255 catch ( ucb::IllegalIdentifierException
const & )
2260 if ( !xTarget
.is() )
2263 = uno::makeAny(beans::PropertyValue(
2264 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2267 uno::makeAny( aTargetUri
),
2268 beans::PropertyState_DIRECT_VALUE
));
2269 ucbhelper::cancelCommandExecution(
2270 ucb::IOErrorCode_CANT_READ
,
2271 uno::Sequence
< uno::Any
>(&aProps
, 1),
2273 rtl::OUString::createFromAscii(
2274 "Cannot instanciate target object!" ),
2279 // Announce transfered content in its new folder.
2280 xTarget
->inserted();
2282 /////////////////////////////////////////////////////////////////////////
2283 // Remove source, if requested
2284 /////////////////////////////////////////////////////////////////////////
2286 if ( rInfo
.MoveData
)
2288 rtl::Reference
< Content
> xSource
;
2291 uno::Reference
< ucb::XContentIdentifier
>
2292 xSourceId
= new ::ucbhelper::ContentIdentifier(
2293 m_xSMgr
, rInfo
.SourceURL
);
2295 // Note: The static cast is okay here, because its sure
2296 // that m_xProvider is always the ContentProvider.
2297 xSource
= static_cast< Content
* >(
2298 m_xProvider
->queryContent( xSourceId
).get() );
2300 catch ( ucb::IllegalIdentifierException
const & )
2305 if ( !xSource
.is() )
2308 = uno::makeAny(beans::PropertyValue(
2309 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2312 uno::makeAny( rInfo
.SourceURL
),
2313 beans::PropertyState_DIRECT_VALUE
));
2314 ucbhelper::cancelCommandExecution(
2315 ucb::IOErrorCode_CANT_READ
,
2316 uno::Sequence
< uno::Any
>(&aProps
, 1),
2318 rtl::OUString::createFromAscii(
2319 "Cannot instanciate target object!" ),
2324 // Propagate destruction (recursively).
2325 xSource
->destroy( sal_True
, xEnv
);
2327 // Remove all persistent data of source and its children.
2328 if ( !xSource
->removeData() )
2332 beans::PropertyValue(
2333 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2336 uno::makeAny( rInfo
.SourceURL
),
2337 beans::PropertyState_DIRECT_VALUE
));
2338 ucbhelper::cancelCommandExecution(
2339 ucb::IOErrorCode_CANT_WRITE
,
2340 uno::Sequence
< uno::Any
>(&aProps
, 1),
2342 rtl::OUString::createFromAscii(
2343 "Cannot remove persistent data of source object!" ),
2348 // Remove own and all children's Additional Core Properties.
2349 if ( !xSource
->removeAdditionalPropertySet( sal_True
) )
2353 beans::PropertyValue(
2354 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2357 uno::makeAny( rInfo
.SourceURL
),
2358 beans::PropertyState_DIRECT_VALUE
));
2359 ucbhelper::cancelCommandExecution(
2360 ucb::IOErrorCode_CANT_WRITE
,
2361 uno::Sequence
< uno::Any
>(&aProps
, 1),
2363 rtl::OUString::createFromAscii(
2364 "Cannot remove additional properties of source object!" ),
2372 //=========================================================================
2373 bool Content::isContentCreator()
2375 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2377 ( m_aProps
.getType() == FOLDER
) || ( m_aProps
.getType() == DOCUMENT
);
2380 //=========================================================================
2382 bool Content::hasData( ContentProvider
* pProvider
, const Uri
& rUri
)
2384 if ( rUri
.isRoot() )
2386 return true; // root has no storage
2388 else if ( rUri
.isDocument() )
2390 uno::Reference
< embed::XStorage
> xStorage
2391 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2392 return xStorage
.is();
2398 // Ask parent storage. In case that rUri describes a stream,
2399 // ContentProvider::queryStorage( rUri ) would return null.
2401 uno::Reference
< embed::XStorage
> xStorage
2402 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2404 if ( !xStorage
.is() )
2407 uno::Reference
< container::XNameAccess
> xParentNA(
2408 xStorage
, uno::UNO_QUERY
);
2410 OSL_ENSURE( xParentNA
.is(), "Got no css.container.XNameAccess!" );
2412 return xParentNA
->hasByName( rUri
.getDecodedName() );
2416 //=========================================================================
2418 bool Content::loadData( ContentProvider
* pProvider
,
2420 ContentProperties
& rProps
)
2422 if ( rUri
.isRoot() ) // root has no storage, but can always be created
2425 = ContentProperties(
2426 ROOT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2428 else if ( rUri
.isDocument() ) // document must have storage
2430 uno::Reference
< embed::XStorage
> xStorage
2431 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2433 if ( !xStorage
.is() )
2437 = ContentProperties(
2438 DOCUMENT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2440 else // stream or folder; stream has no storage; folder has storage
2442 uno::Reference
< embed::XStorage
> xStorage
2443 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2445 if ( !xStorage
.is() )
2448 // Check whether exists at all, is stream or folder
2451 // return: true -> folder
2452 // return: false -> stream
2453 // NoSuchElementException -> neither folder nor stream
2455 = xStorage
->isStorageElement( rUri
.getDecodedName() );
2458 = ContentProperties(
2459 bIsFolder
? FOLDER
: STREAM
,
2460 pProvider
->queryStorageTitle( rUri
.getUri() ) );
2462 catch ( container::NoSuchElementException
const & )
2464 // there is no element with such name
2465 //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2468 catch ( lang::IllegalArgumentException
const & )
2470 // an illegal argument is provided
2471 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2474 catch ( embed::InvalidStorageException
const & )
2476 // this storage is in invalid state for any reason
2477 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2484 //=========================================================================
2485 bool Content::storeData( const uno::Reference
< io::XInputStream
>& xData
,
2486 const uno::Reference
<
2487 ucb::XCommandEnvironment
>& xEnv
)
2488 throw ( ucb::CommandFailedException
,
2489 task::DocumentPasswordRequest
)
2491 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2493 ContentType eType
= m_aProps
.getType();
2494 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2496 OSL_ENSURE( false, "storeData not supported by root and documents!" );
2500 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2502 if ( eType
== FOLDER
)
2504 uno::Reference
< embed::XStorage
> xStorage
2505 = m_pProvider
->queryStorage( aUri
.getUri(), READ_WRITE_CREATE
);
2507 if ( !xStorage
.is() )
2510 uno::Reference
< beans::XPropertySet
> xPropSet(
2511 xStorage
, uno::UNO_QUERY
);
2512 OSL_ENSURE( xPropSet
.is(),
2513 "Content::storeData - Got no XPropertySet interface!" );
2514 if ( !xPropSet
.is() )
2519 // According to MBA, if no mediatype is set, folder and all
2520 // its contents will be lost on save of the document!!!
2521 xPropSet
->setPropertyValue(
2522 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
2524 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2525 // @@@ better mediatype
2526 "application/binary" ) ) ) );
2528 catch ( beans::UnknownPropertyException
const & )
2530 OSL_ENSURE( false, "Property MediaType not supported!" );
2533 catch ( beans::PropertyVetoException
const & )
2535 OSL_ENSURE( false, "Caught PropertyVetoException!" );
2538 catch ( lang::IllegalArgumentException
const & )
2540 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2543 catch ( lang::WrappedTargetException
const & )
2545 OSL_ENSURE( false, "Caught WrappedTargetException!" );
2549 if ( !commitStorage( xStorage
) )
2552 else if ( eType
== STREAM
)
2556 // Important: Parent storage and output stream must be kept alive until
2557 // changes have been committed!
2558 uno::Reference
< embed::XStorage
> xStorage
2559 = m_pProvider
->queryStorage(
2560 aUri
.getParentUri(), READ_WRITE_CREATE
);
2561 uno::Reference
< io::XOutputStream
> xOut
;
2563 if ( !xStorage
.is() )
2568 // May throw CommandFailedException, DocumentPasswordRequest!
2569 xOut
= getTruncatedOutputStream( xEnv
);
2571 OSL_ENSURE( xOut
.is(), "No target data stream!" );
2575 uno::Sequence
< sal_Int8
> aBuffer
;
2576 sal_Int32 nRead
= xData
->readSomeBytes( aBuffer
, 65536 );
2580 aBuffer
.realloc( nRead
);
2581 xOut
->writeBytes( aBuffer
);
2582 aBuffer
.realloc( 0 );
2583 nRead
= xData
->readSomeBytes( aBuffer
, 65536 );
2586 closeOutputStream( xOut
);
2588 catch ( io::NotConnectedException
const & )
2590 // readSomeBytes, writeBytes
2591 OSL_ENSURE( false, "Caught NotConnectedException!" );
2592 closeOutputStream( xOut
);
2595 catch ( io::BufferSizeExceededException
const & )
2597 // readSomeBytes, writeBytes
2598 OSL_ENSURE( false, "Caught BufferSizeExceededException!" );
2599 closeOutputStream( xOut
);
2602 catch ( io::IOException
const & )
2604 // readSomeBytes, writeBytes
2605 OSL_ENSURE( false, "Caught IOException!" );
2606 closeOutputStream( xOut
);
2611 closeOutputStream( xOut
);
2617 if ( !commitStorage( xStorage
) )
2622 OSL_ENSURE( false, "Unknown content type!" );
2628 //=========================================================================
2629 bool Content::renameData(
2630 const uno::Reference
< ucb::XContentIdentifier
>& xOldId
,
2631 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
2633 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2635 ContentType eType
= m_aProps
.getType();
2636 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2638 OSL_ENSURE( false, "renameData not supported by root and documents!" );
2642 Uri
aOldUri( xOldId
->getContentIdentifier() );
2643 uno::Reference
< embed::XStorage
> xStorage
2644 = m_pProvider
->queryStorage(
2645 aOldUri
.getParentUri(), READ_WRITE_NOCREATE
);
2647 if ( !xStorage
.is() )
2652 Uri
aNewUri( xNewId
->getContentIdentifier() );
2653 xStorage
->renameElement(
2654 aOldUri
.getDecodedName(), aNewUri
.getDecodedName() );
2656 catch ( embed::InvalidStorageException
const & )
2658 // this storage is in invalid state for eny reason
2659 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2662 catch ( lang::IllegalArgumentException
const & )
2664 // an illegal argument is provided
2665 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2668 catch ( container::NoSuchElementException
const & )
2670 // there is no element with old name in this storage
2671 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2674 catch ( container::ElementExistException
const & )
2676 // an element with new name already exists in this storage
2677 OSL_ENSURE( false, "Caught ElementExistException!" );
2680 catch ( io::IOException
const & )
2682 // in case of io errors during renaming
2683 OSL_ENSURE( false, "Caught IOException!" );
2686 catch ( embed::StorageWrappedTargetException
const & )
2688 // wraps other exceptions
2689 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2693 return commitStorage( xStorage
);
2696 //=========================================================================
2697 bool Content::removeData()
2699 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2701 ContentType eType
= m_aProps
.getType();
2702 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2704 OSL_ENSURE( false, "removeData not supported by root and documents!" );
2708 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2709 uno::Reference
< embed::XStorage
> xStorage
2710 = m_pProvider
->queryStorage(
2711 aUri
.getParentUri(), READ_WRITE_NOCREATE
);
2713 if ( !xStorage
.is() )
2718 xStorage
->removeElement( aUri
.getDecodedName() );
2720 catch ( embed::InvalidStorageException
const & )
2722 // this storage is in invalid state for eny reason
2723 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2726 catch ( lang::IllegalArgumentException
const & )
2728 // an illegal argument is provided
2729 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2732 catch ( container::NoSuchElementException
const & )
2734 // there is no element with this name in this storage
2735 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2738 catch ( io::IOException
const & )
2740 // in case of io errors during renaming
2741 OSL_ENSURE( false, "Caught IOException!" );
2744 catch ( embed::StorageWrappedTargetException
const & )
2746 // wraps other exceptions
2747 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2751 return commitStorage( xStorage
);
2754 //=========================================================================
2755 bool Content::copyData( const Uri
& rSourceUri
, const rtl::OUString
& rNewName
)
2757 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2759 ContentType eType
= m_aProps
.getType();
2760 if ( ( eType
== ROOT
) || ( eType
== STREAM
) )
2762 OSL_ENSURE( false, "copyData not supported by root and streams!" );
2766 Uri
aDestUri( m_xIdentifier
->getContentIdentifier() );
2767 uno::Reference
< embed::XStorage
> xDestStorage
2768 = m_pProvider
->queryStorage( aDestUri
.getUri(), READ_WRITE_NOCREATE
);
2770 if ( !xDestStorage
.is() )
2773 uno::Reference
< embed::XStorage
> xSourceStorage
2774 = m_pProvider
->queryStorage( rSourceUri
.getParentUri(), READ
);
2776 if ( !xSourceStorage
.is() )
2781 xSourceStorage
->copyElementTo( rSourceUri
.getDecodedName(),
2785 catch ( embed::InvalidStorageException
const & )
2787 // this storage is in invalid state for eny reason
2788 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2791 catch ( lang::IllegalArgumentException
const & )
2793 // an illegal argument is provided
2794 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2797 catch ( container::NoSuchElementException
const & )
2799 // there is no element with this name in this storage
2800 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2803 catch ( container::ElementExistException
const & )
2805 // there is no element with this name in this storage
2806 OSL_ENSURE( false, "Caught ElementExistException!" );
2809 catch ( io::IOException
const & )
2811 // in case of io errors during renaming
2812 OSL_ENSURE( false, "Caught IOException!" );
2815 catch ( embed::StorageWrappedTargetException
const & )
2817 // wraps other exceptions
2818 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2822 return commitStorage( xDestStorage
);
2825 //=========================================================================
2827 bool Content::commitStorage( const uno::Reference
< embed::XStorage
> & xStorage
)
2830 uno::Reference
< embed::XTransactedObject
> xTO( xStorage
, uno::UNO_QUERY
);
2832 OSL_ENSURE( xTO
.is(),
2833 "Required interface css.embed.XTransactedObject missing!" );
2838 catch ( io::IOException
const & )
2840 OSL_ENSURE( false, "Caught IOException!" );
2843 catch ( lang::WrappedTargetException
const & )
2845 OSL_ENSURE( false, "Caught WrappedTargetException!" );
2852 //=========================================================================
2854 bool Content::closeOutputStream(
2855 const uno::Reference
< io::XOutputStream
> & xOut
)
2861 xOut
->closeOutput();
2864 catch ( io::NotConnectedException
const & )
2866 OSL_ENSURE( false, "Caught NotConnectedException!" );
2868 catch ( io::BufferSizeExceededException
const & )
2870 OSL_ENSURE( false, "Caught BufferSizeExceededException!" );
2872 catch ( io::IOException
const & )
2874 OSL_ENSURE( false, "Caught IOException!" );
2880 //=========================================================================
2881 static rtl::OUString
obtainPassword(
2882 const rtl::OUString
& rName
,
2883 task::PasswordRequestMode eMode
,
2884 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2885 throw ( ucb::CommandFailedException
,
2886 task::DocumentPasswordRequest
)
2888 rtl::Reference
< DocumentPasswordRequest
> xRequest
2889 = new DocumentPasswordRequest( eMode
, rName
);
2893 uno::Reference
< task::XInteractionHandler
> xIH
2894 = xEnv
->getInteractionHandler();
2897 xIH
->handle( xRequest
.get() );
2899 rtl::Reference
< ucbhelper::InteractionContinuation
> xSelection
2900 = xRequest
->getSelection();
2902 if ( xSelection
.is() )
2904 // Handler handled the request.
2905 uno::Reference
< task::XInteractionAbort
> xAbort(
2906 xSelection
.get(), uno::UNO_QUERY
);
2909 throw ucb::CommandFailedException(
2910 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2911 "Abort requested by Interaction Handler." ) ),
2912 uno::Reference
< uno::XInterface
>(),
2913 xRequest
->getRequest() );
2916 uno::Reference
< task::XInteractionPassword
> xPassword(
2917 xSelection
.get(), uno::UNO_QUERY
);
2918 if ( xPassword
.is() )
2920 return xPassword
->getPassword();
2923 // Unknown selection. Should never happen.
2924 throw ucb::CommandFailedException(
2925 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2926 "Interaction Handler selected unknown continuation!" ) ),
2927 uno::Reference
< uno::XInterface
>(),
2928 xRequest
->getRequest() );
2933 // No IH or IH did not handle exception.
2934 task::DocumentPasswordRequest aRequest
;
2935 xRequest
->getRequest() >>= aRequest
;
2939 //=========================================================================
2940 uno::Reference
< io::XInputStream
> Content::getInputStream(
2941 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2942 throw ( ucb::CommandFailedException
,
2943 task::DocumentPasswordRequest
)
2946 rtl::OUString aPassword
;
2947 bool bPasswordRequested
= false;
2950 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2952 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2953 "Content::getInputStream - content is no stream!" );
2955 aUri
= Uri( m_xIdentifier
->getContentIdentifier() ).getUri();
2962 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2963 return uno::Reference
< io::XInputStream
>(
2964 m_pProvider
->queryInputStream( aUri
, aPassword
) );
2966 catch ( packages::WrongPasswordException
const & )
2968 // Obtain (new) password.
2970 = obtainPassword( aUri
, /* @@@ find better title */
2972 ? task::PasswordRequestMode_PASSWORD_REENTER
2973 : task::PasswordRequestMode_PASSWORD_ENTER
,
2975 bPasswordRequested
= true;
2980 //=========================================================================
2981 static uno::Reference
< io::XOutputStream
> lcl_getTruncatedOutputStream(
2982 const rtl::OUString
& rUri
,
2983 ContentProvider
* pProvider
,
2984 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2985 throw ( ucb::CommandFailedException
,
2986 task::DocumentPasswordRequest
)
2988 rtl::OUString aPassword
;
2989 bool bPasswordRequested
= false;
2994 return uno::Reference
< io::XOutputStream
>(
2995 pProvider
->queryOutputStream(
2996 rUri
, aPassword
, true /* truncate */ ) );
2998 catch ( packages::WrongPasswordException
const & )
3000 // Obtain (new) password.
3002 = obtainPassword( rUri
, /* @@@ find better title */
3004 ? task::PasswordRequestMode_PASSWORD_REENTER
3005 : task::PasswordRequestMode_PASSWORD_ENTER
,
3007 bPasswordRequested
= true;
3012 //=========================================================================
3013 uno::Reference
< io::XOutputStream
> Content::getTruncatedOutputStream(
3014 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
3015 throw ( ucb::CommandFailedException
,
3016 task::DocumentPasswordRequest
)
3018 OSL_ENSURE( m_aProps
.getType() == STREAM
,
3019 "Content::getTruncatedOutputStream - content is no stream!" );
3021 return lcl_getTruncatedOutputStream(
3022 Uri( m_xIdentifier
->getContentIdentifier() ).getUri(),
3027 //=========================================================================
3028 uno::Reference
< io::XStream
> Content::getStream(
3029 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
3030 throw ( ucb::CommandFailedException
,
3031 task::DocumentPasswordRequest
)
3033 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
3035 OSL_ENSURE( m_aProps
.getType() == STREAM
,
3036 "Content::getStream - content is no stream!" );
3038 rtl::OUString
aUri( Uri( m_xIdentifier
->getContentIdentifier() ).getUri() );
3039 rtl::OUString aPassword
;
3040 bool bPasswordRequested
= false;
3045 return uno::Reference
< io::XStream
>(
3046 m_pProvider
->queryStream(
3047 aUri
, aPassword
, false /* no truncate */ ) );
3049 catch ( packages::WrongPasswordException
const & )
3051 // Obtain (new) password.
3053 = obtainPassword( aUri
, /* @@@ find better title */
3055 ? task::PasswordRequestMode_PASSWORD_REENTER
3056 : task::PasswordRequestMode_PASSWORD_ENTER
,
3058 bPasswordRequested
= true;