Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchycontent.cxx
blob777147bc00ee9cb083f83fd5237122611e084f59
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
31 TODO
32 **************************************************************************
34 - optimize transfer command. "Move" should be implementable much more
35 efficient!
37 **************************************************************************
39 - Root Folder vs. 'normal' Folder
40 - root doesn't support command 'delete'
41 - root doesn't support command 'insert'
42 - root needs not created via XContentCreator - queryContent with root
43 folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0
44 - root has no parent.
46 *************************************************************************/
47 #include <osl/diagnose.h>
49 #include "osl/doublecheckedlocking.h"
50 #include <rtl/ustring.h>
51 #include <rtl/ustring.hxx>
52 #include <com/sun/star/beans/PropertyAttribute.hpp>
53 #include <com/sun/star/beans/PropertyState.hpp>
54 #include <com/sun/star/beans/PropertyValue.hpp>
55 #include <com/sun/star/beans/XPropertyAccess.hpp>
56 #include <com/sun/star/lang/IllegalAccessException.hpp>
57 #include <com/sun/star/sdbc/XRow.hpp>
58 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
59 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
60 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
61 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
62 #include <com/sun/star/ucb/NameClash.hpp>
63 #include <com/sun/star/ucb/NameClashException.hpp>
64 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
65 #include <com/sun/star/ucb/TransferInfo.hpp>
66 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
67 #include <com/sun/star/ucb/XCommandInfo.hpp>
68 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
69 #include <com/sun/star/uno/Any.hxx>
70 #include <com/sun/star/uno/Sequence.hxx>
71 #include <ucbhelper/contentidentifier.hxx>
72 #include <ucbhelper/propertyvalueset.hxx>
73 #include <ucbhelper/cancelcommandexecution.hxx>
74 #include "hierarchycontent.hxx"
75 #include "hierarchyprovider.hxx"
76 #include "dynamicresultset.hxx"
77 #include "hierarchyuri.hxx"
79 #include "../inc/urihelper.hxx"
81 using namespace com::sun::star;
82 using namespace hierarchy_ucp;
84 //=========================================================================
85 //=========================================================================
87 // HierarchyContent Implementation.
89 //=========================================================================
90 //=========================================================================
92 // static ( "virtual" ctor )
93 HierarchyContent* HierarchyContent::create(
94 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
95 HierarchyContentProvider* pProvider,
96 const uno::Reference< ucb::XContentIdentifier >& Identifier )
98 // Fail, if content does not exist.
99 HierarchyContentProperties aProps;
100 if ( !loadData( rxSMgr, pProvider, Identifier, aProps ) )
101 return 0;
103 return new HierarchyContent( rxSMgr, pProvider, Identifier, aProps );
106 //=========================================================================
107 // static ( "virtual" ctor )
108 HierarchyContent* HierarchyContent::create(
109 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
110 HierarchyContentProvider* pProvider,
111 const uno::Reference< ucb::XContentIdentifier >& Identifier,
112 const ucb::ContentInfo& Info )
114 if ( Info.Type.isEmpty() )
115 return 0;
117 if ( Info.Type != HIERARCHY_FOLDER_CONTENT_TYPE && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
118 return 0;
120 return new HierarchyContent( rxSMgr, pProvider, Identifier, Info );
123 //=========================================================================
124 HierarchyContent::HierarchyContent(
125 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
126 HierarchyContentProvider* pProvider,
127 const uno::Reference< ucb::XContentIdentifier >& Identifier,
128 const HierarchyContentProperties& rProps )
129 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
130 m_aProps( rProps ),
131 m_eState( PERSISTENT ),
132 m_pProvider( pProvider ),
133 m_bCheckedReadOnly( false ),
134 m_bIsReadOnly( true )
136 setKind( Identifier );
139 //=========================================================================
140 HierarchyContent::HierarchyContent(
141 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
142 HierarchyContentProvider* pProvider,
143 const uno::Reference< ucb::XContentIdentifier >& Identifier,
144 const ucb::ContentInfo& Info )
145 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
146 m_aProps( Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE ? HierarchyEntryData::FOLDER : HierarchyEntryData::LINK ),
147 m_eState( TRANSIENT ),
148 m_pProvider( pProvider ),
149 m_bCheckedReadOnly( false ),
150 m_bIsReadOnly( true )
152 setKind( Identifier );
155 //=========================================================================
156 // virtual
157 HierarchyContent::~HierarchyContent()
161 //=========================================================================
163 // XInterface methods.
165 //=========================================================================
167 // virtual
168 void SAL_CALL HierarchyContent::acquire()
169 throw( )
171 ContentImplHelper::acquire();
174 //=========================================================================
175 // virtual
176 void SAL_CALL HierarchyContent::release()
177 throw( )
179 ContentImplHelper::release();
182 //=========================================================================
183 // virtual
184 uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType )
185 throw ( uno::RuntimeException )
187 uno::Any aRet = ContentImplHelper::queryInterface( rType );
189 if ( !aRet.hasValue() )
191 // Note: isReadOnly may be relative expensive. So avoid calling it
192 // unless it is really necessary.
193 aRet = cppu::queryInterface(
194 rType, static_cast< ucb::XContentCreator * >( this ) );
195 if ( aRet.hasValue() )
197 if ( !isFolder() || isReadOnly() )
198 return uno::Any();
202 return aRet;
205 //=========================================================================
207 // XTypeProvider methods.
209 //=========================================================================
211 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent );
213 //=========================================================================
214 // virtual
215 uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes()
216 throw( uno::RuntimeException )
218 cppu::OTypeCollection * pCollection = 0;
220 if ( isFolder() && !isReadOnly() )
222 static cppu::OTypeCollection* pFolderTypes = 0;
224 pCollection = pFolderTypes;
225 if ( !pCollection )
227 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
229 pCollection = pFolderTypes;
230 if ( !pCollection )
232 static cppu::OTypeCollection aCollection(
233 CPPU_TYPE_REF( lang::XTypeProvider ),
234 CPPU_TYPE_REF( lang::XServiceInfo ),
235 CPPU_TYPE_REF( lang::XComponent ),
236 CPPU_TYPE_REF( ucb::XContent ),
237 CPPU_TYPE_REF( ucb::XCommandProcessor ),
238 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
239 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
240 CPPU_TYPE_REF( beans::XPropertyContainer ),
241 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
242 CPPU_TYPE_REF( container::XChild ),
243 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
244 pCollection = &aCollection;
245 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
246 pFolderTypes = pCollection;
249 else {
250 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
253 else
255 static cppu::OTypeCollection* pDocumentTypes = 0;
257 pCollection = pDocumentTypes;
258 if ( !pCollection )
260 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
262 pCollection = pDocumentTypes;
263 if ( !pCollection )
265 static cppu::OTypeCollection aCollection(
266 CPPU_TYPE_REF( lang::XTypeProvider ),
267 CPPU_TYPE_REF( lang::XServiceInfo ),
268 CPPU_TYPE_REF( lang::XComponent ),
269 CPPU_TYPE_REF( ucb::XContent ),
270 CPPU_TYPE_REF( ucb::XCommandProcessor ),
271 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
272 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
273 CPPU_TYPE_REF( beans::XPropertyContainer ),
274 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
275 CPPU_TYPE_REF( container::XChild ) );
276 pCollection = &aCollection;
277 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
278 pDocumentTypes = pCollection;
281 else {
282 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
286 return (*pCollection).getTypes();
289 //=========================================================================
291 // XServiceInfo methods.
293 //=========================================================================
295 // virtual
296 rtl::OUString SAL_CALL HierarchyContent::getImplementationName()
297 throw( uno::RuntimeException )
299 return rtl::OUString( "com.sun.star.comp.ucb.HierarchyContent" );
302 //=========================================================================
303 // virtual
304 uno::Sequence< rtl::OUString > SAL_CALL
305 HierarchyContent::getSupportedServiceNames()
306 throw( uno::RuntimeException )
308 uno::Sequence< rtl::OUString > aSNS( 1 );
310 if ( m_eKind == LINK )
311 aSNS.getArray()[ 0 ] = rtl::OUString( HIERARCHY_LINK_CONTENT_SERVICE_NAME );
312 else if ( m_eKind == FOLDER )
313 aSNS.getArray()[ 0 ] = rtl::OUString( HIERARCHY_FOLDER_CONTENT_SERVICE_NAME );
314 else
315 aSNS.getArray()[ 0 ] = rtl::OUString( HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME );
317 return aSNS;
320 //=========================================================================
322 // XContent methods.
324 //=========================================================================
326 // virtual
327 rtl::OUString SAL_CALL HierarchyContent::getContentType()
328 throw( uno::RuntimeException )
330 return m_aProps.getContentType();
333 //=========================================================================
334 // virtual
335 uno::Reference< ucb::XContentIdentifier > SAL_CALL
336 HierarchyContent::getIdentifier()
337 throw( uno::RuntimeException )
339 // Transient?
340 if ( m_eState == TRANSIENT )
342 // Transient contents have no identifier.
343 return uno::Reference< ucb::XContentIdentifier >();
346 return ContentImplHelper::getIdentifier();
349 //=========================================================================
351 // XCommandProcessor methods.
353 //=========================================================================
355 // virtual
356 uno::Any SAL_CALL HierarchyContent::execute(
357 const ucb::Command& aCommand,
358 sal_Int32 /*CommandId*/,
359 const uno::Reference< ucb::XCommandEnvironment >& Environment )
360 throw( uno::Exception,
361 ucb::CommandAbortedException,
362 uno::RuntimeException )
364 uno::Any aRet;
366 if ( aCommand.Name == "getPropertyValues" )
368 //////////////////////////////////////////////////////////////////
369 // getPropertyValues
370 //////////////////////////////////////////////////////////////////
372 uno::Sequence< beans::Property > Properties;
373 if ( !( aCommand.Argument >>= Properties ) )
375 ucbhelper::cancelCommandExecution(
376 uno::makeAny( lang::IllegalArgumentException(
377 rtl::OUString( "Wrong argument type!" ),
378 static_cast< cppu::OWeakObject * >( this ),
379 -1 ) ),
380 Environment );
381 // Unreachable
384 aRet <<= getPropertyValues( Properties );
386 else if ( aCommand.Name == "setPropertyValues" )
388 //////////////////////////////////////////////////////////////////
389 // setPropertyValues
390 //////////////////////////////////////////////////////////////////
392 uno::Sequence< beans::PropertyValue > aProperties;
393 if ( !( aCommand.Argument >>= aProperties ) )
395 ucbhelper::cancelCommandExecution(
396 uno::makeAny( lang::IllegalArgumentException(
397 rtl::OUString( "Wrong argument type!" ),
398 static_cast< cppu::OWeakObject * >( this ),
399 -1 ) ),
400 Environment );
401 // Unreachable
404 if ( !aProperties.getLength() )
406 ucbhelper::cancelCommandExecution(
407 uno::makeAny( lang::IllegalArgumentException(
408 rtl::OUString( "No properties!" ),
409 static_cast< cppu::OWeakObject * >( this ),
410 -1 ) ),
411 Environment );
412 // Unreachable
415 aRet <<= setPropertyValues( aProperties, Environment );
417 else if ( aCommand.Name == "getPropertySetInfo" )
419 //////////////////////////////////////////////////////////////////
420 // getPropertySetInfo
421 //////////////////////////////////////////////////////////////////
423 aRet <<= getPropertySetInfo( Environment );
425 else if ( aCommand.Name == "getCommandInfo" )
427 //////////////////////////////////////////////////////////////////
428 // getCommandInfo
429 //////////////////////////////////////////////////////////////////
431 aRet <<= getCommandInfo( Environment );
433 else if ( aCommand.Name == "open" && isFolder() )
435 //////////////////////////////////////////////////////////////////
436 // open command for a folder content
437 //////////////////////////////////////////////////////////////////
439 ucb::OpenCommandArgument2 aOpenCommand;
440 if ( !( aCommand.Argument >>= aOpenCommand ) )
442 ucbhelper::cancelCommandExecution(
443 uno::makeAny( lang::IllegalArgumentException(
444 rtl::OUString( "Wrong argument type!" ),
445 static_cast< cppu::OWeakObject * >( this ),
446 -1 ) ),
447 Environment );
448 // Unreachable
451 uno::Reference< ucb::XDynamicResultSet > xSet
452 = new DynamicResultSet( m_xSMgr, this, aOpenCommand );
453 aRet <<= xSet;
455 else if ( aCommand.Name == "insert" && ( m_eKind != ROOT ) && !isReadOnly() )
457 //////////////////////////////////////////////////////////////////
458 // insert
459 // ( Not available at root folder )
460 //////////////////////////////////////////////////////////////////
462 ucb::InsertCommandArgument aArg;
463 if ( !( aCommand.Argument >>= aArg ) )
465 ucbhelper::cancelCommandExecution(
466 uno::makeAny( lang::IllegalArgumentException(
467 rtl::OUString( "Wrong argument type!" ),
468 static_cast< cppu::OWeakObject * >( this ),
469 -1 ) ),
470 Environment );
471 // Unreachable
474 sal_Int32 nNameClash = aArg.ReplaceExisting
475 ? ucb::NameClash::OVERWRITE
476 : ucb::NameClash::ERROR;
477 insert( nNameClash, Environment );
479 else if ( aCommand.Name == "delete" && ( m_eKind != ROOT ) && !isReadOnly() )
481 //////////////////////////////////////////////////////////////////
482 // delete
483 // ( Not available at root folder )
484 //////////////////////////////////////////////////////////////////
486 sal_Bool bDeletePhysical = sal_False;
487 aCommand.Argument >>= bDeletePhysical;
488 destroy( bDeletePhysical, Environment );
490 // Remove own and all children's persistent data.
491 if ( !removeData() )
493 uno::Any aProps
494 = uno::makeAny(
495 beans::PropertyValue(
496 rtl::OUString( "Uri"),
498 uno::makeAny(m_xIdentifier->
499 getContentIdentifier()),
500 beans::PropertyState_DIRECT_VALUE));
501 ucbhelper::cancelCommandExecution(
502 ucb::IOErrorCode_CANT_WRITE,
503 uno::Sequence< uno::Any >(&aProps, 1),
504 Environment,
505 rtl::OUString( "Cannot remove persistent data!" ),
506 this );
507 // Unreachable
510 // Remove own and all children's Additional Core Properties.
511 removeAdditionalPropertySet( sal_True );
513 else if ( aCommand.Name == "transfer" && isFolder() && !isReadOnly() )
515 //////////////////////////////////////////////////////////////////
516 // transfer
517 // ( Not available at link objects )
518 //////////////////////////////////////////////////////////////////
520 ucb::TransferInfo aInfo;
521 if ( !( aCommand.Argument >>= aInfo ) )
523 OSL_FAIL( "Wrong argument type!" );
524 ucbhelper::cancelCommandExecution(
525 uno::makeAny( lang::IllegalArgumentException(
526 rtl::OUString( "Wrong argument type!" ),
527 static_cast< cppu::OWeakObject * >( this ),
528 -1 ) ),
529 Environment );
530 // Unreachable
533 transfer( aInfo, Environment );
535 else if ( aCommand.Name == "createNewContent" && isFolder() && !isReadOnly() )
537 //////////////////////////////////////////////////////////////////
538 // createNewContent
539 // ( Not available at link objects )
540 //////////////////////////////////////////////////////////////////
542 ucb::ContentInfo aInfo;
543 if ( !( aCommand.Argument >>= aInfo ) )
545 OSL_FAIL( "Wrong argument type!" );
546 ucbhelper::cancelCommandExecution(
547 uno::makeAny( lang::IllegalArgumentException(
548 rtl::OUString( "Wrong argument type!" ),
549 static_cast< cppu::OWeakObject * >( this ),
550 -1 ) ),
551 Environment );
552 // Unreachable
555 aRet <<= createNewContent( aInfo );
557 else
559 //////////////////////////////////////////////////////////////////
560 // Unsupported command
561 //////////////////////////////////////////////////////////////////
563 ucbhelper::cancelCommandExecution(
564 uno::makeAny( ucb::UnsupportedCommandException(
565 rtl::OUString(),
566 static_cast< cppu::OWeakObject * >( this ) ) ),
567 Environment );
568 // Unreachable
571 return aRet;
574 //=========================================================================
575 // virtual
576 void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ )
577 throw( uno::RuntimeException )
579 // @@@ Generally, no action takes much time...
582 //=========================================================================
584 // XContentCreator methods.
586 //=========================================================================
588 // virtual
589 uno::Sequence< ucb::ContentInfo > SAL_CALL
590 HierarchyContent::queryCreatableContentsInfo()
591 throw( uno::RuntimeException )
593 return m_aProps.getCreatableContentsInfo();
596 //=========================================================================
597 // virtual
598 uno::Reference< ucb::XContent > SAL_CALL
599 HierarchyContent::createNewContent( const ucb::ContentInfo& Info )
600 throw( uno::RuntimeException )
602 if ( isFolder() )
604 osl::Guard< osl::Mutex > aGuard( m_aMutex );
606 if ( Info.Type.isEmpty() )
607 return uno::Reference< ucb::XContent >();
609 sal_Bool bCreateFolder = Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE;
611 if ( !bCreateFolder && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
612 return uno::Reference< ucb::XContent >();
614 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
616 OSL_ENSURE( !aURL.isEmpty(),
617 "HierarchyContent::createNewContent - empty identifier!" );
619 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
620 aURL += rtl::OUString("/");
622 if ( bCreateFolder )
623 aURL += rtl::OUString("New_Folder");
624 else
625 aURL += rtl::OUString("New_Link");
627 uno::Reference< ucb::XContentIdentifier > xId
628 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
630 return create( m_xSMgr, m_pProvider, xId, Info );
632 else
634 OSL_FAIL( "createNewContent called on non-folder object!" );
635 return uno::Reference< ucb::XContent >();
639 //=========================================================================
640 // virtual
641 rtl::OUString HierarchyContent::getParentURL()
643 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
644 return aUri.getParentUri();
647 //=========================================================================
648 //static
649 sal_Bool HierarchyContent::hasData(
650 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
651 HierarchyContentProvider* pProvider,
652 const uno::Reference< ucb::XContentIdentifier >& Identifier )
654 rtl::OUString aURL = Identifier->getContentIdentifier();
656 // Am I a root folder?
657 HierarchyUri aUri( aURL );
658 if ( aUri.isRootFolder() )
660 // hasData must always return 'true' for root folder
661 // even if no persistent data exist!!!
662 return sal_True;
665 return HierarchyEntry( rxSMgr, pProvider, aURL ).hasData();
668 //=========================================================================
669 //static
670 sal_Bool HierarchyContent::loadData(
671 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
672 HierarchyContentProvider* pProvider,
673 const uno::Reference< ucb::XContentIdentifier >& Identifier,
674 HierarchyContentProperties& rProps )
676 rtl::OUString aURL = Identifier->getContentIdentifier();
678 // Am I a root folder?
679 HierarchyUri aUri( aURL );
680 if ( aUri.isRootFolder() )
682 rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER );
684 else
686 HierarchyEntry aEntry( rxSMgr, pProvider, aURL );
687 HierarchyEntryData aData;
688 if ( !aEntry.getData( aData ) )
689 return sal_False;
691 rProps = HierarchyContentProperties( aData );
693 return sal_True;
696 //=========================================================================
697 sal_Bool HierarchyContent::storeData()
699 HierarchyEntry aEntry(
700 m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() );
701 return aEntry.setData( m_aProps.getHierarchyEntryData(), sal_True );
704 //=========================================================================
705 sal_Bool HierarchyContent::renameData(
706 const uno::Reference< ucb::XContentIdentifier >& xOldId,
707 const uno::Reference< ucb::XContentIdentifier >& xNewId )
709 HierarchyEntry aEntry(
710 m_xSMgr, m_pProvider, xOldId->getContentIdentifier() );
711 return aEntry.move( xNewId->getContentIdentifier(),
712 m_aProps.getHierarchyEntryData() );
715 //=========================================================================
716 sal_Bool HierarchyContent::removeData()
718 HierarchyEntry aEntry(
719 m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() );
720 return aEntry.remove();
723 //=========================================================================
724 void HierarchyContent::setKind(
725 const uno::Reference< ucb::XContentIdentifier >& Identifier )
727 if ( m_aProps.getIsFolder() )
729 // Am I a root folder?
730 HierarchyUri aUri( Identifier->getContentIdentifier() );
731 if ( aUri.isRootFolder() )
732 m_eKind = ROOT;
733 else
734 m_eKind = FOLDER;
736 else
737 m_eKind = LINK;
740 //=========================================================================
741 bool HierarchyContent::isReadOnly()
743 if ( !m_bCheckedReadOnly )
745 osl::Guard< osl::Mutex > aGuard( m_aMutex );
746 if ( !m_bCheckedReadOnly )
748 m_bCheckedReadOnly = true;
749 m_bIsReadOnly = true;
751 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
752 uno::Reference< lang::XMultiServiceFactory > xConfigProv
753 = m_pProvider->getConfigProvider( aUri.getService() );
754 if ( xConfigProv.is() )
756 uno::Sequence< rtl::OUString > aNames
757 = xConfigProv->getAvailableServiceNames();
758 sal_Int32 nCount = aNames.getLength();
759 for ( sal_Int32 n = 0; n < nCount; ++n )
761 if ( aNames[ n ] == "com.sun.star.ucb.HierarchyDataReadWriteAccess" )
763 m_bIsReadOnly = false;
764 break;
771 return m_bIsReadOnly;
774 //=========================================================================
775 uno::Reference< ucb::XContentIdentifier >
776 HierarchyContent::makeNewIdentifier( const rtl::OUString& rTitle )
778 osl::Guard< osl::Mutex > aGuard( m_aMutex );
780 // Assemble new content identifier...
781 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
782 rtl::OUString aNewURL = aUri.getParentUri();
783 aNewURL += rtl::OUString("/");
784 aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle );
786 return uno::Reference< ucb::XContentIdentifier >(
787 new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ) );
790 //=========================================================================
791 void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren )
793 if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) )
794 return;
796 // Obtain a list with a snapshot of all currently instanciated contents
797 // from provider and extract the contents which are direct children
798 // of this content.
800 ::ucbhelper::ContentRefList aAllContents;
801 m_xProvider->queryExistingContents( aAllContents );
803 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
804 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
806 if ( nURLPos != ( aURL.getLength() - 1 ) )
808 // No trailing slash found. Append.
809 aURL += rtl::OUString("/");
812 sal_Int32 nLen = aURL.getLength();
814 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
815 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
817 while ( it != end )
819 ::ucbhelper::ContentImplHelperRef xChild = (*it);
820 rtl::OUString aChildURL
821 = xChild->getIdentifier()->getContentIdentifier();
823 // Is aURL a prefix of aChildURL?
824 if ( ( aChildURL.getLength() > nLen ) &&
825 ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
827 sal_Int32 nPos = nLen;
828 nPos = aChildURL.indexOf( '/', nPos );
830 if ( ( nPos == -1 ) ||
831 ( nPos == ( aChildURL.getLength() - 1 ) ) )
833 // No further slashes/ only a final slash. It's a child!
834 rChildren.push_back(
835 HierarchyContentRef(
836 static_cast< HierarchyContent * >( xChild.get() ) ) );
839 ++it;
843 //=========================================================================
844 sal_Bool HierarchyContent::exchangeIdentity(
845 const uno::Reference< ucb::XContentIdentifier >& xNewId )
847 if ( !xNewId.is() )
848 return sal_False;
850 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
852 uno::Reference< ucb::XContent > xThis = this;
854 // Already persistent?
855 if ( m_eState != PERSISTENT )
857 OSL_FAIL( "HierarchyContent::exchangeIdentity - Not persistent!" );
858 return sal_False;
861 // Am I the root folder?
862 if ( m_eKind == ROOT )
864 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
865 "Not supported by root folder!" );
866 return sal_False;
869 // Exchange own identitity.
871 // Fail, if a content with given id already exists.
872 if ( !hasData( xNewId ) )
874 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
876 aGuard.clear();
877 if ( exchange( xNewId ) )
879 if ( m_eKind == FOLDER )
881 // Process instanciated children...
883 HierarchyContentRefList aChildren;
884 queryChildren( aChildren );
886 HierarchyContentRefList::const_iterator it = aChildren.begin();
887 HierarchyContentRefList::const_iterator end = aChildren.end();
889 while ( it != end )
891 HierarchyContentRef xChild = (*it);
893 // Create new content identifier for the child...
894 uno::Reference< ucb::XContentIdentifier > xOldChildId
895 = xChild->getIdentifier();
896 rtl::OUString aOldChildURL
897 = xOldChildId->getContentIdentifier();
898 rtl::OUString aNewChildURL
899 = aOldChildURL.replaceAt(
901 aOldURL.getLength(),
902 xNewId->getContentIdentifier() );
903 uno::Reference< ucb::XContentIdentifier > xNewChildId
904 = new ::ucbhelper::ContentIdentifier(
905 m_xSMgr, aNewChildURL );
907 if ( !xChild->exchangeIdentity( xNewChildId ) )
908 return sal_False;
910 ++it;
913 return sal_True;
917 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
918 "Panic! Cannot exchange identity!" );
919 return sal_False;
922 //=========================================================================
923 // static
924 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
925 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
926 const uno::Sequence< beans::Property >& rProperties,
927 const HierarchyContentProperties& rData,
928 HierarchyContentProvider* pProvider,
929 const rtl::OUString& rContentId )
931 // Note: Empty sequence means "get values of all supported properties".
933 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
934 = new ::ucbhelper::PropertyValueSet( rSMgr );
936 sal_Int32 nCount = rProperties.getLength();
937 if ( nCount )
939 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
940 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
942 const beans::Property* pProps = rProperties.getConstArray();
943 for ( sal_Int32 n = 0; n < nCount; ++n )
945 const beans::Property& rProp = pProps[ n ];
947 // Process Core properties.
949 if ( rProp.Name == "ContentType" )
951 xRow->appendString ( rProp, rData.getContentType() );
953 else if ( rProp.Name == "Title" )
955 xRow->appendString ( rProp, rData.getTitle() );
957 else if ( rProp.Name == "IsDocument" )
959 xRow->appendBoolean( rProp, rData.getIsDocument() );
961 else if ( rProp.Name == "IsFolder" )
963 xRow->appendBoolean( rProp, rData.getIsFolder() );
965 else if ( rProp.Name == "CreatableContentsInfo" )
967 xRow->appendObject(
968 rProp, uno::makeAny( rData.getCreatableContentsInfo() ) );
970 else if ( rProp.Name == "TargetURL" )
972 // TargetURL is only supported by links.
974 if ( rData.getIsDocument() )
975 xRow->appendString( rProp, rData.getTargetURL() );
976 else
977 xRow->appendVoid( rProp );
979 else
981 // Not a Core Property! Maybe it's an Additional Core Property?!
983 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
985 xAdditionalPropSet
986 = uno::Reference< beans::XPropertySet >(
987 pProvider->getAdditionalPropertySet( rContentId,
988 sal_False ),
989 uno::UNO_QUERY );
990 bTriedToGetAdditonalPropSet = sal_True;
993 if ( xAdditionalPropSet.is() )
995 if ( !xRow->appendPropertySetValue(
996 xAdditionalPropSet,
997 rProp ) )
999 // Append empty entry.
1000 xRow->appendVoid( rProp );
1003 else
1005 // Append empty entry.
1006 xRow->appendVoid( rProp );
1011 else
1013 // Append all Core Properties.
1014 xRow->appendString (
1015 beans::Property( rtl::OUString("ContentType"),
1017 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1018 beans::PropertyAttribute::BOUND
1019 | beans::PropertyAttribute::READONLY ),
1020 rData.getContentType() );
1021 xRow->appendString (
1022 beans::Property( rtl::OUString("Title"),
1024 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1025 // @@@ Might actually be read-only!
1026 beans::PropertyAttribute::BOUND ),
1027 rData.getTitle() );
1028 xRow->appendBoolean(
1029 beans::Property( rtl::OUString("IsDocument"),
1031 getCppuBooleanType(),
1032 beans::PropertyAttribute::BOUND
1033 | beans::PropertyAttribute::READONLY ),
1034 rData.getIsDocument() );
1035 xRow->appendBoolean(
1036 beans::Property( rtl::OUString("IsFolder"),
1038 getCppuBooleanType(),
1039 beans::PropertyAttribute::BOUND
1040 | beans::PropertyAttribute::READONLY ),
1041 rData.getIsFolder() );
1043 if ( rData.getIsDocument() )
1044 xRow->appendString(
1045 beans::Property( rtl::OUString("TargetURL"),
1047 getCppuType(
1048 static_cast< const rtl::OUString * >( 0 ) ),
1049 // @@@ Might actually be read-only!
1050 beans::PropertyAttribute::BOUND ),
1051 rData.getTargetURL() );
1052 xRow->appendObject(
1053 beans::Property(
1054 rtl::OUString("CreatableContentsInfo"),
1056 getCppuType( static_cast<
1057 const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
1058 beans::PropertyAttribute::BOUND
1059 | beans::PropertyAttribute::READONLY ),
1060 uno::makeAny( rData.getCreatableContentsInfo() ) );
1062 // Append all Additional Core Properties.
1064 uno::Reference< beans::XPropertySet > xSet(
1065 pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1066 uno::UNO_QUERY );
1067 xRow->appendPropertySet( xSet );
1070 return uno::Reference< sdbc::XRow >( xRow.get() );
1073 //=========================================================================
1074 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
1075 const uno::Sequence< beans::Property >& rProperties )
1077 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1078 return getPropertyValues( m_xSMgr,
1079 rProperties,
1080 m_aProps,
1081 m_pProvider,
1082 m_xIdentifier->getContentIdentifier() );
1085 //=========================================================================
1086 uno::Sequence< uno::Any > HierarchyContent::setPropertyValues(
1087 const uno::Sequence< beans::PropertyValue >& rValues,
1088 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1089 throw( uno::Exception )
1091 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1093 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1094 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1095 sal_Int32 nChanged = 0;
1097 beans::PropertyChangeEvent aEvent;
1098 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1099 aEvent.Further = sal_False;
1100 // aEvent.PropertyName =
1101 aEvent.PropertyHandle = -1;
1102 // aEvent.OldValue =
1103 // aEvent.NewValue =
1105 const beans::PropertyValue* pValues = rValues.getConstArray();
1106 sal_Int32 nCount = rValues.getLength();
1108 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1109 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1111 sal_Bool bExchange = sal_False;
1112 rtl::OUString aOldTitle;
1113 rtl::OUString aOldName;
1114 sal_Int32 nTitlePos = -1;
1116 for ( sal_Int32 n = 0; n < nCount; ++n )
1118 const beans::PropertyValue& rValue = pValues[ n ];
1120 if ( rValue.Name == "ContentType" )
1122 // Read-only property!
1123 aRet[ n ] <<= lang::IllegalAccessException(
1124 rtl::OUString( "Property is read-only!" ),
1125 static_cast< cppu::OWeakObject * >( this ) );
1127 else if ( rValue.Name == "IsDocument" )
1129 // Read-only property!
1130 aRet[ n ] <<= lang::IllegalAccessException(
1131 rtl::OUString( "Property is read-only!" ),
1132 static_cast< cppu::OWeakObject * >( this ) );
1134 else if ( rValue.Name == "IsFolder" )
1136 // Read-only property!
1137 aRet[ n ] <<= lang::IllegalAccessException(
1138 rtl::OUString( "Property is read-only!" ),
1139 static_cast< cppu::OWeakObject * >( this ) );
1141 else if ( rValue.Name == "CreatableContentsInfo" )
1143 // Read-only property!
1144 aRet[ n ] <<= lang::IllegalAccessException(
1145 rtl::OUString( "Property is read-only!" ),
1146 static_cast< cppu::OWeakObject * >( this ) );
1148 else if ( rValue.Name == "Title" )
1150 if ( isReadOnly() )
1152 aRet[ n ] <<= lang::IllegalAccessException(
1153 rtl::OUString( "Property is read-only!" ),
1154 static_cast< cppu::OWeakObject * >( this ) );
1156 else
1158 rtl::OUString aNewValue;
1159 if ( rValue.Value >>= aNewValue )
1161 // No empty titles!
1162 if ( !aNewValue.isEmpty() )
1164 if ( aNewValue != m_aProps.getTitle() )
1166 // modified title -> modified URL -> exchange !
1167 if ( m_eState == PERSISTENT )
1168 bExchange = sal_True;
1170 aOldTitle = m_aProps.getTitle();
1171 aOldName = m_aProps.getName();
1173 m_aProps.setTitle( aNewValue );
1174 m_aProps.setName(
1175 ::ucb_impl::urihelper::encodeSegment(
1176 aNewValue ) );
1178 // property change event will be set later...
1180 // remember position within sequence of values
1181 // (for error handling).
1182 nTitlePos = n;
1185 else
1187 aRet[ n ] <<= lang::IllegalArgumentException(
1188 rtl::OUString( "Empty title not allowed!" ),
1189 static_cast< cppu::OWeakObject * >( this ),
1190 -1 );
1193 else
1195 aRet[ n ] <<= beans::IllegalTypeException(
1196 rtl::OUString( "Property value has wrong type!" ),
1197 static_cast< cppu::OWeakObject * >( this ) );
1201 else if ( rValue.Name == "TargetURL" )
1203 if ( isReadOnly() )
1205 aRet[ n ] <<= lang::IllegalAccessException(
1206 rtl::OUString( "Property is read-only!" ),
1207 static_cast< cppu::OWeakObject * >( this ) );
1209 else
1211 // TargetURL is only supported by links.
1213 if ( m_eKind == LINK )
1215 rtl::OUString aNewValue;
1216 if ( rValue.Value >>= aNewValue )
1218 // No empty target URL's!
1219 if ( !aNewValue.isEmpty() )
1221 if ( aNewValue != m_aProps.getTargetURL() )
1223 aEvent.PropertyName = rValue.Name;
1224 aEvent.OldValue
1225 = uno::makeAny( m_aProps.getTargetURL() );
1226 aEvent.NewValue
1227 = uno::makeAny( aNewValue );
1229 aChanges.getArray()[ nChanged ] = aEvent;
1231 m_aProps.setTargetURL( aNewValue );
1232 nChanged++;
1235 else
1237 aRet[ n ] <<= lang::IllegalArgumentException(
1238 rtl::OUString( "Empty target URL not allowed!" ),
1239 static_cast< cppu::OWeakObject * >( this ),
1240 -1 );
1243 else
1245 aRet[ n ] <<= beans::IllegalTypeException(
1246 rtl::OUString( "Property value has wrong type!" ),
1247 static_cast< cppu::OWeakObject * >( this ) );
1250 else
1252 aRet[ n ] <<= beans::UnknownPropertyException(
1253 rtl::OUString( "TargetURL only supported by links!" ),
1254 static_cast< cppu::OWeakObject * >( this ) );
1258 else
1260 // Not a Core Property! Maybe it's an Additional Core Property?!
1262 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1264 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1265 bTriedToGetAdditonalPropSet = sal_True;
1268 if ( xAdditionalPropSet.is() )
1272 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1273 rValue.Name );
1274 if ( aOldValue != rValue.Value )
1276 xAdditionalPropSet->setPropertyValue(
1277 rValue.Name, rValue.Value );
1279 aEvent.PropertyName = rValue.Name;
1280 aEvent.OldValue = aOldValue;
1281 aEvent.NewValue = rValue.Value;
1283 aChanges.getArray()[ nChanged ] = aEvent;
1284 nChanged++;
1287 catch ( beans::UnknownPropertyException const & e )
1289 aRet[ n ] <<= e;
1291 catch ( lang::WrappedTargetException const & e )
1293 aRet[ n ] <<= e;
1295 catch ( beans::PropertyVetoException const & e )
1297 aRet[ n ] <<= e;
1299 catch ( lang::IllegalArgumentException const & e )
1301 aRet[ n ] <<= e;
1304 else
1306 aRet[ n ] <<= uno::Exception(
1307 rtl::OUString( "No property set for storing the value!" ),
1308 static_cast< cppu::OWeakObject * >( this ) );
1313 if ( bExchange )
1315 uno::Reference< ucb::XContentIdentifier > xOldId
1316 = m_xIdentifier;
1317 uno::Reference< ucb::XContentIdentifier > xNewId
1318 = makeNewIdentifier( m_aProps.getTitle() );
1320 aGuard.clear();
1321 if ( exchangeIdentity( xNewId ) )
1323 // Adapt persistent data.
1324 renameData( xOldId, xNewId );
1326 // Adapt Additional Core Properties.
1327 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1328 xNewId->getContentIdentifier(),
1329 sal_True );
1331 else
1333 // Roll-back.
1334 m_aProps.setTitle( aOldTitle );
1335 m_aProps.setName ( aOldName );
1337 aOldTitle = aOldName = rtl::OUString();
1339 // Set error .
1340 aRet[ nTitlePos ] <<= uno::Exception(
1341 rtl::OUString("Exchange failed!"),
1342 static_cast< cppu::OWeakObject * >( this ) );
1346 if ( !aOldTitle.isEmpty() )
1348 aEvent.PropertyName = rtl::OUString("Title");
1349 aEvent.OldValue = uno::makeAny( aOldTitle );
1350 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() );
1352 aChanges.getArray()[ nChanged ] = aEvent;
1353 nChanged++;
1356 if ( nChanged > 0 )
1358 // Save changes, if content was already made persistent.
1359 if ( !bExchange && ( m_eState == PERSISTENT ) )
1361 if ( !storeData() )
1363 uno::Any aProps
1364 = uno::makeAny(
1365 beans::PropertyValue(
1366 rtl::OUString( "Uri"),
1368 uno::makeAny(m_xIdentifier->
1369 getContentIdentifier()),
1370 beans::PropertyState_DIRECT_VALUE));
1371 ucbhelper::cancelCommandExecution(
1372 ucb::IOErrorCode_CANT_WRITE,
1373 uno::Sequence< uno::Any >(&aProps, 1),
1374 xEnv,
1375 rtl::OUString( "Cannot store persistent data!" ),
1376 this );
1377 // Unreachable
1381 aChanges.realloc( nChanged );
1383 aGuard.clear();
1384 notifyPropertiesChange( aChanges );
1387 return aRet;
1390 //=========================================================================
1391 void HierarchyContent::insert( sal_Int32 nNameClashResolve,
1392 const uno::Reference<
1393 ucb::XCommandEnvironment > & xEnv )
1394 throw( uno::Exception )
1396 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1398 // Am I the root folder?
1399 if ( m_eKind == ROOT )
1401 ucbhelper::cancelCommandExecution(
1402 uno::makeAny( ucb::UnsupportedCommandException(
1403 rtl::OUString( "Not supported by root folder!" ),
1404 static_cast< cppu::OWeakObject * >( this ) ) ),
1405 xEnv );
1406 // Unreachable
1409 // Check, if all required properties were set.
1410 if ( m_aProps.getTitle().isEmpty() )
1412 uno::Sequence< rtl::OUString > aProps( 1 );
1413 aProps[ 0 ] = rtl::OUString("Title");
1414 ucbhelper::cancelCommandExecution(
1415 uno::makeAny( ucb::MissingPropertiesException(
1416 rtl::OUString(),
1417 static_cast< cppu::OWeakObject * >( this ),
1418 aProps ) ),
1419 xEnv );
1420 // Unreachable
1423 // Assemble new content identifier...
1425 uno::Reference< ucb::XContentIdentifier > xId
1426 = makeNewIdentifier( m_aProps.getTitle() );
1428 // Handle possible name clash...
1430 switch ( nNameClashResolve )
1432 // fail.
1433 case ucb::NameClash::ERROR:
1434 if ( hasData( xId ) )
1436 ucbhelper::cancelCommandExecution(
1437 uno::makeAny(
1438 ucb::NameClashException(
1439 rtl::OUString(),
1440 static_cast< cppu::OWeakObject * >( this ),
1441 task::InteractionClassification_ERROR,
1442 m_aProps.getTitle() ) ),
1443 xEnv );
1444 // Unreachable
1446 break;
1448 // replace existing object.
1449 case ucb::NameClash::OVERWRITE:
1450 break;
1452 // "invent" a new valid title.
1453 case ucb::NameClash::RENAME:
1454 if ( hasData( xId ) )
1456 sal_Int32 nTry = 0;
1460 rtl::OUString aNewId = xId->getContentIdentifier();
1461 aNewId += rtl::OUString("_");
1462 aNewId += rtl::OUString::valueOf( ++nTry );
1463 xId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewId );
1465 while ( hasData( xId ) && ( nTry < 1000 ) );
1467 if ( nTry == 1000 )
1469 ucbhelper::cancelCommandExecution(
1470 uno::makeAny(
1471 ucb::UnsupportedNameClashException(
1472 rtl::OUString( "Unable to resolve name clash!" ),
1473 static_cast< cppu::OWeakObject * >( this ),
1474 nNameClashResolve ) ),
1475 xEnv );
1476 // Unreachable
1478 else
1480 rtl::OUString aNewTitle( m_aProps.getTitle() );
1481 aNewTitle += rtl::OUString("_");
1482 aNewTitle += rtl::OUString::valueOf( nTry );
1483 m_aProps.setTitle( aNewTitle );
1486 break;
1488 case ucb::NameClash::KEEP: // deprecated
1489 case ucb::NameClash::ASK:
1490 default:
1491 if ( hasData( xId ) )
1493 ucbhelper::cancelCommandExecution(
1494 uno::makeAny(
1495 ucb::UnsupportedNameClashException(
1496 rtl::OUString(),
1497 static_cast< cppu::OWeakObject * >( this ),
1498 nNameClashResolve ) ),
1499 xEnv );
1500 // Unreachable
1502 break;
1505 // Identifier changed?
1506 sal_Bool bNewId = ( xId->getContentIdentifier()
1507 != m_xIdentifier->getContentIdentifier() );
1508 m_xIdentifier = xId;
1510 if ( !storeData() )
1512 uno::Any aProps
1513 = uno::makeAny(beans::PropertyValue(
1514 rtl::OUString( "Uri"),
1516 uno::makeAny(m_xIdentifier->
1517 getContentIdentifier()),
1518 beans::PropertyState_DIRECT_VALUE));
1519 ucbhelper::cancelCommandExecution(
1520 ucb::IOErrorCode_CANT_WRITE,
1521 uno::Sequence< uno::Any >(&aProps, 1),
1522 xEnv,
1523 rtl::OUString("Cannot store persistent data!"),
1524 this );
1525 // Unreachable
1528 m_eState = PERSISTENT;
1530 if ( bNewId )
1532 aGuard.clear();
1533 inserted();
1537 //=========================================================================
1538 void HierarchyContent::destroy( sal_Bool bDeletePhysical,
1539 const uno::Reference<
1540 ucb::XCommandEnvironment > & xEnv )
1541 throw( uno::Exception )
1543 // @@@ take care about bDeletePhysical -> trashcan support
1545 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1547 uno::Reference< ucb::XContent > xThis = this;
1549 // Persistent?
1550 if ( m_eState != PERSISTENT )
1552 ucbhelper::cancelCommandExecution(
1553 uno::makeAny( ucb::UnsupportedCommandException(
1554 rtl::OUString( "Not persistent!" ),
1555 static_cast< cppu::OWeakObject * >( this ) ) ),
1556 xEnv );
1557 // Unreachable
1560 // Am I the root folder?
1561 if ( m_eKind == ROOT )
1563 ucbhelper::cancelCommandExecution(
1564 uno::makeAny( ucb::UnsupportedCommandException(
1565 rtl::OUString( "Not supported by root folder!" ),
1566 static_cast< cppu::OWeakObject * >( this ) ) ),
1567 xEnv );
1568 // Unreachable
1571 m_eState = DEAD;
1573 aGuard.clear();
1574 deleted();
1576 if ( m_eKind == FOLDER )
1578 // Process instanciated children...
1580 HierarchyContentRefList aChildren;
1581 queryChildren( aChildren );
1583 HierarchyContentRefList::const_iterator it = aChildren.begin();
1584 HierarchyContentRefList::const_iterator end = aChildren.end();
1586 while ( it != end )
1588 (*it)->destroy( bDeletePhysical, xEnv );
1589 ++it;
1594 //=========================================================================
1595 void HierarchyContent::transfer(
1596 const ucb::TransferInfo& rInfo,
1597 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1598 throw( uno::Exception )
1600 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1602 // Persistent?
1603 if ( m_eState != PERSISTENT )
1605 ucbhelper::cancelCommandExecution(
1606 uno::makeAny( ucb::UnsupportedCommandException(
1607 rtl::OUString( "Not persistent!" ),
1608 static_cast< cppu::OWeakObject * >( this ) ) ),
1609 xEnv );
1610 // Unreachable
1613 // Is source a hierarchy content?
1614 if ( ( rInfo.SourceURL.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 2 ) ||
1615 ( rInfo.SourceURL.compareToAscii( HIERARCHY_URL_SCHEME ":/",
1616 HIERARCHY_URL_SCHEME_LENGTH + 2 )
1617 != 0 ) )
1619 ucbhelper::cancelCommandExecution(
1620 uno::makeAny( ucb::InteractiveBadTransferURLException(
1621 rtl::OUString(),
1622 static_cast< cppu::OWeakObject * >( this ) ) ),
1623 xEnv );
1624 // Unreachable
1627 // Is source not a parent of me / not me?
1628 rtl::OUString aId = m_xIdentifier->getContentIdentifier();
1629 sal_Int32 nPos = aId.lastIndexOf( '/' );
1630 if ( nPos != ( aId.getLength() - 1 ) )
1632 // No trailing slash found. Append.
1633 aId += rtl::OUString("/");
1636 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1638 if ( aId.compareTo(
1639 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
1641 uno::Any aProps
1642 = uno::makeAny(beans::PropertyValue(
1643 rtl::OUString( "Uri"),
1645 uno::makeAny(rInfo.SourceURL),
1646 beans::PropertyState_DIRECT_VALUE));
1647 ucbhelper::cancelCommandExecution(
1648 ucb::IOErrorCode_RECURSIVE,
1649 uno::Sequence< uno::Any >(&aProps, 1),
1650 xEnv,
1651 rtl::OUString( "Target is equal to or is a child of source!" ),
1652 this );
1653 // Unreachable
1657 //////////////////////////////////////////////////////////////////////
1658 // 0) Obtain content object for source.
1659 //////////////////////////////////////////////////////////////////////
1661 uno::Reference< ucb::XContentIdentifier > xId
1662 = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL );
1664 // Note: The static cast is okay here, because its sure that
1665 // m_xProvider is always the HierarchyContentProvider.
1666 rtl::Reference< HierarchyContent > xSource;
1670 xSource = static_cast< HierarchyContent * >(
1671 m_xProvider->queryContent( xId ).get() );
1673 catch ( ucb::IllegalIdentifierException const & )
1675 // queryContent
1678 if ( !xSource.is() )
1680 uno::Any aProps
1681 = uno::makeAny(beans::PropertyValue(
1682 rtl::OUString( "Uri"),
1684 uno::makeAny(xId->getContentIdentifier()),
1685 beans::PropertyState_DIRECT_VALUE));
1686 ucbhelper::cancelCommandExecution(
1687 ucb::IOErrorCode_CANT_READ,
1688 uno::Sequence< uno::Any >(&aProps, 1),
1689 xEnv,
1690 rtl::OUString( "Cannot instanciate source object!" ),
1691 this );
1692 // Unreachable
1695 //////////////////////////////////////////////////////////////////////
1696 // 1) Create new child content.
1697 //////////////////////////////////////////////////////////////////////
1699 rtl::OUString aType = xSource->isFolder()
1700 ? rtl::OUString( HIERARCHY_FOLDER_CONTENT_TYPE )
1701 : rtl::OUString( HIERARCHY_LINK_CONTENT_TYPE );
1702 ucb::ContentInfo aContentInfo;
1703 aContentInfo.Type = aType;
1704 aContentInfo.Attributes = 0;
1706 // Note: The static cast is okay here, because its sure that
1707 // createNewContent always creates a HierarchyContent.
1708 rtl::Reference< HierarchyContent > xTarget
1709 = static_cast< HierarchyContent * >(
1710 createNewContent( aContentInfo ).get() );
1711 if ( !xTarget.is() )
1713 uno::Any aProps
1714 = uno::makeAny(beans::PropertyValue(
1715 rtl::OUString( "Folder"),
1717 uno::makeAny(aId),
1718 beans::PropertyState_DIRECT_VALUE));
1719 ucbhelper::cancelCommandExecution(
1720 ucb::IOErrorCode_CANT_CREATE,
1721 uno::Sequence< uno::Any >(&aProps, 1),
1722 xEnv,
1723 rtl::OUString( "XContentCreator::createNewContent failed!" ),
1724 this );
1725 // Unreachable
1728 //////////////////////////////////////////////////////////////////////
1729 // 2) Copy data from source content to child content.
1730 //////////////////////////////////////////////////////////////////////
1732 uno::Sequence< beans::Property > aSourceProps
1733 = xSource->getPropertySetInfo( xEnv )->getProperties();
1734 sal_Int32 nCount = aSourceProps.getLength();
1736 if ( nCount )
1738 sal_Bool bHadTitle = rInfo.NewTitle.isEmpty();
1740 // Get all source values.
1741 uno::Reference< sdbc::XRow > xRow
1742 = xSource->getPropertyValues( aSourceProps );
1744 uno::Sequence< beans::PropertyValue > aValues( nCount );
1745 beans::PropertyValue* pValues = aValues.getArray();
1747 const beans::Property* pProps = aSourceProps.getConstArray();
1748 for ( sal_Int32 n = 0; n < nCount; ++n )
1750 const beans::Property& rProp = pProps[ n ];
1751 beans::PropertyValue& rValue = pValues[ n ];
1753 rValue.Name = rProp.Name;
1754 rValue.Handle = rProp.Handle;
1756 if ( !bHadTitle && rProp.Name == "Title" )
1758 // Set new title instead of original.
1759 bHadTitle = sal_True;
1760 rValue.Value <<= rInfo.NewTitle;
1762 else
1763 rValue.Value = xRow->getObject(
1764 n + 1,
1765 uno::Reference< container::XNameAccess >() );
1767 rValue.State = beans::PropertyState_DIRECT_VALUE;
1769 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1771 // Add Additional Core Property.
1774 xTarget->addProperty( rProp.Name,
1775 rProp.Attributes,
1776 rValue.Value );
1778 catch ( beans::PropertyExistException const & )
1781 catch ( beans::IllegalTypeException const & )
1784 catch ( lang::IllegalArgumentException const & )
1790 // Set target values.
1791 xTarget->setPropertyValues( aValues, xEnv );
1794 //////////////////////////////////////////////////////////////////////
1795 // 3) Commit (insert) child.
1796 //////////////////////////////////////////////////////////////////////
1798 xTarget->insert( rInfo.NameClash, xEnv );
1800 //////////////////////////////////////////////////////////////////////
1801 // 4) Transfer (copy) children of source.
1802 //////////////////////////////////////////////////////////////////////
1804 if ( xSource->isFolder() )
1806 HierarchyEntry aFolder(
1807 m_xSMgr, m_pProvider, xId->getContentIdentifier() );
1808 HierarchyEntry::iterator it;
1810 while ( aFolder.next( it ) )
1812 const HierarchyEntryData& rResult = *it;
1814 rtl::OUString aChildId = xId->getContentIdentifier();
1815 if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() )
1816 aChildId += rtl::OUString("/");
1818 aChildId += rResult.getName();
1820 ucb::TransferInfo aInfo;
1821 aInfo.MoveData = sal_False;
1822 aInfo.NewTitle = rtl::OUString();
1823 aInfo.SourceURL = aChildId;
1824 aInfo.NameClash = rInfo.NameClash;
1826 // Transfer child to target.
1827 xTarget->transfer( aInfo, xEnv );
1831 //////////////////////////////////////////////////////////////////////
1832 // 5) Destroy source ( when moving only ) .
1833 //////////////////////////////////////////////////////////////////////
1835 if ( rInfo.MoveData )
1837 xSource->destroy( sal_True, xEnv );
1839 // Remove all persistent data of source and its children.
1840 if ( !xSource->removeData() )
1842 uno::Any aProps
1843 = uno::makeAny(
1844 beans::PropertyValue(
1845 rtl::OUString( "Uri"),
1847 uno::makeAny(
1848 xSource->m_xIdentifier->
1849 getContentIdentifier()),
1850 beans::PropertyState_DIRECT_VALUE));
1851 ucbhelper::cancelCommandExecution(
1852 ucb::IOErrorCode_CANT_WRITE,
1853 uno::Sequence< uno::Any >(&aProps, 1),
1854 xEnv,
1855 rtl::OUString( "Cannot remove persistent data of source object!" ),
1856 this );
1857 // Unreachable
1860 // Remove own and all children's Additional Core Properties.
1861 xSource->removeAdditionalPropertySet( sal_True );
1865 //=========================================================================
1866 //=========================================================================
1868 // HierarchyContentProperties Implementation.
1870 //=========================================================================
1871 //=========================================================================
1873 uno::Sequence< ucb::ContentInfo >
1874 HierarchyContentProperties::getCreatableContentsInfo() const
1876 if ( getIsFolder() )
1878 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
1880 // Folder.
1881 aSeq.getArray()[ 0 ].Type
1882 = rtl::OUString( HIERARCHY_FOLDER_CONTENT_TYPE );
1883 aSeq.getArray()[ 0 ].Attributes
1884 = ucb::ContentInfoAttribute::KIND_FOLDER;
1886 uno::Sequence< beans::Property > aFolderProps( 1 );
1887 aFolderProps.getArray()[ 0 ] = beans::Property(
1888 rtl::OUString("Title"),
1890 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1891 beans::PropertyAttribute::BOUND );
1892 aSeq.getArray()[ 0 ].Properties = aFolderProps;
1894 // Link.
1895 aSeq.getArray()[ 1 ].Type
1896 = rtl::OUString( HIERARCHY_LINK_CONTENT_TYPE );
1897 aSeq.getArray()[ 1 ].Attributes
1898 = ucb::ContentInfoAttribute::KIND_LINK;
1900 uno::Sequence< beans::Property > aLinkProps( 2 );
1901 aLinkProps.getArray()[ 0 ] = beans::Property(
1902 rtl::OUString("Title"),
1904 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1905 beans::PropertyAttribute::BOUND );
1906 aLinkProps.getArray()[ 1 ] = beans::Property(
1907 rtl::OUString("TargetURL"),
1909 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1910 beans::PropertyAttribute::BOUND );
1911 aSeq.getArray()[ 1 ].Properties = aLinkProps;
1913 return aSeq;
1915 else
1917 return uno::Sequence< ucb::ContentInfo >( 0 );
1921 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */