Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / tdoc / tdoc_content.cxx
blob76ec1aefecb29dcc773a86cc407c8c92acaf4157
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 /**************************************************************************
31 TODO
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 )
85 return ROOT;
86 else if ( rType == TDOC_DOCUMENT_CONTENT_TYPE )
87 return DOCUMENT;
88 else if ( rType == TDOC_FOLDER_CONTENT_TYPE )
89 return FOLDER;
90 else if ( rType == TDOC_STREAM_CONTENT_TYPE )
91 return STREAM;
92 else
94 OSL_FAIL( "Content::Content - unsupported content type string" );
95 return STREAM;
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() ),
117 aProps ) )
118 return 0;
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() )
132 return 0;
134 if ( Info.Type != TDOC_FOLDER_CONTENT_TYPE && Info.Type != TDOC_STREAM_CONTENT_TYPE )
136 OSL_FAIL( "Content::create - unsupported content type!" );
137 return 0;
140 return new Content( rxSMgr, pProvider, Identifier, Info );
143 //=========================================================================
144 Content::Content(
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 ),
150 m_aProps( rProps ),
151 m_eState( PERSISTENT ),
152 m_pProvider( pProvider )
156 //=========================================================================
157 // ctor for a content just created via XContentCreator::createNewContent()
158 Content::Content(
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 //=========================================================================
171 // virtual
172 Content::~Content()
176 //=========================================================================
178 // XInterface methods.
180 //=========================================================================
182 // virtual
183 void SAL_CALL Content::acquire()
184 throw( )
186 ContentImplHelper::acquire();
189 //=========================================================================
190 // virtual
191 void SAL_CALL Content::release()
192 throw( )
194 ContentImplHelper::release();
197 //=========================================================================
198 // virtual
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() )
211 return uno::Any();
215 return aRet;
218 //=========================================================================
220 // XTypeProvider methods.
222 //=========================================================================
224 XTYPEPROVIDER_COMMON_IMPL( Content );
226 //=========================================================================
227 // virtual
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;
238 if ( !pCollection )
240 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
242 pCollection = pFolderTypes;
243 if ( !pCollection )
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;
262 else {
263 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
266 else
268 static cppu::OTypeCollection* pDocumentTypes = 0;
270 pCollection = pDocumentTypes;
271 if ( !pCollection )
273 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
275 pCollection = pDocumentTypes;
276 if ( !pCollection )
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;
294 else {
295 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
299 return (*pCollection).getTypes();
302 //=========================================================================
304 // XServiceInfo methods.
306 //=========================================================================
308 // virtual
309 rtl::OUString SAL_CALL Content::getImplementationName()
310 throw( uno::RuntimeException )
312 return rtl::OUString( "com.sun.star.comp.ucb.TransientDocumentsContent" );
315 //=========================================================================
316 // virtual
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 );
330 else
331 aSNS.getArray()[ 0 ] = rtl::OUString( TDOC_ROOT_CONTENT_SERVICE_NAME );
333 return aSNS;
336 //=========================================================================
338 // XContent methods.
340 //=========================================================================
342 // virtual
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 //=========================================================================
351 // virtual
352 uno::Reference< ucb::XContentIdentifier > SAL_CALL
353 Content::getIdentifier()
354 throw( uno::RuntimeException )
357 osl::Guard< osl::Mutex > aGuard( m_aMutex );
359 // Transient?
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 //=========================================================================
375 // virtual
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 )
384 uno::Any aRet;
386 if ( aCommand.Name == "getPropertyValues" )
388 //////////////////////////////////////////////////////////////////
389 // getPropertyValues
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 ),
399 -1 ) ),
400 Environment );
401 // Unreachable
404 aRet <<= getPropertyValues( Properties );
406 else if ( aCommand.Name == "setPropertyValues" )
408 //////////////////////////////////////////////////////////////////
409 // setPropertyValues
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 ),
419 -1 ) ),
420 Environment );
421 // Unreachable
424 if ( !aProperties.getLength() )
426 ucbhelper::cancelCommandExecution(
427 uno::makeAny( lang::IllegalArgumentException(
428 rtl::OUString( "No properties!" ),
429 static_cast< cppu::OWeakObject * >( this ),
430 -1 ) ),
431 Environment );
432 // Unreachable
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 //////////////////////////////////////////////////////////////////
448 // getCommandInfo
449 //////////////////////////////////////////////////////////////////
451 aRet <<= getCommandInfo( Environment );
453 else if ( aCommand.Name == "open" )
455 //////////////////////////////////////////////////////////////////
456 // open
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 ),
466 -1 ) ),
467 Environment );
468 // Unreachable
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 ) ) ),
487 Environment );
488 // Unreachable
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 * >(
504 this ) ) ),
505 Environment );
506 // Unreachable
509 #endif
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 ),
517 -1 ) ),
518 Environment );
519 // Unreachable
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 * >(
544 this ) ) ),
545 Environment );
546 // Unreachable
550 sal_Bool bDeletePhysical = sal_False;
551 aCommand.Argument >>= bDeletePhysical;
552 destroy( bDeletePhysical, Environment );
554 // Remove own and all children's persistent data.
555 if ( !removeData() )
557 uno::Any aProps
558 = uno::makeAny(
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),
568 Environment,
569 rtl::OUString( "Cannot remove persistent data!" ),
570 this );
571 // Unreachable
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 * >(
594 this ) ) ),
595 Environment );
596 // Unreachable
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 ),
608 -1 ) ),
609 Environment );
610 // Unreachable
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 "
631 "documents!" ),
632 static_cast< cppu::OWeakObject * >(
633 this ) ) ),
634 Environment );
635 // Unreachable
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 ),
647 -1 ) ),
648 Environment );
649 // Unreachable
652 aRet <<= createNewContent( aInfo );
654 else
656 //////////////////////////////////////////////////////////////////
657 // Unsupported command
658 //////////////////////////////////////////////////////////////////
660 ucbhelper::cancelCommandExecution(
661 uno::makeAny( ucb::UnsupportedCommandException(
662 rtl::OUString(),
663 static_cast< cppu::OWeakObject * >( this ) ) ),
664 Environment );
665 // Unreachable
668 return aRet;
671 //=========================================================================
672 // virtual
673 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
674 throw( uno::RuntimeException )
678 //=========================================================================
680 // XContentCreator methods.
682 //=========================================================================
684 // virtual
685 uno::Sequence< ucb::ContentInfo > SAL_CALL
686 Content::queryCreatableContentsInfo()
687 throw( uno::RuntimeException )
689 return m_aProps.getCreatableContentsInfo();
692 //=========================================================================
693 // virtual
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 >();
715 #endif
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("/");
730 if ( bCreateFolder )
731 aURL += rtl::OUString("New_Folder");
732 else
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 );
740 else
742 OSL_FAIL( "createNewContent called on non-contentcreator object!" );
743 return uno::Reference< ucb::XContent >();
747 //=========================================================================
748 // virtual
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 ) );
767 return
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() )
780 return;
782 // Obtain a list with a snapshot of all currently instanciated contents
783 // from provider and extract the contents which are direct children
784 // of this content.
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();
803 while ( it != 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!
820 rChildren.push_back(
821 ContentRef(
822 static_cast< Content * >( xChild.get() ) ) );
825 ++it;
829 //=========================================================================
830 sal_Bool Content::exchangeIdentity(
831 const uno::Reference< ucb::XContentIdentifier >& xNewId )
833 if ( !xNewId.is() )
834 return sal_False;
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!" );
844 return sal_False;
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!" );
853 return sal_False;
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();
863 aGuard.clear();
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();
876 while ( it != 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(
888 aOldURL.getLength(),
889 xNewId->getContentIdentifier() );
890 uno::Reference< ucb::XContentIdentifier > xNewChildId
891 = new ::ucbhelper::ContentIdentifier(
892 m_xSMgr, aNewChildURL );
894 if ( !xChild->exchangeIdentity( xNewChildId ) )
895 return sal_False;
897 ++it;
900 return sal_True;
904 OSL_FAIL( "Content::exchangeIdentity - "
905 "Panic! Cannot exchange identity!" );
906 return sal_False;
909 //=========================================================================
910 // static
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 );
923 else
925 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
926 = new ::ucbhelper::PropertyValueSet( rSMgr );
928 sal_Int32 nCount = rProperties.getLength();
929 if ( nCount )
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 //=========================================================================
941 // static
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();
955 if ( nCount )
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" )
985 xRow->appendObject(
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 )
993 xRow->appendObject(
994 rProp,
995 uno::makeAny(
996 pProvider->queryStorageClone( rContentId ) ) );
997 else
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 )
1005 xRow->appendObject(
1006 rProp,
1007 uno::makeAny(
1008 pProvider->queryDocumentModel( rContentId ) ) );
1009 else
1010 xRow->appendVoid( rProp );
1012 else
1014 // Not a Core Property! Maybe it's an Additional Core Property?!
1016 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1018 xAdditionalPropSet
1019 = uno::Reference< beans::XPropertySet >(
1020 pProvider->getAdditionalPropertySet( rContentId,
1021 sal_False ),
1022 uno::UNO_QUERY );
1023 bTriedToGetAdditonalPropSet = sal_True;
1026 if ( xAdditionalPropSet.is() )
1028 if ( !xRow->appendPropertySetValue(
1029 xAdditionalPropSet,
1030 rProp ) )
1032 // Append empty entry.
1033 xRow->appendVoid( rProp );
1036 else
1038 // Append empty entry.
1039 xRow->appendVoid( rProp );
1044 else
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
1065 : 0 ),
1066 rData.getTitle() );
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() );
1081 xRow->appendObject(
1082 beans::Property(
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 )
1093 xRow->appendObject(
1094 beans::Property( rtl::OUString("Storage"),
1096 getCppuType(
1097 static_cast<
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 )
1105 xRow->appendObject(
1106 beans::Property( rtl::OUString("DocumentModel"),
1108 getCppuType(
1109 static_cast<
1110 const uno::Reference< frame::XModel > * >( 0 ) ),
1111 beans::PropertyAttribute::BOUND
1112 | beans::PropertyAttribute::READONLY ),
1113 uno::makeAny(
1114 pProvider->queryDocumentModel( rContentId ) ) );
1116 // Append all Additional Core Properties.
1118 uno::Reference< beans::XPropertySet > xSet(
1119 pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1120 uno::UNO_QUERY );
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,
1133 rProperties,
1134 m_aProps,
1135 m_pProvider,
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 ) );
1211 else
1213 rtl::OUString aNewValue;
1214 if ( rValue.Value >>= aNewValue )
1216 // No empty titles!
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).
1232 nTitlePos = n;
1235 else
1237 aRet[ n ] <<= lang::IllegalArgumentException(
1238 rtl::OUString( "Empty Title not allowed!" ),
1239 static_cast< cppu::OWeakObject * >( this ),
1240 -1 );
1243 else
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 ) );
1260 else
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 ) );
1277 else
1279 // Storage is only supported by folders.
1280 aRet[ n ] <<= beans::UnknownPropertyException(
1281 rtl::OUString( "DocumentModel property only supported by "
1282 "documents" ),
1283 static_cast< cppu::OWeakObject * >( this ) );
1286 else
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(
1301 rValue.Name );
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;
1312 nChanged++;
1315 catch ( beans::UnknownPropertyException const & e )
1317 aRet[ n ] <<= e;
1319 catch ( lang::WrappedTargetException const & e )
1321 aRet[ n ] <<= e;
1323 catch ( beans::PropertyVetoException const & e )
1325 aRet[ n ] <<= e;
1327 catch ( lang::IllegalArgumentException const & e )
1329 aRet[ n ] <<= e;
1332 else
1334 aRet[ n ] <<= uno::Exception(
1335 rtl::OUString( "No property set for storing the value!" ),
1336 static_cast< cppu::OWeakObject * >( this ) );
1341 if ( bExchange )
1343 uno::Reference< ucb::XContentIdentifier > xOldId
1344 = m_xIdentifier;
1345 uno::Reference< ucb::XContentIdentifier > xNewId
1346 = makeNewIdentifier( m_aProps.getTitle() );
1348 aGuard.clear();
1349 if ( exchangeIdentity( xNewId ) )
1351 // Adapt persistent data.
1352 renameData( xOldId, xNewId );
1354 // Adapt Additional Core Properties.
1355 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1356 xNewId->getContentIdentifier(),
1357 sal_True );
1359 else
1361 // Roll-back.
1362 m_aProps.setTitle( aOldTitle );
1363 aOldTitle = rtl::OUString();
1365 // Set error .
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;
1379 nChanged++;
1382 if ( nChanged > 0 )
1384 // Save changes, if content was already made persistent.
1385 if ( !bExchange && ( m_eState == PERSISTENT ) )
1387 if ( !storeData( uno::Reference< io::XInputStream >(), xEnv ) )
1389 uno::Any aProps
1390 = uno::makeAny(
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),
1400 xEnv,
1401 rtl::OUString( "Cannot store persistent data!" ),
1402 this );
1403 // Unreachable
1407 aChanges.realloc( nChanged );
1409 aGuard.clear();
1410 notifyPropertiesChange( aChanges );
1413 return aRet;
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 );
1434 else
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(
1446 rtl::OUString(),
1447 static_cast< cppu::OWeakObject * >( this ),
1448 sal_Int16( rArg.Mode ) ) ),
1449 xEnv );
1450 // Unreachable
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!
1466 uno::Any aProps
1467 = uno::makeAny(
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
1478 ? xEnv
1479 : uno::Reference< ucb::XCommandEnvironment >(),
1480 rtl::OUString( "Got no data stream!" ),
1481 this );
1482 // Unreachable
1485 // Done.
1486 xDataStreamer->setStream( xStream );
1488 else
1490 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1491 if ( xOut.is() )
1493 // PUSH: write data into xOut
1495 // May throw CommandFailedException, DocumentPasswordRequest!
1496 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1497 if ( !xIn.is() )
1499 // No interaction if we are not persistent!
1500 uno::Any aProps
1501 = uno::makeAny(
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
1512 ? xEnv
1513 : uno::Reference< ucb::XCommandEnvironment >(),
1514 rtl::OUString("Got no data stream!"),
1515 this );
1516 // Unreachable
1521 uno::Sequence< sal_Int8 > aBuffer;
1522 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1524 while ( nRead > 0 )
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
1547 else
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 );
1557 if ( !xIn.is() )
1559 // No interaction if we are not persistent!
1560 uno::Any aProps
1561 = uno::makeAny(
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
1572 ? xEnv
1573 : uno::Reference<
1574 ucb::XCommandEnvironment >(),
1575 rtl::OUString( "Got no data stream!" ),
1576 this );
1577 // Unreachable
1580 // Done.
1581 xDataSink->setInputStream( xIn );
1583 else
1585 ucbhelper::cancelCommandExecution(
1586 uno::makeAny(
1587 ucb::UnsupportedDataSinkException(
1588 rtl::OUString(),
1589 static_cast< cppu::OWeakObject * >( this ),
1590 rArg.Sink ) ),
1591 xEnv );
1592 // Unreachable
1598 return uno::Any();
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!" );
1626 #endif
1627 #endif
1629 // Check, if all required properties were set.
1630 if ( eType == FOLDER )
1632 // Required: Title
1634 if ( m_aProps.getTitle().isEmpty() )
1635 m_aProps.setTitle( aUri.getDecodedName() );
1637 else // stream
1639 // Required: data
1641 if ( !xData.is() )
1643 ucbhelper::cancelCommandExecution(
1644 uno::makeAny( ucb::MissingInputStreamException(
1645 rtl::OUString(),
1646 static_cast< cppu::OWeakObject * >( this ) ) ),
1647 xEnv );
1648 // Unreachable
1651 // Required: Title
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 )
1664 // fail.
1665 case ucb::NameClash::ERROR:
1666 if ( hasData( aNewUri ) )
1668 ucbhelper::cancelCommandExecution(
1669 uno::makeAny( ucb::NameClashException(
1670 rtl::OUString(),
1671 static_cast< cppu::OWeakObject * >( this ),
1672 task::InteractionClassification_ERROR,
1673 m_aProps.getTitle() ) ),
1674 xEnv );
1675 // Unreachable
1677 break;
1679 // replace (possibly) existing object.
1680 case ucb::NameClash::OVERWRITE:
1681 break;
1683 // "invent" a new valid title.
1684 case ucb::NameClash::RENAME:
1685 if ( hasData( aNewUri ) )
1687 sal_Int32 nTry = 0;
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 ) );
1698 if ( nTry == 1000 )
1700 ucbhelper::cancelCommandExecution(
1701 uno::makeAny(
1702 ucb::UnsupportedNameClashException(
1703 rtl::OUString( "Unable to resolve name clash!" ),
1704 static_cast< cppu::OWeakObject * >( this ),
1705 nNameClashResolve ) ),
1706 xEnv );
1707 // Unreachable
1709 else
1711 rtl::OUStringBuffer aNewTitle = m_aProps.getTitle();
1712 aNewTitle.appendAscii( "_" );
1713 aNewTitle.append( rtl::OUString::valueOf( ++nTry ) );
1714 m_aProps.setTitle( aNewTitle.makeStringAndClear() );
1717 break;
1719 case ucb::NameClash::KEEP: // deprecated
1720 case ucb::NameClash::ASK:
1721 default:
1722 if ( hasData( aNewUri ) )
1724 ucbhelper::cancelCommandExecution(
1725 uno::makeAny(
1726 ucb::UnsupportedNameClashException(
1727 rtl::OUString(),
1728 static_cast< cppu::OWeakObject * >( this ),
1729 nNameClashResolve ) ),
1730 xEnv );
1731 // Unreachable
1733 break;
1736 // Identifier changed?
1737 sal_Bool bNewId = ( aUri != aNewUri );
1739 if ( bNewId )
1741 m_xIdentifier
1742 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewUri.getUri() );
1745 if ( !storeData( xData, xEnv ) )
1747 uno::Any aProps
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),
1757 xEnv,
1758 rtl::OUString("Cannot store persistent data!"),
1759 this );
1760 // Unreachable
1763 m_eState = PERSISTENT;
1765 if ( bNewId )
1767 //loadData( m_pProvider, m_aUri, m_aProps );
1769 aGuard.clear();
1770 inserted();
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;
1791 // Persistent?
1792 if ( m_eState != PERSISTENT )
1794 ucbhelper::cancelCommandExecution(
1795 uno::makeAny( ucb::UnsupportedCommandException(
1796 rtl::OUString( "Not persistent!" ),
1797 static_cast< cppu::OWeakObject * >( this ) ) ),
1798 xEnv );
1799 // Unreachable
1802 m_eState = DEAD;
1804 aGuard.clear();
1805 deleted();
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();
1817 while ( it != end )
1819 (*it)->destroy( bDeletePhysical, xEnv );
1820 ++it;
1825 //=========================================================================
1826 void Content::notifyDocumentClosed()
1828 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1830 m_eState = DEAD;
1832 // @@@ anything else to reset or such?
1834 // callback follows!
1835 aGuard.clear();
1837 // Propagate destruction to content event listeners
1838 // Remove this from provider's content list.
1839 deleted();
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 );
1854 else
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 & )
1868 // handled below.
1871 OSL_ENSURE( xChild.is(),
1872 "Content::queryChildContent - unable to create child content!" );
1873 return xChild;
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 );
1885 if ( xChild.is() )
1887 // callback follows!
1888 aGuard.clear();
1890 // Notify "REMOVED" event.
1891 ucb::ContentEvent aEvt(
1892 static_cast< cppu::OWeakObject * >( this ),
1893 ucb::ContentAction::REMOVED,
1894 xChild,
1895 getIdentifier() );
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 );
1909 if ( xChild.is() )
1911 // callback follows!
1912 aGuard.clear();
1914 // Notify "INSERTED" event.
1915 ucb::ContentEvent aEvt(
1916 static_cast< cppu::OWeakObject * >( this ),
1917 ucb::ContentAction::INSERTED,
1918 xChild,
1919 getIdentifier() );
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 );
1932 // Persistent?
1933 if ( m_eState != PERSISTENT )
1935 ucbhelper::cancelCommandExecution(
1936 uno::makeAny( ucb::UnsupportedCommandException(
1937 rtl::OUString( "Not persistent!" ),
1938 static_cast< cppu::OWeakObject * >( this ) ) ),
1939 xEnv );
1940 // Unreachable
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(
1950 rtl::OUString(),
1951 static_cast< cppu::OWeakObject * >( this ) ) ),
1952 xEnv );
1953 // Unreachable
1956 rtl::OUString aScheme
1957 = rInfo.SourceURL.copy( 0, TDOC_URL_SCHEME_LENGTH + 2 )
1958 .toAsciiLowerCase();
1959 if ( aScheme != TDOC_URL_SCHEME ":/" )
1961 // Invalid scheme.
1962 ucbhelper::cancelCommandExecution(
1963 uno::makeAny( ucb::InteractiveBadTransferURLException(
1964 rtl::OUString(),
1965 static_cast< cppu::OWeakObject * >( this ) ) ),
1966 xEnv );
1967 // Unreachable
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 ),
1978 -1 ) ),
1979 xEnv );
1980 // Unreachable
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 ),
1990 -1 ) ),
1991 xEnv );
1992 // Unreachable
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() )
2006 if ( aId.compareTo(
2007 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
2009 uno::Any aProps
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),
2018 xEnv,
2019 rtl::OUString( "Target is equal to or is a child of source!" ),
2020 this );
2021 // Unreachable
2025 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2026 if ( m_aProps.getType() == DOCUMENT )
2028 bool bOK = false;
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 * >(
2045 this ),
2046 -1 ) ),
2047 xEnv );
2048 // Unreachable
2050 bOK = true;
2052 catch ( container::NoSuchElementException const & )
2054 // handled below.
2056 catch ( lang::IllegalArgumentException const & )
2058 // handled below.
2060 catch ( embed::InvalidStorageException const & )
2062 // handled below.
2066 if ( !bOK )
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 ),
2073 -1 ) ),
2074 xEnv );
2075 // Unreachable
2078 #endif
2080 /////////////////////////////////////////////////////////////////////////
2081 // Copy data.
2082 /////////////////////////////////////////////////////////////////////////
2084 rtl::OUString aNewName( !rInfo.NewTitle.isEmpty()
2085 ? rInfo.NewTitle
2086 : aSourceUri.getDecodedName() );
2088 if ( !copyData( aSourceUri, aNewName ) )
2090 uno::Any aProps
2091 = uno::makeAny(
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),
2100 xEnv,
2101 rtl::OUString( "Cannot copy data!" ),
2102 this );
2103 // Unreachable
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 );
2116 else
2117 aTargetUri += aSourceUri.getName();
2119 if ( !copyAdditionalPropertySet(
2120 aSourceUri.getUri(), aTargetUri, sal_True ) )
2122 uno::Any aProps
2123 = uno::makeAny(
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),
2132 xEnv,
2133 rtl::OUString( "Cannot copy additional properties!" ),
2134 this );
2135 // Unreachable
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 & )
2156 // queryContent
2159 if ( !xTarget.is() )
2161 uno::Any aProps
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),
2170 xEnv,
2171 rtl::OUString( "Cannot instanciate target object!" ),
2172 this );
2173 // Unreachable
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 & )
2199 // queryContent
2202 if ( !xSource.is() )
2204 uno::Any aProps
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),
2213 xEnv,
2214 rtl::OUString( "Cannot instanciate target object!" ),
2215 this );
2216 // Unreachable
2219 // Propagate destruction (recursively).
2220 xSource->destroy( sal_True, xEnv );
2222 // Remove all persistent data of source and its children.
2223 if ( !xSource->removeData() )
2225 uno::Any aProps
2226 = uno::makeAny(
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),
2235 xEnv,
2236 rtl::OUString( "Cannot remove persistent data of source object!" ),
2237 this );
2238 // Unreachable
2241 // Remove own and all children's Additional Core Properties.
2242 if ( !xSource->removeAdditionalPropertySet( sal_True ) )
2244 uno::Any aProps
2245 = uno::makeAny(
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),
2254 xEnv,
2255 rtl::OUString( "Cannot remove additional properties of source object!" ),
2256 this );
2257 // Unreachable
2260 } // rInfo.MoveData
2263 //=========================================================================
2264 //static
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();
2277 else
2279 // folder or stream
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() )
2288 return false;
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 //=========================================================================
2300 //static
2301 bool Content::loadData( ContentProvider* pProvider,
2302 const Uri & rUri,
2303 ContentProperties& rProps )
2305 if ( rUri.isRoot() ) // root has no storage, but can always be created
2307 rProps
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() )
2317 return false;
2319 rProps
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() )
2329 return false;
2331 // Check whether exists at all, is stream or folder
2334 // return: true -> folder
2335 // return: false -> stream
2336 // NoSuchElementException -> neither folder nor stream
2337 bool bIsFolder
2338 = xStorage->isStorageElement( rUri.getDecodedName() );
2340 rProps
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!" );
2349 return false;
2351 catch ( lang::IllegalArgumentException const & )
2353 // an illegal argument is provided
2354 OSL_FAIL( "Caught IllegalArgumentException!" );
2355 return false;
2357 catch ( embed::InvalidStorageException const & )
2359 // this storage is in invalid state for any reason
2360 OSL_FAIL( "Caught InvalidStorageException!" );
2361 return false;
2364 return true;
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!" );
2380 return false;
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() )
2391 return false;
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() )
2398 return false;
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" ),
2406 uno::makeAny(
2407 rtl::OUString( // @@@ better mediatype
2408 "application/binary" ) ) );
2410 catch ( beans::UnknownPropertyException const & )
2412 OSL_FAIL( "Property MediaType not supported!" );
2413 return false;
2415 catch ( beans::PropertyVetoException const & )
2417 OSL_FAIL( "Caught PropertyVetoException!" );
2418 return false;
2420 catch ( lang::IllegalArgumentException const & )
2422 OSL_FAIL( "Caught IllegalArgumentException!" );
2423 return false;
2425 catch ( lang::WrappedTargetException const & )
2427 OSL_FAIL( "Caught WrappedTargetException!" );
2428 return false;
2431 if ( !commitStorage( xStorage ) )
2432 return false;
2434 else if ( eType == STREAM )
2436 // 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() )
2446 return false;
2448 if ( xData.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 );
2460 while ( nRead > 0 )
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 );
2475 return false;
2477 catch ( io::BufferSizeExceededException const & )
2479 // readSomeBytes, writeBytes
2480 OSL_FAIL( "Caught BufferSizeExceededException!" );
2481 closeOutputStream( xOut );
2482 return false;
2484 catch ( io::IOException const & )
2486 // readSomeBytes, writeBytes
2487 OSL_FAIL( "Caught IOException!" );
2488 closeOutputStream( xOut );
2489 return false;
2491 catch ( ... )
2493 closeOutputStream( xOut );
2494 throw;
2498 // Commit changes.
2499 if ( !commitStorage( xStorage ) )
2500 return false;
2502 else
2504 OSL_FAIL( "Unknown content type!" );
2505 return false;
2507 return true;
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!" );
2521 return false;
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() )
2530 return false;
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!" );
2542 return false;
2544 catch ( lang::IllegalArgumentException const & )
2546 // an illegal argument is provided
2547 OSL_FAIL( "Caught IllegalArgumentException!" );
2548 return false;
2550 catch ( container::NoSuchElementException const & )
2552 // there is no element with old name in this storage
2553 OSL_FAIL( "Caught NoSuchElementException!" );
2554 return false;
2556 catch ( container::ElementExistException const & )
2558 // an element with new name already exists in this storage
2559 OSL_FAIL( "Caught ElementExistException!" );
2560 return false;
2562 catch ( io::IOException const & )
2564 // in case of io errors during renaming
2565 OSL_FAIL( "Caught IOException!" );
2566 return false;
2568 catch ( embed::StorageWrappedTargetException const & )
2570 // wraps other exceptions
2571 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2572 return false;
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!" );
2587 return false;
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() )
2596 return false;
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!" );
2606 return false;
2608 catch ( lang::IllegalArgumentException const & )
2610 // an illegal argument is provided
2611 OSL_FAIL( "Caught IllegalArgumentException!" );
2612 return false;
2614 catch ( container::NoSuchElementException const & )
2616 // there is no element with this name in this storage
2617 OSL_FAIL( "Caught NoSuchElementException!" );
2618 return false;
2620 catch ( io::IOException const & )
2622 // in case of io errors during renaming
2623 OSL_FAIL( "Caught IOException!" );
2624 return false;
2626 catch ( embed::StorageWrappedTargetException const & )
2628 // wraps other exceptions
2629 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2630 return false;
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!" );
2645 return false;
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() )
2653 return false;
2655 uno::Reference< embed::XStorage > xSourceStorage
2656 = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ );
2658 if ( !xSourceStorage.is() )
2659 return false;
2663 xSourceStorage->copyElementTo( rSourceUri.getDecodedName(),
2664 xDestStorage,
2665 rNewName );
2667 catch ( embed::InvalidStorageException const & )
2669 // this storage is in invalid state for eny reason
2670 OSL_FAIL( "Caught InvalidStorageException!" );
2671 return false;
2673 catch ( lang::IllegalArgumentException const & )
2675 // an illegal argument is provided
2676 OSL_FAIL( "Caught IllegalArgumentException!" );
2677 return false;
2679 catch ( container::NoSuchElementException const & )
2681 // there is no element with this name in this storage
2682 OSL_FAIL( "Caught NoSuchElementException!" );
2683 return false;
2685 catch ( container::ElementExistException const & )
2687 // there is no element with this name in this storage
2688 OSL_FAIL( "Caught ElementExistException!" );
2689 return false;
2691 catch ( io::IOException const & )
2693 // in case of io errors during renaming
2694 OSL_FAIL( "Caught IOException!" );
2695 return false;
2697 catch ( embed::StorageWrappedTargetException const & )
2699 // wraps other exceptions
2700 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2701 return false;
2704 return commitStorage( xDestStorage );
2707 //=========================================================================
2708 // static
2709 bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage )
2711 // Commit changes
2712 uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY );
2714 OSL_ENSURE( xTO.is(),
2715 "Required interface css.embed.XTransactedObject missing!" );
2718 xTO->commit();
2720 catch ( io::IOException const & )
2722 OSL_FAIL( "Caught IOException!" );
2723 return false;
2725 catch ( lang::WrappedTargetException const & )
2727 OSL_FAIL( "Caught WrappedTargetException!" );
2728 return false;
2731 return true;
2734 //=========================================================================
2735 // static
2736 bool Content::closeOutputStream(
2737 const uno::Reference< io::XOutputStream > & xOut )
2739 if ( xOut.is() )
2743 xOut->closeOutput();
2744 return true;
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!" );
2759 return false;
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 );
2773 if ( xEnv.is() )
2775 uno::Reference< task::XInteractionHandler > xIH
2776 = xEnv->getInteractionHandler();
2777 if ( xIH.is() )
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 );
2789 if ( xAbort.is() )
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;
2816 throw aRequest;
2819 //=========================================================================
2820 uno::Reference< io::XInputStream > Content::getInputStream(
2821 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2822 throw ( ucb::CommandFailedException,
2823 task::DocumentPasswordRequest )
2825 rtl::OUString aUri;
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();
2838 for ( ;; )
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.
2849 aPassword
2850 = obtainPassword( aUri, /* @@@ find better title */
2851 bPasswordRequested
2852 ? task::PasswordRequestMode_PASSWORD_REENTER
2853 : task::PasswordRequestMode_PASSWORD_ENTER,
2854 xEnv );
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;
2870 for ( ;; )
2874 return uno::Reference< io::XOutputStream >(
2875 pProvider->queryOutputStream(
2876 rUri, aPassword, true /* truncate */ ) );
2878 catch ( packages::WrongPasswordException const & )
2880 // Obtain (new) password.
2881 aPassword
2882 = obtainPassword( rUri, /* @@@ find better title */
2883 bPasswordRequested
2884 ? task::PasswordRequestMode_PASSWORD_REENTER
2885 : task::PasswordRequestMode_PASSWORD_ENTER,
2886 xEnv );
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(),
2903 m_pProvider,
2904 xEnv );
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;
2921 for ( ;; )
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.
2932 aPassword
2933 = obtainPassword( aUri, /* @@@ find better title */
2934 bPasswordRequested
2935 ? task::PasswordRequestMode_PASSWORD_REENTER
2936 : task::PasswordRequestMode_PASSWORD_ENTER,
2937 xEnv );
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 );
2969 // Folder.
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;
2976 return aSeq;
2978 else
2980 #endif
2981 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
2983 // Folder.
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;
2990 // Stream.
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;
2998 return aSeq;
2999 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
3001 #endif
3003 else
3005 OSL_FAIL( "getCreatableContentsInfo called on non-contentcreator "
3006 "object!" );
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: */