fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / ucb / source / ucp / tdoc / tdoc_content.cxx
blobd158135e0dc90771e2328ad8735c616e66e98a9f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
22 TODO
23 **************************************************************************
25 *************************************************************************/
27 #include "osl/diagnose.h"
28 #include "osl/doublecheckedlocking.h"
29 #include "rtl/ustrbuf.hxx"
31 #include "com/sun/star/beans/PropertyAttribute.hpp"
32 #include "com/sun/star/beans/PropertyValue.hpp"
33 #include "com/sun/star/beans/XPropertySet.hpp"
34 #include "com/sun/star/embed/ElementModes.hpp"
35 #include "com/sun/star/embed/XStorage.hpp"
36 #include "com/sun/star/embed/XTransactedObject.hpp"
37 #include "com/sun/star/io/XActiveDataSink.hpp"
38 #include "com/sun/star/io/XActiveDataStreamer.hpp"
39 #include "com/sun/star/lang/IllegalAccessException.hpp"
40 #include "com/sun/star/sdbc/XRow.hpp"
41 #include "com/sun/star/ucb/ContentAction.hpp"
42 #include "com/sun/star/ucb/ContentInfoAttribute.hpp"
43 #include "com/sun/star/ucb/InsertCommandArgument.hpp"
44 #include "com/sun/star/ucb/InteractiveBadTransferURLException.hpp"
45 #include "com/sun/star/ucb/MissingInputStreamException.hpp"
46 #include "com/sun/star/ucb/MissingPropertiesException.hpp"
47 #include "com/sun/star/ucb/NameClash.hpp"
48 #include "com/sun/star/ucb/NameClashException.hpp"
49 #include "com/sun/star/ucb/OpenCommandArgument2.hpp"
50 #include "com/sun/star/ucb/OpenMode.hpp"
51 #include "com/sun/star/ucb/TransferInfo.hpp"
52 #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
53 #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp"
54 #include "com/sun/star/ucb/UnsupportedNameClashException.hpp"
55 #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp"
56 #include "com/sun/star/ucb/XCommandInfo.hpp"
57 #include "com/sun/star/ucb/XPersistentPropertySet.hpp"
59 #include "comphelper/processfactory.hxx"
60 #include "ucbhelper/cancelcommandexecution.hxx"
61 #include "ucbhelper/contentidentifier.hxx"
62 #include "ucbhelper/propertyvalueset.hxx"
64 #include "tdoc_content.hxx"
65 #include "tdoc_resultset.hxx"
66 #include "tdoc_passwordrequest.hxx"
68 #include "../inc/urihelper.hxx"
70 using namespace com::sun::star;
71 using namespace tdoc_ucp;
74 static ContentType lcl_getContentType( const OUString & rType )
76 if ( rType == TDOC_ROOT_CONTENT_TYPE )
77 return ROOT;
78 else if ( rType == TDOC_DOCUMENT_CONTENT_TYPE )
79 return DOCUMENT;
80 else if ( rType == TDOC_FOLDER_CONTENT_TYPE )
81 return FOLDER;
82 else if ( rType == TDOC_STREAM_CONTENT_TYPE )
83 return STREAM;
84 else
86 OSL_FAIL( "Content::Content - unsupported content type string" );
87 return STREAM;
94 // Content Implementation.
99 // static ( "virtual" ctor )
100 Content* Content::create(
101 const uno::Reference< uno::XComponentContext >& rxContext,
102 ContentProvider* pProvider,
103 const uno::Reference< ucb::XContentIdentifier >& Identifier )
105 // Fail, if resource does not exist.
106 ContentProperties aProps;
107 if ( !Content::loadData( pProvider,
108 Uri( Identifier->getContentIdentifier() ),
109 aProps ) )
110 return 0;
112 return new Content( rxContext, pProvider, Identifier, aProps );
116 // static ( "virtual" ctor )
117 Content* Content::create(
118 const uno::Reference< uno::XComponentContext >& rxContext,
119 ContentProvider* pProvider,
120 const uno::Reference< ucb::XContentIdentifier >& Identifier,
121 const ucb::ContentInfo& Info )
123 if ( Info.Type.isEmpty() )
124 return 0;
126 if ( Info.Type != TDOC_FOLDER_CONTENT_TYPE && Info.Type != TDOC_STREAM_CONTENT_TYPE )
128 OSL_FAIL( "Content::create - unsupported content type!" );
129 return 0;
132 return new Content( rxContext, pProvider, Identifier, Info );
136 Content::Content(
137 const uno::Reference< uno::XComponentContext > & rxContext,
138 ContentProvider * pProvider,
139 const uno::Reference< ucb::XContentIdentifier > & Identifier,
140 const ContentProperties & rProps )
141 : ContentImplHelper( rxContext, pProvider, Identifier ),
142 m_aProps( rProps ),
143 m_eState( PERSISTENT ),
144 m_pProvider( pProvider )
149 // ctor for a content just created via XContentCreator::createNewContent()
150 Content::Content(
151 const uno::Reference< uno::XComponentContext >& rxContext,
152 ContentProvider* pProvider,
153 const uno::Reference< ucb::XContentIdentifier >& Identifier,
154 const ucb::ContentInfo& Info )
155 : ContentImplHelper( rxContext, pProvider, Identifier ),
156 m_aProps( lcl_getContentType( Info.Type ), OUString() ), // no Title (yet)
157 m_eState( TRANSIENT ),
158 m_pProvider( pProvider )
163 // virtual
164 Content::~Content()
170 // XInterface methods.
174 // virtual
175 void SAL_CALL Content::acquire()
176 throw( )
178 ContentImplHelper::acquire();
182 // virtual
183 void SAL_CALL Content::release()
184 throw( )
186 ContentImplHelper::release();
190 // virtual
191 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
192 throw ( uno::RuntimeException, std::exception )
194 uno::Any aRet = ContentImplHelper::queryInterface( rType );
196 if ( !aRet.hasValue() )
198 aRet = cppu::queryInterface(
199 rType, static_cast< ucb::XContentCreator * >( this ) );
200 if ( aRet.hasValue() )
202 if ( !m_aProps.isContentCreator() )
203 return uno::Any();
207 return aRet;
212 // XTypeProvider methods.
216 XTYPEPROVIDER_COMMON_IMPL( Content );
219 // virtual
220 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
221 throw( uno::RuntimeException, std::exception )
223 cppu::OTypeCollection * pCollection = 0;
225 if ( m_aProps.isContentCreator() )
227 static cppu::OTypeCollection* pFolderTypes = 0;
229 pCollection = pFolderTypes;
230 if ( !pCollection )
232 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
234 pCollection = pFolderTypes;
235 if ( !pCollection )
237 static cppu::OTypeCollection aCollection(
238 CPPU_TYPE_REF( lang::XTypeProvider ),
239 CPPU_TYPE_REF( lang::XServiceInfo ),
240 CPPU_TYPE_REF( lang::XComponent ),
241 CPPU_TYPE_REF( ucb::XContent ),
242 CPPU_TYPE_REF( ucb::XCommandProcessor ),
243 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
244 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
245 CPPU_TYPE_REF( beans::XPropertyContainer ),
246 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
247 CPPU_TYPE_REF( container::XChild ),
248 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
249 pCollection = &aCollection;
250 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
251 pFolderTypes = pCollection;
254 else {
255 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
258 else
260 static cppu::OTypeCollection* pDocumentTypes = 0;
262 pCollection = pDocumentTypes;
263 if ( !pCollection )
265 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
267 pCollection = pDocumentTypes;
268 if ( !pCollection )
270 static cppu::OTypeCollection aCollection(
271 CPPU_TYPE_REF( lang::XTypeProvider ),
272 CPPU_TYPE_REF( lang::XServiceInfo ),
273 CPPU_TYPE_REF( lang::XComponent ),
274 CPPU_TYPE_REF( ucb::XContent ),
275 CPPU_TYPE_REF( ucb::XCommandProcessor ),
276 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
277 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
278 CPPU_TYPE_REF( beans::XPropertyContainer ),
279 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
280 CPPU_TYPE_REF( container::XChild ) );
281 pCollection = &aCollection;
282 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
283 pDocumentTypes = pCollection;
286 else {
287 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
291 return (*pCollection).getTypes();
296 // XServiceInfo methods.
300 // virtual
301 OUString SAL_CALL Content::getImplementationName()
302 throw( uno::RuntimeException, std::exception )
304 return OUString( "com.sun.star.comp.ucb.TransientDocumentsContent" );
308 // virtual
309 uno::Sequence< OUString > SAL_CALL Content::getSupportedServiceNames()
310 throw( uno::RuntimeException, std::exception )
312 osl::Guard< osl::Mutex > aGuard( m_aMutex );
314 uno::Sequence< OUString > aSNS( 1 );
316 if ( m_aProps.getType() == STREAM )
317 aSNS.getArray()[ 0 ] = TDOC_STREAM_CONTENT_SERVICE_NAME;
318 else if ( m_aProps.getType() == FOLDER )
319 aSNS.getArray()[ 0 ] = TDOC_FOLDER_CONTENT_SERVICE_NAME;
320 else if ( m_aProps.getType() == DOCUMENT )
321 aSNS.getArray()[ 0 ] = TDOC_DOCUMENT_CONTENT_SERVICE_NAME;
322 else
323 aSNS.getArray()[ 0 ] = TDOC_ROOT_CONTENT_SERVICE_NAME;
325 return aSNS;
330 // XContent methods.
334 // virtual
335 OUString SAL_CALL Content::getContentType()
336 throw( uno::RuntimeException, std::exception )
338 osl::Guard< osl::Mutex > aGuard( m_aMutex );
339 return m_aProps.getContentType();
343 // virtual
344 uno::Reference< ucb::XContentIdentifier > SAL_CALL
345 Content::getIdentifier()
346 throw( uno::RuntimeException, std::exception )
349 osl::Guard< osl::Mutex > aGuard( m_aMutex );
351 // Transient?
352 if ( m_eState == TRANSIENT )
354 // Transient contents have no identifier.
355 return uno::Reference< ucb::XContentIdentifier >();
358 return ContentImplHelper::getIdentifier();
363 // XCommandProcessor methods.
367 // virtual
368 uno::Any SAL_CALL Content::execute(
369 const ucb::Command& aCommand,
370 sal_Int32 /*CommandId*/,
371 const uno::Reference< ucb::XCommandEnvironment >& Environment )
372 throw( uno::Exception,
373 ucb::CommandAbortedException,
374 uno::RuntimeException, std::exception )
376 uno::Any aRet;
378 if ( aCommand.Name == "getPropertyValues" )
381 // getPropertyValues
384 uno::Sequence< beans::Property > Properties;
385 if ( !( aCommand.Argument >>= Properties ) )
387 ucbhelper::cancelCommandExecution(
388 uno::makeAny( lang::IllegalArgumentException(
389 OUString( "Wrong argument type!" ),
390 static_cast< cppu::OWeakObject * >( this ),
391 -1 ) ),
392 Environment );
393 // Unreachable
396 aRet <<= getPropertyValues( Properties );
398 else if ( aCommand.Name == "setPropertyValues" )
401 // setPropertyValues
404 uno::Sequence< beans::PropertyValue > aProperties;
405 if ( !( aCommand.Argument >>= aProperties ) )
407 ucbhelper::cancelCommandExecution(
408 uno::makeAny( lang::IllegalArgumentException(
409 OUString( "Wrong argument type!" ),
410 static_cast< cppu::OWeakObject * >( this ),
411 -1 ) ),
412 Environment );
413 // Unreachable
416 if ( !aProperties.getLength() )
418 ucbhelper::cancelCommandExecution(
419 uno::makeAny( lang::IllegalArgumentException(
420 OUString( "No properties!" ),
421 static_cast< cppu::OWeakObject * >( this ),
422 -1 ) ),
423 Environment );
424 // Unreachable
427 aRet <<= setPropertyValues( aProperties, Environment );
429 else if ( aCommand.Name == "getPropertySetInfo" )
432 // getPropertySetInfo
435 aRet <<= getPropertySetInfo( Environment );
437 else if ( aCommand.Name == "getCommandInfo" )
440 // getCommandInfo
443 aRet <<= getCommandInfo( Environment );
445 else if ( aCommand.Name == "open" )
448 // open
451 ucb::OpenCommandArgument2 aOpenCommand;
452 if ( !( aCommand.Argument >>= aOpenCommand ) )
454 ucbhelper::cancelCommandExecution(
455 uno::makeAny( lang::IllegalArgumentException(
456 OUString( "Wrong argument type!" ),
457 static_cast< cppu::OWeakObject * >( this ),
458 -1 ) ),
459 Environment );
460 // Unreachable
463 aRet = open( aOpenCommand, Environment );
465 else if ( aCommand.Name == "insert" )
468 // insert ( Supported by folders and streams only )
471 ContentType eType = m_aProps.getType();
472 if ( ( eType != FOLDER ) && ( eType != STREAM ) )
474 ucbhelper::cancelCommandExecution(
475 uno::makeAny( ucb::UnsupportedCommandException(
476 OUString( "insert command only supported by "
477 "folders and streams!" ),
478 static_cast< cppu::OWeakObject * >( this ) ) ),
479 Environment );
480 // Unreachable
483 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
484 if ( eType == STREAM )
486 Uri aUri( m_xIdentifier->getContentIdentifier() );
487 Uri aParentUri( aUri.getParentUri() );
488 if ( aParentUri.isDocument() )
490 ucbhelper::cancelCommandExecution(
491 uno::makeAny( ucb::UnsupportedCommandException(
492 OUString( "insert command not supported by "
493 "streams that are direct children "
494 "of document root!" ),
495 static_cast< cppu::OWeakObject * >(
496 this ) ) ),
497 Environment );
498 // Unreachable
501 #endif
502 ucb::InsertCommandArgument aArg;
503 if ( !( aCommand.Argument >>= aArg ) )
505 ucbhelper::cancelCommandExecution(
506 uno::makeAny( lang::IllegalArgumentException(
507 OUString( "Wrong argument type!" ),
508 static_cast< cppu::OWeakObject * >( this ),
509 -1 ) ),
510 Environment );
511 // Unreachable
514 sal_Int32 nNameClash = aArg.ReplaceExisting
515 ? ucb::NameClash::OVERWRITE
516 : ucb::NameClash::ERROR;
517 insert( aArg.Data, nNameClash, Environment );
519 else if ( aCommand.Name == "delete" )
522 // delete ( Supported by folders and streams only )
526 osl::MutexGuard aGuard( m_aMutex );
528 ContentType eType = m_aProps.getType();
529 if ( ( eType != FOLDER ) && ( eType != STREAM ) )
531 ucbhelper::cancelCommandExecution(
532 uno::makeAny( ucb::UnsupportedCommandException(
533 OUString( "delete command only supported by "
534 "folders and streams!" ),
535 static_cast< cppu::OWeakObject * >(
536 this ) ) ),
537 Environment );
538 // Unreachable
542 bool bDeletePhysical = false;
543 aCommand.Argument >>= bDeletePhysical;
544 destroy( bDeletePhysical, Environment );
546 // Remove own and all children's persistent data.
547 if ( !removeData() )
549 uno::Any aProps
550 = uno::makeAny(
551 beans::PropertyValue(
552 OUString( "Uri"),
554 uno::makeAny(m_xIdentifier->
555 getContentIdentifier()),
556 beans::PropertyState_DIRECT_VALUE));
557 ucbhelper::cancelCommandExecution(
558 ucb::IOErrorCode_CANT_WRITE,
559 uno::Sequence< uno::Any >(&aProps, 1),
560 Environment,
561 OUString( "Cannot remove persistent data!" ),
562 this );
563 // Unreachable
566 // Remove own and all children's Additional Core Properties.
567 removeAdditionalPropertySet( true );
569 else if ( aCommand.Name == "transfer" )
572 // transfer ( Supported by document and folders only )
576 osl::MutexGuard aGuard( m_aMutex );
578 ContentType eType = m_aProps.getType();
579 if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) )
581 ucbhelper::cancelCommandExecution(
582 uno::makeAny( ucb::UnsupportedCommandException(
583 OUString( "transfer command only supported "
584 "by folders and documents!" ),
585 static_cast< cppu::OWeakObject * >(
586 this ) ) ),
587 Environment );
588 // Unreachable
592 ucb::TransferInfo aInfo;
593 if ( !( aCommand.Argument >>= aInfo ) )
595 OSL_FAIL( "Wrong argument type!" );
596 ucbhelper::cancelCommandExecution(
597 uno::makeAny( lang::IllegalArgumentException(
598 OUString( "Wrong argument type!" ),
599 static_cast< cppu::OWeakObject * >( this ),
600 -1 ) ),
601 Environment );
602 // Unreachable
605 transfer( aInfo, Environment );
607 else if ( aCommand.Name == "createNewContent" )
610 // createNewContent ( Supported by document and folders only )
614 osl::MutexGuard aGuard( m_aMutex );
616 ContentType eType = m_aProps.getType();
617 if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) )
619 ucbhelper::cancelCommandExecution(
620 uno::makeAny( ucb::UnsupportedCommandException(
621 OUString( "createNewContent command only "
622 "supported by folders and "
623 "documents!" ),
624 static_cast< cppu::OWeakObject * >(
625 this ) ) ),
626 Environment );
627 // Unreachable
631 ucb::ContentInfo aInfo;
632 if ( !( aCommand.Argument >>= aInfo ) )
634 OSL_FAIL( "Wrong argument type!" );
635 ucbhelper::cancelCommandExecution(
636 uno::makeAny( lang::IllegalArgumentException(
637 OUString( "Wrong argument type!" ),
638 static_cast< cppu::OWeakObject * >( this ),
639 -1 ) ),
640 Environment );
641 // Unreachable
644 aRet <<= createNewContent( aInfo );
646 else
649 // Unsupported command
652 ucbhelper::cancelCommandExecution(
653 uno::makeAny( ucb::UnsupportedCommandException(
654 OUString(),
655 static_cast< cppu::OWeakObject * >( this ) ) ),
656 Environment );
657 // Unreachable
660 return aRet;
664 // virtual
665 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
666 throw( uno::RuntimeException, std::exception )
672 // XContentCreator methods.
676 // virtual
677 uno::Sequence< ucb::ContentInfo > SAL_CALL
678 Content::queryCreatableContentsInfo()
679 throw( uno::RuntimeException, std::exception )
681 return m_aProps.getCreatableContentsInfo();
685 // virtual
686 uno::Reference< ucb::XContent > SAL_CALL
687 Content::createNewContent( const ucb::ContentInfo& Info )
688 throw( uno::RuntimeException, std::exception )
690 if ( m_aProps.isContentCreator() )
692 osl::Guard< osl::Mutex > aGuard( m_aMutex );
694 if ( Info.Type.isEmpty() )
695 return uno::Reference< ucb::XContent >();
697 bool bCreateFolder = Info.Type == TDOC_FOLDER_CONTENT_TYPE;
699 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
700 // streams cannot be created as direct children of document root
701 if ( !bCreateFolder && ( m_aProps.getType() == DOCUMENT ) )
703 OSL_FAIL( "Content::createNewContent - streams cannot be "
704 "created as direct children of document root!" );
705 return uno::Reference< ucb::XContent >();
707 #endif
708 if ( !bCreateFolder && Info.Type != TDOC_STREAM_CONTENT_TYPE )
710 OSL_FAIL( "Content::createNewContent - unsupported type!" );
711 return uno::Reference< ucb::XContent >();
714 OUString aURL = m_xIdentifier->getContentIdentifier();
716 OSL_ENSURE( !aURL.isEmpty(),
717 "Content::createNewContent - empty identifier!" );
719 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
720 aURL += "/";
722 if ( bCreateFolder )
723 aURL += "New_Folder";
724 else
725 aURL += "New_Stream";
727 uno::Reference< ucb::XContentIdentifier > xId
728 = new ::ucbhelper::ContentIdentifier( aURL );
730 return create( m_xContext, m_pProvider, xId, Info );
732 else
734 OSL_FAIL( "createNewContent called on non-contentcreator object!" );
735 return uno::Reference< ucb::XContent >();
740 // virtual
741 OUString Content::getParentURL()
743 osl::Guard< osl::Mutex > aGuard( m_aMutex );
744 Uri aUri( m_xIdentifier->getContentIdentifier() );
745 return aUri.getParentUri();
749 uno::Reference< ucb::XContentIdentifier >
750 Content::makeNewIdentifier( const OUString& rTitle )
752 osl::Guard< osl::Mutex > aGuard( m_aMutex );
754 // Assemble new content identifier...
755 Uri aUri( m_xIdentifier->getContentIdentifier() );
756 OUStringBuffer aNewURL = aUri.getParentUri();
757 aNewURL.append( ::ucb_impl::urihelper::encodeSegment( rTitle ) );
759 return
760 uno::Reference< ucb::XContentIdentifier >(
761 new ::ucbhelper::ContentIdentifier( aNewURL.makeStringAndClear() ) );
765 void Content::queryChildren( ContentRefList& rChildren )
767 osl::Guard< osl::Mutex > aGuard( m_aMutex );
769 // Only folders (root, documents, folders) have children.
770 if ( !m_aProps.getIsFolder() )
771 return;
773 // Obtain a list with a snapshot of all currently instantiated contents
774 // from provider and extract the contents which are direct children
775 // of this content.
777 ::ucbhelper::ContentRefList aAllContents;
778 m_xProvider->queryExistingContents( aAllContents );
780 OUString aURL = m_xIdentifier->getContentIdentifier();
781 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
783 if ( nURLPos != ( aURL.getLength() - 1 ) )
785 // No trailing slash found. Append.
786 aURL += "/";
789 sal_Int32 nLen = aURL.getLength();
791 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
792 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
794 while ( it != end )
796 ::ucbhelper::ContentImplHelperRef xChild = (*it);
797 OUString aChildURL
798 = xChild->getIdentifier()->getContentIdentifier();
800 // Is aURL a prefix of aChildURL?
801 if ( ( aChildURL.getLength() > nLen ) &&
802 ( aChildURL.startsWith( aURL ) ) )
804 sal_Int32 nPos = nLen;
805 nPos = aChildURL.indexOf( '/', nPos );
807 if ( ( nPos == -1 ) ||
808 ( nPos == ( aChildURL.getLength() - 1 ) ) )
810 // No further slashes / only a final slash. It's a child!
811 rChildren.push_back(
812 ContentRef(
813 static_cast< Content * >( xChild.get() ) ) );
816 ++it;
821 bool Content::exchangeIdentity(
822 const uno::Reference< ucb::XContentIdentifier >& xNewId )
824 if ( !xNewId.is() )
825 return false;
827 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
829 uno::Reference< ucb::XContent > xThis = this;
831 // Already persistent?
832 if ( m_eState != PERSISTENT )
834 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
835 return false;
838 // Only folders and streams can be renamed -> exchange identity.
839 ContentType eType = m_aProps.getType();
840 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
842 OSL_FAIL( "Content::exchangeIdentity - "
843 "Not supported by root or document!" );
844 return false;
847 // Exchange own identitity.
849 // Fail, if a content with given id already exists.
850 if ( !hasData( Uri( xNewId->getContentIdentifier() ) ) )
852 OUString aOldURL = m_xIdentifier->getContentIdentifier();
854 aGuard.clear();
855 if ( exchange( xNewId ) )
857 if ( eType == FOLDER )
859 // Process instantiated children...
861 ContentRefList aChildren;
862 queryChildren( aChildren );
864 ContentRefList::const_iterator it = aChildren.begin();
865 ContentRefList::const_iterator end = aChildren.end();
867 while ( it != end )
869 ContentRef xChild = (*it);
871 // Create new content identifier for the child...
872 uno::Reference< ucb::XContentIdentifier > xOldChildId
873 = xChild->getIdentifier();
874 OUString aOldChildURL
875 = xOldChildId->getContentIdentifier();
876 OUString aNewChildURL
877 = aOldChildURL.replaceAt(
879 aOldURL.getLength(),
880 xNewId->getContentIdentifier() );
881 uno::Reference< ucb::XContentIdentifier > xNewChildId
882 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
884 if ( !xChild->exchangeIdentity( xNewChildId ) )
885 return false;
887 ++it;
890 return true;
894 OSL_FAIL( "Content::exchangeIdentity - "
895 "Panic! Cannot exchange identity!" );
896 return false;
900 // static
901 uno::Reference< sdbc::XRow > Content::getPropertyValues(
902 const uno::Reference< uno::XComponentContext >& rxContext,
903 const uno::Sequence< beans::Property >& rProperties,
904 ContentProvider* pProvider,
905 const OUString& rContentId )
907 ContentProperties aData;
908 if ( loadData( pProvider, rContentId, aData ) )
910 return getPropertyValues(
911 rxContext, rProperties, aData, pProvider, rContentId );
913 else
915 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
916 = new ::ucbhelper::PropertyValueSet( rxContext );
918 sal_Int32 nCount = rProperties.getLength();
919 if ( nCount )
921 const beans::Property* pProps = rProperties.getConstArray();
922 for ( sal_Int32 n = 0; n < nCount; ++n )
923 xRow->appendVoid( pProps[ n ] );
926 return uno::Reference< sdbc::XRow >( xRow.get() );
931 // static
932 uno::Reference< sdbc::XRow > Content::getPropertyValues(
933 const uno::Reference< uno::XComponentContext >& rxContext,
934 const uno::Sequence< beans::Property >& rProperties,
935 const ContentProperties& rData,
936 ContentProvider* pProvider,
937 const OUString& rContentId )
939 // Note: Empty sequence means "get values of all supported properties".
941 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
942 = new ::ucbhelper::PropertyValueSet( rxContext );
944 sal_Int32 nCount = rProperties.getLength();
945 if ( nCount )
947 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
948 bool bTriedToGetAdditionalPropSet = false;
950 const beans::Property* pProps = rProperties.getConstArray();
951 for ( sal_Int32 n = 0; n < nCount; ++n )
953 const beans::Property& rProp = pProps[ n ];
955 // Process Core properties.
957 if ( rProp.Name == "ContentType" )
959 xRow->appendString ( rProp, rData.getContentType() );
961 else if ( rProp.Name == "Title" )
963 xRow->appendString ( rProp, rData.getTitle() );
965 else if ( rProp.Name == "IsDocument" )
967 xRow->appendBoolean( rProp, rData.getIsDocument() );
969 else if ( rProp.Name == "IsFolder" )
971 xRow->appendBoolean( rProp, rData.getIsFolder() );
973 else if ( rProp.Name == "CreatableContentsInfo" )
975 xRow->appendObject(
976 rProp, uno::makeAny( rData.getCreatableContentsInfo() ) );
978 else if ( rProp.Name == "Storage" )
980 // Storage is only supported by folders.
981 ContentType eType = rData.getType();
982 if ( eType == FOLDER )
983 xRow->appendObject(
984 rProp,
985 uno::makeAny(
986 pProvider->queryStorageClone( rContentId ) ) );
987 else
988 xRow->appendVoid( rProp );
990 else if ( rProp.Name == "DocumentModel" )
992 // DocumentModel is only supported by documents.
993 ContentType eType = rData.getType();
994 if ( eType == DOCUMENT )
995 xRow->appendObject(
996 rProp,
997 uno::makeAny(
998 pProvider->queryDocumentModel( rContentId ) ) );
999 else
1000 xRow->appendVoid( rProp );
1002 else
1004 // Not a Core Property! Maybe it's an Additional Core Property?!
1006 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1008 xAdditionalPropSet
1009 = uno::Reference< beans::XPropertySet >(
1010 pProvider->getAdditionalPropertySet( rContentId,
1011 false ),
1012 uno::UNO_QUERY );
1013 bTriedToGetAdditionalPropSet = true;
1016 if ( xAdditionalPropSet.is() )
1018 if ( !xRow->appendPropertySetValue(
1019 xAdditionalPropSet,
1020 rProp ) )
1022 // Append empty entry.
1023 xRow->appendVoid( rProp );
1026 else
1028 // Append empty entry.
1029 xRow->appendVoid( rProp );
1034 else
1036 // Append all Core Properties.
1037 xRow->appendString (
1038 beans::Property( OUString("ContentType"),
1040 cppu::UnoType<OUString>::get(),
1041 beans::PropertyAttribute::BOUND
1042 | beans::PropertyAttribute::READONLY ),
1043 rData.getContentType() );
1045 ContentType eType = rData.getType();
1047 xRow->appendString (
1048 beans::Property( OUString("Title"),
1050 cppu::UnoType<OUString>::get(),
1051 // Title is read-only for root and documents.
1052 beans::PropertyAttribute::BOUND |
1053 ( ( eType == ROOT ) || ( eType == DOCUMENT )
1054 ? beans::PropertyAttribute::READONLY
1055 : 0 ) ),
1056 rData.getTitle() );
1057 xRow->appendBoolean(
1058 beans::Property( OUString("IsDocument"),
1060 cppu::UnoType<bool>::get(),
1061 beans::PropertyAttribute::BOUND
1062 | beans::PropertyAttribute::READONLY ),
1063 rData.getIsDocument() );
1064 xRow->appendBoolean(
1065 beans::Property( OUString("IsFolder"),
1067 cppu::UnoType<bool>::get(),
1068 beans::PropertyAttribute::BOUND
1069 | beans::PropertyAttribute::READONLY ),
1070 rData.getIsFolder() );
1071 xRow->appendObject(
1072 beans::Property(
1073 OUString("CreatableContentsInfo"),
1075 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
1076 beans::PropertyAttribute::BOUND
1077 | beans::PropertyAttribute::READONLY ),
1078 uno::makeAny( rData.getCreatableContentsInfo() ) );
1080 // Storage is only supported by folders.
1081 if ( eType == FOLDER )
1082 xRow->appendObject(
1083 beans::Property( OUString("Storage"),
1085 cppu::UnoType<embed::XStorage>::get(),
1086 beans::PropertyAttribute::BOUND
1087 | beans::PropertyAttribute::READONLY ),
1088 uno::makeAny( pProvider->queryStorageClone( rContentId ) ) );
1090 // DocumentModel is only supported by documents.
1091 if ( eType == DOCUMENT )
1092 xRow->appendObject(
1093 beans::Property( OUString("DocumentModel"),
1095 cppu::UnoType<frame::XModel>::get(),
1096 beans::PropertyAttribute::BOUND
1097 | beans::PropertyAttribute::READONLY ),
1098 uno::makeAny(
1099 pProvider->queryDocumentModel( rContentId ) ) );
1101 // Append all Additional Core Properties.
1103 uno::Reference< beans::XPropertySet > xSet(
1104 pProvider->getAdditionalPropertySet( rContentId, false ),
1105 uno::UNO_QUERY );
1106 xRow->appendPropertySet( xSet );
1109 return uno::Reference< sdbc::XRow >( xRow.get() );
1113 uno::Reference< sdbc::XRow > Content::getPropertyValues(
1114 const uno::Sequence< beans::Property >& rProperties )
1116 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1117 return getPropertyValues( m_xContext,
1118 rProperties,
1119 m_aProps,
1120 m_pProvider,
1121 m_xIdentifier->getContentIdentifier() );
1125 uno::Sequence< uno::Any > Content::setPropertyValues(
1126 const uno::Sequence< beans::PropertyValue >& rValues,
1127 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1128 throw( uno::Exception )
1130 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1132 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1133 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1134 sal_Int32 nChanged = 0;
1136 beans::PropertyChangeEvent aEvent;
1137 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1138 aEvent.Further = sal_False;
1139 // aEvent.PropertyName =
1140 aEvent.PropertyHandle = -1;
1141 // aEvent.OldValue =
1142 // aEvent.NewValue =
1144 const beans::PropertyValue* pValues = rValues.getConstArray();
1145 sal_Int32 nCount = rValues.getLength();
1147 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1148 bool bTriedToGetAdditionalPropSet = false;
1150 bool bExchange = false;
1151 OUString aOldTitle;
1152 sal_Int32 nTitlePos = -1;
1154 for ( sal_Int32 n = 0; n < nCount; ++n )
1156 const beans::PropertyValue& rValue = pValues[ n ];
1158 if ( rValue.Name == "ContentType" )
1160 // Read-only property!
1161 aRet[ n ] <<= lang::IllegalAccessException(
1162 OUString( "Property is read-only!" ),
1163 static_cast< cppu::OWeakObject * >( this ) );
1165 else if ( rValue.Name == "IsDocument" )
1167 // Read-only property!
1168 aRet[ n ] <<= lang::IllegalAccessException(
1169 OUString( "Property is read-only!" ),
1170 static_cast< cppu::OWeakObject * >( this ) );
1172 else if ( rValue.Name == "IsFolder" )
1174 // Read-only property!
1175 aRet[ n ] <<= lang::IllegalAccessException(
1176 OUString( "Property is read-only!" ),
1177 static_cast< cppu::OWeakObject * >( this ) );
1179 else if ( rValue.Name == "CreatableContentsInfo" )
1181 // Read-only property!
1182 aRet[ n ] <<= lang::IllegalAccessException(
1183 OUString( "Property is read-only!" ),
1184 static_cast< cppu::OWeakObject * >( this ) );
1186 else if ( rValue.Name == "Title" )
1188 // Title is read-only for root and documents.
1189 ContentType eType = m_aProps.getType();
1190 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
1192 aRet[ n ] <<= lang::IllegalAccessException(
1193 OUString( "Property is read-only!" ),
1194 static_cast< cppu::OWeakObject * >( this ) );
1196 else
1198 OUString aNewValue;
1199 if ( rValue.Value >>= aNewValue )
1201 // No empty titles!
1202 if ( !aNewValue.isEmpty() )
1204 if ( aNewValue != m_aProps.getTitle() )
1206 // modified title -> modified URL -> exchange !
1207 if ( m_eState == PERSISTENT )
1208 bExchange = true;
1210 aOldTitle = m_aProps.getTitle();
1211 m_aProps.setTitle( aNewValue );
1213 // property change event will be sent later...
1215 // remember position within sequence of values
1216 // (for error handling).
1217 nTitlePos = n;
1220 else
1222 aRet[ n ] <<= lang::IllegalArgumentException(
1223 OUString( "Empty Title not allowed!" ),
1224 static_cast< cppu::OWeakObject * >( this ),
1225 -1 );
1228 else
1230 aRet[ n ] <<= beans::IllegalTypeException(
1231 OUString( "Title Property value has wrong type!" ),
1232 static_cast< cppu::OWeakObject * >( this ) );
1236 else if ( rValue.Name == "Storage" )
1238 ContentType eType = m_aProps.getType();
1239 if ( eType == FOLDER )
1241 aRet[ n ] <<= lang::IllegalAccessException(
1242 OUString( "Property is read-only!" ),
1243 static_cast< cppu::OWeakObject * >( this ) );
1245 else
1247 // Storage is only supported by folders.
1248 aRet[ n ] <<= beans::UnknownPropertyException(
1249 OUString( "Storage property only supported by folders" ),
1250 static_cast< cppu::OWeakObject * >( this ) );
1253 else if ( rValue.Name == "DocumentModel" )
1255 ContentType eType = m_aProps.getType();
1256 if ( eType == DOCUMENT )
1258 aRet[ n ] <<= lang::IllegalAccessException(
1259 OUString( "Property is read-only!" ),
1260 static_cast< cppu::OWeakObject * >( this ) );
1262 else
1264 // Storage is only supported by folders.
1265 aRet[ n ] <<= beans::UnknownPropertyException(
1266 OUString( "DocumentModel property only supported by "
1267 "documents" ),
1268 static_cast< cppu::OWeakObject * >( this ) );
1271 else
1273 // Not a Core Property! Maybe it's an Additional Core Property?!
1275 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1277 xAdditionalPropSet = getAdditionalPropertySet( false );
1278 bTriedToGetAdditionalPropSet = true;
1281 if ( xAdditionalPropSet.is() )
1285 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1286 rValue.Name );
1287 if ( aOldValue != rValue.Value )
1289 xAdditionalPropSet->setPropertyValue(
1290 rValue.Name, rValue.Value );
1292 aEvent.PropertyName = rValue.Name;
1293 aEvent.OldValue = aOldValue;
1294 aEvent.NewValue = rValue.Value;
1296 aChanges.getArray()[ nChanged ] = aEvent;
1297 nChanged++;
1300 catch ( beans::UnknownPropertyException const & e )
1302 aRet[ n ] <<= e;
1304 catch ( lang::WrappedTargetException const & e )
1306 aRet[ n ] <<= e;
1308 catch ( beans::PropertyVetoException const & e )
1310 aRet[ n ] <<= e;
1312 catch ( lang::IllegalArgumentException const & e )
1314 aRet[ n ] <<= e;
1317 else
1319 aRet[ n ] <<= uno::Exception(
1320 OUString( "No property set for storing the value!" ),
1321 static_cast< cppu::OWeakObject * >( this ) );
1326 if ( bExchange )
1328 uno::Reference< ucb::XContentIdentifier > xOldId
1329 = m_xIdentifier;
1330 uno::Reference< ucb::XContentIdentifier > xNewId
1331 = makeNewIdentifier( m_aProps.getTitle() );
1333 aGuard.clear();
1334 if ( exchangeIdentity( xNewId ) )
1336 // Adapt persistent data.
1337 renameData( xOldId, xNewId );
1339 // Adapt Additional Core Properties.
1340 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1341 xNewId->getContentIdentifier(),
1342 true );
1344 else
1346 // Roll-back.
1347 m_aProps.setTitle( aOldTitle );
1348 aOldTitle.clear();
1350 // Set error .
1351 aRet[ nTitlePos ] <<= uno::Exception(
1352 OUString("Exchange failed!"),
1353 static_cast< cppu::OWeakObject * >( this ) );
1357 if ( !aOldTitle.isEmpty() )
1359 aEvent.PropertyName = "Title";
1360 aEvent.OldValue = uno::makeAny( aOldTitle );
1361 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() );
1363 aChanges.getArray()[ nChanged ] = aEvent;
1364 nChanged++;
1367 if ( nChanged > 0 )
1369 // Save changes, if content was already made persistent.
1370 if ( !bExchange && ( m_eState == PERSISTENT ) )
1372 if ( !storeData( uno::Reference< io::XInputStream >(), xEnv ) )
1374 uno::Any aProps
1375 = uno::makeAny(
1376 beans::PropertyValue(
1377 OUString( "Uri"),
1379 uno::makeAny(m_xIdentifier->
1380 getContentIdentifier()),
1381 beans::PropertyState_DIRECT_VALUE));
1382 ucbhelper::cancelCommandExecution(
1383 ucb::IOErrorCode_CANT_WRITE,
1384 uno::Sequence< uno::Any >(&aProps, 1),
1385 xEnv,
1386 OUString( "Cannot store persistent data!" ),
1387 this );
1388 // Unreachable
1392 aChanges.realloc( nChanged );
1394 aGuard.clear();
1395 notifyPropertiesChange( aChanges );
1398 return aRet;
1402 uno::Any Content::open(
1403 const ucb::OpenCommandArgument2& rArg,
1404 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1405 throw( uno::Exception )
1407 if ( rArg.Mode == ucb::OpenMode::ALL ||
1408 rArg.Mode == ucb::OpenMode::FOLDERS ||
1409 rArg.Mode == ucb::OpenMode::DOCUMENTS )
1412 // open command for a folder content
1415 uno::Reference< ucb::XDynamicResultSet > xSet
1416 = new DynamicResultSet( m_xContext, this, rArg );
1417 return uno::makeAny( xSet );
1419 else
1422 // open command for a document content
1425 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1426 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1428 // Currently(?) unsupported.
1429 ucbhelper::cancelCommandExecution(
1430 uno::makeAny( ucb::UnsupportedOpenModeException(
1431 OUString(),
1432 static_cast< cppu::OWeakObject * >( this ),
1433 sal_Int16( rArg.Mode ) ) ),
1434 xEnv );
1435 // Unreachable
1438 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1440 uno::Reference< io::XActiveDataStreamer > xDataStreamer(
1441 rArg.Sink, uno::UNO_QUERY );
1442 if ( xDataStreamer.is() )
1444 // May throw CommandFailedException, DocumentPasswordRequest!
1445 uno::Reference< io::XStream > xStream = getStream( xEnv );
1446 if ( !xStream.is() )
1448 // No interaction if we are not persistent!
1449 uno::Any aProps
1450 = uno::makeAny(
1451 beans::PropertyValue(
1452 OUString( "Uri"),
1454 uno::makeAny(m_xIdentifier->
1455 getContentIdentifier()),
1456 beans::PropertyState_DIRECT_VALUE));
1457 ucbhelper::cancelCommandExecution(
1458 ucb::IOErrorCode_CANT_READ,
1459 uno::Sequence< uno::Any >(&aProps, 1),
1460 m_eState == PERSISTENT
1461 ? xEnv
1462 : uno::Reference< ucb::XCommandEnvironment >(),
1463 OUString( "Got no data stream!" ),
1464 this );
1465 // Unreachable
1468 // Done.
1469 xDataStreamer->setStream( xStream );
1471 else
1473 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1474 if ( xOut.is() )
1476 // PUSH: write data into xOut
1478 // May throw CommandFailedException, DocumentPasswordRequest!
1479 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1480 if ( !xIn.is() )
1482 // No interaction if we are not persistent!
1483 uno::Any aProps
1484 = uno::makeAny(
1485 beans::PropertyValue(
1486 OUString( "Uri"),
1488 uno::makeAny(m_xIdentifier->
1489 getContentIdentifier()),
1490 beans::PropertyState_DIRECT_VALUE));
1491 ucbhelper::cancelCommandExecution(
1492 ucb::IOErrorCode_CANT_READ,
1493 uno::Sequence< uno::Any >(&aProps, 1),
1494 m_eState == PERSISTENT
1495 ? xEnv
1496 : uno::Reference< ucb::XCommandEnvironment >(),
1497 OUString("Got no data stream!"),
1498 this );
1499 // Unreachable
1504 uno::Sequence< sal_Int8 > aBuffer;
1505 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1507 while ( nRead > 0 )
1509 aBuffer.realloc( nRead );
1510 xOut->writeBytes( aBuffer );
1511 aBuffer.realloc( 0 );
1512 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1515 xOut->closeOutput();
1517 catch ( io::NotConnectedException const & )
1519 // closeOutput, readSomeBytes, writeBytes
1521 catch ( io::BufferSizeExceededException const & )
1523 // closeOutput, readSomeBytes, writeBytes
1525 catch ( io::IOException const & )
1527 // closeOutput, readSomeBytes, writeBytes
1530 else
1532 uno::Reference< io::XActiveDataSink > xDataSink(
1533 rArg.Sink, uno::UNO_QUERY );
1534 if ( xDataSink.is() )
1536 // PULL: wait for client read
1538 // May throw CommandFailedException, DocumentPasswordRequest!
1539 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1540 if ( !xIn.is() )
1542 // No interaction if we are not persistent!
1543 uno::Any aProps
1544 = uno::makeAny(
1545 beans::PropertyValue(
1546 OUString( "Uri"),
1548 uno::makeAny(m_xIdentifier->
1549 getContentIdentifier()),
1550 beans::PropertyState_DIRECT_VALUE));
1551 ucbhelper::cancelCommandExecution(
1552 ucb::IOErrorCode_CANT_READ,
1553 uno::Sequence< uno::Any >(&aProps, 1),
1554 m_eState == PERSISTENT
1555 ? xEnv
1556 : uno::Reference<
1557 ucb::XCommandEnvironment >(),
1558 OUString( "Got no data stream!" ),
1559 this );
1560 // Unreachable
1563 // Done.
1564 xDataSink->setInputStream( xIn );
1566 else
1568 ucbhelper::cancelCommandExecution(
1569 uno::makeAny(
1570 ucb::UnsupportedDataSinkException(
1571 OUString(),
1572 static_cast< cppu::OWeakObject * >( this ),
1573 rArg.Sink ) ),
1574 xEnv );
1575 // Unreachable
1581 return uno::Any();
1585 void Content::insert( const uno::Reference< io::XInputStream >& xData,
1586 sal_Int32 nNameClashResolve,
1587 const uno::Reference<
1588 ucb::XCommandEnvironment > & xEnv )
1589 throw( uno::Exception )
1591 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1593 ContentType eType = m_aProps.getType();
1595 OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ),
1596 "insert command only supported by streams and folders!" );
1598 Uri aUri( m_xIdentifier->getContentIdentifier() );
1600 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
1601 #if OSL_DEBUG_LEVEL > 0
1602 if ( eType == STREAM )
1604 Uri aParentUri( aUri.getParentUri() );
1605 OSL_ENSURE( !aParentUri.isDocument(),
1606 "insert command not supported by streams that are direct "
1607 "children of document root!" );
1609 #endif
1610 #endif
1612 // Check, if all required properties were set.
1613 if ( eType == FOLDER )
1615 // Required: Title
1617 if ( m_aProps.getTitle().isEmpty() )
1618 m_aProps.setTitle( aUri.getDecodedName() );
1620 else // stream
1622 // Required: data
1624 if ( !xData.is() )
1626 ucbhelper::cancelCommandExecution(
1627 uno::makeAny( ucb::MissingInputStreamException(
1628 OUString(),
1629 static_cast< cppu::OWeakObject * >( this ) ) ),
1630 xEnv );
1631 // Unreachable
1634 // Required: Title
1636 if ( m_aProps.getTitle().isEmpty() )
1637 m_aProps.setTitle( aUri.getDecodedName() );
1640 OUStringBuffer aNewURL = aUri.getParentUri();
1641 aNewURL.append( m_aProps.getTitle() );
1642 Uri aNewUri( aNewURL.makeStringAndClear() );
1644 // Handle possible name clash...
1645 switch ( nNameClashResolve )
1647 // fail.
1648 case ucb::NameClash::ERROR:
1649 if ( hasData( aNewUri ) )
1651 ucbhelper::cancelCommandExecution(
1652 uno::makeAny( ucb::NameClashException(
1653 OUString(),
1654 static_cast< cppu::OWeakObject * >( this ),
1655 task::InteractionClassification_ERROR,
1656 m_aProps.getTitle() ) ),
1657 xEnv );
1658 // Unreachable
1660 break;
1662 // replace (possibly) existing object.
1663 case ucb::NameClash::OVERWRITE:
1664 break;
1666 // "invent" a new valid title.
1667 case ucb::NameClash::RENAME:
1668 if ( hasData( aNewUri ) )
1670 sal_Int32 nTry = 0;
1674 OUStringBuffer aNew = aNewUri.getUri();
1675 aNew.appendAscii( "_" );
1676 aNew.append( OUString::number( ++nTry ) );
1677 aNewUri.setUri( aNew.makeStringAndClear() );
1679 while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1681 if ( nTry == 1000 )
1683 ucbhelper::cancelCommandExecution(
1684 uno::makeAny(
1685 ucb::UnsupportedNameClashException(
1686 OUString( "Unable to resolve name clash!" ),
1687 static_cast< cppu::OWeakObject * >( this ),
1688 nNameClashResolve ) ),
1689 xEnv );
1690 // Unreachable
1692 else
1694 OUStringBuffer aNewTitle = m_aProps.getTitle();
1695 aNewTitle.appendAscii( "_" );
1696 aNewTitle.append( OUString::number( ++nTry ) );
1697 m_aProps.setTitle( aNewTitle.makeStringAndClear() );
1700 break;
1702 case ucb::NameClash::KEEP: // deprecated
1703 case ucb::NameClash::ASK:
1704 default:
1705 if ( hasData( aNewUri ) )
1707 ucbhelper::cancelCommandExecution(
1708 uno::makeAny(
1709 ucb::UnsupportedNameClashException(
1710 OUString(),
1711 static_cast< cppu::OWeakObject * >( this ),
1712 nNameClashResolve ) ),
1713 xEnv );
1714 // Unreachable
1716 break;
1719 // Identifier changed?
1720 bool bNewId = ( aUri != aNewUri );
1722 if ( bNewId )
1724 m_xIdentifier
1725 = new ::ucbhelper::ContentIdentifier( aNewUri.getUri() );
1728 if ( !storeData( xData, xEnv ) )
1730 uno::Any aProps
1731 = uno::makeAny(beans::PropertyValue(
1732 OUString( "Uri"),
1734 uno::makeAny(m_xIdentifier->
1735 getContentIdentifier()),
1736 beans::PropertyState_DIRECT_VALUE));
1737 ucbhelper::cancelCommandExecution(
1738 ucb::IOErrorCode_CANT_WRITE,
1739 uno::Sequence< uno::Any >(&aProps, 1),
1740 xEnv,
1741 OUString("Cannot store persistent data!"),
1742 this );
1743 // Unreachable
1746 m_eState = PERSISTENT;
1748 if ( bNewId )
1750 //loadData( m_pProvider, m_aUri, m_aProps );
1752 aGuard.clear();
1753 inserted();
1758 void Content::destroy( bool bDeletePhysical,
1759 const uno::Reference<
1760 ucb::XCommandEnvironment > & xEnv )
1761 throw( uno::Exception )
1763 // @@@ take care about bDeletePhysical -> trashcan support
1765 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1767 ContentType eType = m_aProps.getType();
1769 OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ),
1770 "delete command only supported by streams and folders!" );
1772 uno::Reference< ucb::XContent > xThis = this;
1774 // Persistent?
1775 if ( m_eState != PERSISTENT )
1777 ucbhelper::cancelCommandExecution(
1778 uno::makeAny( ucb::UnsupportedCommandException(
1779 OUString( "Not persistent!" ),
1780 static_cast< cppu::OWeakObject * >( this ) ) ),
1781 xEnv );
1782 // Unreachable
1785 m_eState = DEAD;
1787 aGuard.clear();
1788 deleted();
1790 if ( eType == FOLDER )
1792 // Process instantiated children...
1794 ContentRefList aChildren;
1795 queryChildren( aChildren );
1797 ContentRefList::const_iterator it = aChildren.begin();
1798 ContentRefList::const_iterator end = aChildren.end();
1800 while ( it != end )
1802 (*it)->destroy( bDeletePhysical, xEnv );
1803 ++it;
1809 void Content::notifyDocumentClosed()
1811 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1813 m_eState = DEAD;
1815 // @@@ anything else to reset or such?
1817 // callback follows!
1818 aGuard.clear();
1820 // Propagate destruction to content event listeners
1821 // Remove this from provider's content list.
1822 deleted();
1826 uno::Reference< ucb::XContent >
1827 Content::queryChildContent( const OUString & rRelativeChildUri )
1829 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1831 const OUString aMyId = getIdentifier()->getContentIdentifier();
1832 OUStringBuffer aBuf( aMyId );
1833 if ( !aMyId.endsWith("/") )
1834 aBuf.appendAscii( "/" );
1835 if ( !rRelativeChildUri.startsWith("/") )
1836 aBuf.append( rRelativeChildUri );
1837 else
1838 aBuf.append( rRelativeChildUri.copy( 1 ) );
1840 uno::Reference< ucb::XContentIdentifier > xChildId
1841 = new ::ucbhelper::ContentIdentifier( aBuf.makeStringAndClear() );
1843 uno::Reference< ucb::XContent > xChild;
1846 xChild = m_pProvider->queryContent( xChildId );
1848 catch ( ucb::IllegalIdentifierException const & )
1850 // handled below.
1853 OSL_ENSURE( xChild.is(),
1854 "Content::queryChildContent - unable to create child content!" );
1855 return xChild;
1859 void Content::notifyChildRemoved( const OUString & rRelativeChildUri )
1861 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1863 // Ugly! Need to create child content object, just to fill event properly.
1864 uno::Reference< ucb::XContent > xChild
1865 = queryChildContent( rRelativeChildUri );
1867 if ( xChild.is() )
1869 // callback follows!
1870 aGuard.clear();
1872 // Notify "REMOVED" event.
1873 ucb::ContentEvent aEvt(
1874 static_cast< cppu::OWeakObject * >( this ),
1875 ucb::ContentAction::REMOVED,
1876 xChild,
1877 getIdentifier() );
1878 notifyContentEvent( aEvt );
1883 void Content::notifyChildInserted( const OUString & rRelativeChildUri )
1885 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1887 // Ugly! Need to create child content object, just to fill event properly.
1888 uno::Reference< ucb::XContent > xChild
1889 = queryChildContent( rRelativeChildUri );
1891 if ( xChild.is() )
1893 // callback follows!
1894 aGuard.clear();
1896 // Notify "INSERTED" event.
1897 ucb::ContentEvent aEvt(
1898 static_cast< cppu::OWeakObject * >( this ),
1899 ucb::ContentAction::INSERTED,
1900 xChild,
1901 getIdentifier() );
1902 notifyContentEvent( aEvt );
1907 void Content::transfer(
1908 const ucb::TransferInfo& rInfo,
1909 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1910 throw( uno::Exception )
1912 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1914 // Persistent?
1915 if ( m_eState != PERSISTENT )
1917 ucbhelper::cancelCommandExecution(
1918 uno::makeAny( ucb::UnsupportedCommandException(
1919 OUString( "Not persistent!" ),
1920 static_cast< cppu::OWeakObject * >( this ) ) ),
1921 xEnv );
1922 // Unreachable
1925 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
1927 if ( ( rInfo.SourceURL.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) )
1929 // Invalid length (to short).
1930 ucbhelper::cancelCommandExecution(
1931 uno::makeAny( ucb::InteractiveBadTransferURLException(
1932 OUString(),
1933 static_cast< cppu::OWeakObject * >( this ) ) ),
1934 xEnv );
1935 // Unreachable
1938 OUString aScheme
1939 = rInfo.SourceURL.copy( 0, TDOC_URL_SCHEME_LENGTH + 2 )
1940 .toAsciiLowerCase();
1941 if ( aScheme != TDOC_URL_SCHEME ":/" )
1943 // Invalid scheme.
1944 ucbhelper::cancelCommandExecution(
1945 uno::makeAny( ucb::InteractiveBadTransferURLException(
1946 OUString(),
1947 static_cast< cppu::OWeakObject * >( this ) ) ),
1948 xEnv );
1949 // Unreachable
1952 // Does source URI describe a tdoc folder or stream?
1953 Uri aSourceUri( rInfo.SourceURL );
1954 if ( !aSourceUri.isValid() )
1956 ucbhelper::cancelCommandExecution(
1957 uno::makeAny( lang::IllegalArgumentException(
1958 OUString( "Invalid source URI! Syntax!" ),
1959 static_cast< cppu::OWeakObject * >( this ),
1960 -1 ) ),
1961 xEnv );
1962 // Unreachable
1965 if ( aSourceUri.isRoot() || aSourceUri.isDocument() )
1967 ucbhelper::cancelCommandExecution(
1968 uno::makeAny( lang::IllegalArgumentException(
1969 OUString( "Invalid source URI! "
1970 "Must describe a folder or stream!" ),
1971 static_cast< cppu::OWeakObject * >( this ),
1972 -1 ) ),
1973 xEnv );
1974 // Unreachable
1977 // Is source not a parent of me / not me?
1978 OUString aId = m_xIdentifier->getContentIdentifier();
1979 sal_Int32 nPos = aId.lastIndexOf( '/' );
1980 if ( nPos != ( aId.getLength() - 1 ) )
1982 // No trailing slash found. Append.
1983 aId += "/";
1986 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1988 if ( aId.startsWith( rInfo.SourceURL ) )
1990 uno::Any aProps
1991 = uno::makeAny(beans::PropertyValue(
1992 OUString( "Uri"),
1994 uno::makeAny( rInfo.SourceURL ),
1995 beans::PropertyState_DIRECT_VALUE));
1996 ucbhelper::cancelCommandExecution(
1997 ucb::IOErrorCode_RECURSIVE,
1998 uno::Sequence< uno::Any >(&aProps, 1),
1999 xEnv,
2000 OUString( "Target is equal to or is a child of source!" ),
2001 this );
2002 // Unreachable
2006 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2007 if ( m_aProps.getType() == DOCUMENT )
2009 bool bOK = false;
2011 uno::Reference< embed::XStorage > xStorage
2012 = m_pProvider->queryStorage(
2013 aSourceUri.getParentUri(), READ_WRITE_NOCREATE );
2014 if ( xStorage.is() )
2018 if ( xStorage->isStreamElement( aSourceUri.getDecodedName() ) )
2020 ucbhelper::cancelCommandExecution(
2021 uno::makeAny( lang::IllegalArgumentException(
2022 OUString( "Invalid source URI! "
2023 "Streams cannot be created as "
2024 "children of document root!" ),
2025 static_cast< cppu::OWeakObject * >(
2026 this ),
2027 -1 ) ),
2028 xEnv );
2029 // Unreachable
2031 bOK = true;
2033 catch ( container::NoSuchElementException const & )
2035 // handled below.
2037 catch ( lang::IllegalArgumentException const & )
2039 // handled below.
2041 catch ( embed::InvalidStorageException const & )
2043 // handled below.
2047 if ( !bOK )
2049 ucbhelper::cancelCommandExecution(
2050 uno::makeAny( lang::IllegalArgumentException(
2051 OUString( "Invalid source URI! "
2052 "Unabale to determine source type!" ),
2053 static_cast< cppu::OWeakObject * >( this ),
2054 -1 ) ),
2055 xEnv );
2056 // Unreachable
2059 #endif
2062 // Copy data.
2065 OUString aNewName( !rInfo.NewTitle.isEmpty()
2066 ? rInfo.NewTitle
2067 : aSourceUri.getDecodedName() );
2069 if ( !copyData( aSourceUri, aNewName ) )
2071 uno::Any aProps
2072 = uno::makeAny(
2073 beans::PropertyValue(
2074 OUString( "Uri"),
2076 uno::makeAny( rInfo.SourceURL ),
2077 beans::PropertyState_DIRECT_VALUE));
2078 ucbhelper::cancelCommandExecution(
2079 ucb::IOErrorCode_CANT_WRITE,
2080 uno::Sequence< uno::Any >(&aProps, 1),
2081 xEnv,
2082 OUString( "Cannot copy data!" ),
2083 this );
2084 // Unreachable
2088 // Copy own and all children's Additional Core Properties.
2091 OUString aTargetUri = m_xIdentifier->getContentIdentifier();
2092 if ( ( aTargetUri.lastIndexOf( '/' ) + 1 ) != aTargetUri.getLength() )
2093 aTargetUri += "/";
2095 if ( !rInfo.NewTitle.isEmpty() )
2096 aTargetUri += ::ucb_impl::urihelper::encodeSegment( rInfo.NewTitle );
2097 else
2098 aTargetUri += aSourceUri.getName();
2100 if ( !copyAdditionalPropertySet(
2101 aSourceUri.getUri(), aTargetUri, true ) )
2103 uno::Any aProps
2104 = uno::makeAny(
2105 beans::PropertyValue(
2106 OUString( "Uri"),
2108 uno::makeAny( rInfo.SourceURL ),
2109 beans::PropertyState_DIRECT_VALUE));
2110 ucbhelper::cancelCommandExecution(
2111 ucb::IOErrorCode_CANT_WRITE,
2112 uno::Sequence< uno::Any >(&aProps, 1),
2113 xEnv,
2114 OUString( "Cannot copy additional properties!" ),
2115 this );
2116 // Unreachable
2120 // Propagate new content.
2123 rtl::Reference< Content > xTarget;
2126 uno::Reference< ucb::XContentIdentifier > xTargetId
2127 = new ::ucbhelper::ContentIdentifier( aTargetUri );
2129 // Note: The static cast is okay here, because its sure that
2130 // m_xProvider is always the WebDAVContentProvider.
2131 xTarget = static_cast< Content * >(
2132 m_pProvider->queryContent( xTargetId ).get() );
2135 catch ( ucb::IllegalIdentifierException const & )
2137 // queryContent
2140 if ( !xTarget.is() )
2142 uno::Any aProps
2143 = uno::makeAny(beans::PropertyValue(
2144 OUString( "Uri"),
2146 uno::makeAny( aTargetUri ),
2147 beans::PropertyState_DIRECT_VALUE));
2148 ucbhelper::cancelCommandExecution(
2149 ucb::IOErrorCode_CANT_READ,
2150 uno::Sequence< uno::Any >(&aProps, 1),
2151 xEnv,
2152 OUString( "Cannot instanciate target object!" ),
2153 this );
2154 // Unreachable
2157 // Announce transferred content in its new folder.
2158 xTarget->inserted();
2161 // Remove source, if requested
2164 if ( rInfo.MoveData )
2166 rtl::Reference< Content > xSource;
2169 uno::Reference< ucb::XContentIdentifier >
2170 xSourceId = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
2172 // Note: The static cast is okay here, because its sure
2173 // that m_xProvider is always the ContentProvider.
2174 xSource = static_cast< Content * >(
2175 m_xProvider->queryContent( xSourceId ).get() );
2177 catch ( ucb::IllegalIdentifierException const & )
2179 // queryContent
2182 if ( !xSource.is() )
2184 uno::Any aProps
2185 = uno::makeAny(beans::PropertyValue(
2186 OUString( "Uri"),
2188 uno::makeAny( rInfo.SourceURL ),
2189 beans::PropertyState_DIRECT_VALUE));
2190 ucbhelper::cancelCommandExecution(
2191 ucb::IOErrorCode_CANT_READ,
2192 uno::Sequence< uno::Any >(&aProps, 1),
2193 xEnv,
2194 OUString( "Cannot instanciate target object!" ),
2195 this );
2196 // Unreachable
2199 // Propagate destruction (recursively).
2200 xSource->destroy( true, xEnv );
2202 // Remove all persistent data of source and its children.
2203 if ( !xSource->removeData() )
2205 uno::Any aProps
2206 = uno::makeAny(
2207 beans::PropertyValue(
2208 OUString( "Uri"),
2210 uno::makeAny( rInfo.SourceURL ),
2211 beans::PropertyState_DIRECT_VALUE));
2212 ucbhelper::cancelCommandExecution(
2213 ucb::IOErrorCode_CANT_WRITE,
2214 uno::Sequence< uno::Any >(&aProps, 1),
2215 xEnv,
2216 OUString( "Cannot remove persistent data of source object!" ),
2217 this );
2218 // Unreachable
2221 // Remove own and all children's Additional Core Properties.
2222 if ( !xSource->removeAdditionalPropertySet( true ) )
2224 uno::Any aProps
2225 = uno::makeAny(
2226 beans::PropertyValue(
2227 OUString( "Uri"),
2229 uno::makeAny( rInfo.SourceURL ),
2230 beans::PropertyState_DIRECT_VALUE));
2231 ucbhelper::cancelCommandExecution(
2232 ucb::IOErrorCode_CANT_WRITE,
2233 uno::Sequence< uno::Any >(&aProps, 1),
2234 xEnv,
2235 OUString( "Cannot remove additional properties of source object!" ),
2236 this );
2237 // Unreachable
2240 } // rInfo.MoveData
2244 //static
2245 bool Content::hasData( ContentProvider* pProvider, const Uri & rUri )
2247 if ( rUri.isRoot() )
2249 return true; // root has no storage
2251 else if ( rUri.isDocument() )
2253 uno::Reference< embed::XStorage > xStorage
2254 = pProvider->queryStorage( rUri.getUri(), READ );
2255 return xStorage.is();
2257 else
2259 // folder or stream
2261 // Ask parent storage. In case that rUri describes a stream,
2262 // ContentProvider::queryStorage( rUri ) would return null.
2264 uno::Reference< embed::XStorage > xStorage
2265 = pProvider->queryStorage( rUri.getParentUri(), READ );
2267 if ( !xStorage.is() )
2268 return false;
2270 uno::Reference< container::XNameAccess > xParentNA(
2271 xStorage, uno::UNO_QUERY );
2273 OSL_ENSURE( xParentNA.is(), "Got no css.container.XNameAccess!" );
2275 return xParentNA->hasByName( rUri.getDecodedName() );
2280 //static
2281 bool Content::loadData( ContentProvider* pProvider,
2282 const Uri & rUri,
2283 ContentProperties& rProps )
2285 if ( rUri.isRoot() ) // root has no storage, but can always be created
2287 rProps
2288 = ContentProperties(
2289 ROOT, pProvider->queryStorageTitle( rUri.getUri() ) );
2291 else if ( rUri.isDocument() ) // document must have storage
2293 uno::Reference< embed::XStorage > xStorage
2294 = pProvider->queryStorage( rUri.getUri(), READ );
2296 if ( !xStorage.is() )
2297 return false;
2299 rProps
2300 = ContentProperties(
2301 DOCUMENT, pProvider->queryStorageTitle( rUri.getUri() ) );
2303 else // stream or folder; stream has no storage; folder has storage
2305 uno::Reference< embed::XStorage > xStorage
2306 = pProvider->queryStorage( rUri.getParentUri(), READ );
2308 if ( !xStorage.is() )
2309 return false;
2311 // Check whether exists at all, is stream or folder
2314 // return: true -> folder
2315 // return: false -> stream
2316 // NoSuchElementException -> neither folder nor stream
2317 bool bIsFolder
2318 = xStorage->isStorageElement( rUri.getDecodedName() );
2320 rProps
2321 = ContentProperties(
2322 bIsFolder ? FOLDER : STREAM,
2323 pProvider->queryStorageTitle( rUri.getUri() ) );
2325 catch ( container::NoSuchElementException const & )
2327 // there is no element with such name
2328 //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2329 return false;
2331 catch ( lang::IllegalArgumentException const & )
2333 // an illegal argument is provided
2334 OSL_FAIL( "Caught IllegalArgumentException!" );
2335 return false;
2337 catch ( embed::InvalidStorageException const & )
2339 // this storage is in invalid state for any reason
2340 OSL_FAIL( "Caught InvalidStorageException!" );
2341 return false;
2344 return true;
2348 bool Content::storeData( const uno::Reference< io::XInputStream >& xData,
2349 const uno::Reference<
2350 ucb::XCommandEnvironment >& xEnv )
2351 throw ( ucb::CommandFailedException,
2352 task::DocumentPasswordRequest,
2353 css::uno::RuntimeException )
2355 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2357 ContentType eType = m_aProps.getType();
2358 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2360 OSL_FAIL( "storeData not supported by root and documents!" );
2361 return false;
2364 Uri aUri( m_xIdentifier->getContentIdentifier() );
2366 if ( eType == FOLDER )
2368 uno::Reference< embed::XStorage > xStorage
2369 = m_pProvider->queryStorage( aUri.getUri(), READ_WRITE_CREATE );
2371 if ( !xStorage.is() )
2372 return false;
2374 uno::Reference< beans::XPropertySet > xPropSet(
2375 xStorage, uno::UNO_QUERY );
2376 OSL_ENSURE( xPropSet.is(),
2377 "Content::storeData - Got no XPropertySet interface!" );
2378 if ( !xPropSet.is() )
2379 return false;
2383 // According to MBA, if no mediatype is set, folder and all
2384 // its contents will be lost on save of the document!!!
2385 xPropSet->setPropertyValue(
2386 OUString( "MediaType" ),
2387 uno::makeAny(
2388 OUString( // @@@ better mediatype
2389 "application/binary" ) ) );
2391 catch ( beans::UnknownPropertyException const & )
2393 OSL_FAIL( "Property MediaType not supported!" );
2394 return false;
2396 catch ( beans::PropertyVetoException const & )
2398 OSL_FAIL( "Caught PropertyVetoException!" );
2399 return false;
2401 catch ( lang::IllegalArgumentException const & )
2403 OSL_FAIL( "Caught IllegalArgumentException!" );
2404 return false;
2406 catch ( lang::WrappedTargetException const & )
2408 OSL_FAIL( "Caught WrappedTargetException!" );
2409 return false;
2412 if ( !commitStorage( xStorage ) )
2413 return false;
2415 else if ( eType == STREAM )
2417 // stream
2419 // Important: Parent storage and output stream must be kept alive until
2420 // changes have been committed!
2421 uno::Reference< embed::XStorage > xStorage
2422 = m_pProvider->queryStorage(
2423 aUri.getParentUri(), READ_WRITE_CREATE );
2424 uno::Reference< io::XOutputStream > xOut;
2426 if ( !xStorage.is() )
2427 return false;
2429 if ( xData.is() )
2431 // May throw CommandFailedException, DocumentPasswordRequest!
2432 xOut = getTruncatedOutputStream( xEnv );
2434 OSL_ENSURE( xOut.is(), "No target data stream!" );
2438 uno::Sequence< sal_Int8 > aBuffer;
2439 sal_Int32 nRead = xData->readSomeBytes( aBuffer, 65536 );
2441 while ( nRead > 0 )
2443 aBuffer.realloc( nRead );
2444 xOut->writeBytes( aBuffer );
2445 aBuffer.realloc( 0 );
2446 nRead = xData->readSomeBytes( aBuffer, 65536 );
2449 closeOutputStream( xOut );
2451 catch ( io::NotConnectedException const & )
2453 // readSomeBytes, writeBytes
2454 OSL_FAIL( "Caught NotConnectedException!" );
2455 closeOutputStream( xOut );
2456 return false;
2458 catch ( io::BufferSizeExceededException const & )
2460 // readSomeBytes, writeBytes
2461 OSL_FAIL( "Caught BufferSizeExceededException!" );
2462 closeOutputStream( xOut );
2463 return false;
2465 catch ( io::IOException const & )
2467 // readSomeBytes, writeBytes
2468 OSL_FAIL( "Caught IOException!" );
2469 closeOutputStream( xOut );
2470 return false;
2472 catch ( ... )
2474 closeOutputStream( xOut );
2475 throw;
2479 // Commit changes.
2480 if ( !commitStorage( xStorage ) )
2481 return false;
2483 else
2485 OSL_FAIL( "Unknown content type!" );
2486 return false;
2488 return true;
2492 bool Content::renameData(
2493 const uno::Reference< ucb::XContentIdentifier >& xOldId,
2494 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2496 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2498 ContentType eType = m_aProps.getType();
2499 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2501 OSL_FAIL( "renameData not supported by root and documents!" );
2502 return false;
2505 Uri aOldUri( xOldId->getContentIdentifier() );
2506 uno::Reference< embed::XStorage > xStorage
2507 = m_pProvider->queryStorage(
2508 aOldUri.getParentUri(), READ_WRITE_NOCREATE );
2510 if ( !xStorage.is() )
2511 return false;
2515 Uri aNewUri( xNewId->getContentIdentifier() );
2516 xStorage->renameElement(
2517 aOldUri.getDecodedName(), aNewUri.getDecodedName() );
2519 catch ( embed::InvalidStorageException const & )
2521 // this storage is in invalid state for eny reason
2522 OSL_FAIL( "Caught InvalidStorageException!" );
2523 return false;
2525 catch ( lang::IllegalArgumentException const & )
2527 // an illegal argument is provided
2528 OSL_FAIL( "Caught IllegalArgumentException!" );
2529 return false;
2531 catch ( container::NoSuchElementException const & )
2533 // there is no element with old name in this storage
2534 OSL_FAIL( "Caught NoSuchElementException!" );
2535 return false;
2537 catch ( container::ElementExistException const & )
2539 // an element with new name already exists in this storage
2540 OSL_FAIL( "Caught ElementExistException!" );
2541 return false;
2543 catch ( io::IOException const & )
2545 // in case of io errors during renaming
2546 OSL_FAIL( "Caught IOException!" );
2547 return false;
2549 catch ( embed::StorageWrappedTargetException const & )
2551 // wraps other exceptions
2552 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2553 return false;
2556 return commitStorage( xStorage );
2560 bool Content::removeData()
2562 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2564 ContentType eType = m_aProps.getType();
2565 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2567 OSL_FAIL( "removeData not supported by root and documents!" );
2568 return false;
2571 Uri aUri( m_xIdentifier->getContentIdentifier() );
2572 uno::Reference< embed::XStorage > xStorage
2573 = m_pProvider->queryStorage(
2574 aUri.getParentUri(), READ_WRITE_NOCREATE );
2576 if ( !xStorage.is() )
2577 return false;
2581 xStorage->removeElement( aUri.getDecodedName() );
2583 catch ( embed::InvalidStorageException const & )
2585 // this storage is in invalid state for eny reason
2586 OSL_FAIL( "Caught InvalidStorageException!" );
2587 return false;
2589 catch ( lang::IllegalArgumentException const & )
2591 // an illegal argument is provided
2592 OSL_FAIL( "Caught IllegalArgumentException!" );
2593 return false;
2595 catch ( container::NoSuchElementException const & )
2597 // there is no element with this name in this storage
2598 OSL_FAIL( "Caught NoSuchElementException!" );
2599 return false;
2601 catch ( io::IOException const & )
2603 // in case of io errors during renaming
2604 OSL_FAIL( "Caught IOException!" );
2605 return false;
2607 catch ( embed::StorageWrappedTargetException const & )
2609 // wraps other exceptions
2610 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2611 return false;
2614 return commitStorage( xStorage );
2618 bool Content::copyData( const Uri & rSourceUri, const OUString & rNewName )
2620 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2622 ContentType eType = m_aProps.getType();
2623 if ( ( eType == ROOT ) || ( eType == STREAM ) )
2625 OSL_FAIL( "copyData not supported by root and streams!" );
2626 return false;
2629 Uri aDestUri( m_xIdentifier->getContentIdentifier() );
2630 uno::Reference< embed::XStorage > xDestStorage
2631 = m_pProvider->queryStorage( aDestUri.getUri(), READ_WRITE_NOCREATE );
2633 if ( !xDestStorage.is() )
2634 return false;
2636 uno::Reference< embed::XStorage > xSourceStorage
2637 = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ );
2639 if ( !xSourceStorage.is() )
2640 return false;
2644 xSourceStorage->copyElementTo( rSourceUri.getDecodedName(),
2645 xDestStorage,
2646 rNewName );
2648 catch ( embed::InvalidStorageException const & )
2650 // this storage is in invalid state for eny reason
2651 OSL_FAIL( "Caught InvalidStorageException!" );
2652 return false;
2654 catch ( lang::IllegalArgumentException const & )
2656 // an illegal argument is provided
2657 OSL_FAIL( "Caught IllegalArgumentException!" );
2658 return false;
2660 catch ( container::NoSuchElementException const & )
2662 // there is no element with this name in this storage
2663 OSL_FAIL( "Caught NoSuchElementException!" );
2664 return false;
2666 catch ( container::ElementExistException const & )
2668 // there is no element with this name in this storage
2669 OSL_FAIL( "Caught ElementExistException!" );
2670 return false;
2672 catch ( io::IOException const & )
2674 // in case of io errors during renaming
2675 OSL_FAIL( "Caught IOException!" );
2676 return false;
2678 catch ( embed::StorageWrappedTargetException const & )
2680 // wraps other exceptions
2681 OSL_FAIL( "Caught StorageWrappedTargetException!" );
2682 return false;
2685 return commitStorage( xDestStorage );
2689 // static
2690 bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage )
2692 // Commit changes
2693 uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY );
2695 OSL_ENSURE( xTO.is(),
2696 "Required interface css.embed.XTransactedObject missing!" );
2699 xTO->commit();
2701 catch ( io::IOException const & )
2703 OSL_FAIL( "Caught IOException!" );
2704 return false;
2706 catch ( lang::WrappedTargetException const & )
2708 OSL_FAIL( "Caught WrappedTargetException!" );
2709 return false;
2712 return true;
2716 // static
2717 bool Content::closeOutputStream(
2718 const uno::Reference< io::XOutputStream > & xOut )
2720 if ( xOut.is() )
2724 xOut->closeOutput();
2725 return true;
2727 catch ( io::NotConnectedException const & )
2729 OSL_FAIL( "Caught NotConnectedException!" );
2731 catch ( io::BufferSizeExceededException const & )
2733 OSL_FAIL( "Caught BufferSizeExceededException!" );
2735 catch ( io::IOException const & )
2737 OSL_FAIL( "Caught IOException!" );
2740 return false;
2744 static OUString obtainPassword(
2745 const OUString & rName,
2746 task::PasswordRequestMode eMode,
2747 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2748 throw ( ucb::CommandFailedException,
2749 task::DocumentPasswordRequest )
2751 rtl::Reference< DocumentPasswordRequest > xRequest
2752 = new DocumentPasswordRequest( eMode, rName );
2754 if ( xEnv.is() )
2756 uno::Reference< task::XInteractionHandler > xIH
2757 = xEnv->getInteractionHandler();
2758 if ( xIH.is() )
2760 xIH->handle( xRequest.get() );
2762 rtl::Reference< ucbhelper::InteractionContinuation > xSelection
2763 = xRequest->getSelection();
2765 if ( xSelection.is() )
2767 // Handler handled the request.
2768 uno::Reference< task::XInteractionAbort > xAbort(
2769 xSelection.get(), uno::UNO_QUERY );
2770 if ( xAbort.is() )
2772 throw ucb::CommandFailedException(
2773 OUString( "Abort requested by Interaction Handler." ),
2774 uno::Reference< uno::XInterface >(),
2775 xRequest->getRequest() );
2778 uno::Reference< task::XInteractionPassword > xPassword(
2779 xSelection.get(), uno::UNO_QUERY );
2780 if ( xPassword.is() )
2782 return xPassword->getPassword();
2785 // Unknown selection. Should never happen.
2786 throw ucb::CommandFailedException(
2787 OUString( "Interaction Handler selected unknown continuation!" ),
2788 uno::Reference< uno::XInterface >(),
2789 xRequest->getRequest() );
2794 // No IH or IH did not handle exception.
2795 task::DocumentPasswordRequest aRequest;
2796 xRequest->getRequest() >>= aRequest;
2797 throw aRequest;
2801 uno::Reference< io::XInputStream > Content::getInputStream(
2802 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2803 throw ( ucb::CommandFailedException,
2804 task::DocumentPasswordRequest,
2805 uno::RuntimeException )
2807 OUString aUri;
2808 OUString aPassword;
2809 bool bPasswordRequested = false;
2812 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2814 OSL_ENSURE( m_aProps.getType() == STREAM,
2815 "Content::getInputStream - content is no stream!" );
2817 aUri = Uri( m_xIdentifier->getContentIdentifier() ).getUri();
2820 for ( ;; )
2824 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2825 return uno::Reference< io::XInputStream >(
2826 m_pProvider->queryInputStream( aUri, aPassword ) );
2828 catch ( packages::WrongPasswordException const & )
2830 // Obtain (new) password.
2831 aPassword
2832 = obtainPassword( aUri, /* @@@ find better title */
2833 bPasswordRequested
2834 ? task::PasswordRequestMode_PASSWORD_REENTER
2835 : task::PasswordRequestMode_PASSWORD_ENTER,
2836 xEnv );
2837 bPasswordRequested = true;
2843 static uno::Reference< io::XOutputStream > lcl_getTruncatedOutputStream(
2844 const OUString & rUri,
2845 ContentProvider * pProvider,
2846 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2847 throw ( ucb::CommandFailedException,
2848 task::DocumentPasswordRequest,
2849 uno::RuntimeException )
2851 OUString aPassword;
2852 bool bPasswordRequested = false;
2853 for ( ;; )
2857 return uno::Reference< io::XOutputStream >(
2858 pProvider->queryOutputStream(
2859 rUri, aPassword, true /* truncate */ ) );
2861 catch ( packages::WrongPasswordException const & )
2863 // Obtain (new) password.
2864 aPassword
2865 = obtainPassword( rUri, /* @@@ find better title */
2866 bPasswordRequested
2867 ? task::PasswordRequestMode_PASSWORD_REENTER
2868 : task::PasswordRequestMode_PASSWORD_ENTER,
2869 xEnv );
2870 bPasswordRequested = true;
2876 uno::Reference< io::XOutputStream > Content::getTruncatedOutputStream(
2877 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2878 throw ( ucb::CommandFailedException,
2879 task::DocumentPasswordRequest,
2880 css::uno::RuntimeException )
2882 OSL_ENSURE( m_aProps.getType() == STREAM,
2883 "Content::getTruncatedOutputStream - content is no stream!" );
2885 return lcl_getTruncatedOutputStream(
2886 Uri( m_xIdentifier->getContentIdentifier() ).getUri(),
2887 m_pProvider,
2888 xEnv );
2892 uno::Reference< io::XStream > Content::getStream(
2893 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2894 throw ( ucb::CommandFailedException,
2895 task::DocumentPasswordRequest,
2896 uno::RuntimeException )
2898 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2900 OSL_ENSURE( m_aProps.getType() == STREAM,
2901 "Content::getStream - content is no stream!" );
2903 OUString aUri( Uri( m_xIdentifier->getContentIdentifier() ).getUri() );
2904 OUString aPassword;
2905 bool bPasswordRequested = false;
2906 for ( ;; )
2910 return uno::Reference< io::XStream >(
2911 m_pProvider->queryStream(
2912 aUri, aPassword, false /* no truncate */ ) );
2914 catch ( packages::WrongPasswordException const & )
2916 // Obtain (new) password.
2917 aPassword
2918 = obtainPassword( aUri, /* @@@ find better title */
2919 bPasswordRequested
2920 ? task::PasswordRequestMode_PASSWORD_REENTER
2921 : task::PasswordRequestMode_PASSWORD_ENTER,
2922 xEnv );
2923 bPasswordRequested = true;
2931 // ContentProperties Implementation.
2936 uno::Sequence< ucb::ContentInfo >
2937 ContentProperties::getCreatableContentsInfo() const
2939 if ( isContentCreator() )
2941 uno::Sequence< beans::Property > aProps( 1 );
2942 aProps.getArray()[ 0 ] = beans::Property(
2943 OUString("Title"),
2945 cppu::UnoType<OUString>::get(),
2946 beans::PropertyAttribute::BOUND );
2948 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2949 if ( getType() == DOCUMENT )
2951 // streams cannot be created as direct children of document root
2952 uno::Sequence< ucb::ContentInfo > aSeq( 1 );
2954 // Folder.
2955 aSeq.getArray()[ 0 ].Type = TDOC_FOLDER_CONTENT_TYPE;
2956 aSeq.getArray()[ 0 ].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
2957 aSeq.getArray()[ 0 ].Properties = aProps;
2959 return aSeq;
2961 else
2963 #endif
2964 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
2966 // Folder.
2967 aSeq.getArray()[ 0 ].Type = TDOC_FOLDER_CONTENT_TYPE;
2968 aSeq.getArray()[ 0 ].Attributes
2969 = ucb::ContentInfoAttribute::KIND_FOLDER;
2970 aSeq.getArray()[ 0 ].Properties = aProps;
2972 // Stream.
2973 aSeq.getArray()[ 1 ].Type = TDOC_STREAM_CONTENT_TYPE;
2974 aSeq.getArray()[ 1 ].Attributes
2975 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
2976 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
2977 aSeq.getArray()[ 1 ].Properties = aProps;
2979 return aSeq;
2980 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2982 #endif
2984 else
2986 OSL_FAIL( "getCreatableContentsInfo called on non-contentcreator "
2987 "object!" );
2989 return uno::Sequence< ucb::ContentInfo >( 0 );
2994 bool ContentProperties::isContentCreator() const
2996 return ( getType() == FOLDER ) || ( getType() == DOCUMENT );
2999 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */