Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchycontent.cxx
blob3676019219fc8d5fd26ff4e850924617ab19b304
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;
76 //=========================================================================
77 //=========================================================================
79 // HierarchyContent Implementation.
81 //=========================================================================
82 //=========================================================================
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 );
98 //=========================================================================
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 );
115 //=========================================================================
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 );
131 //=========================================================================
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 );
147 //=========================================================================
148 // virtual
149 HierarchyContent::~HierarchyContent()
153 //=========================================================================
155 // XInterface methods.
157 //=========================================================================
159 // virtual
160 void SAL_CALL HierarchyContent::acquire()
161 throw( )
163 ContentImplHelper::acquire();
166 //=========================================================================
167 // virtual
168 void SAL_CALL HierarchyContent::release()
169 throw( )
171 ContentImplHelper::release();
174 //=========================================================================
175 // virtual
176 uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType )
177 throw ( uno::RuntimeException )
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;
197 //=========================================================================
199 // XTypeProvider methods.
201 //=========================================================================
203 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent );
205 //=========================================================================
206 // virtual
207 uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes()
208 throw( uno::RuntimeException )
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();
281 //=========================================================================
283 // XServiceInfo methods.
285 //=========================================================================
287 // virtual
288 rtl::OUString SAL_CALL HierarchyContent::getImplementationName()
289 throw( uno::RuntimeException )
291 return rtl::OUString( "com.sun.star.comp.ucb.HierarchyContent" );
294 //=========================================================================
295 // virtual
296 uno::Sequence< rtl::OUString > SAL_CALL
297 HierarchyContent::getSupportedServiceNames()
298 throw( uno::RuntimeException )
300 uno::Sequence< rtl::OUString > aSNS( 1 );
302 if ( m_eKind == LINK )
303 aSNS.getArray()[ 0 ] = rtl::OUString( HIERARCHY_LINK_CONTENT_SERVICE_NAME );
304 else if ( m_eKind == FOLDER )
305 aSNS.getArray()[ 0 ] = rtl::OUString( HIERARCHY_FOLDER_CONTENT_SERVICE_NAME );
306 else
307 aSNS.getArray()[ 0 ] = rtl::OUString( HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME );
309 return aSNS;
312 //=========================================================================
314 // XContent methods.
316 //=========================================================================
318 // virtual
319 rtl::OUString SAL_CALL HierarchyContent::getContentType()
320 throw( uno::RuntimeException )
322 return m_aProps.getContentType();
325 //=========================================================================
326 // virtual
327 uno::Reference< ucb::XContentIdentifier > SAL_CALL
328 HierarchyContent::getIdentifier()
329 throw( uno::RuntimeException )
331 // Transient?
332 if ( m_eState == TRANSIENT )
334 // Transient contents have no identifier.
335 return uno::Reference< ucb::XContentIdentifier >();
338 return ContentImplHelper::getIdentifier();
341 //=========================================================================
343 // XCommandProcessor methods.
345 //=========================================================================
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 )
356 uno::Any aRet;
358 if ( aCommand.Name == "getPropertyValues" )
360 //////////////////////////////////////////////////////////////////
361 // getPropertyValues
362 //////////////////////////////////////////////////////////////////
364 uno::Sequence< beans::Property > Properties;
365 if ( !( aCommand.Argument >>= Properties ) )
367 ucbhelper::cancelCommandExecution(
368 uno::makeAny( lang::IllegalArgumentException(
369 rtl::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" )
380 //////////////////////////////////////////////////////////////////
381 // setPropertyValues
382 //////////////////////////////////////////////////////////////////
384 uno::Sequence< beans::PropertyValue > aProperties;
385 if ( !( aCommand.Argument >>= aProperties ) )
387 ucbhelper::cancelCommandExecution(
388 uno::makeAny( lang::IllegalArgumentException(
389 rtl::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 rtl::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" )
411 //////////////////////////////////////////////////////////////////
412 // getPropertySetInfo
413 //////////////////////////////////////////////////////////////////
415 aRet <<= getPropertySetInfo( Environment );
417 else if ( aCommand.Name == "getCommandInfo" )
419 //////////////////////////////////////////////////////////////////
420 // getCommandInfo
421 //////////////////////////////////////////////////////////////////
423 aRet <<= getCommandInfo( Environment );
425 else if ( aCommand.Name == "open" && isFolder() )
427 //////////////////////////////////////////////////////////////////
428 // open command for a folder content
429 //////////////////////////////////////////////////////////////////
431 ucb::OpenCommandArgument2 aOpenCommand;
432 if ( !( aCommand.Argument >>= aOpenCommand ) )
434 ucbhelper::cancelCommandExecution(
435 uno::makeAny( lang::IllegalArgumentException(
436 rtl::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() )
449 //////////////////////////////////////////////////////////////////
450 // insert
451 // ( Not available at root folder )
452 //////////////////////////////////////////////////////////////////
454 ucb::InsertCommandArgument aArg;
455 if ( !( aCommand.Argument >>= aArg ) )
457 ucbhelper::cancelCommandExecution(
458 uno::makeAny( lang::IllegalArgumentException(
459 rtl::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() )
473 //////////////////////////////////////////////////////////////////
474 // delete
475 // ( Not available at root folder )
476 //////////////////////////////////////////////////////////////////
478 sal_Bool bDeletePhysical = sal_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 rtl::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 rtl::OUString( "Cannot remove persistent data!" ),
498 this );
499 // Unreachable
502 // Remove own and all children's Additional Core Properties.
503 removeAdditionalPropertySet( sal_True );
505 else if ( aCommand.Name == "transfer" && isFolder() && !isReadOnly() )
507 //////////////////////////////////////////////////////////////////
508 // transfer
509 // ( Not available at link objects )
510 //////////////////////////////////////////////////////////////////
512 ucb::TransferInfo aInfo;
513 if ( !( aCommand.Argument >>= aInfo ) )
515 OSL_FAIL( "Wrong argument type!" );
516 ucbhelper::cancelCommandExecution(
517 uno::makeAny( lang::IllegalArgumentException(
518 rtl::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() )
529 //////////////////////////////////////////////////////////////////
530 // createNewContent
531 // ( Not available at link objects )
532 //////////////////////////////////////////////////////////////////
534 ucb::ContentInfo aInfo;
535 if ( !( aCommand.Argument >>= aInfo ) )
537 OSL_FAIL( "Wrong argument type!" );
538 ucbhelper::cancelCommandExecution(
539 uno::makeAny( lang::IllegalArgumentException(
540 rtl::OUString( "Wrong argument type!" ),
541 static_cast< cppu::OWeakObject * >( this ),
542 -1 ) ),
543 Environment );
544 // Unreachable
547 aRet <<= createNewContent( aInfo );
549 else
551 //////////////////////////////////////////////////////////////////
552 // Unsupported command
553 //////////////////////////////////////////////////////////////////
555 ucbhelper::cancelCommandExecution(
556 uno::makeAny( ucb::UnsupportedCommandException(
557 rtl::OUString(),
558 static_cast< cppu::OWeakObject * >( this ) ) ),
559 Environment );
560 // Unreachable
563 return aRet;
566 //=========================================================================
567 // virtual
568 void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ )
569 throw( uno::RuntimeException )
571 // @@@ Generally, no action takes much time...
574 //=========================================================================
576 // XContentCreator methods.
578 //=========================================================================
580 // virtual
581 uno::Sequence< ucb::ContentInfo > SAL_CALL
582 HierarchyContent::queryCreatableContentsInfo()
583 throw( uno::RuntimeException )
585 return m_aProps.getCreatableContentsInfo();
588 //=========================================================================
589 // virtual
590 uno::Reference< ucb::XContent > SAL_CALL
591 HierarchyContent::createNewContent( const ucb::ContentInfo& Info )
592 throw( uno::RuntimeException )
594 if ( isFolder() )
596 osl::Guard< osl::Mutex > aGuard( m_aMutex );
598 if ( Info.Type.isEmpty() )
599 return uno::Reference< ucb::XContent >();
601 sal_Bool bCreateFolder = Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE;
603 if ( !bCreateFolder && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
604 return uno::Reference< ucb::XContent >();
606 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
608 OSL_ENSURE( !aURL.isEmpty(),
609 "HierarchyContent::createNewContent - empty identifier!" );
611 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
612 aURL += rtl::OUString("/");
614 if ( bCreateFolder )
615 aURL += rtl::OUString("New_Folder");
616 else
617 aURL += rtl::OUString("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 >();
631 //=========================================================================
632 // virtual
633 rtl::OUString HierarchyContent::getParentURL()
635 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
636 return aUri.getParentUri();
639 //=========================================================================
640 //static
641 sal_Bool HierarchyContent::hasData(
642 const uno::Reference< uno::XComponentContext >& rxContext,
643 HierarchyContentProvider* pProvider,
644 const uno::Reference< ucb::XContentIdentifier >& Identifier )
646 rtl::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 sal_True;
657 return HierarchyEntry( rxContext, pProvider, aURL ).hasData();
660 //=========================================================================
661 //static
662 sal_Bool HierarchyContent::loadData(
663 const uno::Reference< uno::XComponentContext >& rxContext,
664 HierarchyContentProvider* pProvider,
665 const uno::Reference< ucb::XContentIdentifier >& Identifier,
666 HierarchyContentProperties& rProps )
668 rtl::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 sal_False;
683 rProps = HierarchyContentProperties( aData );
685 return sal_True;
688 //=========================================================================
689 sal_Bool HierarchyContent::storeData()
691 HierarchyEntry aEntry(
692 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
693 return aEntry.setData( m_aProps.getHierarchyEntryData(), sal_True );
696 //=========================================================================
697 sal_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() );
707 //=========================================================================
708 sal_Bool HierarchyContent::removeData()
710 HierarchyEntry aEntry(
711 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
712 return aEntry.remove();
715 //=========================================================================
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;
732 //=========================================================================
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< rtl::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;
766 //=========================================================================
767 uno::Reference< ucb::XContentIdentifier >
768 HierarchyContent::makeNewIdentifier( const rtl::OUString& rTitle )
770 osl::Guard< osl::Mutex > aGuard( m_aMutex );
772 // Assemble new content identifier...
773 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
774 rtl::OUString aNewURL = aUri.getParentUri();
775 aNewURL += rtl::OUString("/");
776 aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle );
778 return uno::Reference< ucb::XContentIdentifier >(
779 new ::ucbhelper::ContentIdentifier( aNewURL ) );
782 //=========================================================================
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 instanciated 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 rtl::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 += rtl::OUString("/");
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 rtl::OUString aChildURL
813 = xChild->getIdentifier()->getContentIdentifier();
815 // Is aURL a prefix of aChildURL?
816 if ( ( aChildURL.getLength() > nLen ) &&
817 ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
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;
835 //=========================================================================
836 sal_Bool HierarchyContent::exchangeIdentity(
837 const uno::Reference< ucb::XContentIdentifier >& xNewId )
839 if ( !xNewId.is() )
840 return sal_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 sal_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 sal_False;
861 // Exchange own identitity.
863 // Fail, if a content with given id already exists.
864 if ( !hasData( xNewId ) )
866 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
868 aGuard.clear();
869 if ( exchange( xNewId ) )
871 if ( m_eKind == FOLDER )
873 // Process instanciated 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 rtl::OUString aOldChildURL
889 = xOldChildId->getContentIdentifier();
890 rtl::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 sal_False;
901 ++it;
904 return sal_True;
908 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
909 "Panic! Cannot exchange identity!" );
910 return sal_False;
913 //=========================================================================
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 rtl::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 sal_Bool bTriedToGetAdditonalPropSet = sal_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 ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
976 xAdditionalPropSet
977 = uno::Reference< beans::XPropertySet >(
978 pProvider->getAdditionalPropertySet( rContentId,
979 sal_False ),
980 uno::UNO_QUERY );
981 bTriedToGetAdditonalPropSet = sal_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( rtl::OUString("ContentType"),
1008 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1009 beans::PropertyAttribute::BOUND
1010 | beans::PropertyAttribute::READONLY ),
1011 rData.getContentType() );
1012 xRow->appendString (
1013 beans::Property( rtl::OUString("Title"),
1015 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1016 // @@@ Might actually be read-only!
1017 beans::PropertyAttribute::BOUND ),
1018 rData.getTitle() );
1019 xRow->appendBoolean(
1020 beans::Property( rtl::OUString("IsDocument"),
1022 getCppuBooleanType(),
1023 beans::PropertyAttribute::BOUND
1024 | beans::PropertyAttribute::READONLY ),
1025 rData.getIsDocument() );
1026 xRow->appendBoolean(
1027 beans::Property( rtl::OUString("IsFolder"),
1029 getCppuBooleanType(),
1030 beans::PropertyAttribute::BOUND
1031 | beans::PropertyAttribute::READONLY ),
1032 rData.getIsFolder() );
1034 if ( rData.getIsDocument() )
1035 xRow->appendString(
1036 beans::Property( rtl::OUString("TargetURL"),
1038 getCppuType(
1039 static_cast< const rtl::OUString * >( 0 ) ),
1040 // @@@ Might actually be read-only!
1041 beans::PropertyAttribute::BOUND ),
1042 rData.getTargetURL() );
1043 xRow->appendObject(
1044 beans::Property(
1045 rtl::OUString("CreatableContentsInfo"),
1047 getCppuType( static_cast<
1048 const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
1049 beans::PropertyAttribute::BOUND
1050 | beans::PropertyAttribute::READONLY ),
1051 uno::makeAny( rData.getCreatableContentsInfo() ) );
1053 // Append all Additional Core Properties.
1055 uno::Reference< beans::XPropertySet > xSet(
1056 pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1057 uno::UNO_QUERY );
1058 xRow->appendPropertySet( xSet );
1061 return uno::Reference< sdbc::XRow >( xRow.get() );
1064 //=========================================================================
1065 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
1066 const uno::Sequence< beans::Property >& rProperties )
1068 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1069 return getPropertyValues( m_xContext,
1070 rProperties,
1071 m_aProps,
1072 m_pProvider,
1073 m_xIdentifier->getContentIdentifier() );
1076 //=========================================================================
1077 uno::Sequence< uno::Any > HierarchyContent::setPropertyValues(
1078 const uno::Sequence< beans::PropertyValue >& rValues,
1079 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1080 throw( uno::Exception )
1082 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1084 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1085 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1086 sal_Int32 nChanged = 0;
1088 beans::PropertyChangeEvent aEvent;
1089 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1090 aEvent.Further = sal_False;
1091 // aEvent.PropertyName =
1092 aEvent.PropertyHandle = -1;
1093 // aEvent.OldValue =
1094 // aEvent.NewValue =
1096 const beans::PropertyValue* pValues = rValues.getConstArray();
1097 sal_Int32 nCount = rValues.getLength();
1099 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1100 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1102 sal_Bool bExchange = sal_False;
1103 rtl::OUString aOldTitle;
1104 rtl::OUString aOldName;
1105 sal_Int32 nTitlePos = -1;
1107 for ( sal_Int32 n = 0; n < nCount; ++n )
1109 const beans::PropertyValue& rValue = pValues[ n ];
1111 if ( rValue.Name == "ContentType" )
1113 // Read-only property!
1114 aRet[ n ] <<= lang::IllegalAccessException(
1115 rtl::OUString( "Property is read-only!" ),
1116 static_cast< cppu::OWeakObject * >( this ) );
1118 else if ( rValue.Name == "IsDocument" )
1120 // Read-only property!
1121 aRet[ n ] <<= lang::IllegalAccessException(
1122 rtl::OUString( "Property is read-only!" ),
1123 static_cast< cppu::OWeakObject * >( this ) );
1125 else if ( rValue.Name == "IsFolder" )
1127 // Read-only property!
1128 aRet[ n ] <<= lang::IllegalAccessException(
1129 rtl::OUString( "Property is read-only!" ),
1130 static_cast< cppu::OWeakObject * >( this ) );
1132 else if ( rValue.Name == "CreatableContentsInfo" )
1134 // Read-only property!
1135 aRet[ n ] <<= lang::IllegalAccessException(
1136 rtl::OUString( "Property is read-only!" ),
1137 static_cast< cppu::OWeakObject * >( this ) );
1139 else if ( rValue.Name == "Title" )
1141 if ( isReadOnly() )
1143 aRet[ n ] <<= lang::IllegalAccessException(
1144 rtl::OUString( "Property is read-only!" ),
1145 static_cast< cppu::OWeakObject * >( this ) );
1147 else
1149 rtl::OUString aNewValue;
1150 if ( rValue.Value >>= aNewValue )
1152 // No empty titles!
1153 if ( !aNewValue.isEmpty() )
1155 if ( aNewValue != m_aProps.getTitle() )
1157 // modified title -> modified URL -> exchange !
1158 if ( m_eState == PERSISTENT )
1159 bExchange = sal_True;
1161 aOldTitle = m_aProps.getTitle();
1162 aOldName = m_aProps.getName();
1164 m_aProps.setTitle( aNewValue );
1165 m_aProps.setName(
1166 ::ucb_impl::urihelper::encodeSegment(
1167 aNewValue ) );
1169 // property change event will be set later...
1171 // remember position within sequence of values
1172 // (for error handling).
1173 nTitlePos = n;
1176 else
1178 aRet[ n ] <<= lang::IllegalArgumentException(
1179 rtl::OUString( "Empty title not allowed!" ),
1180 static_cast< cppu::OWeakObject * >( this ),
1181 -1 );
1184 else
1186 aRet[ n ] <<= beans::IllegalTypeException(
1187 rtl::OUString( "Property value has wrong type!" ),
1188 static_cast< cppu::OWeakObject * >( this ) );
1192 else if ( rValue.Name == "TargetURL" )
1194 if ( isReadOnly() )
1196 aRet[ n ] <<= lang::IllegalAccessException(
1197 rtl::OUString( "Property is read-only!" ),
1198 static_cast< cppu::OWeakObject * >( this ) );
1200 else
1202 // TargetURL is only supported by links.
1204 if ( m_eKind == LINK )
1206 rtl::OUString aNewValue;
1207 if ( rValue.Value >>= aNewValue )
1209 // No empty target URL's!
1210 if ( !aNewValue.isEmpty() )
1212 if ( aNewValue != m_aProps.getTargetURL() )
1214 aEvent.PropertyName = rValue.Name;
1215 aEvent.OldValue
1216 = uno::makeAny( m_aProps.getTargetURL() );
1217 aEvent.NewValue
1218 = uno::makeAny( aNewValue );
1220 aChanges.getArray()[ nChanged ] = aEvent;
1222 m_aProps.setTargetURL( aNewValue );
1223 nChanged++;
1226 else
1228 aRet[ n ] <<= lang::IllegalArgumentException(
1229 rtl::OUString( "Empty target URL not allowed!" ),
1230 static_cast< cppu::OWeakObject * >( this ),
1231 -1 );
1234 else
1236 aRet[ n ] <<= beans::IllegalTypeException(
1237 rtl::OUString( "Property value has wrong type!" ),
1238 static_cast< cppu::OWeakObject * >( this ) );
1241 else
1243 aRet[ n ] <<= beans::UnknownPropertyException(
1244 rtl::OUString( "TargetURL only supported by links!" ),
1245 static_cast< cppu::OWeakObject * >( this ) );
1249 else
1251 // Not a Core Property! Maybe it's an Additional Core Property?!
1253 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1255 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1256 bTriedToGetAdditonalPropSet = sal_True;
1259 if ( xAdditionalPropSet.is() )
1263 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1264 rValue.Name );
1265 if ( aOldValue != rValue.Value )
1267 xAdditionalPropSet->setPropertyValue(
1268 rValue.Name, rValue.Value );
1270 aEvent.PropertyName = rValue.Name;
1271 aEvent.OldValue = aOldValue;
1272 aEvent.NewValue = rValue.Value;
1274 aChanges.getArray()[ nChanged ] = aEvent;
1275 nChanged++;
1278 catch ( beans::UnknownPropertyException const & e )
1280 aRet[ n ] <<= e;
1282 catch ( lang::WrappedTargetException const & e )
1284 aRet[ n ] <<= e;
1286 catch ( beans::PropertyVetoException const & e )
1288 aRet[ n ] <<= e;
1290 catch ( lang::IllegalArgumentException const & e )
1292 aRet[ n ] <<= e;
1295 else
1297 aRet[ n ] <<= uno::Exception(
1298 rtl::OUString( "No property set for storing the value!" ),
1299 static_cast< cppu::OWeakObject * >( this ) );
1304 if ( bExchange )
1306 uno::Reference< ucb::XContentIdentifier > xOldId
1307 = m_xIdentifier;
1308 uno::Reference< ucb::XContentIdentifier > xNewId
1309 = makeNewIdentifier( m_aProps.getTitle() );
1311 aGuard.clear();
1312 if ( exchangeIdentity( xNewId ) )
1314 // Adapt persistent data.
1315 renameData( xOldId, xNewId );
1317 // Adapt Additional Core Properties.
1318 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1319 xNewId->getContentIdentifier(),
1320 sal_True );
1322 else
1324 // Roll-back.
1325 m_aProps.setTitle( aOldTitle );
1326 m_aProps.setName ( aOldName );
1328 aOldTitle = aOldName = rtl::OUString();
1330 // Set error .
1331 aRet[ nTitlePos ] <<= uno::Exception(
1332 rtl::OUString("Exchange failed!"),
1333 static_cast< cppu::OWeakObject * >( this ) );
1337 if ( !aOldTitle.isEmpty() )
1339 aEvent.PropertyName = rtl::OUString("Title");
1340 aEvent.OldValue = uno::makeAny( aOldTitle );
1341 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() );
1343 aChanges.getArray()[ nChanged ] = aEvent;
1344 nChanged++;
1347 if ( nChanged > 0 )
1349 // Save changes, if content was already made persistent.
1350 if ( !bExchange && ( m_eState == PERSISTENT ) )
1352 if ( !storeData() )
1354 uno::Any aProps
1355 = uno::makeAny(
1356 beans::PropertyValue(
1357 rtl::OUString( "Uri"),
1359 uno::makeAny(m_xIdentifier->
1360 getContentIdentifier()),
1361 beans::PropertyState_DIRECT_VALUE));
1362 ucbhelper::cancelCommandExecution(
1363 ucb::IOErrorCode_CANT_WRITE,
1364 uno::Sequence< uno::Any >(&aProps, 1),
1365 xEnv,
1366 rtl::OUString( "Cannot store persistent data!" ),
1367 this );
1368 // Unreachable
1372 aChanges.realloc( nChanged );
1374 aGuard.clear();
1375 notifyPropertiesChange( aChanges );
1378 return aRet;
1381 //=========================================================================
1382 void HierarchyContent::insert( sal_Int32 nNameClashResolve,
1383 const uno::Reference<
1384 ucb::XCommandEnvironment > & xEnv )
1385 throw( uno::Exception )
1387 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1389 // Am I the root folder?
1390 if ( m_eKind == ROOT )
1392 ucbhelper::cancelCommandExecution(
1393 uno::makeAny( ucb::UnsupportedCommandException(
1394 rtl::OUString( "Not supported by root folder!" ),
1395 static_cast< cppu::OWeakObject * >( this ) ) ),
1396 xEnv );
1397 // Unreachable
1400 // Check, if all required properties were set.
1401 if ( m_aProps.getTitle().isEmpty() )
1403 uno::Sequence< rtl::OUString > aProps( 1 );
1404 aProps[ 0 ] = rtl::OUString("Title");
1405 ucbhelper::cancelCommandExecution(
1406 uno::makeAny( ucb::MissingPropertiesException(
1407 rtl::OUString(),
1408 static_cast< cppu::OWeakObject * >( this ),
1409 aProps ) ),
1410 xEnv );
1411 // Unreachable
1414 // Assemble new content identifier...
1416 uno::Reference< ucb::XContentIdentifier > xId
1417 = makeNewIdentifier( m_aProps.getTitle() );
1419 // Handle possible name clash...
1421 switch ( nNameClashResolve )
1423 // fail.
1424 case ucb::NameClash::ERROR:
1425 if ( hasData( xId ) )
1427 ucbhelper::cancelCommandExecution(
1428 uno::makeAny(
1429 ucb::NameClashException(
1430 rtl::OUString(),
1431 static_cast< cppu::OWeakObject * >( this ),
1432 task::InteractionClassification_ERROR,
1433 m_aProps.getTitle() ) ),
1434 xEnv );
1435 // Unreachable
1437 break;
1439 // replace existing object.
1440 case ucb::NameClash::OVERWRITE:
1441 break;
1443 // "invent" a new valid title.
1444 case ucb::NameClash::RENAME:
1445 if ( hasData( xId ) )
1447 sal_Int32 nTry = 0;
1451 rtl::OUString aNewId = xId->getContentIdentifier();
1452 aNewId += rtl::OUString("_");
1453 aNewId += rtl::OUString::valueOf( ++nTry );
1454 xId = new ::ucbhelper::ContentIdentifier( aNewId );
1456 while ( hasData( xId ) && ( nTry < 1000 ) );
1458 if ( nTry == 1000 )
1460 ucbhelper::cancelCommandExecution(
1461 uno::makeAny(
1462 ucb::UnsupportedNameClashException(
1463 rtl::OUString( "Unable to resolve name clash!" ),
1464 static_cast< cppu::OWeakObject * >( this ),
1465 nNameClashResolve ) ),
1466 xEnv );
1467 // Unreachable
1469 else
1471 rtl::OUString aNewTitle( m_aProps.getTitle() );
1472 aNewTitle += rtl::OUString("_");
1473 aNewTitle += rtl::OUString::valueOf( nTry );
1474 m_aProps.setTitle( aNewTitle );
1477 break;
1479 case ucb::NameClash::KEEP: // deprecated
1480 case ucb::NameClash::ASK:
1481 default:
1482 if ( hasData( xId ) )
1484 ucbhelper::cancelCommandExecution(
1485 uno::makeAny(
1486 ucb::UnsupportedNameClashException(
1487 rtl::OUString(),
1488 static_cast< cppu::OWeakObject * >( this ),
1489 nNameClashResolve ) ),
1490 xEnv );
1491 // Unreachable
1493 break;
1496 // Identifier changed?
1497 sal_Bool bNewId = ( xId->getContentIdentifier()
1498 != m_xIdentifier->getContentIdentifier() );
1499 m_xIdentifier = xId;
1501 if ( !storeData() )
1503 uno::Any aProps
1504 = uno::makeAny(beans::PropertyValue(
1505 rtl::OUString( "Uri"),
1507 uno::makeAny(m_xIdentifier->
1508 getContentIdentifier()),
1509 beans::PropertyState_DIRECT_VALUE));
1510 ucbhelper::cancelCommandExecution(
1511 ucb::IOErrorCode_CANT_WRITE,
1512 uno::Sequence< uno::Any >(&aProps, 1),
1513 xEnv,
1514 rtl::OUString("Cannot store persistent data!"),
1515 this );
1516 // Unreachable
1519 m_eState = PERSISTENT;
1521 if ( bNewId )
1523 aGuard.clear();
1524 inserted();
1528 //=========================================================================
1529 void HierarchyContent::destroy( sal_Bool bDeletePhysical,
1530 const uno::Reference<
1531 ucb::XCommandEnvironment > & xEnv )
1532 throw( uno::Exception )
1534 // @@@ take care about bDeletePhysical -> trashcan support
1536 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1538 uno::Reference< ucb::XContent > xThis = this;
1540 // Persistent?
1541 if ( m_eState != PERSISTENT )
1543 ucbhelper::cancelCommandExecution(
1544 uno::makeAny( ucb::UnsupportedCommandException(
1545 rtl::OUString( "Not persistent!" ),
1546 static_cast< cppu::OWeakObject * >( this ) ) ),
1547 xEnv );
1548 // Unreachable
1551 // Am I the root folder?
1552 if ( m_eKind == ROOT )
1554 ucbhelper::cancelCommandExecution(
1555 uno::makeAny( ucb::UnsupportedCommandException(
1556 rtl::OUString( "Not supported by root folder!" ),
1557 static_cast< cppu::OWeakObject * >( this ) ) ),
1558 xEnv );
1559 // Unreachable
1562 m_eState = DEAD;
1564 aGuard.clear();
1565 deleted();
1567 if ( m_eKind == FOLDER )
1569 // Process instanciated children...
1571 HierarchyContentRefList aChildren;
1572 queryChildren( aChildren );
1574 HierarchyContentRefList::const_iterator it = aChildren.begin();
1575 HierarchyContentRefList::const_iterator end = aChildren.end();
1577 while ( it != end )
1579 (*it)->destroy( bDeletePhysical, xEnv );
1580 ++it;
1585 //=========================================================================
1586 void HierarchyContent::transfer(
1587 const ucb::TransferInfo& rInfo,
1588 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1589 throw( uno::Exception )
1591 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1593 // Persistent?
1594 if ( m_eState != PERSISTENT )
1596 ucbhelper::cancelCommandExecution(
1597 uno::makeAny( ucb::UnsupportedCommandException(
1598 rtl::OUString( "Not persistent!" ),
1599 static_cast< cppu::OWeakObject * >( this ) ) ),
1600 xEnv );
1601 // Unreachable
1604 // Is source a hierarchy content?
1605 if ( ( rInfo.SourceURL.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 2 ) ||
1606 ( rInfo.SourceURL.compareToAscii( HIERARCHY_URL_SCHEME ":/",
1607 HIERARCHY_URL_SCHEME_LENGTH + 2 )
1608 != 0 ) )
1610 ucbhelper::cancelCommandExecution(
1611 uno::makeAny( ucb::InteractiveBadTransferURLException(
1612 rtl::OUString(),
1613 static_cast< cppu::OWeakObject * >( this ) ) ),
1614 xEnv );
1615 // Unreachable
1618 // Is source not a parent of me / not me?
1619 rtl::OUString aId = m_xIdentifier->getContentIdentifier();
1620 sal_Int32 nPos = aId.lastIndexOf( '/' );
1621 if ( nPos != ( aId.getLength() - 1 ) )
1623 // No trailing slash found. Append.
1624 aId += rtl::OUString("/");
1627 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1629 if ( aId.compareTo(
1630 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
1632 uno::Any aProps
1633 = uno::makeAny(beans::PropertyValue(
1634 rtl::OUString( "Uri"),
1636 uno::makeAny(rInfo.SourceURL),
1637 beans::PropertyState_DIRECT_VALUE));
1638 ucbhelper::cancelCommandExecution(
1639 ucb::IOErrorCode_RECURSIVE,
1640 uno::Sequence< uno::Any >(&aProps, 1),
1641 xEnv,
1642 rtl::OUString( "Target is equal to or is a child of source!" ),
1643 this );
1644 // Unreachable
1648 //////////////////////////////////////////////////////////////////////
1649 // 0) Obtain content object for source.
1650 //////////////////////////////////////////////////////////////////////
1652 uno::Reference< ucb::XContentIdentifier > xId
1653 = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
1655 // Note: The static cast is okay here, because its sure that
1656 // m_xProvider is always the HierarchyContentProvider.
1657 rtl::Reference< HierarchyContent > xSource;
1661 xSource = static_cast< HierarchyContent * >(
1662 m_xProvider->queryContent( xId ).get() );
1664 catch ( ucb::IllegalIdentifierException const & )
1666 // queryContent
1669 if ( !xSource.is() )
1671 uno::Any aProps
1672 = uno::makeAny(beans::PropertyValue(
1673 rtl::OUString( "Uri"),
1675 uno::makeAny(xId->getContentIdentifier()),
1676 beans::PropertyState_DIRECT_VALUE));
1677 ucbhelper::cancelCommandExecution(
1678 ucb::IOErrorCode_CANT_READ,
1679 uno::Sequence< uno::Any >(&aProps, 1),
1680 xEnv,
1681 rtl::OUString( "Cannot instanciate source object!" ),
1682 this );
1683 // Unreachable
1686 //////////////////////////////////////////////////////////////////////
1687 // 1) Create new child content.
1688 //////////////////////////////////////////////////////////////////////
1690 rtl::OUString aType = xSource->isFolder()
1691 ? rtl::OUString( HIERARCHY_FOLDER_CONTENT_TYPE )
1692 : rtl::OUString( HIERARCHY_LINK_CONTENT_TYPE );
1693 ucb::ContentInfo aContentInfo;
1694 aContentInfo.Type = aType;
1695 aContentInfo.Attributes = 0;
1697 // Note: The static cast is okay here, because its sure that
1698 // createNewContent always creates a HierarchyContent.
1699 rtl::Reference< HierarchyContent > xTarget
1700 = static_cast< HierarchyContent * >(
1701 createNewContent( aContentInfo ).get() );
1702 if ( !xTarget.is() )
1704 uno::Any aProps
1705 = uno::makeAny(beans::PropertyValue(
1706 rtl::OUString( "Folder"),
1708 uno::makeAny(aId),
1709 beans::PropertyState_DIRECT_VALUE));
1710 ucbhelper::cancelCommandExecution(
1711 ucb::IOErrorCode_CANT_CREATE,
1712 uno::Sequence< uno::Any >(&aProps, 1),
1713 xEnv,
1714 rtl::OUString( "XContentCreator::createNewContent failed!" ),
1715 this );
1716 // Unreachable
1719 //////////////////////////////////////////////////////////////////////
1720 // 2) Copy data from source content to child content.
1721 //////////////////////////////////////////////////////////////////////
1723 uno::Sequence< beans::Property > aSourceProps
1724 = xSource->getPropertySetInfo( xEnv )->getProperties();
1725 sal_Int32 nCount = aSourceProps.getLength();
1727 if ( nCount )
1729 sal_Bool bHadTitle = rInfo.NewTitle.isEmpty();
1731 // Get all source values.
1732 uno::Reference< sdbc::XRow > xRow
1733 = xSource->getPropertyValues( aSourceProps );
1735 uno::Sequence< beans::PropertyValue > aValues( nCount );
1736 beans::PropertyValue* pValues = aValues.getArray();
1738 const beans::Property* pProps = aSourceProps.getConstArray();
1739 for ( sal_Int32 n = 0; n < nCount; ++n )
1741 const beans::Property& rProp = pProps[ n ];
1742 beans::PropertyValue& rValue = pValues[ n ];
1744 rValue.Name = rProp.Name;
1745 rValue.Handle = rProp.Handle;
1747 if ( !bHadTitle && rProp.Name == "Title" )
1749 // Set new title instead of original.
1750 bHadTitle = sal_True;
1751 rValue.Value <<= rInfo.NewTitle;
1753 else
1754 rValue.Value = xRow->getObject(
1755 n + 1,
1756 uno::Reference< container::XNameAccess >() );
1758 rValue.State = beans::PropertyState_DIRECT_VALUE;
1760 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1762 // Add Additional Core Property.
1765 xTarget->addProperty( rProp.Name,
1766 rProp.Attributes,
1767 rValue.Value );
1769 catch ( beans::PropertyExistException const & )
1772 catch ( beans::IllegalTypeException const & )
1775 catch ( lang::IllegalArgumentException const & )
1781 // Set target values.
1782 xTarget->setPropertyValues( aValues, xEnv );
1785 //////////////////////////////////////////////////////////////////////
1786 // 3) Commit (insert) child.
1787 //////////////////////////////////////////////////////////////////////
1789 xTarget->insert( rInfo.NameClash, xEnv );
1791 //////////////////////////////////////////////////////////////////////
1792 // 4) Transfer (copy) children of source.
1793 //////////////////////////////////////////////////////////////////////
1795 if ( xSource->isFolder() )
1797 HierarchyEntry aFolder(
1798 m_xContext, m_pProvider, xId->getContentIdentifier() );
1799 HierarchyEntry::iterator it;
1801 while ( aFolder.next( it ) )
1803 const HierarchyEntryData& rResult = *it;
1805 rtl::OUString aChildId = xId->getContentIdentifier();
1806 if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() )
1807 aChildId += rtl::OUString("/");
1809 aChildId += rResult.getName();
1811 ucb::TransferInfo aInfo;
1812 aInfo.MoveData = sal_False;
1813 aInfo.NewTitle = rtl::OUString();
1814 aInfo.SourceURL = aChildId;
1815 aInfo.NameClash = rInfo.NameClash;
1817 // Transfer child to target.
1818 xTarget->transfer( aInfo, xEnv );
1822 //////////////////////////////////////////////////////////////////////
1823 // 5) Destroy source ( when moving only ) .
1824 //////////////////////////////////////////////////////////////////////
1826 if ( rInfo.MoveData )
1828 xSource->destroy( sal_True, xEnv );
1830 // Remove all persistent data of source and its children.
1831 if ( !xSource->removeData() )
1833 uno::Any aProps
1834 = uno::makeAny(
1835 beans::PropertyValue(
1836 rtl::OUString( "Uri"),
1838 uno::makeAny(
1839 xSource->m_xIdentifier->
1840 getContentIdentifier()),
1841 beans::PropertyState_DIRECT_VALUE));
1842 ucbhelper::cancelCommandExecution(
1843 ucb::IOErrorCode_CANT_WRITE,
1844 uno::Sequence< uno::Any >(&aProps, 1),
1845 xEnv,
1846 rtl::OUString( "Cannot remove persistent data of source object!" ),
1847 this );
1848 // Unreachable
1851 // Remove own and all children's Additional Core Properties.
1852 xSource->removeAdditionalPropertySet( sal_True );
1856 //=========================================================================
1857 //=========================================================================
1859 // HierarchyContentProperties Implementation.
1861 //=========================================================================
1862 //=========================================================================
1864 uno::Sequence< ucb::ContentInfo >
1865 HierarchyContentProperties::getCreatableContentsInfo() const
1867 if ( getIsFolder() )
1869 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
1871 // Folder.
1872 aSeq.getArray()[ 0 ].Type
1873 = rtl::OUString( HIERARCHY_FOLDER_CONTENT_TYPE );
1874 aSeq.getArray()[ 0 ].Attributes
1875 = ucb::ContentInfoAttribute::KIND_FOLDER;
1877 uno::Sequence< beans::Property > aFolderProps( 1 );
1878 aFolderProps.getArray()[ 0 ] = beans::Property(
1879 rtl::OUString("Title"),
1881 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1882 beans::PropertyAttribute::BOUND );
1883 aSeq.getArray()[ 0 ].Properties = aFolderProps;
1885 // Link.
1886 aSeq.getArray()[ 1 ].Type
1887 = rtl::OUString( HIERARCHY_LINK_CONTENT_TYPE );
1888 aSeq.getArray()[ 1 ].Attributes
1889 = ucb::ContentInfoAttribute::KIND_LINK;
1891 uno::Sequence< beans::Property > aLinkProps( 2 );
1892 aLinkProps.getArray()[ 0 ] = beans::Property(
1893 rtl::OUString("Title"),
1895 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1896 beans::PropertyAttribute::BOUND );
1897 aLinkProps.getArray()[ 1 ] = beans::Property(
1898 rtl::OUString("TargetURL"),
1900 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1901 beans::PropertyAttribute::BOUND );
1902 aSeq.getArray()[ 1 ].Properties = aLinkProps;
1904 return aSeq;
1906 else
1908 return uno::Sequence< ucb::ContentInfo >( 0 );
1912 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */