1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
32 **************************************************************************
34 *************************************************************************/
36 #include "osl/diagnose.h"
37 #include "osl/doublecheckedlocking.h"
38 #include "rtl/ustrbuf.hxx"
40 #include "com/sun/star/beans/PropertyAttribute.hpp"
41 #include "com/sun/star/beans/PropertyValue.hpp"
42 #include "com/sun/star/beans/XPropertySet.hpp"
43 #include "com/sun/star/embed/ElementModes.hpp"
44 #include "com/sun/star/embed/XStorage.hpp"
45 #include "com/sun/star/embed/XTransactedObject.hpp"
46 #include "com/sun/star/io/XActiveDataSink.hpp"
47 #include "com/sun/star/io/XActiveDataStreamer.hpp"
48 #include "com/sun/star/lang/IllegalAccessException.hpp"
49 #include "com/sun/star/sdbc/XRow.hpp"
50 #include "com/sun/star/ucb/ContentAction.hpp"
51 #include "com/sun/star/ucb/ContentInfoAttribute.hpp"
52 #include "com/sun/star/ucb/InsertCommandArgument.hpp"
53 #include "com/sun/star/ucb/InteractiveBadTransferURLException.hpp"
54 #include "com/sun/star/ucb/MissingInputStreamException.hpp"
55 #include "com/sun/star/ucb/MissingPropertiesException.hpp"
56 #include "com/sun/star/ucb/NameClash.hpp"
57 #include "com/sun/star/ucb/NameClashException.hpp"
58 #include "com/sun/star/ucb/OpenCommandArgument2.hpp"
59 #include "com/sun/star/ucb/OpenMode.hpp"
60 #include "com/sun/star/ucb/TransferInfo.hpp"
61 #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
62 #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp"
63 #include "com/sun/star/ucb/UnsupportedNameClashException.hpp"
64 #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp"
65 #include "com/sun/star/ucb/XCommandInfo.hpp"
66 #include "com/sun/star/ucb/XPersistentPropertySet.hpp"
68 #include "ucbhelper/cancelcommandexecution.hxx"
69 #include "ucbhelper/contentidentifier.hxx"
70 #include "ucbhelper/propertyvalueset.hxx"
72 #include "tdoc_content.hxx"
73 #include "tdoc_resultset.hxx"
74 #include "tdoc_passwordrequest.hxx"
76 #include "../inc/urihelper.hxx"
78 using namespace com::sun::star
;
79 using namespace tdoc_ucp
;
81 //=========================================================================
82 static ContentType
lcl_getContentType( const rtl::OUString
& rType
)
84 if ( rType
== TDOC_ROOT_CONTENT_TYPE
)
86 else if ( rType
== TDOC_DOCUMENT_CONTENT_TYPE
)
88 else if ( rType
== TDOC_FOLDER_CONTENT_TYPE
)
90 else if ( rType
== TDOC_STREAM_CONTENT_TYPE
)
94 OSL_FAIL( "Content::Content - unsupported content type string" );
99 //=========================================================================
100 //=========================================================================
102 // Content Implementation.
104 //=========================================================================
105 //=========================================================================
107 // static ( "virtual" ctor )
108 Content
* Content::create(
109 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
110 ContentProvider
* pProvider
,
111 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
113 // Fail, if resource does not exist.
114 ContentProperties aProps
;
115 if ( !Content::loadData( pProvider
,
116 Uri( Identifier
->getContentIdentifier() ),
120 return new Content( rxSMgr
, pProvider
, Identifier
, aProps
);
123 //=========================================================================
124 // static ( "virtual" ctor )
125 Content
* Content::create(
126 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
127 ContentProvider
* pProvider
,
128 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
129 const ucb::ContentInfo
& Info
)
131 if ( Info
.Type
.isEmpty() )
134 if ( Info
.Type
!= TDOC_FOLDER_CONTENT_TYPE
&& Info
.Type
!= TDOC_STREAM_CONTENT_TYPE
)
136 OSL_FAIL( "Content::create - unsupported content type!" );
140 return new Content( rxSMgr
, pProvider
, Identifier
, Info
);
143 //=========================================================================
145 const uno::Reference
< lang::XMultiServiceFactory
> & rxSMgr
,
146 ContentProvider
* pProvider
,
147 const uno::Reference
< ucb::XContentIdentifier
> & Identifier
,
148 const ContentProperties
& rProps
)
149 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
151 m_eState( PERSISTENT
),
152 m_pProvider( pProvider
)
156 //=========================================================================
157 // ctor for a content just created via XContentCreator::createNewContent()
159 const uno::Reference
< lang::XMultiServiceFactory
>& rxSMgr
,
160 ContentProvider
* pProvider
,
161 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
162 const ucb::ContentInfo
& Info
)
163 : ContentImplHelper( rxSMgr
, pProvider
, Identifier
),
164 m_aProps( lcl_getContentType( Info
.Type
), rtl::OUString() ), // no Title (yet)
165 m_eState( TRANSIENT
),
166 m_pProvider( pProvider
)
170 //=========================================================================
176 //=========================================================================
178 // XInterface methods.
180 //=========================================================================
183 void SAL_CALL
Content::acquire()
186 ContentImplHelper::acquire();
189 //=========================================================================
191 void SAL_CALL
Content::release()
194 ContentImplHelper::release();
197 //=========================================================================
199 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
)
200 throw ( uno::RuntimeException
)
202 uno::Any aRet
= ContentImplHelper::queryInterface( rType
);
204 if ( !aRet
.hasValue() )
206 aRet
= cppu::queryInterface(
207 rType
, static_cast< ucb::XContentCreator
* >( this ) );
208 if ( aRet
.hasValue() )
210 if ( !m_aProps
.isContentCreator() )
218 //=========================================================================
220 // XTypeProvider methods.
222 //=========================================================================
224 XTYPEPROVIDER_COMMON_IMPL( Content
);
226 //=========================================================================
228 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes()
229 throw( uno::RuntimeException
)
231 cppu::OTypeCollection
* pCollection
= 0;
233 if ( m_aProps
.isContentCreator() )
235 static cppu::OTypeCollection
* pFolderTypes
= 0;
237 pCollection
= pFolderTypes
;
240 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
242 pCollection
= pFolderTypes
;
245 static cppu::OTypeCollection
aCollection(
246 CPPU_TYPE_REF( lang::XTypeProvider
),
247 CPPU_TYPE_REF( lang::XServiceInfo
),
248 CPPU_TYPE_REF( lang::XComponent
),
249 CPPU_TYPE_REF( ucb::XContent
),
250 CPPU_TYPE_REF( ucb::XCommandProcessor
),
251 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
252 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
253 CPPU_TYPE_REF( beans::XPropertyContainer
),
254 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
255 CPPU_TYPE_REF( container::XChild
),
256 CPPU_TYPE_REF( ucb::XContentCreator
) ); // !!
257 pCollection
= &aCollection
;
258 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
259 pFolderTypes
= pCollection
;
263 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
268 static cppu::OTypeCollection
* pDocumentTypes
= 0;
270 pCollection
= pDocumentTypes
;
273 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
275 pCollection
= pDocumentTypes
;
278 static cppu::OTypeCollection
aCollection(
279 CPPU_TYPE_REF( lang::XTypeProvider
),
280 CPPU_TYPE_REF( lang::XServiceInfo
),
281 CPPU_TYPE_REF( lang::XComponent
),
282 CPPU_TYPE_REF( ucb::XContent
),
283 CPPU_TYPE_REF( ucb::XCommandProcessor
),
284 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
285 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
286 CPPU_TYPE_REF( beans::XPropertyContainer
),
287 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
288 CPPU_TYPE_REF( container::XChild
) );
289 pCollection
= &aCollection
;
290 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
291 pDocumentTypes
= pCollection
;
295 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
299 return (*pCollection
).getTypes();
302 //=========================================================================
304 // XServiceInfo methods.
306 //=========================================================================
309 rtl::OUString SAL_CALL
Content::getImplementationName()
310 throw( uno::RuntimeException
)
312 return rtl::OUString( "com.sun.star.comp.ucb.TransientDocumentsContent" );
315 //=========================================================================
317 uno::Sequence
< rtl::OUString
> SAL_CALL
Content::getSupportedServiceNames()
318 throw( uno::RuntimeException
)
320 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
322 uno::Sequence
< rtl::OUString
> aSNS( 1 );
324 if ( m_aProps
.getType() == STREAM
)
325 aSNS
.getArray()[ 0 ] = rtl::OUString( TDOC_STREAM_CONTENT_SERVICE_NAME
);
326 else if ( m_aProps
.getType() == FOLDER
)
327 aSNS
.getArray()[ 0 ] = rtl::OUString( TDOC_FOLDER_CONTENT_SERVICE_NAME
);
328 else if ( m_aProps
.getType() == DOCUMENT
)
329 aSNS
.getArray()[ 0 ] = rtl::OUString( TDOC_DOCUMENT_CONTENT_SERVICE_NAME
);
331 aSNS
.getArray()[ 0 ] = rtl::OUString( TDOC_ROOT_CONTENT_SERVICE_NAME
);
336 //=========================================================================
340 //=========================================================================
343 rtl::OUString SAL_CALL
Content::getContentType()
344 throw( uno::RuntimeException
)
346 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
347 return m_aProps
.getContentType();
350 //=========================================================================
352 uno::Reference
< ucb::XContentIdentifier
> SAL_CALL
353 Content::getIdentifier()
354 throw( uno::RuntimeException
)
357 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
360 if ( m_eState
== TRANSIENT
)
362 // Transient contents have no identifier.
363 return uno::Reference
< ucb::XContentIdentifier
>();
366 return ContentImplHelper::getIdentifier();
369 //=========================================================================
371 // XCommandProcessor methods.
373 //=========================================================================
376 uno::Any SAL_CALL
Content::execute(
377 const ucb::Command
& aCommand
,
378 sal_Int32
/*CommandId*/,
379 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
380 throw( uno::Exception
,
381 ucb::CommandAbortedException
,
382 uno::RuntimeException
)
386 if ( aCommand
.Name
== "getPropertyValues" )
388 //////////////////////////////////////////////////////////////////
390 //////////////////////////////////////////////////////////////////
392 uno::Sequence
< beans::Property
> Properties
;
393 if ( !( aCommand
.Argument
>>= Properties
) )
395 ucbhelper::cancelCommandExecution(
396 uno::makeAny( lang::IllegalArgumentException(
397 rtl::OUString( "Wrong argument type!" ),
398 static_cast< cppu::OWeakObject
* >( this ),
404 aRet
<<= getPropertyValues( Properties
);
406 else if ( aCommand
.Name
== "setPropertyValues" )
408 //////////////////////////////////////////////////////////////////
410 //////////////////////////////////////////////////////////////////
412 uno::Sequence
< beans::PropertyValue
> aProperties
;
413 if ( !( aCommand
.Argument
>>= aProperties
) )
415 ucbhelper::cancelCommandExecution(
416 uno::makeAny( lang::IllegalArgumentException(
417 rtl::OUString( "Wrong argument type!" ),
418 static_cast< cppu::OWeakObject
* >( this ),
424 if ( !aProperties
.getLength() )
426 ucbhelper::cancelCommandExecution(
427 uno::makeAny( lang::IllegalArgumentException(
428 rtl::OUString( "No properties!" ),
429 static_cast< cppu::OWeakObject
* >( this ),
435 aRet
<<= setPropertyValues( aProperties
, Environment
);
437 else if ( aCommand
.Name
== "getPropertySetInfo" )
439 //////////////////////////////////////////////////////////////////
440 // getPropertySetInfo
441 //////////////////////////////////////////////////////////////////
443 aRet
<<= getPropertySetInfo( Environment
);
445 else if ( aCommand
.Name
== "getCommandInfo" )
447 //////////////////////////////////////////////////////////////////
449 //////////////////////////////////////////////////////////////////
451 aRet
<<= getCommandInfo( Environment
);
453 else if ( aCommand
.Name
== "open" )
455 //////////////////////////////////////////////////////////////////
457 //////////////////////////////////////////////////////////////////
459 ucb::OpenCommandArgument2 aOpenCommand
;
460 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
462 ucbhelper::cancelCommandExecution(
463 uno::makeAny( lang::IllegalArgumentException(
464 rtl::OUString( "Wrong argument type!" ),
465 static_cast< cppu::OWeakObject
* >( this ),
471 aRet
= open( aOpenCommand
, Environment
);
473 else if ( aCommand
.Name
== "insert" )
475 //////////////////////////////////////////////////////////////////
476 // insert ( Supported by folders and streams only )
477 //////////////////////////////////////////////////////////////////
479 ContentType eType
= m_aProps
.getType();
480 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
482 ucbhelper::cancelCommandExecution(
483 uno::makeAny( ucb::UnsupportedCommandException(
484 rtl::OUString( "insert command only supported by "
485 "folders and streams!" ),
486 static_cast< cppu::OWeakObject
* >( this ) ) ),
491 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
492 if ( eType
== STREAM
)
494 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
495 Uri
aParentUri( aUri
.getParentUri() );
496 if ( aParentUri
.isDocument() )
498 ucbhelper::cancelCommandExecution(
499 uno::makeAny( ucb::UnsupportedCommandException(
500 rtl::OUString( "insert command not supported by "
501 "streams that are direct children "
502 "of document root!" ),
503 static_cast< cppu::OWeakObject
* >(
510 ucb::InsertCommandArgument aArg
;
511 if ( !( aCommand
.Argument
>>= aArg
) )
513 ucbhelper::cancelCommandExecution(
514 uno::makeAny( lang::IllegalArgumentException(
515 rtl::OUString( "Wrong argument type!" ),
516 static_cast< cppu::OWeakObject
* >( this ),
522 sal_Int32 nNameClash
= aArg
.ReplaceExisting
523 ? ucb::NameClash::OVERWRITE
524 : ucb::NameClash::ERROR
;
525 insert( aArg
.Data
, nNameClash
, Environment
);
527 else if ( aCommand
.Name
== "delete" )
529 //////////////////////////////////////////////////////////////////
530 // delete ( Supported by folders and streams only )
531 //////////////////////////////////////////////////////////////////
534 osl::MutexGuard
aGuard( m_aMutex
);
536 ContentType eType
= m_aProps
.getType();
537 if ( ( eType
!= FOLDER
) && ( eType
!= STREAM
) )
539 ucbhelper::cancelCommandExecution(
540 uno::makeAny( ucb::UnsupportedCommandException(
541 rtl::OUString( "delete command only supported by "
542 "folders and streams!" ),
543 static_cast< cppu::OWeakObject
* >(
550 sal_Bool bDeletePhysical
= sal_False
;
551 aCommand
.Argument
>>= bDeletePhysical
;
552 destroy( bDeletePhysical
, Environment
);
554 // Remove own and all children's persistent data.
559 beans::PropertyValue(
560 rtl::OUString( "Uri"),
562 uno::makeAny(m_xIdentifier
->
563 getContentIdentifier()),
564 beans::PropertyState_DIRECT_VALUE
));
565 ucbhelper::cancelCommandExecution(
566 ucb::IOErrorCode_CANT_WRITE
,
567 uno::Sequence
< uno::Any
>(&aProps
, 1),
569 rtl::OUString( "Cannot remove persistent data!" ),
574 // Remove own and all children's Additional Core Properties.
575 removeAdditionalPropertySet( sal_True
);
577 else if ( aCommand
.Name
== "transfer" )
579 //////////////////////////////////////////////////////////////////
580 // transfer ( Supported by document and folders only )
581 //////////////////////////////////////////////////////////////////
584 osl::MutexGuard
aGuard( m_aMutex
);
586 ContentType eType
= m_aProps
.getType();
587 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
589 ucbhelper::cancelCommandExecution(
590 uno::makeAny( ucb::UnsupportedCommandException(
591 rtl::OUString( "transfer command only supported "
592 "by folders and documents!" ),
593 static_cast< cppu::OWeakObject
* >(
600 ucb::TransferInfo aInfo
;
601 if ( !( aCommand
.Argument
>>= aInfo
) )
603 OSL_FAIL( "Wrong argument type!" );
604 ucbhelper::cancelCommandExecution(
605 uno::makeAny( lang::IllegalArgumentException(
606 rtl::OUString( "Wrong argument type!" ),
607 static_cast< cppu::OWeakObject
* >( this ),
613 transfer( aInfo
, Environment
);
615 else if ( aCommand
.Name
== "createNewContent" )
617 //////////////////////////////////////////////////////////////////
618 // createNewContent ( Supported by document and folders only )
619 //////////////////////////////////////////////////////////////////
622 osl::MutexGuard
aGuard( m_aMutex
);
624 ContentType eType
= m_aProps
.getType();
625 if ( ( eType
!= FOLDER
) && ( eType
!= DOCUMENT
) )
627 ucbhelper::cancelCommandExecution(
628 uno::makeAny( ucb::UnsupportedCommandException(
629 rtl::OUString( "createNewContent command only "
630 "supported by folders and "
632 static_cast< cppu::OWeakObject
* >(
639 ucb::ContentInfo aInfo
;
640 if ( !( aCommand
.Argument
>>= aInfo
) )
642 OSL_FAIL( "Wrong argument type!" );
643 ucbhelper::cancelCommandExecution(
644 uno::makeAny( lang::IllegalArgumentException(
645 rtl::OUString( "Wrong argument type!" ),
646 static_cast< cppu::OWeakObject
* >( this ),
652 aRet
<<= createNewContent( aInfo
);
656 //////////////////////////////////////////////////////////////////
657 // Unsupported command
658 //////////////////////////////////////////////////////////////////
660 ucbhelper::cancelCommandExecution(
661 uno::makeAny( ucb::UnsupportedCommandException(
663 static_cast< cppu::OWeakObject
* >( this ) ) ),
671 //=========================================================================
673 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
674 throw( uno::RuntimeException
)
678 //=========================================================================
680 // XContentCreator methods.
682 //=========================================================================
685 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
686 Content::queryCreatableContentsInfo()
687 throw( uno::RuntimeException
)
689 return m_aProps
.getCreatableContentsInfo();
692 //=========================================================================
694 uno::Reference
< ucb::XContent
> SAL_CALL
695 Content::createNewContent( const ucb::ContentInfo
& Info
)
696 throw( uno::RuntimeException
)
698 if ( m_aProps
.isContentCreator() )
700 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
702 if ( Info
.Type
.isEmpty() )
703 return uno::Reference
< ucb::XContent
>();
705 sal_Bool bCreateFolder
= Info
.Type
== TDOC_FOLDER_CONTENT_TYPE
;
707 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
708 // streams cannot be created as direct children of document root
709 if ( !bCreateFolder
&& ( m_aProps
.getType() == DOCUMENT
) )
711 OSL_FAIL( "Content::createNewContent - streams cannot be "
712 "created as direct children of document root!" );
713 return uno::Reference
< ucb::XContent
>();
716 if ( !bCreateFolder
&& Info
.Type
!= TDOC_STREAM_CONTENT_TYPE
)
718 OSL_FAIL( "Content::createNewContent - unsupported type!" );
719 return uno::Reference
< ucb::XContent
>();
722 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
724 OSL_ENSURE( !aURL
.isEmpty(),
725 "Content::createNewContent - empty identifier!" );
727 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
728 aURL
+= rtl::OUString("/");
731 aURL
+= rtl::OUString("New_Folder");
733 aURL
+= rtl::OUString("New_Stream");
735 uno::Reference
< ucb::XContentIdentifier
> xId
736 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aURL
);
738 return create( m_xSMgr
, m_pProvider
, xId
, Info
);
742 OSL_FAIL( "createNewContent called on non-contentcreator object!" );
743 return uno::Reference
< ucb::XContent
>();
747 //=========================================================================
749 rtl::OUString
Content::getParentURL()
751 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
752 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
753 return aUri
.getParentUri();
756 //=========================================================================
757 uno::Reference
< ucb::XContentIdentifier
>
758 Content::makeNewIdentifier( const rtl::OUString
& rTitle
)
760 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
762 // Assemble new content identifier...
763 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
764 rtl::OUStringBuffer aNewURL
= aUri
.getParentUri();
765 aNewURL
.append( ::ucb_impl::urihelper::encodeSegment( rTitle
) );
768 uno::Reference
< ucb::XContentIdentifier
>(
769 new ::ucbhelper::ContentIdentifier(
770 m_xSMgr
, aNewURL
.makeStringAndClear() ) );
773 //=========================================================================
774 void Content::queryChildren( ContentRefList
& rChildren
)
776 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
778 // Only folders (root, documents, folders) have children.
779 if ( !m_aProps
.getIsFolder() )
782 // Obtain a list with a snapshot of all currently instanciated contents
783 // from provider and extract the contents which are direct children
786 ::ucbhelper::ContentRefList aAllContents
;
787 m_xProvider
->queryExistingContents( aAllContents
);
789 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
790 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
792 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
794 // No trailing slash found. Append.
795 aURL
+= rtl::OUString("/");
798 sal_Int32 nLen
= aURL
.getLength();
800 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
801 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
805 ::ucbhelper::ContentImplHelperRef xChild
= (*it
);
806 rtl::OUString aChildURL
807 = xChild
->getIdentifier()->getContentIdentifier();
809 // Is aURL a prefix of aChildURL?
810 if ( ( aChildURL
.getLength() > nLen
) &&
811 ( aChildURL
.compareTo( aURL
, nLen
) == 0 ) )
813 sal_Int32 nPos
= nLen
;
814 nPos
= aChildURL
.indexOf( '/', nPos
);
816 if ( ( nPos
== -1 ) ||
817 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
819 // No further slashes / only a final slash. It's a child!
822 static_cast< Content
* >( xChild
.get() ) ) );
829 //=========================================================================
830 sal_Bool
Content::exchangeIdentity(
831 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
836 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
838 uno::Reference
< ucb::XContent
> xThis
= this;
840 // Already persistent?
841 if ( m_eState
!= PERSISTENT
)
843 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
847 // Only folders and streams can be renamed -> exchange identity.
848 ContentType eType
= m_aProps
.getType();
849 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
851 OSL_FAIL( "Content::exchangeIdentity - "
852 "Not supported by root or document!" );
856 // Exchange own identitity.
858 // Fail, if a content with given id already exists.
859 if ( !hasData( Uri( xNewId
->getContentIdentifier() ) ) )
861 rtl::OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
864 if ( exchange( xNewId
) )
866 if ( eType
== FOLDER
)
868 // Process instanciated children...
870 ContentRefList aChildren
;
871 queryChildren( aChildren
);
873 ContentRefList::const_iterator it
= aChildren
.begin();
874 ContentRefList::const_iterator end
= aChildren
.end();
878 ContentRef xChild
= (*it
);
880 // Create new content identifier for the child...
881 uno::Reference
< ucb::XContentIdentifier
> xOldChildId
882 = xChild
->getIdentifier();
883 rtl::OUString aOldChildURL
884 = xOldChildId
->getContentIdentifier();
885 rtl::OUString aNewChildURL
886 = aOldChildURL
.replaceAt(
889 xNewId
->getContentIdentifier() );
890 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
891 = new ::ucbhelper::ContentIdentifier(
892 m_xSMgr
, aNewChildURL
);
894 if ( !xChild
->exchangeIdentity( xNewChildId
) )
904 OSL_FAIL( "Content::exchangeIdentity - "
905 "Panic! Cannot exchange identity!" );
909 //=========================================================================
911 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
912 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
913 const uno::Sequence
< beans::Property
>& rProperties
,
914 ContentProvider
* pProvider
,
915 const rtl::OUString
& rContentId
)
917 ContentProperties aData
;
918 if ( loadData( pProvider
, rContentId
, aData
) )
920 return getPropertyValues(
921 rSMgr
, rProperties
, aData
, pProvider
, rContentId
);
925 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
926 = new ::ucbhelper::PropertyValueSet( rSMgr
);
928 sal_Int32 nCount
= rProperties
.getLength();
931 const beans::Property
* pProps
= rProperties
.getConstArray();
932 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
933 xRow
->appendVoid( pProps
[ n
] );
936 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
940 //=========================================================================
942 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
943 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
944 const uno::Sequence
< beans::Property
>& rProperties
,
945 const ContentProperties
& rData
,
946 ContentProvider
* pProvider
,
947 const rtl::OUString
& rContentId
)
949 // Note: Empty sequence means "get values of all supported properties".
951 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
952 = new ::ucbhelper::PropertyValueSet( rSMgr
);
954 sal_Int32 nCount
= rProperties
.getLength();
957 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
958 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
960 const beans::Property
* pProps
= rProperties
.getConstArray();
961 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
963 const beans::Property
& rProp
= pProps
[ n
];
965 // Process Core properties.
967 if ( rProp
.Name
== "ContentType" )
969 xRow
->appendString ( rProp
, rData
.getContentType() );
971 else if ( rProp
.Name
== "Title" )
973 xRow
->appendString ( rProp
, rData
.getTitle() );
975 else if ( rProp
.Name
== "IsDocument" )
977 xRow
->appendBoolean( rProp
, rData
.getIsDocument() );
979 else if ( rProp
.Name
== "IsFolder" )
981 xRow
->appendBoolean( rProp
, rData
.getIsFolder() );
983 else if ( rProp
.Name
== "CreatableContentsInfo" )
986 rProp
, uno::makeAny( rData
.getCreatableContentsInfo() ) );
988 else if ( rProp
.Name
== "Storage" )
990 // Storage is only supported by folders.
991 ContentType eType
= rData
.getType();
992 if ( eType
== FOLDER
)
996 pProvider
->queryStorageClone( rContentId
) ) );
998 xRow
->appendVoid( rProp
);
1000 else if ( rProp
.Name
== "DocumentModel" )
1002 // DocumentModel is only supported by documents.
1003 ContentType eType
= rData
.getType();
1004 if ( eType
== DOCUMENT
)
1008 pProvider
->queryDocumentModel( rContentId
) ) );
1010 xRow
->appendVoid( rProp
);
1014 // Not a Core Property! Maybe it's an Additional Core Property?!
1016 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1019 = uno::Reference
< beans::XPropertySet
>(
1020 pProvider
->getAdditionalPropertySet( rContentId
,
1023 bTriedToGetAdditonalPropSet
= sal_True
;
1026 if ( xAdditionalPropSet
.is() )
1028 if ( !xRow
->appendPropertySetValue(
1032 // Append empty entry.
1033 xRow
->appendVoid( rProp
);
1038 // Append empty entry.
1039 xRow
->appendVoid( rProp
);
1046 // Append all Core Properties.
1047 xRow
->appendString (
1048 beans::Property( rtl::OUString("ContentType"),
1050 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1051 beans::PropertyAttribute::BOUND
1052 | beans::PropertyAttribute::READONLY
),
1053 rData
.getContentType() );
1055 ContentType eType
= rData
.getType();
1057 xRow
->appendString (
1058 beans::Property( rtl::OUString("Title"),
1060 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1061 // Title is read-only for root and documents.
1062 beans::PropertyAttribute::BOUND
||
1063 ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
1064 ? beans::PropertyAttribute::READONLY
1067 xRow
->appendBoolean(
1068 beans::Property( rtl::OUString("IsDocument"),
1070 getCppuBooleanType(),
1071 beans::PropertyAttribute::BOUND
1072 | beans::PropertyAttribute::READONLY
),
1073 rData
.getIsDocument() );
1074 xRow
->appendBoolean(
1075 beans::Property( rtl::OUString("IsFolder"),
1077 getCppuBooleanType(),
1078 beans::PropertyAttribute::BOUND
1079 | beans::PropertyAttribute::READONLY
),
1080 rData
.getIsFolder() );
1083 rtl::OUString("CreatableContentsInfo"),
1085 getCppuType( static_cast<
1086 const uno::Sequence
< ucb::ContentInfo
> * >( 0 ) ),
1087 beans::PropertyAttribute::BOUND
1088 | beans::PropertyAttribute::READONLY
),
1089 uno::makeAny( rData
.getCreatableContentsInfo() ) );
1091 // Storage is only supported by folders.
1092 if ( eType
== FOLDER
)
1094 beans::Property( rtl::OUString("Storage"),
1098 const uno::Reference
< embed::XStorage
> * >( 0 ) ),
1099 beans::PropertyAttribute::BOUND
1100 | beans::PropertyAttribute::READONLY
),
1101 uno::makeAny( pProvider
->queryStorageClone( rContentId
) ) );
1103 // DocumentModel is only supported by documents.
1104 if ( eType
== DOCUMENT
)
1106 beans::Property( rtl::OUString("DocumentModel"),
1110 const uno::Reference
< frame::XModel
> * >( 0 ) ),
1111 beans::PropertyAttribute::BOUND
1112 | beans::PropertyAttribute::READONLY
),
1114 pProvider
->queryDocumentModel( rContentId
) ) );
1116 // Append all Additional Core Properties.
1118 uno::Reference
< beans::XPropertySet
> xSet(
1119 pProvider
->getAdditionalPropertySet( rContentId
, sal_False
),
1121 xRow
->appendPropertySet( xSet
);
1124 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1127 //=========================================================================
1128 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
1129 const uno::Sequence
< beans::Property
>& rProperties
)
1131 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1132 return getPropertyValues( m_xSMgr
,
1136 m_xIdentifier
->getContentIdentifier() );
1139 //=========================================================================
1140 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1141 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1142 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1143 throw( uno::Exception
)
1145 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1147 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1148 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1149 sal_Int32 nChanged
= 0;
1151 beans::PropertyChangeEvent aEvent
;
1152 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1153 aEvent
.Further
= sal_False
;
1154 // aEvent.PropertyName =
1155 aEvent
.PropertyHandle
= -1;
1156 // aEvent.OldValue =
1157 // aEvent.NewValue =
1159 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1160 sal_Int32 nCount
= rValues
.getLength();
1162 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1163 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1165 sal_Bool bExchange
= sal_False
;
1166 rtl::OUString aOldTitle
;
1167 sal_Int32 nTitlePos
= -1;
1169 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1171 const beans::PropertyValue
& rValue
= pValues
[ n
];
1173 if ( rValue
.Name
== "ContentType" )
1175 // Read-only property!
1176 aRet
[ n
] <<= lang::IllegalAccessException(
1177 rtl::OUString( "Property is read-only!" ),
1178 static_cast< cppu::OWeakObject
* >( this ) );
1180 else if ( rValue
.Name
== "IsDocument" )
1182 // Read-only property!
1183 aRet
[ n
] <<= lang::IllegalAccessException(
1184 rtl::OUString( "Property is read-only!" ),
1185 static_cast< cppu::OWeakObject
* >( this ) );
1187 else if ( rValue
.Name
== "IsFolder" )
1189 // Read-only property!
1190 aRet
[ n
] <<= lang::IllegalAccessException(
1191 rtl::OUString( "Property is read-only!" ),
1192 static_cast< cppu::OWeakObject
* >( this ) );
1194 else if ( rValue
.Name
== "CreatableContentsInfo" )
1196 // Read-only property!
1197 aRet
[ n
] <<= lang::IllegalAccessException(
1198 rtl::OUString( "Property is read-only!" ),
1199 static_cast< cppu::OWeakObject
* >( this ) );
1201 else if ( rValue
.Name
== "Title" )
1203 // Title is read-only for root and documents.
1204 ContentType eType
= m_aProps
.getType();
1205 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
1207 aRet
[ n
] <<= lang::IllegalAccessException(
1208 rtl::OUString( "Property is read-only!" ),
1209 static_cast< cppu::OWeakObject
* >( this ) );
1213 rtl::OUString aNewValue
;
1214 if ( rValue
.Value
>>= aNewValue
)
1217 if ( !aNewValue
.isEmpty() )
1219 if ( aNewValue
!= m_aProps
.getTitle() )
1221 // modified title -> modified URL -> exchange !
1222 if ( m_eState
== PERSISTENT
)
1223 bExchange
= sal_True
;
1225 aOldTitle
= m_aProps
.getTitle();
1226 m_aProps
.setTitle( aNewValue
);
1228 // property change event will be sent later...
1230 // remember position within sequence of values
1231 // (for error handling).
1237 aRet
[ n
] <<= lang::IllegalArgumentException(
1238 rtl::OUString( "Empty Title not allowed!" ),
1239 static_cast< cppu::OWeakObject
* >( this ),
1245 aRet
[ n
] <<= beans::IllegalTypeException(
1246 rtl::OUString( "Title Property value has wrong type!" ),
1247 static_cast< cppu::OWeakObject
* >( this ) );
1251 else if ( rValue
.Name
== "Storage" )
1253 ContentType eType
= m_aProps
.getType();
1254 if ( eType
== FOLDER
)
1256 aRet
[ n
] <<= lang::IllegalAccessException(
1257 rtl::OUString( "Property is read-only!" ),
1258 static_cast< cppu::OWeakObject
* >( this ) );
1262 // Storage is only supported by folders.
1263 aRet
[ n
] <<= beans::UnknownPropertyException(
1264 rtl::OUString( "Storage property only supported by folders" ),
1265 static_cast< cppu::OWeakObject
* >( this ) );
1268 else if ( rValue
.Name
== "DocumentModel" )
1270 ContentType eType
= m_aProps
.getType();
1271 if ( eType
== DOCUMENT
)
1273 aRet
[ n
] <<= lang::IllegalAccessException(
1274 rtl::OUString( "Property is read-only!" ),
1275 static_cast< cppu::OWeakObject
* >( this ) );
1279 // Storage is only supported by folders.
1280 aRet
[ n
] <<= beans::UnknownPropertyException(
1281 rtl::OUString( "DocumentModel property only supported by "
1283 static_cast< cppu::OWeakObject
* >( this ) );
1288 // Not a Core Property! Maybe it's an Additional Core Property?!
1290 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1292 xAdditionalPropSet
= getAdditionalPropertySet( sal_False
);
1293 bTriedToGetAdditonalPropSet
= sal_True
;
1296 if ( xAdditionalPropSet
.is() )
1300 uno::Any aOldValue
= xAdditionalPropSet
->getPropertyValue(
1302 if ( aOldValue
!= rValue
.Value
)
1304 xAdditionalPropSet
->setPropertyValue(
1305 rValue
.Name
, rValue
.Value
);
1307 aEvent
.PropertyName
= rValue
.Name
;
1308 aEvent
.OldValue
= aOldValue
;
1309 aEvent
.NewValue
= rValue
.Value
;
1311 aChanges
.getArray()[ nChanged
] = aEvent
;
1315 catch ( beans::UnknownPropertyException
const & e
)
1319 catch ( lang::WrappedTargetException
const & e
)
1323 catch ( beans::PropertyVetoException
const & e
)
1327 catch ( lang::IllegalArgumentException
const & e
)
1334 aRet
[ n
] <<= uno::Exception(
1335 rtl::OUString( "No property set for storing the value!" ),
1336 static_cast< cppu::OWeakObject
* >( this ) );
1343 uno::Reference
< ucb::XContentIdentifier
> xOldId
1345 uno::Reference
< ucb::XContentIdentifier
> xNewId
1346 = makeNewIdentifier( m_aProps
.getTitle() );
1349 if ( exchangeIdentity( xNewId
) )
1351 // Adapt persistent data.
1352 renameData( xOldId
, xNewId
);
1354 // Adapt Additional Core Properties.
1355 renameAdditionalPropertySet( xOldId
->getContentIdentifier(),
1356 xNewId
->getContentIdentifier(),
1362 m_aProps
.setTitle( aOldTitle
);
1363 aOldTitle
= rtl::OUString();
1366 aRet
[ nTitlePos
] <<= uno::Exception(
1367 rtl::OUString("Exchange failed!"),
1368 static_cast< cppu::OWeakObject
* >( this ) );
1372 if ( !aOldTitle
.isEmpty() )
1374 aEvent
.PropertyName
= rtl::OUString("Title");
1375 aEvent
.OldValue
= uno::makeAny( aOldTitle
);
1376 aEvent
.NewValue
= uno::makeAny( m_aProps
.getTitle() );
1378 aChanges
.getArray()[ nChanged
] = aEvent
;
1384 // Save changes, if content was already made persistent.
1385 if ( !bExchange
&& ( m_eState
== PERSISTENT
) )
1387 if ( !storeData( uno::Reference
< io::XInputStream
>(), xEnv
) )
1391 beans::PropertyValue(
1392 rtl::OUString( "Uri"),
1394 uno::makeAny(m_xIdentifier
->
1395 getContentIdentifier()),
1396 beans::PropertyState_DIRECT_VALUE
));
1397 ucbhelper::cancelCommandExecution(
1398 ucb::IOErrorCode_CANT_WRITE
,
1399 uno::Sequence
< uno::Any
>(&aProps
, 1),
1401 rtl::OUString( "Cannot store persistent data!" ),
1407 aChanges
.realloc( nChanged
);
1410 notifyPropertiesChange( aChanges
);
1416 //=========================================================================
1417 uno::Any
Content::open(
1418 const ucb::OpenCommandArgument2
& rArg
,
1419 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1420 throw( uno::Exception
)
1422 if ( rArg
.Mode
== ucb::OpenMode::ALL
||
1423 rArg
.Mode
== ucb::OpenMode::FOLDERS
||
1424 rArg
.Mode
== ucb::OpenMode::DOCUMENTS
)
1426 //////////////////////////////////////////////////////////////////
1427 // open command for a folder content
1428 //////////////////////////////////////////////////////////////////
1430 uno::Reference
< ucb::XDynamicResultSet
> xSet
1431 = new DynamicResultSet( m_xSMgr
, this, rArg
);
1432 return uno::makeAny( xSet
);
1436 //////////////////////////////////////////////////////////////////
1437 // open command for a document content
1438 //////////////////////////////////////////////////////////////////
1440 if ( ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
1441 ( rArg
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
) )
1443 // Currently(?) unsupported.
1444 ucbhelper::cancelCommandExecution(
1445 uno::makeAny( ucb::UnsupportedOpenModeException(
1447 static_cast< cppu::OWeakObject
* >( this ),
1448 sal_Int16( rArg
.Mode
) ) ),
1453 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1455 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
1457 uno::Reference
< io::XActiveDataStreamer
> xDataStreamer(
1458 rArg
.Sink
, uno::UNO_QUERY
);
1459 if ( xDataStreamer
.is() )
1461 // May throw CommandFailedException, DocumentPasswordRequest!
1462 uno::Reference
< io::XStream
> xStream
= getStream( xEnv
);
1463 if ( !xStream
.is() )
1465 // No interaction if we are not persistent!
1468 beans::PropertyValue(
1469 rtl::OUString( "Uri"),
1471 uno::makeAny(m_xIdentifier
->
1472 getContentIdentifier()),
1473 beans::PropertyState_DIRECT_VALUE
));
1474 ucbhelper::cancelCommandExecution(
1475 ucb::IOErrorCode_CANT_READ
,
1476 uno::Sequence
< uno::Any
>(&aProps
, 1),
1477 m_eState
== PERSISTENT
1479 : uno::Reference
< ucb::XCommandEnvironment
>(),
1480 rtl::OUString( "Got no data stream!" ),
1486 xDataStreamer
->setStream( xStream
);
1490 uno::Reference
< io::XOutputStream
> xOut( rArg
.Sink
, uno::UNO_QUERY
);
1493 // PUSH: write data into xOut
1495 // May throw CommandFailedException, DocumentPasswordRequest!
1496 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1499 // No interaction if we are not persistent!
1502 beans::PropertyValue(
1503 rtl::OUString( "Uri"),
1505 uno::makeAny(m_xIdentifier
->
1506 getContentIdentifier()),
1507 beans::PropertyState_DIRECT_VALUE
));
1508 ucbhelper::cancelCommandExecution(
1509 ucb::IOErrorCode_CANT_READ
,
1510 uno::Sequence
< uno::Any
>(&aProps
, 1),
1511 m_eState
== PERSISTENT
1513 : uno::Reference
< ucb::XCommandEnvironment
>(),
1514 rtl::OUString("Got no data stream!"),
1521 uno::Sequence
< sal_Int8
> aBuffer
;
1522 sal_Int32 nRead
= xIn
->readSomeBytes( aBuffer
, 65536 );
1526 aBuffer
.realloc( nRead
);
1527 xOut
->writeBytes( aBuffer
);
1528 aBuffer
.realloc( 0 );
1529 nRead
= xIn
->readSomeBytes( aBuffer
, 65536 );
1532 xOut
->closeOutput();
1534 catch ( io::NotConnectedException
const & )
1536 // closeOutput, readSomeBytes, writeBytes
1538 catch ( io::BufferSizeExceededException
const & )
1540 // closeOutput, readSomeBytes, writeBytes
1542 catch ( io::IOException
const & )
1544 // closeOutput, readSomeBytes, writeBytes
1549 uno::Reference
< io::XActiveDataSink
> xDataSink(
1550 rArg
.Sink
, uno::UNO_QUERY
);
1551 if ( xDataSink
.is() )
1553 // PULL: wait for client read
1555 // May throw CommandFailedException, DocumentPasswordRequest!
1556 uno::Reference
< io::XInputStream
> xIn
= getInputStream( xEnv
);
1559 // No interaction if we are not persistent!
1562 beans::PropertyValue(
1563 rtl::OUString( "Uri"),
1565 uno::makeAny(m_xIdentifier
->
1566 getContentIdentifier()),
1567 beans::PropertyState_DIRECT_VALUE
));
1568 ucbhelper::cancelCommandExecution(
1569 ucb::IOErrorCode_CANT_READ
,
1570 uno::Sequence
< uno::Any
>(&aProps
, 1),
1571 m_eState
== PERSISTENT
1574 ucb::XCommandEnvironment
>(),
1575 rtl::OUString( "Got no data stream!" ),
1581 xDataSink
->setInputStream( xIn
);
1585 ucbhelper::cancelCommandExecution(
1587 ucb::UnsupportedDataSinkException(
1589 static_cast< cppu::OWeakObject
* >( this ),
1601 //=========================================================================
1602 void Content::insert( const uno::Reference
< io::XInputStream
>& xData
,
1603 sal_Int32 nNameClashResolve
,
1604 const uno::Reference
<
1605 ucb::XCommandEnvironment
> & xEnv
)
1606 throw( uno::Exception
)
1608 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1610 ContentType eType
= m_aProps
.getType();
1612 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1613 "insert command only supported by streams and folders!" );
1615 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
1617 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
1618 #if OSL_DEBUG_LEVEL > 0
1619 if ( eType
== STREAM
)
1621 Uri
aParentUri( aUri
.getParentUri() );
1622 OSL_ENSURE( !aParentUri
.isDocument(),
1623 "insert command not supported by streams that are direct "
1624 "children of document root!" );
1629 // Check, if all required properties were set.
1630 if ( eType
== FOLDER
)
1634 if ( m_aProps
.getTitle().isEmpty() )
1635 m_aProps
.setTitle( aUri
.getDecodedName() );
1643 ucbhelper::cancelCommandExecution(
1644 uno::makeAny( ucb::MissingInputStreamException(
1646 static_cast< cppu::OWeakObject
* >( this ) ) ),
1653 if ( m_aProps
.getTitle().isEmpty() )
1654 m_aProps
.setTitle( aUri
.getDecodedName() );
1657 rtl::OUStringBuffer aNewURL
= aUri
.getParentUri();
1658 aNewURL
.append( m_aProps
.getTitle() );
1659 Uri
aNewUri( aNewURL
.makeStringAndClear() );
1661 // Handle possible name clash...
1662 switch ( nNameClashResolve
)
1665 case ucb::NameClash::ERROR
:
1666 if ( hasData( aNewUri
) )
1668 ucbhelper::cancelCommandExecution(
1669 uno::makeAny( ucb::NameClashException(
1671 static_cast< cppu::OWeakObject
* >( this ),
1672 task::InteractionClassification_ERROR
,
1673 m_aProps
.getTitle() ) ),
1679 // replace (possibly) existing object.
1680 case ucb::NameClash::OVERWRITE
:
1683 // "invent" a new valid title.
1684 case ucb::NameClash::RENAME
:
1685 if ( hasData( aNewUri
) )
1691 rtl::OUStringBuffer aNew
= aNewUri
.getUri();
1692 aNew
.appendAscii( "_" );
1693 aNew
.append( rtl::OUString::valueOf( ++nTry
) );
1694 aNewUri
.setUri( aNew
.makeStringAndClear() );
1696 while ( hasData( aNewUri
) && ( nTry
< 1000 ) );
1700 ucbhelper::cancelCommandExecution(
1702 ucb::UnsupportedNameClashException(
1703 rtl::OUString( "Unable to resolve name clash!" ),
1704 static_cast< cppu::OWeakObject
* >( this ),
1705 nNameClashResolve
) ),
1711 rtl::OUStringBuffer aNewTitle
= m_aProps
.getTitle();
1712 aNewTitle
.appendAscii( "_" );
1713 aNewTitle
.append( rtl::OUString::valueOf( ++nTry
) );
1714 m_aProps
.setTitle( aNewTitle
.makeStringAndClear() );
1719 case ucb::NameClash::KEEP
: // deprecated
1720 case ucb::NameClash::ASK
:
1722 if ( hasData( aNewUri
) )
1724 ucbhelper::cancelCommandExecution(
1726 ucb::UnsupportedNameClashException(
1728 static_cast< cppu::OWeakObject
* >( this ),
1729 nNameClashResolve
) ),
1736 // Identifier changed?
1737 sal_Bool bNewId
= ( aUri
!= aNewUri
);
1742 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aNewUri
.getUri() );
1745 if ( !storeData( xData
, xEnv
) )
1748 = uno::makeAny(beans::PropertyValue(
1749 rtl::OUString( "Uri"),
1751 uno::makeAny(m_xIdentifier
->
1752 getContentIdentifier()),
1753 beans::PropertyState_DIRECT_VALUE
));
1754 ucbhelper::cancelCommandExecution(
1755 ucb::IOErrorCode_CANT_WRITE
,
1756 uno::Sequence
< uno::Any
>(&aProps
, 1),
1758 rtl::OUString("Cannot store persistent data!"),
1763 m_eState
= PERSISTENT
;
1767 //loadData( m_pProvider, m_aUri, m_aProps );
1774 //=========================================================================
1775 void Content::destroy( sal_Bool bDeletePhysical
,
1776 const uno::Reference
<
1777 ucb::XCommandEnvironment
> & xEnv
)
1778 throw( uno::Exception
)
1780 // @@@ take care about bDeletePhysical -> trashcan support
1782 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1784 ContentType eType
= m_aProps
.getType();
1786 OSL_ENSURE( ( eType
== FOLDER
) || ( eType
== STREAM
),
1787 "delete command only supported by streams and folders!" );
1789 uno::Reference
< ucb::XContent
> xThis
= this;
1792 if ( m_eState
!= PERSISTENT
)
1794 ucbhelper::cancelCommandExecution(
1795 uno::makeAny( ucb::UnsupportedCommandException(
1796 rtl::OUString( "Not persistent!" ),
1797 static_cast< cppu::OWeakObject
* >( this ) ) ),
1807 if ( eType
== FOLDER
)
1809 // Process instanciated children...
1811 ContentRefList aChildren
;
1812 queryChildren( aChildren
);
1814 ContentRefList::const_iterator it
= aChildren
.begin();
1815 ContentRefList::const_iterator end
= aChildren
.end();
1819 (*it
)->destroy( bDeletePhysical
, xEnv
);
1825 //=========================================================================
1826 void Content::notifyDocumentClosed()
1828 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1832 // @@@ anything else to reset or such?
1834 // callback follows!
1837 // Propagate destruction to content event listeners
1838 // Remove this from provider's content list.
1842 //=========================================================================
1843 uno::Reference
< ucb::XContent
>
1844 Content::queryChildContent( const rtl::OUString
& rRelativeChildUri
)
1846 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1848 const rtl::OUString aMyId
= getIdentifier()->getContentIdentifier();
1849 rtl::OUStringBuffer
aBuf( aMyId
);
1850 if ( aMyId
.getStr()[ aMyId
.getLength() - 1 ] != sal_Unicode( '/' ) )
1851 aBuf
.appendAscii( "/" );
1852 if ( rRelativeChildUri
.getStr()[ 0 ] != sal_Unicode( '/' ) )
1853 aBuf
.append( rRelativeChildUri
);
1855 aBuf
.append( rRelativeChildUri
.copy( 1 ) );
1857 uno::Reference
< ucb::XContentIdentifier
> xChildId
1858 = new ::ucbhelper::ContentIdentifier(
1859 m_xSMgr
, aBuf
.makeStringAndClear() );
1861 uno::Reference
< ucb::XContent
> xChild
;
1864 xChild
= m_pProvider
->queryContent( xChildId
);
1866 catch ( ucb::IllegalIdentifierException
const & )
1871 OSL_ENSURE( xChild
.is(),
1872 "Content::queryChildContent - unable to create child content!" );
1876 //=========================================================================
1877 void Content::notifyChildRemoved( const rtl::OUString
& rRelativeChildUri
)
1879 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1881 // Ugly! Need to create child content object, just to fill event properly.
1882 uno::Reference
< ucb::XContent
> xChild
1883 = queryChildContent( rRelativeChildUri
);
1887 // callback follows!
1890 // Notify "REMOVED" event.
1891 ucb::ContentEvent
aEvt(
1892 static_cast< cppu::OWeakObject
* >( this ),
1893 ucb::ContentAction::REMOVED
,
1896 notifyContentEvent( aEvt
);
1900 //=========================================================================
1901 void Content::notifyChildInserted( const rtl::OUString
& rRelativeChildUri
)
1903 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1905 // Ugly! Need to create child content object, just to fill event properly.
1906 uno::Reference
< ucb::XContent
> xChild
1907 = queryChildContent( rRelativeChildUri
);
1911 // callback follows!
1914 // Notify "INSERTED" event.
1915 ucb::ContentEvent
aEvt(
1916 static_cast< cppu::OWeakObject
* >( this ),
1917 ucb::ContentAction::INSERTED
,
1920 notifyContentEvent( aEvt
);
1924 //=========================================================================
1925 void Content::transfer(
1926 const ucb::TransferInfo
& rInfo
,
1927 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1928 throw( uno::Exception
)
1930 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1933 if ( m_eState
!= PERSISTENT
)
1935 ucbhelper::cancelCommandExecution(
1936 uno::makeAny( ucb::UnsupportedCommandException(
1937 rtl::OUString( "Not persistent!" ),
1938 static_cast< cppu::OWeakObject
* >( this ) ) ),
1943 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
1945 if ( ( rInfo
.SourceURL
.getLength() < TDOC_URL_SCHEME_LENGTH
+ 2 ) )
1947 // Invaild length (to short).
1948 ucbhelper::cancelCommandExecution(
1949 uno::makeAny( ucb::InteractiveBadTransferURLException(
1951 static_cast< cppu::OWeakObject
* >( this ) ) ),
1956 rtl::OUString aScheme
1957 = rInfo
.SourceURL
.copy( 0, TDOC_URL_SCHEME_LENGTH
+ 2 )
1958 .toAsciiLowerCase();
1959 if ( aScheme
!= TDOC_URL_SCHEME
":/" )
1962 ucbhelper::cancelCommandExecution(
1963 uno::makeAny( ucb::InteractiveBadTransferURLException(
1965 static_cast< cppu::OWeakObject
* >( this ) ) ),
1970 // Does source URI describe a tdoc folder or stream?
1971 Uri
aSourceUri( rInfo
.SourceURL
);
1972 if ( !aSourceUri
.isValid() )
1974 ucbhelper::cancelCommandExecution(
1975 uno::makeAny( lang::IllegalArgumentException(
1976 rtl::OUString( "Invalid source URI! Syntax!" ),
1977 static_cast< cppu::OWeakObject
* >( this ),
1983 if ( aSourceUri
.isRoot() || aSourceUri
.isDocument() )
1985 ucbhelper::cancelCommandExecution(
1986 uno::makeAny( lang::IllegalArgumentException(
1987 rtl::OUString( "Invalid source URI! "
1988 "Must describe a folder or stream!" ),
1989 static_cast< cppu::OWeakObject
* >( this ),
1995 // Is source not a parent of me / not me?
1996 rtl::OUString aId
= m_xIdentifier
->getContentIdentifier();
1997 sal_Int32 nPos
= aId
.lastIndexOf( '/' );
1998 if ( nPos
!= ( aId
.getLength() - 1 ) )
2000 // No trailing slash found. Append.
2001 aId
+= rtl::OUString("/");
2004 if ( rInfo
.SourceURL
.getLength() <= aId
.getLength() )
2007 rInfo
.SourceURL
, rInfo
.SourceURL
.getLength() ) == 0 )
2010 = uno::makeAny(beans::PropertyValue(
2011 rtl::OUString( "Uri"),
2013 uno::makeAny( rInfo
.SourceURL
),
2014 beans::PropertyState_DIRECT_VALUE
));
2015 ucbhelper::cancelCommandExecution(
2016 ucb::IOErrorCode_RECURSIVE
,
2017 uno::Sequence
< uno::Any
>(&aProps
, 1),
2019 rtl::OUString( "Target is equal to or is a child of source!" ),
2025 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2026 if ( m_aProps
.getType() == DOCUMENT
)
2030 uno::Reference
< embed::XStorage
> xStorage
2031 = m_pProvider
->queryStorage(
2032 aSourceUri
.getParentUri(), READ_WRITE_NOCREATE
);
2033 if ( xStorage
.is() )
2037 if ( xStorage
->isStreamElement( aSourceUri
.getDecodedName() ) )
2039 ucbhelper::cancelCommandExecution(
2040 uno::makeAny( lang::IllegalArgumentException(
2041 rtl::OUString( "Invalid source URI! "
2042 "Streams cannot be created as "
2043 "children of document root!" ),
2044 static_cast< cppu::OWeakObject
* >(
2052 catch ( container::NoSuchElementException
const & )
2056 catch ( lang::IllegalArgumentException
const & )
2060 catch ( embed::InvalidStorageException
const & )
2068 ucbhelper::cancelCommandExecution(
2069 uno::makeAny( lang::IllegalArgumentException(
2070 rtl::OUString( "Invalid source URI! "
2071 "Unabale to determine source type!" ),
2072 static_cast< cppu::OWeakObject
* >( this ),
2080 /////////////////////////////////////////////////////////////////////////
2082 /////////////////////////////////////////////////////////////////////////
2084 rtl::OUString
aNewName( !rInfo
.NewTitle
.isEmpty()
2086 : aSourceUri
.getDecodedName() );
2088 if ( !copyData( aSourceUri
, aNewName
) )
2092 beans::PropertyValue(
2093 rtl::OUString( "Uri"),
2095 uno::makeAny( rInfo
.SourceURL
),
2096 beans::PropertyState_DIRECT_VALUE
));
2097 ucbhelper::cancelCommandExecution(
2098 ucb::IOErrorCode_CANT_WRITE
,
2099 uno::Sequence
< uno::Any
>(&aProps
, 1),
2101 rtl::OUString( "Cannot copy data!" ),
2106 /////////////////////////////////////////////////////////////////////////
2107 // Copy own and all children's Additional Core Properties.
2108 /////////////////////////////////////////////////////////////////////////
2110 rtl::OUString aTargetUri
= m_xIdentifier
->getContentIdentifier();
2111 if ( ( aTargetUri
.lastIndexOf( '/' ) + 1 ) != aTargetUri
.getLength() )
2112 aTargetUri
+= rtl::OUString("/");
2114 if ( !rInfo
.NewTitle
.isEmpty() )
2115 aTargetUri
+= ::ucb_impl::urihelper::encodeSegment( rInfo
.NewTitle
);
2117 aTargetUri
+= aSourceUri
.getName();
2119 if ( !copyAdditionalPropertySet(
2120 aSourceUri
.getUri(), aTargetUri
, sal_True
) )
2124 beans::PropertyValue(
2125 rtl::OUString( "Uri"),
2127 uno::makeAny( rInfo
.SourceURL
),
2128 beans::PropertyState_DIRECT_VALUE
));
2129 ucbhelper::cancelCommandExecution(
2130 ucb::IOErrorCode_CANT_WRITE
,
2131 uno::Sequence
< uno::Any
>(&aProps
, 1),
2133 rtl::OUString( "Cannot copy additional properties!" ),
2138 /////////////////////////////////////////////////////////////////////////
2139 // Propagate new content.
2140 /////////////////////////////////////////////////////////////////////////
2142 rtl::Reference
< Content
> xTarget
;
2145 uno::Reference
< ucb::XContentIdentifier
> xTargetId
2146 = new ::ucbhelper::ContentIdentifier( m_xSMgr
, aTargetUri
);
2148 // Note: The static cast is okay here, because its sure that
2149 // m_xProvider is always the WebDAVContentProvider.
2150 xTarget
= static_cast< Content
* >(
2151 m_pProvider
->queryContent( xTargetId
).get() );
2154 catch ( ucb::IllegalIdentifierException
const & )
2159 if ( !xTarget
.is() )
2162 = uno::makeAny(beans::PropertyValue(
2163 rtl::OUString( "Uri"),
2165 uno::makeAny( aTargetUri
),
2166 beans::PropertyState_DIRECT_VALUE
));
2167 ucbhelper::cancelCommandExecution(
2168 ucb::IOErrorCode_CANT_READ
,
2169 uno::Sequence
< uno::Any
>(&aProps
, 1),
2171 rtl::OUString( "Cannot instanciate target object!" ),
2176 // Announce transfered content in its new folder.
2177 xTarget
->inserted();
2179 /////////////////////////////////////////////////////////////////////////
2180 // Remove source, if requested
2181 /////////////////////////////////////////////////////////////////////////
2183 if ( rInfo
.MoveData
)
2185 rtl::Reference
< Content
> xSource
;
2188 uno::Reference
< ucb::XContentIdentifier
>
2189 xSourceId
= new ::ucbhelper::ContentIdentifier(
2190 m_xSMgr
, rInfo
.SourceURL
);
2192 // Note: The static cast is okay here, because its sure
2193 // that m_xProvider is always the ContentProvider.
2194 xSource
= static_cast< Content
* >(
2195 m_xProvider
->queryContent( xSourceId
).get() );
2197 catch ( ucb::IllegalIdentifierException
const & )
2202 if ( !xSource
.is() )
2205 = uno::makeAny(beans::PropertyValue(
2206 rtl::OUString( "Uri"),
2208 uno::makeAny( rInfo
.SourceURL
),
2209 beans::PropertyState_DIRECT_VALUE
));
2210 ucbhelper::cancelCommandExecution(
2211 ucb::IOErrorCode_CANT_READ
,
2212 uno::Sequence
< uno::Any
>(&aProps
, 1),
2214 rtl::OUString( "Cannot instanciate target object!" ),
2219 // Propagate destruction (recursively).
2220 xSource
->destroy( sal_True
, xEnv
);
2222 // Remove all persistent data of source and its children.
2223 if ( !xSource
->removeData() )
2227 beans::PropertyValue(
2228 rtl::OUString( "Uri"),
2230 uno::makeAny( rInfo
.SourceURL
),
2231 beans::PropertyState_DIRECT_VALUE
));
2232 ucbhelper::cancelCommandExecution(
2233 ucb::IOErrorCode_CANT_WRITE
,
2234 uno::Sequence
< uno::Any
>(&aProps
, 1),
2236 rtl::OUString( "Cannot remove persistent data of source object!" ),
2241 // Remove own and all children's Additional Core Properties.
2242 if ( !xSource
->removeAdditionalPropertySet( sal_True
) )
2246 beans::PropertyValue(
2247 rtl::OUString( "Uri"),
2249 uno::makeAny( rInfo
.SourceURL
),
2250 beans::PropertyState_DIRECT_VALUE
));
2251 ucbhelper::cancelCommandExecution(
2252 ucb::IOErrorCode_CANT_WRITE
,
2253 uno::Sequence
< uno::Any
>(&aProps
, 1),
2255 rtl::OUString( "Cannot remove additional properties of source object!" ),
2263 //=========================================================================
2265 bool Content::hasData( ContentProvider
* pProvider
, const Uri
& rUri
)
2267 if ( rUri
.isRoot() )
2269 return true; // root has no storage
2271 else if ( rUri
.isDocument() )
2273 uno::Reference
< embed::XStorage
> xStorage
2274 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2275 return xStorage
.is();
2281 // Ask parent storage. In case that rUri describes a stream,
2282 // ContentProvider::queryStorage( rUri ) would return null.
2284 uno::Reference
< embed::XStorage
> xStorage
2285 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2287 if ( !xStorage
.is() )
2290 uno::Reference
< container::XNameAccess
> xParentNA(
2291 xStorage
, uno::UNO_QUERY
);
2293 OSL_ENSURE( xParentNA
.is(), "Got no css.container.XNameAccess!" );
2295 return xParentNA
->hasByName( rUri
.getDecodedName() );
2299 //=========================================================================
2301 bool Content::loadData( ContentProvider
* pProvider
,
2303 ContentProperties
& rProps
)
2305 if ( rUri
.isRoot() ) // root has no storage, but can always be created
2308 = ContentProperties(
2309 ROOT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2311 else if ( rUri
.isDocument() ) // document must have storage
2313 uno::Reference
< embed::XStorage
> xStorage
2314 = pProvider
->queryStorage( rUri
.getUri(), READ
);
2316 if ( !xStorage
.is() )
2320 = ContentProperties(
2321 DOCUMENT
, pProvider
->queryStorageTitle( rUri
.getUri() ) );
2323 else // stream or folder; stream has no storage; folder has storage
2325 uno::Reference
< embed::XStorage
> xStorage
2326 = pProvider
->queryStorage( rUri
.getParentUri(), READ
);
2328 if ( !xStorage
.is() )
2331 // Check whether exists at all, is stream or folder
2334 // return: true -> folder
2335 // return: false -> stream
2336 // NoSuchElementException -> neither folder nor stream
2338 = xStorage
->isStorageElement( rUri
.getDecodedName() );
2341 = ContentProperties(
2342 bIsFolder
? FOLDER
: STREAM
,
2343 pProvider
->queryStorageTitle( rUri
.getUri() ) );
2345 catch ( container::NoSuchElementException
const & )
2347 // there is no element with such name
2348 //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2351 catch ( lang::IllegalArgumentException
const & )
2353 // an illegal argument is provided
2354 OSL_FAIL( "Caught IllegalArgumentException!" );
2357 catch ( embed::InvalidStorageException
const & )
2359 // this storage is in invalid state for any reason
2360 OSL_FAIL( "Caught InvalidStorageException!" );
2367 //=========================================================================
2368 bool Content::storeData( const uno::Reference
< io::XInputStream
>& xData
,
2369 const uno::Reference
<
2370 ucb::XCommandEnvironment
>& xEnv
)
2371 throw ( ucb::CommandFailedException
,
2372 task::DocumentPasswordRequest
)
2374 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2376 ContentType eType
= m_aProps
.getType();
2377 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2379 OSL_FAIL( "storeData not supported by root and documents!" );
2383 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2385 if ( eType
== FOLDER
)
2387 uno::Reference
< embed::XStorage
> xStorage
2388 = m_pProvider
->queryStorage( aUri
.getUri(), READ_WRITE_CREATE
);
2390 if ( !xStorage
.is() )
2393 uno::Reference
< beans::XPropertySet
> xPropSet(
2394 xStorage
, uno::UNO_QUERY
);
2395 OSL_ENSURE( xPropSet
.is(),
2396 "Content::storeData - Got no XPropertySet interface!" );
2397 if ( !xPropSet
.is() )
2402 // According to MBA, if no mediatype is set, folder and all
2403 // its contents will be lost on save of the document!!!
2404 xPropSet
->setPropertyValue(
2405 rtl::OUString( "MediaType" ),
2407 rtl::OUString( // @@@ better mediatype
2408 "application/binary" ) ) );
2410 catch ( beans::UnknownPropertyException
const & )
2412 OSL_FAIL( "Property MediaType not supported!" );
2415 catch ( beans::PropertyVetoException
const & )
2417 OSL_FAIL( "Caught PropertyVetoException!" );
2420 catch ( lang::IllegalArgumentException
const & )
2422 OSL_FAIL( "Caught IllegalArgumentException!" );
2425 catch ( lang::WrappedTargetException
const & )
2427 OSL_FAIL( "Caught WrappedTargetException!" );
2431 if ( !commitStorage( xStorage
) )
2434 else if ( eType
== STREAM
)
2438 // Important: Parent storage and output stream must be kept alive until
2439 // changes have been committed!
2440 uno::Reference
< embed::XStorage
> xStorage
2441 = m_pProvider
->queryStorage(
2442 aUri
.getParentUri(), READ_WRITE_CREATE
);
2443 uno::Reference
< io::XOutputStream
> xOut
;
2445 if ( !xStorage
.is() )
2450 // May throw CommandFailedException, DocumentPasswordRequest!
2451 xOut
= getTruncatedOutputStream( xEnv
);
2453 OSL_ENSURE( xOut
.is(), "No target data stream!" );
2457 uno::Sequence
< sal_Int8
> aBuffer
;
2458 sal_Int32 nRead
= xData
->readSomeBytes( aBuffer
, 65536 );
2462 aBuffer
.realloc( nRead
);
2463 xOut
->writeBytes( aBuffer
);
2464 aBuffer
.realloc( 0 );
2465 nRead
= xData
->readSomeBytes( aBuffer
, 65536 );
2468 closeOutputStream( xOut
);
2470 catch ( io::NotConnectedException
const & )
2472 // readSomeBytes, writeBytes
2473 OSL_FAIL( "Caught NotConnectedException!" );
2474 closeOutputStream( xOut
);
2477 catch ( io::BufferSizeExceededException
const & )
2479 // readSomeBytes, writeBytes
2480 OSL_FAIL( "Caught BufferSizeExceededException!" );
2481 closeOutputStream( xOut
);
2484 catch ( io::IOException
const & )
2486 // readSomeBytes, writeBytes
2487 OSL_FAIL( "Caught IOException!" );
2488 closeOutputStream( xOut
);
2493 closeOutputStream( xOut
);
2499 if ( !commitStorage( xStorage
) )
2504 OSL_FAIL( "Unknown content type!" );
2510 //=========================================================================
2511 bool Content::renameData(
2512 const uno::Reference
< ucb::XContentIdentifier
>& xOldId
,
2513 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
2515 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2517 ContentType eType
= m_aProps
.getType();
2518 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2520 OSL_FAIL( "renameData not supported by root and documents!" );
2524 Uri
aOldUri( xOldId
->getContentIdentifier() );
2525 uno::Reference
< embed::XStorage
> xStorage
2526 = m_pProvider
->queryStorage(
2527 aOldUri
.getParentUri(), READ_WRITE_NOCREATE
);
2529 if ( !xStorage
.is() )
2534 Uri
aNewUri( xNewId
->getContentIdentifier() );
2535 xStorage
->renameElement(
2536 aOldUri
.getDecodedName(), aNewUri
.getDecodedName() );
2538 catch ( embed::InvalidStorageException
const & )
2540 // this storage is in invalid state for eny reason
2541 OSL_FAIL( "Caught InvalidStorageException!" );
2544 catch ( lang::IllegalArgumentException
const & )
2546 // an illegal argument is provided
2547 OSL_FAIL( "Caught IllegalArgumentException!" );
2550 catch ( container::NoSuchElementException
const & )
2552 // there is no element with old name in this storage
2553 OSL_FAIL( "Caught NoSuchElementException!" );
2556 catch ( container::ElementExistException
const & )
2558 // an element with new name already exists in this storage
2559 OSL_FAIL( "Caught ElementExistException!" );
2562 catch ( io::IOException
const & )
2564 // in case of io errors during renaming
2565 OSL_FAIL( "Caught IOException!" );
2568 catch ( embed::StorageWrappedTargetException
const & )
2570 // wraps other exceptions
2571 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2575 return commitStorage( xStorage
);
2578 //=========================================================================
2579 bool Content::removeData()
2581 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2583 ContentType eType
= m_aProps
.getType();
2584 if ( ( eType
== ROOT
) || ( eType
== DOCUMENT
) )
2586 OSL_FAIL( "removeData not supported by root and documents!" );
2590 Uri
aUri( m_xIdentifier
->getContentIdentifier() );
2591 uno::Reference
< embed::XStorage
> xStorage
2592 = m_pProvider
->queryStorage(
2593 aUri
.getParentUri(), READ_WRITE_NOCREATE
);
2595 if ( !xStorage
.is() )
2600 xStorage
->removeElement( aUri
.getDecodedName() );
2602 catch ( embed::InvalidStorageException
const & )
2604 // this storage is in invalid state for eny reason
2605 OSL_FAIL( "Caught InvalidStorageException!" );
2608 catch ( lang::IllegalArgumentException
const & )
2610 // an illegal argument is provided
2611 OSL_FAIL( "Caught IllegalArgumentException!" );
2614 catch ( container::NoSuchElementException
const & )
2616 // there is no element with this name in this storage
2617 OSL_FAIL( "Caught NoSuchElementException!" );
2620 catch ( io::IOException
const & )
2622 // in case of io errors during renaming
2623 OSL_FAIL( "Caught IOException!" );
2626 catch ( embed::StorageWrappedTargetException
const & )
2628 // wraps other exceptions
2629 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2633 return commitStorage( xStorage
);
2636 //=========================================================================
2637 bool Content::copyData( const Uri
& rSourceUri
, const rtl::OUString
& rNewName
)
2639 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2641 ContentType eType
= m_aProps
.getType();
2642 if ( ( eType
== ROOT
) || ( eType
== STREAM
) )
2644 OSL_FAIL( "copyData not supported by root and streams!" );
2648 Uri
aDestUri( m_xIdentifier
->getContentIdentifier() );
2649 uno::Reference
< embed::XStorage
> xDestStorage
2650 = m_pProvider
->queryStorage( aDestUri
.getUri(), READ_WRITE_NOCREATE
);
2652 if ( !xDestStorage
.is() )
2655 uno::Reference
< embed::XStorage
> xSourceStorage
2656 = m_pProvider
->queryStorage( rSourceUri
.getParentUri(), READ
);
2658 if ( !xSourceStorage
.is() )
2663 xSourceStorage
->copyElementTo( rSourceUri
.getDecodedName(),
2667 catch ( embed::InvalidStorageException
const & )
2669 // this storage is in invalid state for eny reason
2670 OSL_FAIL( "Caught InvalidStorageException!" );
2673 catch ( lang::IllegalArgumentException
const & )
2675 // an illegal argument is provided
2676 OSL_FAIL( "Caught IllegalArgumentException!" );
2679 catch ( container::NoSuchElementException
const & )
2681 // there is no element with this name in this storage
2682 OSL_FAIL( "Caught NoSuchElementException!" );
2685 catch ( container::ElementExistException
const & )
2687 // there is no element with this name in this storage
2688 OSL_FAIL( "Caught ElementExistException!" );
2691 catch ( io::IOException
const & )
2693 // in case of io errors during renaming
2694 OSL_FAIL( "Caught IOException!" );
2697 catch ( embed::StorageWrappedTargetException
const & )
2699 // wraps other exceptions
2700 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2704 return commitStorage( xDestStorage
);
2707 //=========================================================================
2709 bool Content::commitStorage( const uno::Reference
< embed::XStorage
> & xStorage
)
2712 uno::Reference
< embed::XTransactedObject
> xTO( xStorage
, uno::UNO_QUERY
);
2714 OSL_ENSURE( xTO
.is(),
2715 "Required interface css.embed.XTransactedObject missing!" );
2720 catch ( io::IOException
const & )
2722 OSL_FAIL( "Caught IOException!" );
2725 catch ( lang::WrappedTargetException
const & )
2727 OSL_FAIL( "Caught WrappedTargetException!" );
2734 //=========================================================================
2736 bool Content::closeOutputStream(
2737 const uno::Reference
< io::XOutputStream
> & xOut
)
2743 xOut
->closeOutput();
2746 catch ( io::NotConnectedException
const & )
2748 OSL_FAIL( "Caught NotConnectedException!" );
2750 catch ( io::BufferSizeExceededException
const & )
2752 OSL_FAIL( "Caught BufferSizeExceededException!" );
2754 catch ( io::IOException
const & )
2756 OSL_FAIL( "Caught IOException!" );
2762 //=========================================================================
2763 static rtl::OUString
obtainPassword(
2764 const rtl::OUString
& rName
,
2765 task::PasswordRequestMode eMode
,
2766 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2767 throw ( ucb::CommandFailedException
,
2768 task::DocumentPasswordRequest
)
2770 rtl::Reference
< DocumentPasswordRequest
> xRequest
2771 = new DocumentPasswordRequest( eMode
, rName
);
2775 uno::Reference
< task::XInteractionHandler
> xIH
2776 = xEnv
->getInteractionHandler();
2779 xIH
->handle( xRequest
.get() );
2781 rtl::Reference
< ucbhelper::InteractionContinuation
> xSelection
2782 = xRequest
->getSelection();
2784 if ( xSelection
.is() )
2786 // Handler handled the request.
2787 uno::Reference
< task::XInteractionAbort
> xAbort(
2788 xSelection
.get(), uno::UNO_QUERY
);
2791 throw ucb::CommandFailedException(
2792 rtl::OUString( "Abort requested by Interaction Handler." ),
2793 uno::Reference
< uno::XInterface
>(),
2794 xRequest
->getRequest() );
2797 uno::Reference
< task::XInteractionPassword
> xPassword(
2798 xSelection
.get(), uno::UNO_QUERY
);
2799 if ( xPassword
.is() )
2801 return xPassword
->getPassword();
2804 // Unknown selection. Should never happen.
2805 throw ucb::CommandFailedException(
2806 rtl::OUString( "Interaction Handler selected unknown continuation!" ),
2807 uno::Reference
< uno::XInterface
>(),
2808 xRequest
->getRequest() );
2813 // No IH or IH did not handle exception.
2814 task::DocumentPasswordRequest aRequest
;
2815 xRequest
->getRequest() >>= aRequest
;
2819 //=========================================================================
2820 uno::Reference
< io::XInputStream
> Content::getInputStream(
2821 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2822 throw ( ucb::CommandFailedException
,
2823 task::DocumentPasswordRequest
)
2826 rtl::OUString aPassword
;
2827 bool bPasswordRequested
= false;
2830 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2832 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2833 "Content::getInputStream - content is no stream!" );
2835 aUri
= Uri( m_xIdentifier
->getContentIdentifier() ).getUri();
2842 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2843 return uno::Reference
< io::XInputStream
>(
2844 m_pProvider
->queryInputStream( aUri
, aPassword
) );
2846 catch ( packages::WrongPasswordException
const & )
2848 // Obtain (new) password.
2850 = obtainPassword( aUri
, /* @@@ find better title */
2852 ? task::PasswordRequestMode_PASSWORD_REENTER
2853 : task::PasswordRequestMode_PASSWORD_ENTER
,
2855 bPasswordRequested
= true;
2860 //=========================================================================
2861 static uno::Reference
< io::XOutputStream
> lcl_getTruncatedOutputStream(
2862 const rtl::OUString
& rUri
,
2863 ContentProvider
* pProvider
,
2864 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2865 throw ( ucb::CommandFailedException
,
2866 task::DocumentPasswordRequest
)
2868 rtl::OUString aPassword
;
2869 bool bPasswordRequested
= false;
2874 return uno::Reference
< io::XOutputStream
>(
2875 pProvider
->queryOutputStream(
2876 rUri
, aPassword
, true /* truncate */ ) );
2878 catch ( packages::WrongPasswordException
const & )
2880 // Obtain (new) password.
2882 = obtainPassword( rUri
, /* @@@ find better title */
2884 ? task::PasswordRequestMode_PASSWORD_REENTER
2885 : task::PasswordRequestMode_PASSWORD_ENTER
,
2887 bPasswordRequested
= true;
2892 //=========================================================================
2893 uno::Reference
< io::XOutputStream
> Content::getTruncatedOutputStream(
2894 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2895 throw ( ucb::CommandFailedException
,
2896 task::DocumentPasswordRequest
)
2898 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2899 "Content::getTruncatedOutputStream - content is no stream!" );
2901 return lcl_getTruncatedOutputStream(
2902 Uri( m_xIdentifier
->getContentIdentifier() ).getUri(),
2907 //=========================================================================
2908 uno::Reference
< io::XStream
> Content::getStream(
2909 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
2910 throw ( ucb::CommandFailedException
,
2911 task::DocumentPasswordRequest
)
2913 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
2915 OSL_ENSURE( m_aProps
.getType() == STREAM
,
2916 "Content::getStream - content is no stream!" );
2918 rtl::OUString
aUri( Uri( m_xIdentifier
->getContentIdentifier() ).getUri() );
2919 rtl::OUString aPassword
;
2920 bool bPasswordRequested
= false;
2925 return uno::Reference
< io::XStream
>(
2926 m_pProvider
->queryStream(
2927 aUri
, aPassword
, false /* no truncate */ ) );
2929 catch ( packages::WrongPasswordException
const & )
2931 // Obtain (new) password.
2933 = obtainPassword( aUri
, /* @@@ find better title */
2935 ? task::PasswordRequestMode_PASSWORD_REENTER
2936 : task::PasswordRequestMode_PASSWORD_ENTER
,
2938 bPasswordRequested
= true;
2943 //=========================================================================
2944 //=========================================================================
2946 // ContentProperties Implementation.
2948 //=========================================================================
2949 //=========================================================================
2951 uno::Sequence
< ucb::ContentInfo
>
2952 ContentProperties::getCreatableContentsInfo() const
2954 if ( isContentCreator() )
2956 uno::Sequence
< beans::Property
> aProps( 1 );
2957 aProps
.getArray()[ 0 ] = beans::Property(
2958 rtl::OUString("Title"),
2960 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
2961 beans::PropertyAttribute::BOUND
);
2963 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2964 if ( getType() == DOCUMENT
)
2966 // streams cannot be created as direct children of document root
2967 uno::Sequence
< ucb::ContentInfo
> aSeq( 1 );
2970 aSeq
.getArray()[ 0 ].Type
2971 = rtl::OUString( TDOC_FOLDER_CONTENT_TYPE
);
2972 aSeq
.getArray()[ 0 ].Attributes
2973 = ucb::ContentInfoAttribute::KIND_FOLDER
;
2974 aSeq
.getArray()[ 0 ].Properties
= aProps
;
2981 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
2984 aSeq
.getArray()[ 0 ].Type
2985 = rtl::OUString( TDOC_FOLDER_CONTENT_TYPE
);
2986 aSeq
.getArray()[ 0 ].Attributes
2987 = ucb::ContentInfoAttribute::KIND_FOLDER
;
2988 aSeq
.getArray()[ 0 ].Properties
= aProps
;
2991 aSeq
.getArray()[ 1 ].Type
2992 = rtl::OUString( TDOC_STREAM_CONTENT_TYPE
);
2993 aSeq
.getArray()[ 1 ].Attributes
2994 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
2995 | ucb::ContentInfoAttribute::KIND_DOCUMENT
;
2996 aSeq
.getArray()[ 1 ].Properties
= aProps
;
2999 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
3005 OSL_FAIL( "getCreatableContentsInfo called on non-contentcreator "
3008 return uno::Sequence
< ucb::ContentInfo
>( 0 );
3012 //=========================================================================
3013 bool ContentProperties::isContentCreator() const
3015 return ( getType() == FOLDER
) || ( getType() == DOCUMENT
);
3018 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */