bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchycontent.cxx
blob63da66520a4f61fe9bfb76f5d2f6ae3923e321cc
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 - optimize transfer command. "Move" should be implementable much more
26 efficient!
28 **************************************************************************
30 - Root Folder vs. 'normal' Folder
31 - root doesn't support command 'delete'
32 - root doesn't support command 'insert'
33 - root needs not created via XContentCreator - queryContent with root
34 folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0
35 - root has no parent.
37 *************************************************************************/
38 #include <osl/diagnose.h>
40 #include "osl/doublecheckedlocking.h"
41 #include <rtl/ustring.h>
42 #include <rtl/ustring.hxx>
43 #include <com/sun/star/beans/PropertyAttribute.hpp>
44 #include <com/sun/star/beans/PropertyState.hpp>
45 #include <com/sun/star/beans/PropertyValue.hpp>
46 #include <com/sun/star/beans/XPropertyAccess.hpp>
47 #include <com/sun/star/lang/IllegalAccessException.hpp>
48 #include <com/sun/star/sdbc/XRow.hpp>
49 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
50 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
51 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
52 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
53 #include <com/sun/star/ucb/NameClash.hpp>
54 #include <com/sun/star/ucb/NameClashException.hpp>
55 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
56 #include <com/sun/star/ucb/TransferInfo.hpp>
57 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
58 #include <com/sun/star/ucb/XCommandInfo.hpp>
59 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
60 #include <com/sun/star/uno/Any.hxx>
61 #include <com/sun/star/uno/Sequence.hxx>
62 #include <comphelper/processfactory.hxx>
63 #include <ucbhelper/contentidentifier.hxx>
64 #include <ucbhelper/propertyvalueset.hxx>
65 #include <ucbhelper/cancelcommandexecution.hxx>
66 #include "hierarchycontent.hxx"
67 #include "hierarchyprovider.hxx"
68 #include "dynamicresultset.hxx"
69 #include "hierarchyuri.hxx"
71 #include "../inc/urihelper.hxx"
73 using namespace com::sun::star;
74 using namespace hierarchy_ucp;
79 // HierarchyContent Implementation.
84 // static ( "virtual" ctor )
85 HierarchyContent* HierarchyContent::create(
86 const uno::Reference< uno::XComponentContext >& rxContext,
87 HierarchyContentProvider* pProvider,
88 const uno::Reference< ucb::XContentIdentifier >& Identifier )
90 // Fail, if content does not exist.
91 HierarchyContentProperties aProps;
92 if ( !loadData( rxContext, pProvider, Identifier, aProps ) )
93 return 0;
95 return new HierarchyContent( rxContext, pProvider, Identifier, aProps );
99 // static ( "virtual" ctor )
100 HierarchyContent* HierarchyContent::create(
101 const uno::Reference< uno::XComponentContext >& rxContext,
102 HierarchyContentProvider* pProvider,
103 const uno::Reference< ucb::XContentIdentifier >& Identifier,
104 const ucb::ContentInfo& Info )
106 if ( Info.Type.isEmpty() )
107 return 0;
109 if ( Info.Type != HIERARCHY_FOLDER_CONTENT_TYPE && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
110 return 0;
112 return new HierarchyContent( rxContext, pProvider, Identifier, Info );
116 HierarchyContent::HierarchyContent(
117 const uno::Reference< uno::XComponentContext >& rxContext,
118 HierarchyContentProvider* pProvider,
119 const uno::Reference< ucb::XContentIdentifier >& Identifier,
120 const HierarchyContentProperties& rProps )
121 : ContentImplHelper( rxContext, pProvider, Identifier ),
122 m_aProps( rProps ),
123 m_eState( PERSISTENT ),
124 m_pProvider( pProvider ),
125 m_bCheckedReadOnly( false ),
126 m_bIsReadOnly( true )
128 setKind( Identifier );
132 HierarchyContent::HierarchyContent(
133 const uno::Reference< uno::XComponentContext >& rxContext,
134 HierarchyContentProvider* pProvider,
135 const uno::Reference< ucb::XContentIdentifier >& Identifier,
136 const ucb::ContentInfo& Info )
137 : ContentImplHelper( rxContext, pProvider, Identifier ),
138 m_aProps( Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE ? HierarchyEntryData::FOLDER : HierarchyEntryData::LINK ),
139 m_eState( TRANSIENT ),
140 m_pProvider( pProvider ),
141 m_bCheckedReadOnly( false ),
142 m_bIsReadOnly( true )
144 setKind( Identifier );
148 // virtual
149 HierarchyContent::~HierarchyContent()
155 // XInterface methods.
159 // virtual
160 void SAL_CALL HierarchyContent::acquire()
161 throw( )
163 ContentImplHelper::acquire();
167 // virtual
168 void SAL_CALL HierarchyContent::release()
169 throw( )
171 ContentImplHelper::release();
175 // virtual
176 uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType )
177 throw ( uno::RuntimeException, std::exception )
179 uno::Any aRet = ContentImplHelper::queryInterface( rType );
181 if ( !aRet.hasValue() )
183 // Note: isReadOnly may be relative expensive. So avoid calling it
184 // unless it is really necessary.
185 aRet = cppu::queryInterface(
186 rType, static_cast< ucb::XContentCreator * >( this ) );
187 if ( aRet.hasValue() )
189 if ( !isFolder() || isReadOnly() )
190 return uno::Any();
194 return aRet;
199 // XTypeProvider methods.
203 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent );
206 // virtual
207 uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes()
208 throw( uno::RuntimeException, std::exception )
210 cppu::OTypeCollection * pCollection = 0;
212 if ( isFolder() && !isReadOnly() )
214 static cppu::OTypeCollection* pFolderTypes = 0;
216 pCollection = pFolderTypes;
217 if ( !pCollection )
219 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
221 pCollection = pFolderTypes;
222 if ( !pCollection )
224 static cppu::OTypeCollection aCollection(
225 CPPU_TYPE_REF( lang::XTypeProvider ),
226 CPPU_TYPE_REF( lang::XServiceInfo ),
227 CPPU_TYPE_REF( lang::XComponent ),
228 CPPU_TYPE_REF( ucb::XContent ),
229 CPPU_TYPE_REF( ucb::XCommandProcessor ),
230 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
231 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
232 CPPU_TYPE_REF( beans::XPropertyContainer ),
233 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
234 CPPU_TYPE_REF( container::XChild ),
235 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
236 pCollection = &aCollection;
237 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
238 pFolderTypes = pCollection;
241 else {
242 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
245 else
247 static cppu::OTypeCollection* pDocumentTypes = 0;
249 pCollection = pDocumentTypes;
250 if ( !pCollection )
252 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
254 pCollection = pDocumentTypes;
255 if ( !pCollection )
257 static cppu::OTypeCollection aCollection(
258 CPPU_TYPE_REF( lang::XTypeProvider ),
259 CPPU_TYPE_REF( lang::XServiceInfo ),
260 CPPU_TYPE_REF( lang::XComponent ),
261 CPPU_TYPE_REF( ucb::XContent ),
262 CPPU_TYPE_REF( ucb::XCommandProcessor ),
263 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
264 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
265 CPPU_TYPE_REF( beans::XPropertyContainer ),
266 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
267 CPPU_TYPE_REF( container::XChild ) );
268 pCollection = &aCollection;
269 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
270 pDocumentTypes = pCollection;
273 else {
274 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
278 return (*pCollection).getTypes();
283 // XServiceInfo methods.
287 // virtual
288 OUString SAL_CALL HierarchyContent::getImplementationName()
289 throw( uno::RuntimeException, std::exception )
291 return OUString( "com.sun.star.comp.ucb.HierarchyContent" );
295 // virtual
296 uno::Sequence< OUString > SAL_CALL
297 HierarchyContent::getSupportedServiceNames()
298 throw( uno::RuntimeException, std::exception )
300 uno::Sequence< OUString > aSNS( 1 );
302 if ( m_eKind == LINK )
303 aSNS.getArray()[ 0 ] = HIERARCHY_LINK_CONTENT_SERVICE_NAME;
304 else if ( m_eKind == FOLDER )
305 aSNS.getArray()[ 0 ] = HIERARCHY_FOLDER_CONTENT_SERVICE_NAME;
306 else
307 aSNS.getArray()[ 0 ] = HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME;
309 return aSNS;
314 // XContent methods.
318 // virtual
319 OUString SAL_CALL HierarchyContent::getContentType()
320 throw( uno::RuntimeException, std::exception )
322 return m_aProps.getContentType();
326 // virtual
327 uno::Reference< ucb::XContentIdentifier > SAL_CALL
328 HierarchyContent::getIdentifier()
329 throw( uno::RuntimeException, std::exception )
331 // Transient?
332 if ( m_eState == TRANSIENT )
334 // Transient contents have no identifier.
335 return uno::Reference< ucb::XContentIdentifier >();
338 return ContentImplHelper::getIdentifier();
343 // XCommandProcessor methods.
347 // virtual
348 uno::Any SAL_CALL HierarchyContent::execute(
349 const ucb::Command& aCommand,
350 sal_Int32 /*CommandId*/,
351 const uno::Reference< ucb::XCommandEnvironment >& Environment )
352 throw( uno::Exception,
353 ucb::CommandAbortedException,
354 uno::RuntimeException, std::exception )
356 uno::Any aRet;
358 if ( aCommand.Name == "getPropertyValues" )
361 // getPropertyValues
364 uno::Sequence< beans::Property > Properties;
365 if ( !( aCommand.Argument >>= Properties ) )
367 ucbhelper::cancelCommandExecution(
368 uno::makeAny( lang::IllegalArgumentException(
369 OUString( "Wrong argument type!" ),
370 static_cast< cppu::OWeakObject * >( this ),
371 -1 ) ),
372 Environment );
373 // Unreachable
376 aRet <<= getPropertyValues( Properties );
378 else if ( aCommand.Name == "setPropertyValues" )
381 // setPropertyValues
384 uno::Sequence< beans::PropertyValue > aProperties;
385 if ( !( aCommand.Argument >>= aProperties ) )
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 if ( !aProperties.getLength() )
398 ucbhelper::cancelCommandExecution(
399 uno::makeAny( lang::IllegalArgumentException(
400 OUString( "No properties!" ),
401 static_cast< cppu::OWeakObject * >( this ),
402 -1 ) ),
403 Environment );
404 // Unreachable
407 aRet <<= setPropertyValues( aProperties, Environment );
409 else if ( aCommand.Name == "getPropertySetInfo" )
412 // getPropertySetInfo
415 aRet <<= getPropertySetInfo( Environment );
417 else if ( aCommand.Name == "getCommandInfo" )
420 // getCommandInfo
423 aRet <<= getCommandInfo( Environment );
425 else if ( aCommand.Name == "open" && isFolder() )
428 // open command for a folder content
431 ucb::OpenCommandArgument2 aOpenCommand;
432 if ( !( aCommand.Argument >>= aOpenCommand ) )
434 ucbhelper::cancelCommandExecution(
435 uno::makeAny( lang::IllegalArgumentException(
436 OUString( "Wrong argument type!" ),
437 static_cast< cppu::OWeakObject * >( this ),
438 -1 ) ),
439 Environment );
440 // Unreachable
443 uno::Reference< ucb::XDynamicResultSet > xSet
444 = new DynamicResultSet( m_xContext, this, aOpenCommand );
445 aRet <<= xSet;
447 else if ( aCommand.Name == "insert" && ( m_eKind != ROOT ) && !isReadOnly() )
450 // insert
451 // ( Not available at root folder )
454 ucb::InsertCommandArgument aArg;
455 if ( !( aCommand.Argument >>= aArg ) )
457 ucbhelper::cancelCommandExecution(
458 uno::makeAny( lang::IllegalArgumentException(
459 OUString( "Wrong argument type!" ),
460 static_cast< cppu::OWeakObject * >( this ),
461 -1 ) ),
462 Environment );
463 // Unreachable
466 sal_Int32 nNameClash = aArg.ReplaceExisting
467 ? ucb::NameClash::OVERWRITE
468 : ucb::NameClash::ERROR;
469 insert( nNameClash, Environment );
471 else if ( aCommand.Name == "delete" && ( m_eKind != ROOT ) && !isReadOnly() )
474 // delete
475 // ( Not available at root folder )
478 bool bDeletePhysical = false;
479 aCommand.Argument >>= bDeletePhysical;
480 destroy( bDeletePhysical, Environment );
482 // Remove own and all children's persistent data.
483 if ( !removeData() )
485 uno::Any aProps
486 = uno::makeAny(
487 beans::PropertyValue(
488 OUString( "Uri"),
490 uno::makeAny(m_xIdentifier->
491 getContentIdentifier()),
492 beans::PropertyState_DIRECT_VALUE));
493 ucbhelper::cancelCommandExecution(
494 ucb::IOErrorCode_CANT_WRITE,
495 uno::Sequence< uno::Any >(&aProps, 1),
496 Environment,
497 OUString( "Cannot remove persistent data!" ),
498 this );
499 // Unreachable
502 // Remove own and all children's Additional Core Properties.
503 removeAdditionalPropertySet( true );
505 else if ( aCommand.Name == "transfer" && isFolder() && !isReadOnly() )
508 // transfer
509 // ( Not available at link objects )
512 ucb::TransferInfo aInfo;
513 if ( !( aCommand.Argument >>= aInfo ) )
515 OSL_FAIL( "Wrong argument type!" );
516 ucbhelper::cancelCommandExecution(
517 uno::makeAny( lang::IllegalArgumentException(
518 OUString( "Wrong argument type!" ),
519 static_cast< cppu::OWeakObject * >( this ),
520 -1 ) ),
521 Environment );
522 // Unreachable
525 transfer( aInfo, Environment );
527 else if ( aCommand.Name == "createNewContent" && isFolder() && !isReadOnly() )
530 // createNewContent
531 // ( Not available at link objects )
534 ucb::ContentInfo aInfo;
535 if ( !( aCommand.Argument >>= aInfo ) )
537 OSL_FAIL( "Wrong argument type!" );
538 ucbhelper::cancelCommandExecution(
539 uno::makeAny( lang::IllegalArgumentException(
540 OUString( "Wrong argument type!" ),
541 static_cast< cppu::OWeakObject * >( this ),
542 -1 ) ),
543 Environment );
544 // Unreachable
547 aRet <<= createNewContent( aInfo );
549 else
552 // Unsupported command
555 ucbhelper::cancelCommandExecution(
556 uno::makeAny( ucb::UnsupportedCommandException(
557 OUString(),
558 static_cast< cppu::OWeakObject * >( this ) ) ),
559 Environment );
560 // Unreachable
563 return aRet;
567 // virtual
568 void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ )
569 throw( uno::RuntimeException, std::exception )
571 // @@@ Generally, no action takes much time...
576 // XContentCreator methods.
580 // virtual
581 uno::Sequence< ucb::ContentInfo > SAL_CALL
582 HierarchyContent::queryCreatableContentsInfo()
583 throw( uno::RuntimeException, std::exception )
585 return m_aProps.getCreatableContentsInfo();
589 // virtual
590 uno::Reference< ucb::XContent > SAL_CALL
591 HierarchyContent::createNewContent( const ucb::ContentInfo& Info )
592 throw( uno::RuntimeException, std::exception )
594 if ( isFolder() )
596 osl::Guard< osl::Mutex > aGuard( m_aMutex );
598 if ( Info.Type.isEmpty() )
599 return uno::Reference< ucb::XContent >();
601 bool bCreateFolder = Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE;
603 if ( !bCreateFolder && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
604 return uno::Reference< ucb::XContent >();
606 OUString aURL = m_xIdentifier->getContentIdentifier();
608 OSL_ENSURE( !aURL.isEmpty(),
609 "HierarchyContent::createNewContent - empty identifier!" );
611 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
612 aURL += "/";
614 if ( bCreateFolder )
615 aURL += "New_Folder";
616 else
617 aURL += "New_Link";
619 uno::Reference< ucb::XContentIdentifier > xId
620 = new ::ucbhelper::ContentIdentifier( aURL );
622 return create( m_xContext, m_pProvider, xId, Info );
624 else
626 OSL_FAIL( "createNewContent called on non-folder object!" );
627 return uno::Reference< ucb::XContent >();
632 // virtual
633 OUString HierarchyContent::getParentURL()
635 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
636 return aUri.getParentUri();
640 //static
641 bool HierarchyContent::hasData(
642 const uno::Reference< uno::XComponentContext >& rxContext,
643 HierarchyContentProvider* pProvider,
644 const uno::Reference< ucb::XContentIdentifier >& Identifier )
646 OUString aURL = Identifier->getContentIdentifier();
648 // Am I a root folder?
649 HierarchyUri aUri( aURL );
650 if ( aUri.isRootFolder() )
652 // hasData must always return 'true' for root folder
653 // even if no persistent data exist!!!
654 return true;
657 return HierarchyEntry( rxContext, pProvider, aURL ).hasData();
661 //static
662 bool HierarchyContent::loadData(
663 const uno::Reference< uno::XComponentContext >& rxContext,
664 HierarchyContentProvider* pProvider,
665 const uno::Reference< ucb::XContentIdentifier >& Identifier,
666 HierarchyContentProperties& rProps )
668 OUString aURL = Identifier->getContentIdentifier();
670 // Am I a root folder?
671 HierarchyUri aUri( aURL );
672 if ( aUri.isRootFolder() )
674 rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER );
676 else
678 HierarchyEntry aEntry( rxContext, pProvider, aURL );
679 HierarchyEntryData aData;
680 if ( !aEntry.getData( aData ) )
681 return false;
683 rProps = HierarchyContentProperties( aData );
685 return true;
689 bool HierarchyContent::storeData()
691 HierarchyEntry aEntry(
692 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
693 return aEntry.setData( m_aProps.getHierarchyEntryData(), true );
697 bool HierarchyContent::renameData(
698 const uno::Reference< ucb::XContentIdentifier >& xOldId,
699 const uno::Reference< ucb::XContentIdentifier >& xNewId )
701 HierarchyEntry aEntry(
702 m_xContext, m_pProvider, xOldId->getContentIdentifier() );
703 return aEntry.move( xNewId->getContentIdentifier(),
704 m_aProps.getHierarchyEntryData() );
708 bool HierarchyContent::removeData()
710 HierarchyEntry aEntry(
711 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
712 return aEntry.remove();
716 void HierarchyContent::setKind(
717 const uno::Reference< ucb::XContentIdentifier >& Identifier )
719 if ( m_aProps.getIsFolder() )
721 // Am I a root folder?
722 HierarchyUri aUri( Identifier->getContentIdentifier() );
723 if ( aUri.isRootFolder() )
724 m_eKind = ROOT;
725 else
726 m_eKind = FOLDER;
728 else
729 m_eKind = LINK;
733 bool HierarchyContent::isReadOnly()
735 if ( !m_bCheckedReadOnly )
737 osl::Guard< osl::Mutex > aGuard( m_aMutex );
738 if ( !m_bCheckedReadOnly )
740 m_bCheckedReadOnly = true;
741 m_bIsReadOnly = true;
743 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
744 uno::Reference< lang::XMultiServiceFactory > xConfigProv
745 = m_pProvider->getConfigProvider( aUri.getService() );
746 if ( xConfigProv.is() )
748 uno::Sequence< OUString > aNames
749 = xConfigProv->getAvailableServiceNames();
750 sal_Int32 nCount = aNames.getLength();
751 for ( sal_Int32 n = 0; n < nCount; ++n )
753 if ( aNames[ n ] == "com.sun.star.ucb.HierarchyDataReadWriteAccess" )
755 m_bIsReadOnly = false;
756 break;
763 return m_bIsReadOnly;
767 uno::Reference< ucb::XContentIdentifier >
768 HierarchyContent::makeNewIdentifier( const OUString& rTitle )
770 osl::Guard< osl::Mutex > aGuard( m_aMutex );
772 // Assemble new content identifier...
773 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
774 OUString aNewURL = aUri.getParentUri();
775 aNewURL += "/";
776 aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle );
778 return uno::Reference< ucb::XContentIdentifier >(
779 new ::ucbhelper::ContentIdentifier( aNewURL ) );
783 void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren )
785 if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) )
786 return;
788 // Obtain a list with a snapshot of all currently instantiated contents
789 // from provider and extract the contents which are direct children
790 // of this content.
792 ::ucbhelper::ContentRefList aAllContents;
793 m_xProvider->queryExistingContents( aAllContents );
795 OUString aURL = m_xIdentifier->getContentIdentifier();
796 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
798 if ( nURLPos != ( aURL.getLength() - 1 ) )
800 // No trailing slash found. Append.
801 aURL += "/";
804 sal_Int32 nLen = aURL.getLength();
806 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
807 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
809 while ( it != end )
811 ::ucbhelper::ContentImplHelperRef xChild = (*it);
812 OUString aChildURL
813 = xChild->getIdentifier()->getContentIdentifier();
815 // Is aURL a prefix of aChildURL?
816 if ( ( aChildURL.getLength() > nLen ) &&
817 ( aChildURL.startsWith( aURL ) ) )
819 sal_Int32 nPos = nLen;
820 nPos = aChildURL.indexOf( '/', nPos );
822 if ( ( nPos == -1 ) ||
823 ( nPos == ( aChildURL.getLength() - 1 ) ) )
825 // No further slashes/ only a final slash. It's a child!
826 rChildren.push_back(
827 HierarchyContentRef(
828 static_cast< HierarchyContent * >( xChild.get() ) ) );
831 ++it;
836 bool HierarchyContent::exchangeIdentity(
837 const uno::Reference< ucb::XContentIdentifier >& xNewId )
839 if ( !xNewId.is() )
840 return false;
842 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
844 uno::Reference< ucb::XContent > xThis = this;
846 // Already persistent?
847 if ( m_eState != PERSISTENT )
849 OSL_FAIL( "HierarchyContent::exchangeIdentity - Not persistent!" );
850 return false;
853 // Am I the root folder?
854 if ( m_eKind == ROOT )
856 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
857 "Not supported by root folder!" );
858 return false;
861 // Exchange own identitity.
863 // Fail, if a content with given id already exists.
864 if ( !hasData( xNewId ) )
866 OUString aOldURL = m_xIdentifier->getContentIdentifier();
868 aGuard.clear();
869 if ( exchange( xNewId ) )
871 if ( m_eKind == FOLDER )
873 // Process instantiated children...
875 HierarchyContentRefList aChildren;
876 queryChildren( aChildren );
878 HierarchyContentRefList::const_iterator it = aChildren.begin();
879 HierarchyContentRefList::const_iterator end = aChildren.end();
881 while ( it != end )
883 HierarchyContentRef xChild = (*it);
885 // Create new content identifier for the child...
886 uno::Reference< ucb::XContentIdentifier > xOldChildId
887 = xChild->getIdentifier();
888 OUString aOldChildURL
889 = xOldChildId->getContentIdentifier();
890 OUString aNewChildURL
891 = aOldChildURL.replaceAt(
893 aOldURL.getLength(),
894 xNewId->getContentIdentifier() );
895 uno::Reference< ucb::XContentIdentifier > xNewChildId
896 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
898 if ( !xChild->exchangeIdentity( xNewChildId ) )
899 return false;
901 ++it;
904 return true;
908 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
909 "Panic! Cannot exchange identity!" );
910 return false;
914 // static
915 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
916 const uno::Reference< uno::XComponentContext >& rxContext,
917 const uno::Sequence< beans::Property >& rProperties,
918 const HierarchyContentProperties& rData,
919 HierarchyContentProvider* pProvider,
920 const OUString& rContentId )
922 // Note: Empty sequence means "get values of all supported properties".
924 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
925 = new ::ucbhelper::PropertyValueSet( rxContext );
927 sal_Int32 nCount = rProperties.getLength();
928 if ( nCount )
930 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
931 bool bTriedToGetAdditionalPropSet = false;
933 const beans::Property* pProps = rProperties.getConstArray();
934 for ( sal_Int32 n = 0; n < nCount; ++n )
936 const beans::Property& rProp = pProps[ n ];
938 // Process Core properties.
940 if ( rProp.Name == "ContentType" )
942 xRow->appendString ( rProp, rData.getContentType() );
944 else if ( rProp.Name == "Title" )
946 xRow->appendString ( rProp, rData.getTitle() );
948 else if ( rProp.Name == "IsDocument" )
950 xRow->appendBoolean( rProp, rData.getIsDocument() );
952 else if ( rProp.Name == "IsFolder" )
954 xRow->appendBoolean( rProp, rData.getIsFolder() );
956 else if ( rProp.Name == "CreatableContentsInfo" )
958 xRow->appendObject(
959 rProp, uno::makeAny( rData.getCreatableContentsInfo() ) );
961 else if ( rProp.Name == "TargetURL" )
963 // TargetURL is only supported by links.
965 if ( rData.getIsDocument() )
966 xRow->appendString( rProp, rData.getTargetURL() );
967 else
968 xRow->appendVoid( rProp );
970 else
972 // Not a Core Property! Maybe it's an Additional Core Property?!
974 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
976 xAdditionalPropSet
977 = uno::Reference< beans::XPropertySet >(
978 pProvider->getAdditionalPropertySet( rContentId,
979 false ),
980 uno::UNO_QUERY );
981 bTriedToGetAdditionalPropSet = true;
984 if ( xAdditionalPropSet.is() )
986 if ( !xRow->appendPropertySetValue(
987 xAdditionalPropSet,
988 rProp ) )
990 // Append empty entry.
991 xRow->appendVoid( rProp );
994 else
996 // Append empty entry.
997 xRow->appendVoid( rProp );
1002 else
1004 // Append all Core Properties.
1005 xRow->appendString (
1006 beans::Property( OUString("ContentType"),
1008 cppu::UnoType<OUString>::get(),
1009 beans::PropertyAttribute::BOUND
1010 | beans::PropertyAttribute::READONLY ),
1011 rData.getContentType() );
1012 xRow->appendString (
1013 beans::Property( OUString("Title"),
1015 cppu::UnoType<OUString>::get(),
1016 // @@@ Might actually be read-only!
1017 beans::PropertyAttribute::BOUND ),
1018 rData.getTitle() );
1019 xRow->appendBoolean(
1020 beans::Property( OUString("IsDocument"),
1022 cppu::UnoType<bool>::get(),
1023 beans::PropertyAttribute::BOUND
1024 | beans::PropertyAttribute::READONLY ),
1025 rData.getIsDocument() );
1026 xRow->appendBoolean(
1027 beans::Property( OUString("IsFolder"),
1029 cppu::UnoType<bool>::get(),
1030 beans::PropertyAttribute::BOUND
1031 | beans::PropertyAttribute::READONLY ),
1032 rData.getIsFolder() );
1034 if ( rData.getIsDocument() )
1035 xRow->appendString(
1036 beans::Property( OUString("TargetURL"),
1038 cppu::UnoType<OUString>::get(),
1039 // @@@ Might actually be read-only!
1040 beans::PropertyAttribute::BOUND ),
1041 rData.getTargetURL() );
1042 xRow->appendObject(
1043 beans::Property(
1044 OUString("CreatableContentsInfo"),
1046 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
1047 beans::PropertyAttribute::BOUND
1048 | beans::PropertyAttribute::READONLY ),
1049 uno::makeAny( rData.getCreatableContentsInfo() ) );
1051 // Append all Additional Core Properties.
1053 uno::Reference< beans::XPropertySet > xSet(
1054 pProvider->getAdditionalPropertySet( rContentId, false ),
1055 uno::UNO_QUERY );
1056 xRow->appendPropertySet( xSet );
1059 return uno::Reference< sdbc::XRow >( xRow.get() );
1063 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
1064 const uno::Sequence< beans::Property >& rProperties )
1066 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1067 return getPropertyValues( m_xContext,
1068 rProperties,
1069 m_aProps,
1070 m_pProvider,
1071 m_xIdentifier->getContentIdentifier() );
1075 uno::Sequence< uno::Any > HierarchyContent::setPropertyValues(
1076 const uno::Sequence< beans::PropertyValue >& rValues,
1077 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1078 throw( uno::Exception )
1080 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1082 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1083 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1084 sal_Int32 nChanged = 0;
1086 beans::PropertyChangeEvent aEvent;
1087 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1088 aEvent.Further = sal_False;
1089 // aEvent.PropertyName =
1090 aEvent.PropertyHandle = -1;
1091 // aEvent.OldValue =
1092 // aEvent.NewValue =
1094 const beans::PropertyValue* pValues = rValues.getConstArray();
1095 sal_Int32 nCount = rValues.getLength();
1097 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1098 bool bTriedToGetAdditionalPropSet = false;
1100 bool bExchange = false;
1101 OUString aOldTitle;
1102 OUString aOldName;
1103 sal_Int32 nTitlePos = -1;
1105 for ( sal_Int32 n = 0; n < nCount; ++n )
1107 const beans::PropertyValue& rValue = pValues[ n ];
1109 if ( rValue.Name == "ContentType" )
1111 // Read-only property!
1112 aRet[ n ] <<= lang::IllegalAccessException(
1113 OUString( "Property is read-only!" ),
1114 static_cast< cppu::OWeakObject * >( this ) );
1116 else if ( rValue.Name == "IsDocument" )
1118 // Read-only property!
1119 aRet[ n ] <<= lang::IllegalAccessException(
1120 OUString( "Property is read-only!" ),
1121 static_cast< cppu::OWeakObject * >( this ) );
1123 else if ( rValue.Name == "IsFolder" )
1125 // Read-only property!
1126 aRet[ n ] <<= lang::IllegalAccessException(
1127 OUString( "Property is read-only!" ),
1128 static_cast< cppu::OWeakObject * >( this ) );
1130 else if ( rValue.Name == "CreatableContentsInfo" )
1132 // Read-only property!
1133 aRet[ n ] <<= lang::IllegalAccessException(
1134 OUString( "Property is read-only!" ),
1135 static_cast< cppu::OWeakObject * >( this ) );
1137 else if ( rValue.Name == "Title" )
1139 if ( isReadOnly() )
1141 aRet[ n ] <<= lang::IllegalAccessException(
1142 OUString( "Property is read-only!" ),
1143 static_cast< cppu::OWeakObject * >( this ) );
1145 else
1147 OUString aNewValue;
1148 if ( rValue.Value >>= aNewValue )
1150 // No empty titles!
1151 if ( !aNewValue.isEmpty() )
1153 if ( aNewValue != m_aProps.getTitle() )
1155 // modified title -> modified URL -> exchange !
1156 if ( m_eState == PERSISTENT )
1157 bExchange = true;
1159 aOldTitle = m_aProps.getTitle();
1160 aOldName = m_aProps.getName();
1162 m_aProps.setTitle( aNewValue );
1163 m_aProps.setName(
1164 ::ucb_impl::urihelper::encodeSegment(
1165 aNewValue ) );
1167 // property change event will be set later...
1169 // remember position within sequence of values
1170 // (for error handling).
1171 nTitlePos = n;
1174 else
1176 aRet[ n ] <<= lang::IllegalArgumentException(
1177 OUString( "Empty title not allowed!" ),
1178 static_cast< cppu::OWeakObject * >( this ),
1179 -1 );
1182 else
1184 aRet[ n ] <<= beans::IllegalTypeException(
1185 OUString( "Property value has wrong type!" ),
1186 static_cast< cppu::OWeakObject * >( this ) );
1190 else if ( rValue.Name == "TargetURL" )
1192 if ( isReadOnly() )
1194 aRet[ n ] <<= lang::IllegalAccessException(
1195 OUString( "Property is read-only!" ),
1196 static_cast< cppu::OWeakObject * >( this ) );
1198 else
1200 // TargetURL is only supported by links.
1202 if ( m_eKind == LINK )
1204 OUString aNewValue;
1205 if ( rValue.Value >>= aNewValue )
1207 // No empty target URL's!
1208 if ( !aNewValue.isEmpty() )
1210 if ( aNewValue != m_aProps.getTargetURL() )
1212 aEvent.PropertyName = rValue.Name;
1213 aEvent.OldValue
1214 = uno::makeAny( m_aProps.getTargetURL() );
1215 aEvent.NewValue
1216 = uno::makeAny( aNewValue );
1218 aChanges.getArray()[ nChanged ] = aEvent;
1220 m_aProps.setTargetURL( aNewValue );
1221 nChanged++;
1224 else
1226 aRet[ n ] <<= lang::IllegalArgumentException(
1227 OUString( "Empty target URL not allowed!" ),
1228 static_cast< cppu::OWeakObject * >( this ),
1229 -1 );
1232 else
1234 aRet[ n ] <<= beans::IllegalTypeException(
1235 OUString( "Property value has wrong type!" ),
1236 static_cast< cppu::OWeakObject * >( this ) );
1239 else
1241 aRet[ n ] <<= beans::UnknownPropertyException(
1242 OUString( "TargetURL only supported by links!" ),
1243 static_cast< cppu::OWeakObject * >( this ) );
1247 else
1249 // Not a Core Property! Maybe it's an Additional Core Property?!
1251 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1253 xAdditionalPropSet = getAdditionalPropertySet( false );
1254 bTriedToGetAdditionalPropSet = true;
1257 if ( xAdditionalPropSet.is() )
1261 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1262 rValue.Name );
1263 if ( aOldValue != rValue.Value )
1265 xAdditionalPropSet->setPropertyValue(
1266 rValue.Name, rValue.Value );
1268 aEvent.PropertyName = rValue.Name;
1269 aEvent.OldValue = aOldValue;
1270 aEvent.NewValue = rValue.Value;
1272 aChanges.getArray()[ nChanged ] = aEvent;
1273 nChanged++;
1276 catch ( beans::UnknownPropertyException const & e )
1278 aRet[ n ] <<= e;
1280 catch ( lang::WrappedTargetException const & e )
1282 aRet[ n ] <<= e;
1284 catch ( beans::PropertyVetoException const & e )
1286 aRet[ n ] <<= e;
1288 catch ( lang::IllegalArgumentException const & e )
1290 aRet[ n ] <<= e;
1293 else
1295 aRet[ n ] <<= uno::Exception(
1296 OUString( "No property set for storing the value!" ),
1297 static_cast< cppu::OWeakObject * >( this ) );
1302 if ( bExchange )
1304 uno::Reference< ucb::XContentIdentifier > xOldId
1305 = m_xIdentifier;
1306 uno::Reference< ucb::XContentIdentifier > xNewId
1307 = makeNewIdentifier( m_aProps.getTitle() );
1309 aGuard.clear();
1310 if ( exchangeIdentity( xNewId ) )
1312 // Adapt persistent data.
1313 renameData( xOldId, xNewId );
1315 // Adapt Additional Core Properties.
1316 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1317 xNewId->getContentIdentifier(),
1318 true );
1320 else
1322 // Roll-back.
1323 m_aProps.setTitle( aOldTitle );
1324 m_aProps.setName ( aOldName );
1326 aOldTitle.clear();
1327 aOldName.clear();
1329 // Set error .
1330 aRet[ nTitlePos ] <<= uno::Exception(
1331 OUString("Exchange failed!"),
1332 static_cast< cppu::OWeakObject * >( this ) );
1336 if ( !aOldTitle.isEmpty() )
1338 aEvent.PropertyName = "Title";
1339 aEvent.OldValue = uno::makeAny( aOldTitle );
1340 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() );
1342 aChanges.getArray()[ nChanged ] = aEvent;
1343 nChanged++;
1346 if ( nChanged > 0 )
1348 // Save changes, if content was already made persistent.
1349 if ( !bExchange && ( m_eState == PERSISTENT ) )
1351 if ( !storeData() )
1353 uno::Any aProps
1354 = uno::makeAny(
1355 beans::PropertyValue(
1356 OUString( "Uri"),
1358 uno::makeAny(m_xIdentifier->
1359 getContentIdentifier()),
1360 beans::PropertyState_DIRECT_VALUE));
1361 ucbhelper::cancelCommandExecution(
1362 ucb::IOErrorCode_CANT_WRITE,
1363 uno::Sequence< uno::Any >(&aProps, 1),
1364 xEnv,
1365 OUString( "Cannot store persistent data!" ),
1366 this );
1367 // Unreachable
1371 aChanges.realloc( nChanged );
1373 aGuard.clear();
1374 notifyPropertiesChange( aChanges );
1377 return aRet;
1381 void HierarchyContent::insert( sal_Int32 nNameClashResolve,
1382 const uno::Reference<
1383 ucb::XCommandEnvironment > & xEnv )
1384 throw( uno::Exception )
1386 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1388 // Am I the root folder?
1389 if ( m_eKind == ROOT )
1391 ucbhelper::cancelCommandExecution(
1392 uno::makeAny( ucb::UnsupportedCommandException(
1393 OUString( "Not supported by root folder!" ),
1394 static_cast< cppu::OWeakObject * >( this ) ) ),
1395 xEnv );
1396 // Unreachable
1399 // Check, if all required properties were set.
1400 if ( m_aProps.getTitle().isEmpty() )
1402 uno::Sequence< OUString > aProps( 1 );
1403 aProps[ 0 ] = "Title";
1404 ucbhelper::cancelCommandExecution(
1405 uno::makeAny( ucb::MissingPropertiesException(
1406 OUString(),
1407 static_cast< cppu::OWeakObject * >( this ),
1408 aProps ) ),
1409 xEnv );
1410 // Unreachable
1413 // Assemble new content identifier...
1415 uno::Reference< ucb::XContentIdentifier > xId
1416 = makeNewIdentifier( m_aProps.getTitle() );
1418 // Handle possible name clash...
1420 switch ( nNameClashResolve )
1422 // fail.
1423 case ucb::NameClash::ERROR:
1424 if ( hasData( xId ) )
1426 ucbhelper::cancelCommandExecution(
1427 uno::makeAny(
1428 ucb::NameClashException(
1429 OUString(),
1430 static_cast< cppu::OWeakObject * >( this ),
1431 task::InteractionClassification_ERROR,
1432 m_aProps.getTitle() ) ),
1433 xEnv );
1434 // Unreachable
1436 break;
1438 // replace existing object.
1439 case ucb::NameClash::OVERWRITE:
1440 break;
1442 // "invent" a new valid title.
1443 case ucb::NameClash::RENAME:
1444 if ( hasData( xId ) )
1446 sal_Int32 nTry = 0;
1450 OUString aNewId = xId->getContentIdentifier();
1451 aNewId += "_";
1452 aNewId += OUString::number( ++nTry );
1453 xId = new ::ucbhelper::ContentIdentifier( aNewId );
1455 while ( hasData( xId ) && ( nTry < 1000 ) );
1457 if ( nTry == 1000 )
1459 ucbhelper::cancelCommandExecution(
1460 uno::makeAny(
1461 ucb::UnsupportedNameClashException(
1462 OUString( "Unable to resolve name clash!" ),
1463 static_cast< cppu::OWeakObject * >( this ),
1464 nNameClashResolve ) ),
1465 xEnv );
1466 // Unreachable
1468 else
1470 OUString aNewTitle( m_aProps.getTitle() );
1471 aNewTitle += "_";
1472 aNewTitle += OUString::number( nTry );
1473 m_aProps.setTitle( aNewTitle );
1476 break;
1478 case ucb::NameClash::KEEP: // deprecated
1479 case ucb::NameClash::ASK:
1480 default:
1481 if ( hasData( xId ) )
1483 ucbhelper::cancelCommandExecution(
1484 uno::makeAny(
1485 ucb::UnsupportedNameClashException(
1486 OUString(),
1487 static_cast< cppu::OWeakObject * >( this ),
1488 nNameClashResolve ) ),
1489 xEnv );
1490 // Unreachable
1492 break;
1495 // Identifier changed?
1496 bool bNewId = ( xId->getContentIdentifier()
1497 != m_xIdentifier->getContentIdentifier() );
1498 m_xIdentifier = xId;
1500 if ( !storeData() )
1502 uno::Any aProps
1503 = uno::makeAny(beans::PropertyValue(
1504 OUString( "Uri"),
1506 uno::makeAny(m_xIdentifier->
1507 getContentIdentifier()),
1508 beans::PropertyState_DIRECT_VALUE));
1509 ucbhelper::cancelCommandExecution(
1510 ucb::IOErrorCode_CANT_WRITE,
1511 uno::Sequence< uno::Any >(&aProps, 1),
1512 xEnv,
1513 OUString("Cannot store persistent data!"),
1514 this );
1515 // Unreachable
1518 m_eState = PERSISTENT;
1520 if ( bNewId )
1522 aGuard.clear();
1523 inserted();
1528 void HierarchyContent::destroy( bool bDeletePhysical,
1529 const uno::Reference<
1530 ucb::XCommandEnvironment > & xEnv )
1531 throw( uno::Exception )
1533 // @@@ take care about bDeletePhysical -> trashcan support
1535 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1537 uno::Reference< ucb::XContent > xThis = this;
1539 // Persistent?
1540 if ( m_eState != PERSISTENT )
1542 ucbhelper::cancelCommandExecution(
1543 uno::makeAny( ucb::UnsupportedCommandException(
1544 OUString( "Not persistent!" ),
1545 static_cast< cppu::OWeakObject * >( this ) ) ),
1546 xEnv );
1547 // Unreachable
1550 // Am I the root folder?
1551 if ( m_eKind == ROOT )
1553 ucbhelper::cancelCommandExecution(
1554 uno::makeAny( ucb::UnsupportedCommandException(
1555 OUString( "Not supported by root folder!" ),
1556 static_cast< cppu::OWeakObject * >( this ) ) ),
1557 xEnv );
1558 // Unreachable
1561 m_eState = DEAD;
1563 aGuard.clear();
1564 deleted();
1566 if ( m_eKind == FOLDER )
1568 // Process instantiated children...
1570 HierarchyContentRefList aChildren;
1571 queryChildren( aChildren );
1573 HierarchyContentRefList::const_iterator it = aChildren.begin();
1574 HierarchyContentRefList::const_iterator end = aChildren.end();
1576 while ( it != end )
1578 (*it)->destroy( bDeletePhysical, xEnv );
1579 ++it;
1585 void HierarchyContent::transfer(
1586 const ucb::TransferInfo& rInfo,
1587 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1588 throw( uno::Exception )
1590 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1592 // Persistent?
1593 if ( m_eState != PERSISTENT )
1595 ucbhelper::cancelCommandExecution(
1596 uno::makeAny( ucb::UnsupportedCommandException(
1597 OUString( "Not persistent!" ),
1598 static_cast< cppu::OWeakObject * >( this ) ) ),
1599 xEnv );
1600 // Unreachable
1603 // Is source a hierarchy content?
1604 if ( !rInfo.SourceURL.startsWith( HIERARCHY_URL_SCHEME ":/" ) )
1606 ucbhelper::cancelCommandExecution(
1607 uno::makeAny( ucb::InteractiveBadTransferURLException(
1608 OUString(),
1609 static_cast< cppu::OWeakObject * >( this ) ) ),
1610 xEnv );
1611 // Unreachable
1614 // Is source not a parent of me / not me?
1615 OUString aId = m_xIdentifier->getContentIdentifier();
1616 sal_Int32 nPos = aId.lastIndexOf( '/' );
1617 if ( nPos != ( aId.getLength() - 1 ) )
1619 // No trailing slash found. Append.
1620 aId += "/";
1623 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1625 if ( aId.startsWith( rInfo.SourceURL ) )
1627 uno::Any aProps
1628 = uno::makeAny(beans::PropertyValue(
1629 OUString( "Uri"),
1631 uno::makeAny(rInfo.SourceURL),
1632 beans::PropertyState_DIRECT_VALUE));
1633 ucbhelper::cancelCommandExecution(
1634 ucb::IOErrorCode_RECURSIVE,
1635 uno::Sequence< uno::Any >(&aProps, 1),
1636 xEnv,
1637 OUString( "Target is equal to or is a child of source!" ),
1638 this );
1639 // Unreachable
1644 // 0) Obtain content object for source.
1647 uno::Reference< ucb::XContentIdentifier > xId
1648 = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
1650 // Note: The static cast is okay here, because its sure that
1651 // m_xProvider is always the HierarchyContentProvider.
1652 rtl::Reference< HierarchyContent > xSource;
1656 xSource = static_cast< HierarchyContent * >(
1657 m_xProvider->queryContent( xId ).get() );
1659 catch ( ucb::IllegalIdentifierException const & )
1661 // queryContent
1664 if ( !xSource.is() )
1666 uno::Any aProps
1667 = uno::makeAny(beans::PropertyValue(
1668 OUString( "Uri"),
1670 uno::makeAny(xId->getContentIdentifier()),
1671 beans::PropertyState_DIRECT_VALUE));
1672 ucbhelper::cancelCommandExecution(
1673 ucb::IOErrorCode_CANT_READ,
1674 uno::Sequence< uno::Any >(&aProps, 1),
1675 xEnv,
1676 OUString( "Cannot instanciate source object!" ),
1677 this );
1678 // Unreachable
1682 // 1) Create new child content.
1685 OUString aType = xSource->isFolder()
1686 ? OUString( HIERARCHY_FOLDER_CONTENT_TYPE )
1687 : OUString( HIERARCHY_LINK_CONTENT_TYPE );
1688 ucb::ContentInfo aContentInfo;
1689 aContentInfo.Type = aType;
1690 aContentInfo.Attributes = 0;
1692 // Note: The static cast is okay here, because its sure that
1693 // createNewContent always creates a HierarchyContent.
1694 rtl::Reference< HierarchyContent > xTarget
1695 = static_cast< HierarchyContent * >(
1696 createNewContent( aContentInfo ).get() );
1697 if ( !xTarget.is() )
1699 uno::Any aProps
1700 = uno::makeAny(beans::PropertyValue(
1701 OUString( "Folder"),
1703 uno::makeAny(aId),
1704 beans::PropertyState_DIRECT_VALUE));
1705 ucbhelper::cancelCommandExecution(
1706 ucb::IOErrorCode_CANT_CREATE,
1707 uno::Sequence< uno::Any >(&aProps, 1),
1708 xEnv,
1709 OUString( "XContentCreator::createNewContent failed!" ),
1710 this );
1711 // Unreachable
1715 // 2) Copy data from source content to child content.
1718 uno::Sequence< beans::Property > aSourceProps
1719 = xSource->getPropertySetInfo( xEnv )->getProperties();
1720 sal_Int32 nCount = aSourceProps.getLength();
1722 if ( nCount )
1724 bool bHadTitle = rInfo.NewTitle.isEmpty();
1726 // Get all source values.
1727 uno::Reference< sdbc::XRow > xRow
1728 = xSource->getPropertyValues( aSourceProps );
1730 uno::Sequence< beans::PropertyValue > aValues( nCount );
1731 beans::PropertyValue* pValues = aValues.getArray();
1733 const beans::Property* pProps = aSourceProps.getConstArray();
1734 for ( sal_Int32 n = 0; n < nCount; ++n )
1736 const beans::Property& rProp = pProps[ n ];
1737 beans::PropertyValue& rValue = pValues[ n ];
1739 rValue.Name = rProp.Name;
1740 rValue.Handle = rProp.Handle;
1742 if ( !bHadTitle && rProp.Name == "Title" )
1744 // Set new title instead of original.
1745 bHadTitle = true;
1746 rValue.Value <<= rInfo.NewTitle;
1748 else
1749 rValue.Value = xRow->getObject(
1750 n + 1,
1751 uno::Reference< container::XNameAccess >() );
1753 rValue.State = beans::PropertyState_DIRECT_VALUE;
1755 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1757 // Add Additional Core Property.
1760 xTarget->addProperty( rProp.Name,
1761 rProp.Attributes,
1762 rValue.Value );
1764 catch ( beans::PropertyExistException const & )
1767 catch ( beans::IllegalTypeException const & )
1770 catch ( lang::IllegalArgumentException const & )
1776 // Set target values.
1777 xTarget->setPropertyValues( aValues, xEnv );
1781 // 3) Commit (insert) child.
1784 xTarget->insert( rInfo.NameClash, xEnv );
1787 // 4) Transfer (copy) children of source.
1790 if ( xSource->isFolder() )
1792 HierarchyEntry aFolder(
1793 m_xContext, m_pProvider, xId->getContentIdentifier() );
1794 HierarchyEntry::iterator it;
1796 while ( aFolder.next( it ) )
1798 const HierarchyEntryData& rResult = *it;
1800 OUString aChildId = xId->getContentIdentifier();
1801 if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() )
1802 aChildId += "/";
1804 aChildId += rResult.getName();
1806 ucb::TransferInfo aInfo;
1807 aInfo.MoveData = sal_False;
1808 aInfo.NewTitle.clear();
1809 aInfo.SourceURL = aChildId;
1810 aInfo.NameClash = rInfo.NameClash;
1812 // Transfer child to target.
1813 xTarget->transfer( aInfo, xEnv );
1818 // 5) Destroy source ( when moving only ) .
1821 if ( rInfo.MoveData )
1823 xSource->destroy( true, xEnv );
1825 // Remove all persistent data of source and its children.
1826 if ( !xSource->removeData() )
1828 uno::Any aProps
1829 = uno::makeAny(
1830 beans::PropertyValue(
1831 OUString( "Uri"),
1833 uno::makeAny(
1834 xSource->m_xIdentifier->
1835 getContentIdentifier()),
1836 beans::PropertyState_DIRECT_VALUE));
1837 ucbhelper::cancelCommandExecution(
1838 ucb::IOErrorCode_CANT_WRITE,
1839 uno::Sequence< uno::Any >(&aProps, 1),
1840 xEnv,
1841 OUString( "Cannot remove persistent data of source object!" ),
1842 this );
1843 // Unreachable
1846 // Remove own and all children's Additional Core Properties.
1847 xSource->removeAdditionalPropertySet( true );
1854 // HierarchyContentProperties Implementation.
1859 uno::Sequence< ucb::ContentInfo >
1860 HierarchyContentProperties::getCreatableContentsInfo() const
1862 if ( getIsFolder() )
1864 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
1866 // Folder.
1867 aSeq.getArray()[ 0 ].Type = HIERARCHY_FOLDER_CONTENT_TYPE;
1868 aSeq.getArray()[ 0 ].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
1870 uno::Sequence< beans::Property > aFolderProps( 1 );
1871 aFolderProps.getArray()[ 0 ] = beans::Property(
1872 OUString("Title"),
1874 cppu::UnoType<OUString>::get(),
1875 beans::PropertyAttribute::BOUND );
1876 aSeq.getArray()[ 0 ].Properties = aFolderProps;
1878 // Link.
1879 aSeq.getArray()[ 1 ].Type = HIERARCHY_LINK_CONTENT_TYPE;
1880 aSeq.getArray()[ 1 ].Attributes = ucb::ContentInfoAttribute::KIND_LINK;
1882 uno::Sequence< beans::Property > aLinkProps( 2 );
1883 aLinkProps.getArray()[ 0 ] = beans::Property(
1884 OUString("Title"),
1886 cppu::UnoType<OUString>::get(),
1887 beans::PropertyAttribute::BOUND );
1888 aLinkProps.getArray()[ 1 ] = beans::Property(
1889 OUString("TargetURL"),
1891 cppu::UnoType<OUString>::get(),
1892 beans::PropertyAttribute::BOUND );
1893 aSeq.getArray()[ 1 ].Properties = aLinkProps;
1895 return aSeq;
1897 else
1899 return uno::Sequence< ucb::ContentInfo >( 0 );
1903 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */