Update ooo320-m1
[ooovba.git] / ucb / source / ucp / tdoc / tdoc_content.cxx
blob308dd0a934627995d82d755e27862195a992c63d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tdoc_content.cxx,v $
10 * $Revision: 1.16 $
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 /**************************************************************************
35 TODO
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 ) ) )
90 return ROOT;
91 else if ( rType.equalsAsciiL(
92 RTL_CONSTASCII_STRINGPARAM( TDOC_DOCUMENT_CONTENT_TYPE ) ) )
93 return DOCUMENT;
94 else if ( rType.equalsAsciiL(
95 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) )
96 return FOLDER;
97 else if ( rType.equalsAsciiL(
98 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) )
99 return STREAM;
100 else
102 OSL_ENSURE( sal_False,
103 "Content::Content - unsupported content type string" );
104 return STREAM;
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() ),
126 aProps ) )
127 return 0;
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() )
141 return 0;
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!" );
149 return 0;
152 #if 0
153 // Fail, if content does exist.
154 if ( Content::hasData( pProvider,
155 Uri( Identifier->getContentIdentifier() ) ) )
156 return 0;
157 #endif
159 return new Content( rxSMgr, pProvider, Identifier, Info );
162 //=========================================================================
163 Content::Content(
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 ),
169 m_aProps( rProps ),
170 m_eState( PERSISTENT ),
171 m_pProvider( pProvider )
175 //=========================================================================
176 // ctor for a content just created via XContentCreator::createNewContent()
177 Content::Content(
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 //=========================================================================
190 // virtual
191 Content::~Content()
195 //=========================================================================
197 // XInterface methods.
199 //=========================================================================
201 // virtual
202 void SAL_CALL Content::acquire()
203 throw( )
205 ContentImplHelper::acquire();
208 //=========================================================================
209 // virtual
210 void SAL_CALL Content::release()
211 throw( )
213 ContentImplHelper::release();
216 //=========================================================================
217 // virtual
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() )
230 return uno::Any();
234 return aRet;
237 //=========================================================================
239 // XTypeProvider methods.
241 //=========================================================================
243 XTYPEPROVIDER_COMMON_IMPL( Content );
245 //=========================================================================
246 // virtual
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;
257 if ( !pCollection )
259 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
261 pCollection = pFolderTypes;
262 if ( !pCollection )
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;
281 else {
282 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
285 else
287 static cppu::OTypeCollection* pDocumentTypes = 0;
289 pCollection = pDocumentTypes;
290 if ( !pCollection )
292 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
294 pCollection = pDocumentTypes;
295 if ( !pCollection )
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;
313 else {
314 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
318 return (*pCollection).getTypes();
321 //=========================================================================
323 // XServiceInfo methods.
325 //=========================================================================
327 // virtual
328 rtl::OUString SAL_CALL Content::getImplementationName()
329 throw( uno::RuntimeException )
331 return rtl::OUString::createFromAscii(
332 "com.sun.star.comp.ucb.TransientDocumentsContent" );
335 //=========================================================================
336 // virtual
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 );
353 else
354 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
355 TDOC_ROOT_CONTENT_SERVICE_NAME );
357 return aSNS;
360 //=========================================================================
362 // XContent methods.
364 //=========================================================================
366 // virtual
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 //=========================================================================
375 // virtual
376 uno::Reference< ucb::XContentIdentifier > SAL_CALL
377 Content::getIdentifier()
378 throw( uno::RuntimeException )
381 osl::Guard< osl::Mutex > aGuard( m_aMutex );
383 // Transient?
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 //=========================================================================
399 // virtual
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 )
408 uno::Any aRet;
410 if ( aCommand.Name.equalsAsciiL(
411 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
413 //////////////////////////////////////////////////////////////////
414 // getPropertyValues
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 ),
425 -1 ) ),
426 Environment );
427 // Unreachable
430 aRet <<= getPropertyValues( Properties );
432 else if ( aCommand.Name.equalsAsciiL(
433 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
435 //////////////////////////////////////////////////////////////////
436 // setPropertyValues
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 ),
447 -1 ) ),
448 Environment );
449 // Unreachable
452 if ( !aProperties.getLength() )
454 ucbhelper::cancelCommandExecution(
455 uno::makeAny( lang::IllegalArgumentException(
456 rtl::OUString::createFromAscii(
457 "No properties!" ),
458 static_cast< cppu::OWeakObject * >( this ),
459 -1 ) ),
460 Environment );
461 // Unreachable
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 //////////////////////////////////////////////////////////////////
479 // getCommandInfo
480 //////////////////////////////////////////////////////////////////
482 aRet <<= getCommandInfo( Environment );
484 else if ( aCommand.Name.equalsAsciiL(
485 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
487 //////////////////////////////////////////////////////////////////
488 // open
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 ),
499 -1 ) ),
500 Environment );
501 // Unreachable
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(
518 rtl::OUString(
519 RTL_CONSTASCII_USTRINGPARAM(
520 "insert command only supported by "
521 "folders and streams!" ) ),
522 static_cast< cppu::OWeakObject * >( this ) ) ),
523 Environment );
524 // Unreachable
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(
536 rtl::OUString(
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 * >(
542 this ) ) ),
543 Environment );
544 // Unreachable
547 #endif
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 ),
556 -1 ) ),
557 Environment );
558 // Unreachable
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(
581 rtl::OUString(
582 RTL_CONSTASCII_USTRINGPARAM(
583 "delete command only supported by "
584 "folders and streams!" ) ),
585 static_cast< cppu::OWeakObject * >(
586 this ) ) ),
587 Environment );
588 // Unreachable
592 sal_Bool bDeletePhysical = sal_False;
593 aCommand.Argument >>= bDeletePhysical;
594 destroy( bDeletePhysical, Environment );
596 // Remove own and all children's persistent data.
597 if ( !removeData() )
599 uno::Any aProps
600 = uno::makeAny(
601 beans::PropertyValue(
602 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
603 "Uri")),
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),
611 Environment,
612 rtl::OUString::createFromAscii(
613 "Cannot remove persistent data!" ),
614 this );
615 // Unreachable
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(
636 rtl::OUString(
637 RTL_CONSTASCII_USTRINGPARAM(
638 "transfer command only supported "
639 "by folders and documents!" ) ),
640 static_cast< cppu::OWeakObject * >(
641 this ) ) ),
642 Environment );
643 // Unreachable
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 ),
656 -1 ) ),
657 Environment );
658 // Unreachable
661 transfer( aInfo, Environment );
663 else
665 //////////////////////////////////////////////////////////////////
666 // Unsupported command
667 //////////////////////////////////////////////////////////////////
669 ucbhelper::cancelCommandExecution(
670 uno::makeAny( ucb::UnsupportedCommandException(
671 rtl::OUString(),
672 static_cast< cppu::OWeakObject * >( this ) ) ),
673 Environment );
674 // Unreachable
677 return aRet;
680 //=========================================================================
681 // virtual
682 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
683 throw( uno::RuntimeException )
687 //=========================================================================
689 // XContentCreator methods.
691 //=========================================================================
693 // virtual
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 );
715 // Folder.
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;
722 return aSeq;
724 else
726 #endif
727 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
729 // Folder.
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;
736 // Stream.
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;
744 return aSeq;
745 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
747 #endif
749 else
751 OSL_ENSURE( sal_False,
752 "queryCreatableContentsInfo called on non-contentcreator "
753 "object!" );
755 return uno::Sequence< ucb::ContentInfo >( 0 );
759 //=========================================================================
760 // virtual
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 >();
785 #endif
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( "/" );
803 if ( bCreateFolder )
804 aURL += rtl::OUString::createFromAscii( "New_Folder" );
805 else
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 );
813 else
815 OSL_ENSURE( sal_False,
816 "createNewContent called on non-contentcreator object!" );
817 return uno::Reference< ucb::XContent >();
821 //=========================================================================
822 // virtual
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 ) );
841 return
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() )
854 return;
856 // Obtain a list with a snapshot of all currently instanciated contents
857 // from provider and extract the contents which are direct children
858 // of this content.
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();
877 while ( it != 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!
894 rChildren.push_back(
895 ContentRef(
896 static_cast< Content * >( xChild.get() ) ) );
899 ++it;
903 //=========================================================================
904 sal_Bool Content::exchangeIdentity(
905 const uno::Reference< ucb::XContentIdentifier >& xNewId )
907 if ( !xNewId.is() )
908 return sal_False;
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!" );
919 return sal_False;
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!" );
928 return sal_False;
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();
938 aGuard.clear();
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();
951 while ( it != 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(
963 aOldURL.getLength(),
964 xNewId->getContentIdentifier() );
965 uno::Reference< ucb::XContentIdentifier > xNewChildId
966 = new ::ucbhelper::ContentIdentifier(
967 m_xSMgr, aNewChildURL );
969 if ( !xChild->exchangeIdentity( xNewChildId ) )
970 return sal_False;
972 ++it;
975 return sal_True;
979 OSL_ENSURE( sal_False,
980 "Content::exchangeIdentity - "
981 "Panic! Cannot exchange identity!" );
982 return sal_False;
985 //=========================================================================
986 // static
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 );
999 else
1001 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
1002 = new ::ucbhelper::PropertyValueSet( rSMgr );
1004 sal_Int32 nCount = rProperties.getLength();
1005 if ( nCount )
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 //=========================================================================
1017 // static
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();
1031 if ( nCount )
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 )
1069 xRow->appendObject(
1070 rProp,
1071 uno::makeAny(
1072 pProvider->queryStorageClone( rContentId ) ) );
1073 else
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 )
1082 xRow->appendObject(
1083 rProp,
1084 uno::makeAny(
1085 pProvider->queryDocumentModel( rContentId ) ) );
1086 else
1087 xRow->appendVoid( rProp );
1089 else
1091 // Not a Core Property! Maybe it's an Additional Core Property?!
1093 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1095 xAdditionalPropSet
1096 = uno::Reference< beans::XPropertySet >(
1097 pProvider->getAdditionalPropertySet( rContentId,
1098 sal_False ),
1099 uno::UNO_QUERY );
1100 bTriedToGetAdditonalPropSet = sal_True;
1103 if ( xAdditionalPropSet.is() )
1105 if ( !xRow->appendPropertySetValue(
1106 xAdditionalPropSet,
1107 rProp ) )
1109 // Append empty entry.
1110 xRow->appendVoid( rProp );
1113 else
1115 // Append empty entry.
1116 xRow->appendVoid( rProp );
1121 else
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
1142 : 0 ),
1143 rData.getTitle() );
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 )
1161 xRow->appendObject(
1162 beans::Property( rtl::OUString::createFromAscii( "Storage" ),
1164 getCppuType(
1165 static_cast<
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 )
1173 xRow->appendObject(
1174 beans::Property( rtl::OUString::createFromAscii( "DocumentModel" ),
1176 getCppuType(
1177 static_cast<
1178 const uno::Reference< frame::XModel > * >( 0 ) ),
1179 beans::PropertyAttribute::BOUND
1180 | beans::PropertyAttribute::READONLY ),
1181 uno::makeAny(
1182 pProvider->queryDocumentModel( rContentId ) ) );
1184 // Append all Additional Core Properties.
1186 uno::Reference< beans::XPropertySet > xSet(
1187 pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1188 uno::UNO_QUERY );
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,
1201 rProperties,
1202 m_aProps,
1203 m_pProvider,
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 ) );
1280 else
1282 rtl::OUString aNewValue;
1283 if ( rValue.Value >>= aNewValue )
1285 // No empty titles!
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).
1301 nTitlePos = n;
1304 else
1306 aRet[ n ] <<= lang::IllegalArgumentException(
1307 rtl::OUString::createFromAscii(
1308 "Empty Title not allowed!" ),
1309 static_cast< cppu::OWeakObject * >( this ),
1310 -1 );
1313 else
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 ) );
1333 else
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 ) );
1353 else
1355 // Storage is only supported by folders.
1356 aRet[ n ] <<= beans::UnknownPropertyException(
1357 rtl::OUString::createFromAscii(
1358 "DocumentModel property only supported by "
1359 "documents" ),
1360 static_cast< cppu::OWeakObject * >( this ) );
1363 else
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(
1378 rValue.Name );
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;
1389 nChanged++;
1392 catch ( beans::UnknownPropertyException const & e )
1394 aRet[ n ] <<= e;
1396 catch ( lang::WrappedTargetException const & e )
1398 aRet[ n ] <<= e;
1400 catch ( beans::PropertyVetoException const & e )
1402 aRet[ n ] <<= e;
1404 catch ( lang::IllegalArgumentException const & e )
1406 aRet[ n ] <<= e;
1409 else
1411 aRet[ n ] <<= uno::Exception(
1412 rtl::OUString::createFromAscii(
1413 "No property set for storing the value!" ),
1414 static_cast< cppu::OWeakObject * >( this ) );
1419 if ( bExchange )
1421 uno::Reference< ucb::XContentIdentifier > xOldId
1422 = m_xIdentifier;
1423 uno::Reference< ucb::XContentIdentifier > xNewId
1424 = makeNewIdentifier( m_aProps.getTitle() );
1426 aGuard.clear();
1427 if ( exchangeIdentity( xNewId ) )
1429 // Adapt persistent data.
1430 renameData( xOldId, xNewId );
1432 // Adapt Additional Core Properties.
1433 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1434 xNewId->getContentIdentifier(),
1435 sal_True );
1437 else
1439 // Roll-back.
1440 m_aProps.setTitle( aOldTitle );
1441 aOldTitle = rtl::OUString();
1443 // Set error .
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;
1457 nChanged++;
1460 if ( nChanged > 0 )
1462 // Save changes, if content was already made persistent.
1463 if ( !bExchange && ( m_eState == PERSISTENT ) )
1465 if ( !storeData( uno::Reference< io::XInputStream >(), xEnv ) )
1467 uno::Any aProps
1468 = uno::makeAny(
1469 beans::PropertyValue(
1470 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1471 "Uri")),
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),
1479 xEnv,
1480 rtl::OUString::createFromAscii(
1481 "Cannot store persistent data!" ),
1482 this );
1483 // Unreachable
1487 aChanges.realloc( nChanged );
1489 aGuard.clear();
1490 notifyPropertiesChange( aChanges );
1493 return aRet;
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 );
1514 else
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(
1526 rtl::OUString(),
1527 static_cast< cppu::OWeakObject * >( this ),
1528 sal_Int16( rArg.Mode ) ) ),
1529 xEnv );
1530 // Unreachable
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!
1546 uno::Any aProps
1547 = uno::makeAny(
1548 beans::PropertyValue(
1549 rtl::OUString(
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
1559 ? xEnv
1560 : uno::Reference< ucb::XCommandEnvironment >(),
1561 rtl::OUString::createFromAscii(
1562 "Got no data stream!" ),
1563 this );
1564 // Unreachable
1567 // Done.
1568 xDataStreamer->setStream( xStream );
1570 else
1572 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1573 if ( xOut.is() )
1575 // PUSH: write data into xOut
1577 // May throw CommandFailedException, DocumentPasswordRequest!
1578 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1579 if ( !xIn.is() )
1581 // No interaction if we are not persistent!
1582 uno::Any aProps
1583 = uno::makeAny(
1584 beans::PropertyValue(
1585 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1586 "Uri")),
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
1595 ? xEnv
1596 : uno::Reference< ucb::XCommandEnvironment >(),
1597 rtl::OUString::createFromAscii( "Got no data stream!" ),
1598 this );
1599 // Unreachable
1604 uno::Sequence< sal_Int8 > aBuffer;
1605 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1607 while ( nRead > 0 )
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
1630 else
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 );
1640 if ( !xIn.is() )
1642 // No interaction if we are not persistent!
1643 uno::Any aProps
1644 = uno::makeAny(
1645 beans::PropertyValue(
1646 rtl::OUString(
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
1656 ? xEnv
1657 : uno::Reference<
1658 ucb::XCommandEnvironment >(),
1659 rtl::OUString::createFromAscii(
1660 "Got no data stream!" ),
1661 this );
1662 // Unreachable
1665 // Done.
1666 xDataSink->setInputStream( xIn );
1668 else
1670 ucbhelper::cancelCommandExecution(
1671 uno::makeAny(
1672 ucb::UnsupportedDataSinkException(
1673 rtl::OUString(),
1674 static_cast< cppu::OWeakObject * >( this ),
1675 rArg.Sink ) ),
1676 xEnv );
1677 // Unreachable
1683 return uno::Any();
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!" );
1711 #endif
1712 #endif
1714 // Check, if all required properties were set.
1715 if ( eType == FOLDER )
1717 // Required: Title
1719 if ( m_aProps.getTitle().getLength() == 0 )
1720 m_aProps.setTitle( aUri.getDecodedName() );
1722 else // stream
1724 // Required: data
1726 if ( !xData.is() )
1728 ucbhelper::cancelCommandExecution(
1729 uno::makeAny( ucb::MissingInputStreamException(
1730 rtl::OUString(),
1731 static_cast< cppu::OWeakObject * >( this ) ) ),
1732 xEnv );
1733 // Unreachable
1736 // Required: Title
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 )
1749 // fail.
1750 case ucb::NameClash::ERROR:
1751 if ( hasData( aNewUri ) )
1753 ucbhelper::cancelCommandExecution(
1754 uno::makeAny( ucb::NameClashException(
1755 rtl::OUString(),
1756 static_cast< cppu::OWeakObject * >( this ),
1757 task::InteractionClassification_ERROR,
1758 m_aProps.getTitle() ) ),
1759 xEnv );
1760 // Unreachable
1762 break;
1764 // replace (possibly) existing object.
1765 case ucb::NameClash::OVERWRITE:
1766 break;
1768 // "invent" a new valid title.
1769 case ucb::NameClash::RENAME:
1770 if ( hasData( aNewUri ) )
1772 sal_Int32 nTry = 0;
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 ) );
1783 if ( nTry == 1000 )
1785 ucbhelper::cancelCommandExecution(
1786 uno::makeAny(
1787 ucb::UnsupportedNameClashException(
1788 rtl::OUString::createFromAscii(
1789 "Unable to resolve name clash!" ),
1790 static_cast< cppu::OWeakObject * >( this ),
1791 nNameClashResolve ) ),
1792 xEnv );
1793 // Unreachable
1795 else
1797 rtl::OUStringBuffer aNewTitle = m_aProps.getTitle();
1798 aNewTitle.appendAscii( "_" );
1799 aNewTitle.append( rtl::OUString::valueOf( ++nTry ) );
1800 m_aProps.setTitle( aNewTitle.makeStringAndClear() );
1803 break;
1805 case ucb::NameClash::KEEP: // deprecated
1806 case ucb::NameClash::ASK:
1807 default:
1808 if ( hasData( aNewUri ) )
1810 ucbhelper::cancelCommandExecution(
1811 uno::makeAny(
1812 ucb::UnsupportedNameClashException(
1813 rtl::OUString(),
1814 static_cast< cppu::OWeakObject * >( this ),
1815 nNameClashResolve ) ),
1816 xEnv );
1817 // Unreachable
1819 break;
1822 // Identifier changed?
1823 sal_Bool bNewId = ( aUri != aNewUri );
1825 if ( bNewId )
1827 m_xIdentifier
1828 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewUri.getUri() );
1831 if ( !storeData( xData, xEnv ) )
1833 uno::Any aProps
1834 = uno::makeAny(beans::PropertyValue(
1835 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1836 "Uri")),
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),
1844 xEnv,
1845 rtl::OUString::createFromAscii( "Cannot store persistent data!" ),
1846 this );
1847 // Unreachable
1850 m_eState = PERSISTENT;
1852 if ( bNewId )
1854 //loadData( m_pProvider, m_aUri, m_aProps );
1856 aGuard.clear();
1857 inserted();
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;
1878 // Persistent?
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 ) ) ),
1886 xEnv );
1887 // Unreachable
1890 m_eState = DEAD;
1892 aGuard.clear();
1893 deleted();
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();
1905 while ( it != end )
1907 (*it)->destroy( bDeletePhysical, xEnv );
1908 ++it;
1913 //=========================================================================
1914 void Content::notifyDocumentClosed()
1916 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1918 m_eState = DEAD;
1920 // @@@ anything else to reset or such?
1922 // callback follows!
1923 aGuard.clear();
1925 // Propagate destruction to content event listeners
1926 // Remove this from provider's content list.
1927 deleted();
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 );
1942 else
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 & )
1956 // handled below.
1959 OSL_ENSURE( xChild.is(),
1960 "Content::queryChildContent - unable to create child content!" );
1961 return xChild;
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 );
1973 if ( xChild.is() )
1975 // callback follows!
1976 aGuard.clear();
1978 // Notify "REMOVED" event.
1979 ucb::ContentEvent aEvt(
1980 static_cast< cppu::OWeakObject * >( this ),
1981 ucb::ContentAction::REMOVED,
1982 xChild,
1983 getIdentifier() );
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 );
1997 if ( xChild.is() )
1999 // callback follows!
2000 aGuard.clear();
2002 // Notify "INSERTED" event.
2003 ucb::ContentEvent aEvt(
2004 static_cast< cppu::OWeakObject * >( this ),
2005 ucb::ContentAction::INSERTED,
2006 xChild,
2007 getIdentifier() );
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 );
2020 // Persistent?
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 ) ) ),
2028 xEnv );
2029 // Unreachable
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(
2039 rtl::OUString(),
2040 static_cast< cppu::OWeakObject * >( this ) ) ),
2041 xEnv );
2042 // Unreachable
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 ":/" ) ) )
2051 // Invalid scheme.
2052 ucbhelper::cancelCommandExecution(
2053 uno::makeAny( ucb::InteractiveBadTransferURLException(
2054 rtl::OUString(),
2055 static_cast< cppu::OWeakObject * >( this ) ) ),
2056 xEnv );
2057 // Unreachable
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 ),
2069 -1 ) ),
2070 xEnv );
2071 // Unreachable
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 ),
2082 -1 ) ),
2083 xEnv );
2084 // Unreachable
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() )
2098 if ( aId.compareTo(
2099 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
2101 uno::Any aProps
2102 = uno::makeAny(beans::PropertyValue(
2103 rtl::OUString(
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),
2111 xEnv,
2112 rtl::OUString::createFromAscii(
2113 "Target is equal to or is a child of source!" ),
2114 this );
2115 // Unreachable
2119 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2120 if ( m_aProps.getType() == DOCUMENT )
2122 bool bOK = false;
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 * >(
2140 this ),
2141 -1 ) ),
2142 xEnv );
2143 // Unreachable
2145 bOK = true;
2147 catch ( container::NoSuchElementException const & )
2149 // handled below.
2151 catch ( lang::IllegalArgumentException const & )
2153 // handled below.
2155 catch ( embed::InvalidStorageException const & )
2157 // handled below.
2161 if ( !bOK )
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 ),
2169 -1 ) ),
2170 xEnv );
2171 // Unreachable
2174 #endif
2176 /////////////////////////////////////////////////////////////////////////
2177 // Copy data.
2178 /////////////////////////////////////////////////////////////////////////
2180 rtl::OUString aNewName( rInfo.NewTitle.getLength() > 0
2181 ? rInfo.NewTitle
2182 : aSourceUri.getDecodedName() );
2184 if ( !copyData( aSourceUri, aNewName ) )
2186 uno::Any aProps
2187 = uno::makeAny(
2188 beans::PropertyValue(
2189 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2190 "Uri")),
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),
2197 xEnv,
2198 rtl::OUString(
2199 RTL_CONSTASCII_USTRINGPARAM( "Cannot copy data!" ) ),
2200 this );
2201 // Unreachable
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 );
2214 else
2215 aTargetUri += aSourceUri.getName();
2217 if ( !copyAdditionalPropertySet(
2218 aSourceUri.getUri(), aTargetUri, sal_True ) )
2220 uno::Any aProps
2221 = uno::makeAny(
2222 beans::PropertyValue(
2223 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2224 "Uri")),
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),
2231 xEnv,
2232 rtl::OUString(
2233 RTL_CONSTASCII_USTRINGPARAM(
2234 "Cannot copy additional properties!" ) ),
2235 this );
2236 // Unreachable
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 & )
2257 // queryContent
2260 if ( !xTarget.is() )
2262 uno::Any aProps
2263 = uno::makeAny(beans::PropertyValue(
2264 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2265 "Uri")),
2267 uno::makeAny( aTargetUri ),
2268 beans::PropertyState_DIRECT_VALUE));
2269 ucbhelper::cancelCommandExecution(
2270 ucb::IOErrorCode_CANT_READ,
2271 uno::Sequence< uno::Any >(&aProps, 1),
2272 xEnv,
2273 rtl::OUString::createFromAscii(
2274 "Cannot instanciate target object!" ),
2275 this );
2276 // Unreachable
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 & )
2302 // queryContent
2305 if ( !xSource.is() )
2307 uno::Any aProps
2308 = uno::makeAny(beans::PropertyValue(
2309 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2310 "Uri")),
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),
2317 xEnv,
2318 rtl::OUString::createFromAscii(
2319 "Cannot instanciate target object!" ),
2320 this );
2321 // Unreachable
2324 // Propagate destruction (recursively).
2325 xSource->destroy( sal_True, xEnv );
2327 // Remove all persistent data of source and its children.
2328 if ( !xSource->removeData() )
2330 uno::Any aProps
2331 = uno::makeAny(
2332 beans::PropertyValue(
2333 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2334 "Uri")),
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),
2341 xEnv,
2342 rtl::OUString::createFromAscii(
2343 "Cannot remove persistent data of source object!" ),
2344 this );
2345 // Unreachable
2348 // Remove own and all children's Additional Core Properties.
2349 if ( !xSource->removeAdditionalPropertySet( sal_True ) )
2351 uno::Any aProps
2352 = uno::makeAny(
2353 beans::PropertyValue(
2354 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2355 "Uri")),
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),
2362 xEnv,
2363 rtl::OUString::createFromAscii(
2364 "Cannot remove additional properties of source object!" ),
2365 this );
2366 // Unreachable
2369 } // rInfo.MoveData
2372 //=========================================================================
2373 bool Content::isContentCreator()
2375 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2376 return
2377 ( m_aProps.getType() == FOLDER ) || ( m_aProps.getType() == DOCUMENT );
2380 //=========================================================================
2381 //static
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();
2394 else
2396 // folder or stream
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() )
2405 return false;
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 //=========================================================================
2417 //static
2418 bool Content::loadData( ContentProvider* pProvider,
2419 const Uri & rUri,
2420 ContentProperties& rProps )
2422 if ( rUri.isRoot() ) // root has no storage, but can always be created
2424 rProps
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() )
2434 return false;
2436 rProps
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() )
2446 return false;
2448 // Check whether exists at all, is stream or folder
2451 // return: true -> folder
2452 // return: false -> stream
2453 // NoSuchElementException -> neither folder nor stream
2454 bool bIsFolder
2455 = xStorage->isStorageElement( rUri.getDecodedName() );
2457 rProps
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!" );
2466 return false;
2468 catch ( lang::IllegalArgumentException const & )
2470 // an illegal argument is provided
2471 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2472 return false;
2474 catch ( embed::InvalidStorageException const & )
2476 // this storage is in invalid state for any reason
2477 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2478 return false;
2481 return true;
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!" );
2497 return false;
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() )
2508 return false;
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() )
2515 return false;
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" ) ),
2523 uno::makeAny(
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!" );
2531 return false;
2533 catch ( beans::PropertyVetoException const & )
2535 OSL_ENSURE( false, "Caught PropertyVetoException!" );
2536 return false;
2538 catch ( lang::IllegalArgumentException const & )
2540 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2541 return false;
2543 catch ( lang::WrappedTargetException const & )
2545 OSL_ENSURE( false, "Caught WrappedTargetException!" );
2546 return false;
2549 if ( !commitStorage( xStorage ) )
2550 return false;
2552 else if ( eType == STREAM )
2554 // 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() )
2564 return false;
2566 if ( xData.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 );
2578 while ( nRead > 0 )
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 );
2593 return false;
2595 catch ( io::BufferSizeExceededException const & )
2597 // readSomeBytes, writeBytes
2598 OSL_ENSURE( false, "Caught BufferSizeExceededException!" );
2599 closeOutputStream( xOut );
2600 return false;
2602 catch ( io::IOException const & )
2604 // readSomeBytes, writeBytes
2605 OSL_ENSURE( false, "Caught IOException!" );
2606 closeOutputStream( xOut );
2607 return false;
2609 catch ( ... )
2611 closeOutputStream( xOut );
2612 throw;
2616 // Commit changes.
2617 if ( !commitStorage( xStorage ) )
2618 return false;
2620 else
2622 OSL_ENSURE( false, "Unknown content type!" );
2623 return false;
2625 return true;
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!" );
2639 return false;
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() )
2648 return false;
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!" );
2660 return false;
2662 catch ( lang::IllegalArgumentException const & )
2664 // an illegal argument is provided
2665 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2666 return false;
2668 catch ( container::NoSuchElementException const & )
2670 // there is no element with old name in this storage
2671 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2672 return false;
2674 catch ( container::ElementExistException const & )
2676 // an element with new name already exists in this storage
2677 OSL_ENSURE( false, "Caught ElementExistException!" );
2678 return false;
2680 catch ( io::IOException const & )
2682 // in case of io errors during renaming
2683 OSL_ENSURE( false, "Caught IOException!" );
2684 return false;
2686 catch ( embed::StorageWrappedTargetException const & )
2688 // wraps other exceptions
2689 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2690 return false;
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!" );
2705 return false;
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() )
2714 return false;
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!" );
2724 return false;
2726 catch ( lang::IllegalArgumentException const & )
2728 // an illegal argument is provided
2729 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2730 return false;
2732 catch ( container::NoSuchElementException const & )
2734 // there is no element with this name in this storage
2735 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2736 return false;
2738 catch ( io::IOException const & )
2740 // in case of io errors during renaming
2741 OSL_ENSURE( false, "Caught IOException!" );
2742 return false;
2744 catch ( embed::StorageWrappedTargetException const & )
2746 // wraps other exceptions
2747 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2748 return false;
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!" );
2763 return false;
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() )
2771 return false;
2773 uno::Reference< embed::XStorage > xSourceStorage
2774 = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ );
2776 if ( !xSourceStorage.is() )
2777 return false;
2781 xSourceStorage->copyElementTo( rSourceUri.getDecodedName(),
2782 xDestStorage,
2783 rNewName );
2785 catch ( embed::InvalidStorageException const & )
2787 // this storage is in invalid state for eny reason
2788 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2789 return false;
2791 catch ( lang::IllegalArgumentException const & )
2793 // an illegal argument is provided
2794 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2795 return false;
2797 catch ( container::NoSuchElementException const & )
2799 // there is no element with this name in this storage
2800 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2801 return false;
2803 catch ( container::ElementExistException const & )
2805 // there is no element with this name in this storage
2806 OSL_ENSURE( false, "Caught ElementExistException!" );
2807 return false;
2809 catch ( io::IOException const & )
2811 // in case of io errors during renaming
2812 OSL_ENSURE( false, "Caught IOException!" );
2813 return false;
2815 catch ( embed::StorageWrappedTargetException const & )
2817 // wraps other exceptions
2818 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2819 return false;
2822 return commitStorage( xDestStorage );
2825 //=========================================================================
2826 // static
2827 bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage )
2829 // Commit changes
2830 uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY );
2832 OSL_ENSURE( xTO.is(),
2833 "Required interface css.embed.XTransactedObject missing!" );
2836 xTO->commit();
2838 catch ( io::IOException const & )
2840 OSL_ENSURE( false, "Caught IOException!" );
2841 return false;
2843 catch ( lang::WrappedTargetException const & )
2845 OSL_ENSURE( false, "Caught WrappedTargetException!" );
2846 return false;
2849 return true;
2852 //=========================================================================
2853 // static
2854 bool Content::closeOutputStream(
2855 const uno::Reference< io::XOutputStream > & xOut )
2857 if ( xOut.is() )
2861 xOut->closeOutput();
2862 return true;
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!" );
2877 return false;
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 );
2891 if ( xEnv.is() )
2893 uno::Reference< task::XInteractionHandler > xIH
2894 = xEnv->getInteractionHandler();
2895 if ( xIH.is() )
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 );
2907 if ( xAbort.is() )
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;
2936 throw aRequest;
2939 //=========================================================================
2940 uno::Reference< io::XInputStream > Content::getInputStream(
2941 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2942 throw ( ucb::CommandFailedException,
2943 task::DocumentPasswordRequest )
2945 rtl::OUString aUri;
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();
2958 for ( ;; )
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.
2969 aPassword
2970 = obtainPassword( aUri, /* @@@ find better title */
2971 bPasswordRequested
2972 ? task::PasswordRequestMode_PASSWORD_REENTER
2973 : task::PasswordRequestMode_PASSWORD_ENTER,
2974 xEnv );
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;
2990 for ( ;; )
2994 return uno::Reference< io::XOutputStream >(
2995 pProvider->queryOutputStream(
2996 rUri, aPassword, true /* truncate */ ) );
2998 catch ( packages::WrongPasswordException const & )
3000 // Obtain (new) password.
3001 aPassword
3002 = obtainPassword( rUri, /* @@@ find better title */
3003 bPasswordRequested
3004 ? task::PasswordRequestMode_PASSWORD_REENTER
3005 : task::PasswordRequestMode_PASSWORD_ENTER,
3006 xEnv );
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(),
3023 m_pProvider,
3024 xEnv );
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;
3041 for ( ;; )
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.
3052 aPassword
3053 = obtainPassword( aUri, /* @@@ find better title */
3054 bPasswordRequested
3055 ? task::PasswordRequestMode_PASSWORD_REENTER
3056 : task::PasswordRequestMode_PASSWORD_ENTER,
3057 xEnv );
3058 bPasswordRequested = true;