merge the formfield patch from ooo-build
[ooovba.git] / ucb / source / ucp / hierarchy / hierarchycontent.cxx
blob49774e943f1909e0dc60af38fd17b2384921d386
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hierarchycontent.cxx,v $
10 * $Revision: 1.31 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
35 TODO
36 **************************************************************************
38 - optimize transfer command. "Move" should be implementable much more
39 efficient!
41 **************************************************************************
43 - Root Folder vs. 'normal' Folder
44 - root doesn't support command 'delete'
45 - root doesn't support command 'insert'
46 - root needs not created via XContentCreator - queryContent with root
47 folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0
48 - root has no parent.
50 *************************************************************************/
51 #include <osl/diagnose.h>
53 #include "osl/doublecheckedlocking.h"
54 #include <rtl/ustring.h>
55 #include <rtl/ustring.hxx>
56 #include <com/sun/star/beans/PropertyAttribute.hpp>
57 #include <com/sun/star/beans/PropertyState.hpp>
58 #include <com/sun/star/beans/PropertyValue.hpp>
59 #include <com/sun/star/beans/XPropertyAccess.hpp>
60 #include <com/sun/star/lang/IllegalAccessException.hpp>
61 #include <com/sun/star/sdbc/XRow.hpp>
62 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
63 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
64 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
65 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
66 #include <com/sun/star/ucb/NameClash.hpp>
67 #include <com/sun/star/ucb/NameClashException.hpp>
68 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
69 #include <com/sun/star/ucb/TransferInfo.hpp>
70 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
71 #include <com/sun/star/ucb/XCommandInfo.hpp>
72 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
73 #include <com/sun/star/uno/Any.hxx>
74 #include <com/sun/star/uno/Sequence.hxx>
75 #include <ucbhelper/contentidentifier.hxx>
76 #include <ucbhelper/propertyvalueset.hxx>
77 #include <ucbhelper/cancelcommandexecution.hxx>
78 #include "hierarchycontent.hxx"
79 #include "hierarchyprovider.hxx"
80 #include "dynamicresultset.hxx"
81 #include "hierarchyuri.hxx"
83 #include "../inc/urihelper.hxx"
85 using namespace com::sun::star;
86 using namespace hierarchy_ucp;
88 //=========================================================================
89 //=========================================================================
91 // HierarchyContent Implementation.
93 //=========================================================================
94 //=========================================================================
96 // static ( "virtual" ctor )
97 HierarchyContent* HierarchyContent::create(
98 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
99 HierarchyContentProvider* pProvider,
100 const uno::Reference< ucb::XContentIdentifier >& Identifier )
102 // Fail, if content does not exist.
103 HierarchyContentProperties aProps;
104 if ( !loadData( rxSMgr, pProvider, Identifier, aProps ) )
105 return 0;
107 return new HierarchyContent( rxSMgr, pProvider, Identifier, aProps );
110 //=========================================================================
111 // static ( "virtual" ctor )
112 HierarchyContent* HierarchyContent::create(
113 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
114 HierarchyContentProvider* pProvider,
115 const uno::Reference< ucb::XContentIdentifier >& Identifier,
116 const ucb::ContentInfo& Info )
118 if ( !Info.Type.getLength() )
119 return 0;
121 if ( !Info.Type.equalsAsciiL(
122 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) &&
123 !Info.Type.equalsAsciiL(
124 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) )
125 return 0;
127 #if 0
128 // Fail, if content does exist.
129 if ( hasData( rxSMgr, pProvider, Identifier ) )
130 return 0;
131 #endif
133 return new HierarchyContent( rxSMgr, pProvider, Identifier, Info );
136 //=========================================================================
137 HierarchyContent::HierarchyContent(
138 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
139 HierarchyContentProvider* pProvider,
140 const uno::Reference< ucb::XContentIdentifier >& Identifier,
141 const HierarchyContentProperties& rProps )
142 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
143 m_aProps( rProps ),
144 m_eState( PERSISTENT ),
145 m_pProvider( pProvider ),
146 m_bCheckedReadOnly( false ),
147 m_bIsReadOnly( true )
149 setKind( Identifier );
152 //=========================================================================
153 HierarchyContent::HierarchyContent(
154 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
155 HierarchyContentProvider* pProvider,
156 const uno::Reference< ucb::XContentIdentifier >& Identifier,
157 const ucb::ContentInfo& Info )
158 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
159 m_aProps( Info.Type.equalsAsciiL(
160 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) )
161 ? HierarchyEntryData::FOLDER
162 : HierarchyEntryData::LINK ),
163 m_eState( TRANSIENT ),
164 m_pProvider( pProvider ),
165 m_bCheckedReadOnly( false ),
166 m_bIsReadOnly( true )
168 setKind( Identifier );
171 //=========================================================================
172 // virtual
173 HierarchyContent::~HierarchyContent()
177 //=========================================================================
179 // XInterface methods.
181 //=========================================================================
183 // virtual
184 void SAL_CALL HierarchyContent::acquire()
185 throw( )
187 ContentImplHelper::acquire();
190 //=========================================================================
191 // virtual
192 void SAL_CALL HierarchyContent::release()
193 throw( )
195 ContentImplHelper::release();
198 //=========================================================================
199 // virtual
200 uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType )
201 throw ( uno::RuntimeException )
203 uno::Any aRet = ContentImplHelper::queryInterface( rType );
205 if ( !aRet.hasValue() )
207 // Note: isReadOnly may be relative expensive. So avoid calling it
208 // unless it is really necessary.
209 aRet = cppu::queryInterface(
210 rType, static_cast< ucb::XContentCreator * >( this ) );
211 if ( aRet.hasValue() )
213 if ( !isFolder() || isReadOnly() )
214 return uno::Any();
218 return aRet;
221 //=========================================================================
223 // XTypeProvider methods.
225 //=========================================================================
227 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent );
229 //=========================================================================
230 // virtual
231 uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes()
232 throw( uno::RuntimeException )
234 cppu::OTypeCollection * pCollection = 0;
236 if ( isFolder() && !isReadOnly() )
238 static cppu::OTypeCollection* pFolderTypes = 0;
240 pCollection = pFolderTypes;
241 if ( !pCollection )
243 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
245 pCollection = pFolderTypes;
246 if ( !pCollection )
248 static cppu::OTypeCollection aCollection(
249 CPPU_TYPE_REF( lang::XTypeProvider ),
250 CPPU_TYPE_REF( lang::XServiceInfo ),
251 CPPU_TYPE_REF( lang::XComponent ),
252 CPPU_TYPE_REF( ucb::XContent ),
253 CPPU_TYPE_REF( ucb::XCommandProcessor ),
254 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
255 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
256 CPPU_TYPE_REF( beans::XPropertyContainer ),
257 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
258 CPPU_TYPE_REF( container::XChild ),
259 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
260 pCollection = &aCollection;
261 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
262 pFolderTypes = pCollection;
265 else {
266 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
269 else
271 static cppu::OTypeCollection* pDocumentTypes = 0;
273 pCollection = pDocumentTypes;
274 if ( !pCollection )
276 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
278 pCollection = pDocumentTypes;
279 if ( !pCollection )
281 static cppu::OTypeCollection aCollection(
282 CPPU_TYPE_REF( lang::XTypeProvider ),
283 CPPU_TYPE_REF( lang::XServiceInfo ),
284 CPPU_TYPE_REF( lang::XComponent ),
285 CPPU_TYPE_REF( ucb::XContent ),
286 CPPU_TYPE_REF( ucb::XCommandProcessor ),
287 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
288 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
289 CPPU_TYPE_REF( beans::XPropertyContainer ),
290 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
291 CPPU_TYPE_REF( container::XChild ) );
292 pCollection = &aCollection;
293 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
294 pDocumentTypes = pCollection;
297 else {
298 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
302 return (*pCollection).getTypes();
305 //=========================================================================
307 // XServiceInfo methods.
309 //=========================================================================
311 // virtual
312 rtl::OUString SAL_CALL HierarchyContent::getImplementationName()
313 throw( uno::RuntimeException )
315 return rtl::OUString::createFromAscii(
316 "com.sun.star.comp.ucb.HierarchyContent" );
319 //=========================================================================
320 // virtual
321 uno::Sequence< rtl::OUString > SAL_CALL
322 HierarchyContent::getSupportedServiceNames()
323 throw( uno::RuntimeException )
325 uno::Sequence< rtl::OUString > aSNS( 1 );
327 if ( m_eKind == LINK )
328 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
329 HIERARCHY_LINK_CONTENT_SERVICE_NAME );
330 else if ( m_eKind == FOLDER )
331 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
332 HIERARCHY_FOLDER_CONTENT_SERVICE_NAME );
333 else
334 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
335 HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME );
337 return aSNS;
340 //=========================================================================
342 // XContent methods.
344 //=========================================================================
346 // virtual
347 rtl::OUString SAL_CALL HierarchyContent::getContentType()
348 throw( uno::RuntimeException )
350 return m_aProps.getContentType();
353 //=========================================================================
354 // virtual
355 uno::Reference< ucb::XContentIdentifier > SAL_CALL
356 HierarchyContent::getIdentifier()
357 throw( uno::RuntimeException )
359 // Transient?
360 if ( m_eState == TRANSIENT )
362 // Transient contents have no identifier.
363 return uno::Reference< ucb::XContentIdentifier >();
366 return ContentImplHelper::getIdentifier();
369 //=========================================================================
371 // XCommandProcessor methods.
373 //=========================================================================
375 // virtual
376 uno::Any SAL_CALL HierarchyContent::execute(
377 const ucb::Command& aCommand,
378 sal_Int32 /*CommandId*/,
379 const uno::Reference< ucb::XCommandEnvironment >& Environment )
380 throw( uno::Exception,
381 ucb::CommandAbortedException,
382 uno::RuntimeException )
384 uno::Any aRet;
386 if ( aCommand.Name.equalsAsciiL(
387 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
389 //////////////////////////////////////////////////////////////////
390 // getPropertyValues
391 //////////////////////////////////////////////////////////////////
393 uno::Sequence< beans::Property > Properties;
394 if ( !( aCommand.Argument >>= Properties ) )
396 ucbhelper::cancelCommandExecution(
397 uno::makeAny( lang::IllegalArgumentException(
398 rtl::OUString::createFromAscii(
399 "Wrong argument type!" ),
400 static_cast< cppu::OWeakObject * >( this ),
401 -1 ) ),
402 Environment );
403 // Unreachable
406 aRet <<= getPropertyValues( Properties );
408 else if ( aCommand.Name.equalsAsciiL(
409 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
411 //////////////////////////////////////////////////////////////////
412 // setPropertyValues
413 //////////////////////////////////////////////////////////////////
415 uno::Sequence< beans::PropertyValue > aProperties;
416 if ( !( aCommand.Argument >>= aProperties ) )
418 ucbhelper::cancelCommandExecution(
419 uno::makeAny( lang::IllegalArgumentException(
420 rtl::OUString::createFromAscii(
421 "Wrong argument type!" ),
422 static_cast< cppu::OWeakObject * >( this ),
423 -1 ) ),
424 Environment );
425 // Unreachable
428 if ( !aProperties.getLength() )
430 ucbhelper::cancelCommandExecution(
431 uno::makeAny( lang::IllegalArgumentException(
432 rtl::OUString::createFromAscii(
433 "No properties!" ),
434 static_cast< cppu::OWeakObject * >( this ),
435 -1 ) ),
436 Environment );
437 // Unreachable
440 aRet <<= setPropertyValues( aProperties, Environment );
442 else if ( aCommand.Name.equalsAsciiL(
443 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
445 //////////////////////////////////////////////////////////////////
446 // getPropertySetInfo
447 //////////////////////////////////////////////////////////////////
449 aRet <<= getPropertySetInfo( Environment );
451 else if ( aCommand.Name.equalsAsciiL(
452 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
454 //////////////////////////////////////////////////////////////////
455 // getCommandInfo
456 //////////////////////////////////////////////////////////////////
458 aRet <<= getCommandInfo( Environment );
460 else if ( isFolder() && aCommand.Name.equalsAsciiL(
461 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
463 //////////////////////////////////////////////////////////////////
464 // open command for a folder content
465 //////////////////////////////////////////////////////////////////
467 ucb::OpenCommandArgument2 aOpenCommand;
468 if ( !( aCommand.Argument >>= aOpenCommand ) )
470 ucbhelper::cancelCommandExecution(
471 uno::makeAny( lang::IllegalArgumentException(
472 rtl::OUString::createFromAscii(
473 "Wrong argument type!" ),
474 static_cast< cppu::OWeakObject * >( this ),
475 -1 ) ),
476 Environment );
477 // Unreachable
480 uno::Reference< ucb::XDynamicResultSet > xSet
481 = new DynamicResultSet( m_xSMgr, this, aOpenCommand );
482 aRet <<= xSet;
484 else if ( ( m_eKind != ROOT ) && !isReadOnly() &&
485 aCommand.Name.equalsAsciiL(
486 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
488 //////////////////////////////////////////////////////////////////
489 // insert
490 // ( Not available at root folder )
491 //////////////////////////////////////////////////////////////////
493 ucb::InsertCommandArgument aArg;
494 if ( !( aCommand.Argument >>= aArg ) )
496 ucbhelper::cancelCommandExecution(
497 uno::makeAny( lang::IllegalArgumentException(
498 rtl::OUString::createFromAscii(
499 "Wrong argument type!" ),
500 static_cast< cppu::OWeakObject * >( this ),
501 -1 ) ),
502 Environment );
503 // Unreachable
506 sal_Int32 nNameClash = aArg.ReplaceExisting
507 ? ucb::NameClash::OVERWRITE
508 : ucb::NameClash::ERROR;
509 insert( nNameClash, Environment );
511 else if ( ( m_eKind != ROOT ) && !isReadOnly() &&
512 aCommand.Name.equalsAsciiL(
513 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
515 //////////////////////////////////////////////////////////////////
516 // delete
517 // ( Not available at root folder )
518 //////////////////////////////////////////////////////////////////
520 sal_Bool bDeletePhysical = sal_False;
521 aCommand.Argument >>= bDeletePhysical;
522 destroy( bDeletePhysical, Environment );
524 // Remove own and all children's persistent data.
525 if ( !removeData() )
527 uno::Any aProps
528 = uno::makeAny(
529 beans::PropertyValue(
530 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
531 "Uri")),
533 uno::makeAny(m_xIdentifier->
534 getContentIdentifier()),
535 beans::PropertyState_DIRECT_VALUE));
536 ucbhelper::cancelCommandExecution(
537 ucb::IOErrorCode_CANT_WRITE,
538 uno::Sequence< uno::Any >(&aProps, 1),
539 Environment,
540 rtl::OUString::createFromAscii(
541 "Cannot remove persistent data!" ),
542 this );
543 // Unreachable
546 // Remove own and all children's Additional Core Properties.
547 removeAdditionalPropertySet( sal_True );
549 else if ( isFolder() && !isReadOnly() &&
550 aCommand.Name.equalsAsciiL(
551 RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) )
553 //////////////////////////////////////////////////////////////////
554 // transfer
555 // ( Not available at link objects )
556 //////////////////////////////////////////////////////////////////
558 ucb::TransferInfo aInfo;
559 if ( !( aCommand.Argument >>= aInfo ) )
561 OSL_ENSURE( sal_False, "Wrong argument type!" );
562 ucbhelper::cancelCommandExecution(
563 uno::makeAny( lang::IllegalArgumentException(
564 rtl::OUString::createFromAscii(
565 "Wrong argument type!" ),
566 static_cast< cppu::OWeakObject * >( this ),
567 -1 ) ),
568 Environment );
569 // Unreachable
572 transfer( aInfo, Environment );
574 else
576 //////////////////////////////////////////////////////////////////
577 // Unsupported command
578 //////////////////////////////////////////////////////////////////
580 ucbhelper::cancelCommandExecution(
581 uno::makeAny( ucb::UnsupportedCommandException(
582 rtl::OUString(),
583 static_cast< cppu::OWeakObject * >( this ) ) ),
584 Environment );
585 // Unreachable
588 return aRet;
591 //=========================================================================
592 // virtual
593 void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ )
594 throw( uno::RuntimeException )
596 // @@@ Generally, no action takes much time...
599 //=========================================================================
601 // XContentCreator methods.
603 //=========================================================================
605 // virtual
606 uno::Sequence< ucb::ContentInfo > SAL_CALL
607 HierarchyContent::queryCreatableContentsInfo()
608 throw( uno::RuntimeException )
610 if ( isFolder() )
612 osl::Guard< osl::Mutex > aGuard( m_aMutex );
614 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
616 // Folder.
617 aSeq.getArray()[ 0 ].Type
618 = rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE );
619 aSeq.getArray()[ 0 ].Attributes
620 = ucb::ContentInfoAttribute::KIND_FOLDER;
622 uno::Sequence< beans::Property > aFolderProps( 1 );
623 aFolderProps.getArray()[ 0 ] = beans::Property(
624 rtl::OUString::createFromAscii( "Title" ),
626 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
627 beans::PropertyAttribute::BOUND );
628 aSeq.getArray()[ 0 ].Properties = aFolderProps;
630 // Link.
631 aSeq.getArray()[ 1 ].Type
632 = rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE );
633 aSeq.getArray()[ 1 ].Attributes
634 = ucb::ContentInfoAttribute::KIND_LINK;
636 uno::Sequence< beans::Property > aLinkProps( 2 );
637 aLinkProps.getArray()[ 0 ] = beans::Property(
638 rtl::OUString::createFromAscii( "Title" ),
640 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
641 beans::PropertyAttribute::BOUND );
642 aLinkProps.getArray()[ 1 ] = beans::Property(
643 rtl::OUString::createFromAscii( "TargetURL" ),
645 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
646 beans::PropertyAttribute::BOUND );
647 aSeq.getArray()[ 1 ].Properties = aLinkProps;
649 return aSeq;
651 else
653 OSL_ENSURE( sal_False,
654 "queryCreatableContentsInfo called on non-folder object!" );
656 return uno::Sequence< ucb::ContentInfo >( 0 );
660 //=========================================================================
661 // virtual
662 uno::Reference< ucb::XContent > SAL_CALL
663 HierarchyContent::createNewContent( const ucb::ContentInfo& Info )
664 throw( uno::RuntimeException )
666 if ( isFolder() )
668 osl::Guard< osl::Mutex > aGuard( m_aMutex );
670 if ( !Info.Type.getLength() )
671 return uno::Reference< ucb::XContent >();
673 sal_Bool bCreateFolder =
674 Info.Type.equalsAsciiL(
675 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) );
677 if ( !bCreateFolder &&
678 !Info.Type.equalsAsciiL(
679 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) )
680 return uno::Reference< ucb::XContent >();
682 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
684 OSL_ENSURE( aURL.getLength() > 0,
685 "HierarchyContent::createNewContent - empty identifier!" );
687 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
688 aURL += rtl::OUString::createFromAscii( "/" );
690 if ( bCreateFolder )
691 aURL += rtl::OUString::createFromAscii( "New_Folder" );
692 else
693 aURL += rtl::OUString::createFromAscii( "New_Link" );
695 uno::Reference< ucb::XContentIdentifier > xId
696 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
698 return create( m_xSMgr, m_pProvider, xId, Info );
700 else
702 OSL_ENSURE( sal_False,
703 "createNewContent called on non-folder object!" );
704 return uno::Reference< ucb::XContent >();
708 //=========================================================================
709 // virtual
710 rtl::OUString HierarchyContent::getParentURL()
712 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
713 return aUri.getParentUri();
716 //=========================================================================
717 //static
718 sal_Bool HierarchyContent::hasData(
719 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
720 HierarchyContentProvider* pProvider,
721 const uno::Reference< ucb::XContentIdentifier >& Identifier )
723 rtl::OUString aURL = Identifier->getContentIdentifier();
725 // Am I a root folder?
726 HierarchyUri aUri( aURL );
727 if ( aUri.isRootFolder() )
729 // hasData must always return 'true' for root folder
730 // even if no persistent data exist!!!
731 return sal_True;
734 return HierarchyEntry( rxSMgr, pProvider, aURL ).hasData();
737 //=========================================================================
738 //static
739 sal_Bool HierarchyContent::loadData(
740 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
741 HierarchyContentProvider* pProvider,
742 const uno::Reference< ucb::XContentIdentifier >& Identifier,
743 HierarchyContentProperties& rProps )
745 rtl::OUString aURL = Identifier->getContentIdentifier();
747 // Am I a root folder?
748 HierarchyUri aUri( aURL );
749 if ( aUri.isRootFolder() )
751 rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER );
753 else
755 HierarchyEntry aEntry( rxSMgr, pProvider, aURL );
756 HierarchyEntryData aData;
757 if ( !aEntry.getData( aData ) )
758 return sal_False;
760 rProps = HierarchyContentProperties( aData );
762 return sal_True;
765 //=========================================================================
766 sal_Bool HierarchyContent::storeData()
768 HierarchyEntry aEntry(
769 m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() );
770 return aEntry.setData( m_aProps.getHierarchyEntryData(), sal_True );
773 //=========================================================================
774 sal_Bool HierarchyContent::renameData(
775 const uno::Reference< ucb::XContentIdentifier >& xOldId,
776 const uno::Reference< ucb::XContentIdentifier >& xNewId )
778 HierarchyEntry aEntry(
779 m_xSMgr, m_pProvider, xOldId->getContentIdentifier() );
780 return aEntry.move( xNewId->getContentIdentifier(),
781 m_aProps.getHierarchyEntryData() );
784 //=========================================================================
785 sal_Bool HierarchyContent::removeData()
787 HierarchyEntry aEntry(
788 m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() );
789 return aEntry.remove();
792 //=========================================================================
793 void HierarchyContent::setKind(
794 const uno::Reference< ucb::XContentIdentifier >& Identifier )
796 if ( m_aProps.getIsFolder() )
798 // Am I a root folder?
799 HierarchyUri aUri( Identifier->getContentIdentifier() );
800 if ( aUri.isRootFolder() )
801 m_eKind = ROOT;
802 else
803 m_eKind = FOLDER;
805 else
806 m_eKind = LINK;
809 //=========================================================================
810 bool HierarchyContent::isReadOnly()
812 if ( !m_bCheckedReadOnly )
814 osl::Guard< osl::Mutex > aGuard( m_aMutex );
815 if ( !m_bCheckedReadOnly )
817 m_bCheckedReadOnly = true;
818 m_bIsReadOnly = true;
820 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
821 uno::Reference< lang::XMultiServiceFactory > xConfigProv
822 = m_pProvider->getConfigProvider( aUri.getService() );
823 if ( xConfigProv.is() )
825 uno::Sequence< rtl::OUString > aNames
826 = xConfigProv->getAvailableServiceNames();
827 sal_Int32 nCount = aNames.getLength();
828 for ( sal_Int32 n = 0; n < nCount; ++n )
830 if ( aNames[ n ].equalsAsciiL(
831 RTL_CONSTASCII_STRINGPARAM(
832 "com.sun.star.ucb.HierarchyDataReadWriteAccess"
833 ) ) )
835 m_bIsReadOnly = false;
836 break;
843 return m_bIsReadOnly;
846 //=========================================================================
847 uno::Reference< ucb::XContentIdentifier >
848 HierarchyContent::makeNewIdentifier( const rtl::OUString& rTitle )
850 osl::Guard< osl::Mutex > aGuard( m_aMutex );
852 // Assemble new content identifier...
853 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
854 rtl::OUString aNewURL = aUri.getParentUri();
855 aNewURL += rtl::OUString::createFromAscii( "/" );
856 aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle );
858 return uno::Reference< ucb::XContentIdentifier >(
859 new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ) );
862 //=========================================================================
863 void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren )
865 if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) )
866 return;
868 // Obtain a list with a snapshot of all currently instanciated contents
869 // from provider and extract the contents which are direct children
870 // of this content.
872 ::ucbhelper::ContentRefList aAllContents;
873 m_xProvider->queryExistingContents( aAllContents );
875 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
876 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
878 if ( nURLPos != ( aURL.getLength() - 1 ) )
880 // No trailing slash found. Append.
881 aURL += rtl::OUString::createFromAscii( "/" );
884 sal_Int32 nLen = aURL.getLength();
886 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
887 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
889 while ( it != end )
891 ::ucbhelper::ContentImplHelperRef xChild = (*it);
892 rtl::OUString aChildURL
893 = xChild->getIdentifier()->getContentIdentifier();
895 // Is aURL a prefix of aChildURL?
896 if ( ( aChildURL.getLength() > nLen ) &&
897 ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
899 sal_Int32 nPos = nLen;
900 nPos = aChildURL.indexOf( '/', nPos );
902 if ( ( nPos == -1 ) ||
903 ( nPos == ( aChildURL.getLength() - 1 ) ) )
905 // No further slashes/ only a final slash. It's a child!
906 rChildren.push_back(
907 HierarchyContentRef(
908 static_cast< HierarchyContent * >( xChild.get() ) ) );
911 ++it;
915 //=========================================================================
916 sal_Bool HierarchyContent::exchangeIdentity(
917 const uno::Reference< ucb::XContentIdentifier >& xNewId )
919 if ( !xNewId.is() )
920 return sal_False;
922 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
924 uno::Reference< ucb::XContent > xThis = this;
926 // Already persistent?
927 if ( m_eState != PERSISTENT )
929 OSL_ENSURE( sal_False,
930 "HierarchyContent::exchangeIdentity - Not persistent!" );
931 return sal_False;
934 // Am I the root folder?
935 if ( m_eKind == ROOT )
937 OSL_ENSURE( sal_False, "HierarchyContent::exchangeIdentity - "
938 "Not supported by root folder!" );
939 return sal_False;
942 // Exchange own identitity.
944 // Fail, if a content with given id already exists.
945 if ( !hasData( xNewId ) )
947 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
949 aGuard.clear();
950 if ( exchange( xNewId ) )
952 if ( m_eKind == FOLDER )
954 // Process instanciated children...
956 HierarchyContentRefList aChildren;
957 queryChildren( aChildren );
959 HierarchyContentRefList::const_iterator it = aChildren.begin();
960 HierarchyContentRefList::const_iterator end = aChildren.end();
962 while ( it != end )
964 HierarchyContentRef xChild = (*it);
966 // Create new content identifier for the child...
967 uno::Reference< ucb::XContentIdentifier > xOldChildId
968 = xChild->getIdentifier();
969 rtl::OUString aOldChildURL
970 = xOldChildId->getContentIdentifier();
971 rtl::OUString aNewChildURL
972 = aOldChildURL.replaceAt(
974 aOldURL.getLength(),
975 xNewId->getContentIdentifier() );
976 uno::Reference< ucb::XContentIdentifier > xNewChildId
977 = new ::ucbhelper::ContentIdentifier(
978 m_xSMgr, aNewChildURL );
980 if ( !xChild->exchangeIdentity( xNewChildId ) )
981 return sal_False;
983 ++it;
986 return sal_True;
990 OSL_ENSURE( sal_False,
991 "HierarchyContent::exchangeIdentity - "
992 "Panic! Cannot exchange identity!" );
993 return sal_False;
996 //=========================================================================
997 // static
998 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
999 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
1000 const uno::Sequence< beans::Property >& rProperties,
1001 const HierarchyContentProperties& rData,
1002 HierarchyContentProvider* pProvider,
1003 const rtl::OUString& rContentId )
1005 // Note: Empty sequence means "get values of all supported properties".
1007 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
1008 = new ::ucbhelper::PropertyValueSet( rSMgr );
1010 sal_Int32 nCount = rProperties.getLength();
1011 if ( nCount )
1013 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
1014 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1016 const beans::Property* pProps = rProperties.getConstArray();
1017 for ( sal_Int32 n = 0; n < nCount; ++n )
1019 const beans::Property& rProp = pProps[ n ];
1021 // Process Core properties.
1023 if ( rProp.Name.equalsAsciiL(
1024 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1026 xRow->appendString ( rProp, rData.getContentType() );
1028 else if ( rProp.Name.equalsAsciiL(
1029 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1031 xRow->appendString ( rProp, rData.getTitle() );
1033 else if ( rProp.Name.equalsAsciiL(
1034 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1036 xRow->appendBoolean( rProp, rData.getIsDocument() );
1038 else if ( rProp.Name.equalsAsciiL(
1039 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1041 xRow->appendBoolean( rProp, rData.getIsFolder() );
1043 else if ( rProp.Name.equalsAsciiL(
1044 RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) )
1046 // TargetURL is only supported by links.
1048 if ( rData.getIsDocument() )
1049 xRow->appendString( rProp, rData.getTargetURL() );
1050 else
1051 xRow->appendVoid( rProp );
1053 else
1055 // Not a Core Property! Maybe it's an Additional Core Property?!
1057 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1059 xAdditionalPropSet
1060 = uno::Reference< beans::XPropertySet >(
1061 pProvider->getAdditionalPropertySet( rContentId,
1062 sal_False ),
1063 uno::UNO_QUERY );
1064 bTriedToGetAdditonalPropSet = sal_True;
1067 if ( xAdditionalPropSet.is() )
1069 if ( !xRow->appendPropertySetValue(
1070 xAdditionalPropSet,
1071 rProp ) )
1073 // Append empty entry.
1074 xRow->appendVoid( rProp );
1077 else
1079 // Append empty entry.
1080 xRow->appendVoid( rProp );
1085 else
1087 // Append all Core Properties.
1088 xRow->appendString (
1089 beans::Property( rtl::OUString::createFromAscii( "ContentType" ),
1091 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1092 beans::PropertyAttribute::BOUND
1093 | beans::PropertyAttribute::READONLY ),
1094 rData.getContentType() );
1095 xRow->appendString (
1096 beans::Property( rtl::OUString::createFromAscii( "Title" ),
1098 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1099 // @@@ Might actually be read-only!
1100 beans::PropertyAttribute::BOUND ),
1101 rData.getTitle() );
1102 xRow->appendBoolean(
1103 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
1105 getCppuBooleanType(),
1106 beans::PropertyAttribute::BOUND
1107 | beans::PropertyAttribute::READONLY ),
1108 rData.getIsDocument() );
1109 xRow->appendBoolean(
1110 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ),
1112 getCppuBooleanType(),
1113 beans::PropertyAttribute::BOUND
1114 | beans::PropertyAttribute::READONLY ),
1115 rData.getIsFolder() );
1117 if ( rData.getIsDocument() )
1118 xRow->appendString(
1119 beans::Property( rtl::OUString::createFromAscii( "TargetURL" ),
1121 getCppuType(
1122 static_cast< const rtl::OUString * >( 0 ) ),
1123 // @@@ Might actually be read-only!
1124 beans::PropertyAttribute::BOUND ),
1125 rData.getTargetURL() );
1127 // Append all Additional Core Properties.
1129 uno::Reference< beans::XPropertySet > xSet(
1130 pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1131 uno::UNO_QUERY );
1132 xRow->appendPropertySet( xSet );
1135 return uno::Reference< sdbc::XRow >( xRow.get() );
1138 //=========================================================================
1139 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
1140 const uno::Sequence< beans::Property >& rProperties )
1142 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1143 return getPropertyValues( m_xSMgr,
1144 rProperties,
1145 m_aProps,
1146 m_pProvider,
1147 m_xIdentifier->getContentIdentifier() );
1150 //=========================================================================
1151 uno::Sequence< uno::Any > HierarchyContent::setPropertyValues(
1152 const uno::Sequence< beans::PropertyValue >& rValues,
1153 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1154 throw( uno::Exception )
1156 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1158 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1159 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1160 sal_Int32 nChanged = 0;
1162 beans::PropertyChangeEvent aEvent;
1163 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1164 aEvent.Further = sal_False;
1165 // aEvent.PropertyName =
1166 aEvent.PropertyHandle = -1;
1167 // aEvent.OldValue =
1168 // aEvent.NewValue =
1170 const beans::PropertyValue* pValues = rValues.getConstArray();
1171 sal_Int32 nCount = rValues.getLength();
1173 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1174 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1176 sal_Bool bExchange = sal_False;
1177 rtl::OUString aOldTitle;
1178 rtl::OUString aOldName;
1179 sal_Int32 nTitlePos = -1;
1181 for ( sal_Int32 n = 0; n < nCount; ++n )
1183 const beans::PropertyValue& rValue = pValues[ n ];
1185 if ( rValue.Name.equalsAsciiL(
1186 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1188 // Read-only property!
1189 aRet[ n ] <<= lang::IllegalAccessException(
1190 rtl::OUString::createFromAscii(
1191 "Property is read-only!" ),
1192 static_cast< cppu::OWeakObject * >( this ) );
1194 else if ( rValue.Name.equalsAsciiL(
1195 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1197 // Read-only property!
1198 aRet[ n ] <<= lang::IllegalAccessException(
1199 rtl::OUString::createFromAscii(
1200 "Property is read-only!" ),
1201 static_cast< cppu::OWeakObject * >( this ) );
1203 else if ( rValue.Name.equalsAsciiL(
1204 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1206 // Read-only property!
1207 aRet[ n ] <<= lang::IllegalAccessException(
1208 rtl::OUString::createFromAscii(
1209 "Property is read-only!" ),
1210 static_cast< cppu::OWeakObject * >( this ) );
1212 else if ( rValue.Name.equalsAsciiL(
1213 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1215 if ( isReadOnly() )
1217 aRet[ n ] <<= lang::IllegalAccessException(
1218 rtl::OUString::createFromAscii(
1219 "Property is read-only!" ),
1220 static_cast< cppu::OWeakObject * >( this ) );
1222 else
1224 rtl::OUString aNewValue;
1225 if ( rValue.Value >>= aNewValue )
1227 // No empty titles!
1228 if ( aNewValue.getLength() > 0 )
1230 if ( aNewValue != m_aProps.getTitle() )
1232 // modified title -> modified URL -> exchange !
1233 if ( m_eState == PERSISTENT )
1234 bExchange = sal_True;
1236 aOldTitle = m_aProps.getTitle();
1237 aOldName = m_aProps.getName();
1239 m_aProps.setTitle( aNewValue );
1240 m_aProps.setName(
1241 ::ucb_impl::urihelper::encodeSegment(
1242 aNewValue ) );
1244 // property change event will be set later...
1246 // remember position within sequence of values
1247 // (for error handling).
1248 nTitlePos = n;
1251 else
1253 aRet[ n ] <<= lang::IllegalArgumentException(
1254 rtl::OUString::createFromAscii(
1255 "Empty title not allowed!" ),
1256 static_cast< cppu::OWeakObject * >( this ),
1257 -1 );
1260 else
1262 aRet[ n ] <<= beans::IllegalTypeException(
1263 rtl::OUString::createFromAscii(
1264 "Property value has wrong type!" ),
1265 static_cast< cppu::OWeakObject * >( this ) );
1269 else if ( rValue.Name.equalsAsciiL(
1270 RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) )
1272 if ( isReadOnly() )
1274 aRet[ n ] <<= lang::IllegalAccessException(
1275 rtl::OUString::createFromAscii(
1276 "Property is read-only!" ),
1277 static_cast< cppu::OWeakObject * >( this ) );
1279 else
1281 // TargetURL is only supported by links.
1283 if ( m_eKind == LINK )
1285 rtl::OUString aNewValue;
1286 if ( rValue.Value >>= aNewValue )
1288 // No empty target URL's!
1289 if ( aNewValue.getLength() > 0 )
1291 if ( aNewValue != m_aProps.getTargetURL() )
1293 aEvent.PropertyName = rValue.Name;
1294 aEvent.OldValue
1295 = uno::makeAny( m_aProps.getTargetURL() );
1296 aEvent.NewValue
1297 = uno::makeAny( aNewValue );
1299 aChanges.getArray()[ nChanged ] = aEvent;
1301 m_aProps.setTargetURL( aNewValue );
1302 nChanged++;
1305 else
1307 aRet[ n ] <<= lang::IllegalArgumentException(
1308 rtl::OUString::createFromAscii(
1309 "Empty target URL not allowed!" ),
1310 static_cast< cppu::OWeakObject * >( this ),
1311 -1 );
1314 else
1316 aRet[ n ] <<= beans::IllegalTypeException(
1317 rtl::OUString::createFromAscii(
1318 "Property value has wrong type!" ),
1319 static_cast< cppu::OWeakObject * >( this ) );
1322 else
1324 aRet[ n ] <<= beans::UnknownPropertyException(
1325 rtl::OUString::createFromAscii(
1326 "TargetURL only supported by links!" ),
1327 static_cast< cppu::OWeakObject * >( this ) );
1331 else
1333 // Not a Core Property! Maybe it's an Additional Core Property?!
1335 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1337 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1338 bTriedToGetAdditonalPropSet = sal_True;
1341 if ( xAdditionalPropSet.is() )
1345 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1346 rValue.Name );
1347 if ( aOldValue != rValue.Value )
1349 xAdditionalPropSet->setPropertyValue(
1350 rValue.Name, rValue.Value );
1352 aEvent.PropertyName = rValue.Name;
1353 aEvent.OldValue = aOldValue;
1354 aEvent.NewValue = rValue.Value;
1356 aChanges.getArray()[ nChanged ] = aEvent;
1357 nChanged++;
1360 catch ( beans::UnknownPropertyException const & e )
1362 aRet[ n ] <<= e;
1364 catch ( lang::WrappedTargetException const & e )
1366 aRet[ n ] <<= e;
1368 catch ( beans::PropertyVetoException const & e )
1370 aRet[ n ] <<= e;
1372 catch ( lang::IllegalArgumentException const & e )
1374 aRet[ n ] <<= e;
1377 else
1379 aRet[ n ] <<= uno::Exception(
1380 rtl::OUString::createFromAscii(
1381 "No property set for storing the value!" ),
1382 static_cast< cppu::OWeakObject * >( this ) );
1387 if ( bExchange )
1389 uno::Reference< ucb::XContentIdentifier > xOldId
1390 = m_xIdentifier;
1391 uno::Reference< ucb::XContentIdentifier > xNewId
1392 = makeNewIdentifier( m_aProps.getTitle() );
1394 aGuard.clear();
1395 if ( exchangeIdentity( xNewId ) )
1397 // Adapt persistent data.
1398 renameData( xOldId, xNewId );
1400 // Adapt Additional Core Properties.
1401 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1402 xNewId->getContentIdentifier(),
1403 sal_True );
1405 else
1407 // Roll-back.
1408 m_aProps.setTitle( aOldTitle );
1409 m_aProps.setName ( aOldName );
1411 aOldTitle = aOldName = rtl::OUString();
1413 // Set error .
1414 aRet[ nTitlePos ] <<= uno::Exception(
1415 rtl::OUString::createFromAscii( "Exchange failed!" ),
1416 static_cast< cppu::OWeakObject * >( this ) );
1420 if ( aOldTitle.getLength() )
1422 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" );
1423 aEvent.OldValue = uno::makeAny( aOldTitle );
1424 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() );
1426 aChanges.getArray()[ nChanged ] = aEvent;
1427 nChanged++;
1430 if ( nChanged > 0 )
1432 // Save changes, if content was already made persistent.
1433 if ( !bExchange && ( m_eState == PERSISTENT ) )
1435 if ( !storeData() )
1437 uno::Any aProps
1438 = uno::makeAny(
1439 beans::PropertyValue(
1440 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1441 "Uri")),
1443 uno::makeAny(m_xIdentifier->
1444 getContentIdentifier()),
1445 beans::PropertyState_DIRECT_VALUE));
1446 ucbhelper::cancelCommandExecution(
1447 ucb::IOErrorCode_CANT_WRITE,
1448 uno::Sequence< uno::Any >(&aProps, 1),
1449 xEnv,
1450 rtl::OUString::createFromAscii(
1451 "Cannot store persistent data!" ),
1452 this );
1453 // Unreachable
1457 aChanges.realloc( nChanged );
1459 aGuard.clear();
1460 notifyPropertiesChange( aChanges );
1463 return aRet;
1466 //=========================================================================
1467 void HierarchyContent::insert( sal_Int32 nNameClashResolve,
1468 const uno::Reference<
1469 ucb::XCommandEnvironment > & xEnv )
1470 throw( uno::Exception )
1472 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1474 // Am I the root folder?
1475 if ( m_eKind == ROOT )
1477 ucbhelper::cancelCommandExecution(
1478 uno::makeAny( ucb::UnsupportedCommandException(
1479 rtl::OUString::createFromAscii(
1480 "Not supported by root folder!" ),
1481 static_cast< cppu::OWeakObject * >( this ) ) ),
1482 xEnv );
1483 // Unreachable
1486 // Check, if all required properties were set.
1487 if ( m_aProps.getTitle().getLength() == 0 )
1489 uno::Sequence< rtl::OUString > aProps( 1 );
1490 aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" );
1491 ucbhelper::cancelCommandExecution(
1492 uno::makeAny( ucb::MissingPropertiesException(
1493 rtl::OUString(),
1494 static_cast< cppu::OWeakObject * >( this ),
1495 aProps ) ),
1496 xEnv );
1497 // Unreachable
1500 // Assemble new content identifier...
1502 uno::Reference< ucb::XContentIdentifier > xId
1503 = makeNewIdentifier( m_aProps.getTitle() );
1505 // Handle possible name clash...
1507 switch ( nNameClashResolve )
1509 // fail.
1510 case ucb::NameClash::ERROR:
1511 if ( hasData( xId ) )
1513 ucbhelper::cancelCommandExecution(
1514 uno::makeAny(
1515 ucb::NameClashException(
1516 rtl::OUString(),
1517 static_cast< cppu::OWeakObject * >( this ),
1518 task::InteractionClassification_ERROR,
1519 m_aProps.getTitle() ) ),
1520 xEnv );
1521 // Unreachable
1523 break;
1525 // replace existing object.
1526 case ucb::NameClash::OVERWRITE:
1527 break;
1529 // "invent" a new valid title.
1530 case ucb::NameClash::RENAME:
1531 if ( hasData( xId ) )
1533 sal_Int32 nTry = 0;
1537 rtl::OUString aNewId = xId->getContentIdentifier();
1538 aNewId += rtl::OUString::createFromAscii( "_" );
1539 aNewId += rtl::OUString::valueOf( ++nTry );
1540 xId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewId );
1542 while ( hasData( xId ) && ( nTry < 1000 ) );
1544 if ( nTry == 1000 )
1546 ucbhelper::cancelCommandExecution(
1547 uno::makeAny(
1548 ucb::UnsupportedNameClashException(
1549 rtl::OUString::createFromAscii(
1550 "Unable to resolve name clash!" ),
1551 static_cast< cppu::OWeakObject * >( this ),
1552 nNameClashResolve ) ),
1553 xEnv );
1554 // Unreachable
1556 else
1558 rtl::OUString aNewTitle( m_aProps.getTitle() );
1559 aNewTitle += rtl::OUString::createFromAscii( "_" );
1560 aNewTitle += rtl::OUString::valueOf( nTry );
1561 m_aProps.setTitle( aNewTitle );
1564 break;
1566 case ucb::NameClash::KEEP: // deprecated
1567 case ucb::NameClash::ASK:
1568 default:
1569 if ( hasData( xId ) )
1571 ucbhelper::cancelCommandExecution(
1572 uno::makeAny(
1573 ucb::UnsupportedNameClashException(
1574 rtl::OUString(),
1575 static_cast< cppu::OWeakObject * >( this ),
1576 nNameClashResolve ) ),
1577 xEnv );
1578 // Unreachable
1580 break;
1583 // Identifier changed?
1584 sal_Bool bNewId = ( xId->getContentIdentifier()
1585 != m_xIdentifier->getContentIdentifier() );
1586 m_xIdentifier = xId;
1588 if ( !storeData() )
1590 uno::Any aProps
1591 = uno::makeAny(beans::PropertyValue(
1592 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1593 "Uri")),
1595 uno::makeAny(m_xIdentifier->
1596 getContentIdentifier()),
1597 beans::PropertyState_DIRECT_VALUE));
1598 ucbhelper::cancelCommandExecution(
1599 ucb::IOErrorCode_CANT_WRITE,
1600 uno::Sequence< uno::Any >(&aProps, 1),
1601 xEnv,
1602 rtl::OUString::createFromAscii( "Cannot store persistent data!" ),
1603 this );
1604 // Unreachable
1607 m_eState = PERSISTENT;
1609 if ( bNewId )
1611 aGuard.clear();
1612 inserted();
1616 //=========================================================================
1617 void HierarchyContent::destroy( sal_Bool bDeletePhysical,
1618 const uno::Reference<
1619 ucb::XCommandEnvironment > & xEnv )
1620 throw( uno::Exception )
1622 // @@@ take care about bDeletePhysical -> trashcan support
1624 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1626 uno::Reference< ucb::XContent > xThis = this;
1628 // Persistent?
1629 if ( m_eState != PERSISTENT )
1631 ucbhelper::cancelCommandExecution(
1632 uno::makeAny( ucb::UnsupportedCommandException(
1633 rtl::OUString::createFromAscii(
1634 "Not persistent!" ),
1635 static_cast< cppu::OWeakObject * >( this ) ) ),
1636 xEnv );
1637 // Unreachable
1640 // Am I the root folder?
1641 if ( m_eKind == ROOT )
1643 ucbhelper::cancelCommandExecution(
1644 uno::makeAny( ucb::UnsupportedCommandException(
1645 rtl::OUString::createFromAscii(
1646 "Not supported by root folder!" ),
1647 static_cast< cppu::OWeakObject * >( this ) ) ),
1648 xEnv );
1649 // Unreachable
1652 m_eState = DEAD;
1654 aGuard.clear();
1655 deleted();
1657 if ( m_eKind == FOLDER )
1659 // Process instanciated children...
1661 HierarchyContentRefList aChildren;
1662 queryChildren( aChildren );
1664 HierarchyContentRefList::const_iterator it = aChildren.begin();
1665 HierarchyContentRefList::const_iterator end = aChildren.end();
1667 while ( it != end )
1669 (*it)->destroy( bDeletePhysical, xEnv );
1670 ++it;
1675 //=========================================================================
1676 void HierarchyContent::transfer(
1677 const ucb::TransferInfo& rInfo,
1678 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1679 throw( uno::Exception )
1681 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1683 // Persistent?
1684 if ( m_eState != PERSISTENT )
1686 ucbhelper::cancelCommandExecution(
1687 uno::makeAny( ucb::UnsupportedCommandException(
1688 rtl::OUString::createFromAscii(
1689 "Not persistent!" ),
1690 static_cast< cppu::OWeakObject * >( this ) ) ),
1691 xEnv );
1692 // Unreachable
1695 // Is source a hierarchy content?
1696 if ( ( rInfo.SourceURL.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 2 ) ||
1697 ( rInfo.SourceURL.compareToAscii( HIERARCHY_URL_SCHEME ":/",
1698 HIERARCHY_URL_SCHEME_LENGTH + 2 )
1699 != 0 ) )
1701 ucbhelper::cancelCommandExecution(
1702 uno::makeAny( ucb::InteractiveBadTransferURLException(
1703 rtl::OUString(),
1704 static_cast< cppu::OWeakObject * >( this ) ) ),
1705 xEnv );
1706 // Unreachable
1709 // Is source not a parent of me / not me?
1710 rtl::OUString aId = m_xIdentifier->getContentIdentifier();
1711 sal_Int32 nPos = aId.lastIndexOf( '/' );
1712 if ( nPos != ( aId.getLength() - 1 ) )
1714 // No trailing slash found. Append.
1715 aId += rtl::OUString::createFromAscii( "/" );
1718 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1720 if ( aId.compareTo(
1721 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
1723 uno::Any aProps
1724 = uno::makeAny(beans::PropertyValue(
1725 rtl::OUString(
1726 RTL_CONSTASCII_USTRINGPARAM("Uri")),
1728 uno::makeAny(rInfo.SourceURL),
1729 beans::PropertyState_DIRECT_VALUE));
1730 ucbhelper::cancelCommandExecution(
1731 ucb::IOErrorCode_RECURSIVE,
1732 uno::Sequence< uno::Any >(&aProps, 1),
1733 xEnv,
1734 rtl::OUString::createFromAscii(
1735 "Target is equal to or is a child of source!" ),
1736 this );
1737 // Unreachable
1741 //////////////////////////////////////////////////////////////////////
1742 // 0) Obtain content object for source.
1743 //////////////////////////////////////////////////////////////////////
1745 uno::Reference< ucb::XContentIdentifier > xId
1746 = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL );
1748 // Note: The static cast is okay here, because its sure that
1749 // m_xProvider is always the HierarchyContentProvider.
1750 rtl::Reference< HierarchyContent > xSource;
1754 xSource = static_cast< HierarchyContent * >(
1755 m_xProvider->queryContent( xId ).get() );
1757 catch ( ucb::IllegalIdentifierException const & )
1759 // queryContent
1762 if ( !xSource.is() )
1764 uno::Any aProps
1765 = uno::makeAny(beans::PropertyValue(
1766 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1767 "Uri")),
1769 uno::makeAny(xId->getContentIdentifier()),
1770 beans::PropertyState_DIRECT_VALUE));
1771 ucbhelper::cancelCommandExecution(
1772 ucb::IOErrorCode_CANT_READ,
1773 uno::Sequence< uno::Any >(&aProps, 1),
1774 xEnv,
1775 rtl::OUString::createFromAscii(
1776 "Cannot instanciate source object!" ),
1777 this );
1778 // Unreachable
1781 //////////////////////////////////////////////////////////////////////
1782 // 1) Create new child content.
1783 //////////////////////////////////////////////////////////////////////
1785 rtl::OUString aType = xSource->isFolder()
1786 ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE )
1787 : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE );
1788 ucb::ContentInfo aContentInfo;
1789 aContentInfo.Type = aType;
1790 aContentInfo.Attributes = 0;
1792 // Note: The static cast is okay here, because its sure that
1793 // createNewContent always creates a HierarchyContent.
1794 rtl::Reference< HierarchyContent > xTarget
1795 = static_cast< HierarchyContent * >(
1796 createNewContent( aContentInfo ).get() );
1797 if ( !xTarget.is() )
1799 uno::Any aProps
1800 = uno::makeAny(beans::PropertyValue(
1801 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1802 "Folder")),
1804 uno::makeAny(aId),
1805 beans::PropertyState_DIRECT_VALUE));
1806 ucbhelper::cancelCommandExecution(
1807 ucb::IOErrorCode_CANT_CREATE,
1808 uno::Sequence< uno::Any >(&aProps, 1),
1809 xEnv,
1810 rtl::OUString::createFromAscii(
1811 "XContentCreator::createNewContent failed!" ),
1812 this );
1813 // Unreachable
1816 //////////////////////////////////////////////////////////////////////
1817 // 2) Copy data from source content to child content.
1818 //////////////////////////////////////////////////////////////////////
1820 uno::Sequence< beans::Property > aSourceProps
1821 = xSource->getPropertySetInfo( xEnv )->getProperties();
1822 sal_Int32 nCount = aSourceProps.getLength();
1824 if ( nCount )
1826 sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 );
1828 // Get all source values.
1829 uno::Reference< sdbc::XRow > xRow
1830 = xSource->getPropertyValues( aSourceProps );
1832 uno::Sequence< beans::PropertyValue > aValues( nCount );
1833 beans::PropertyValue* pValues = aValues.getArray();
1835 const beans::Property* pProps = aSourceProps.getConstArray();
1836 for ( sal_Int32 n = 0; n < nCount; ++n )
1838 const beans::Property& rProp = pProps[ n ];
1839 beans::PropertyValue& rValue = pValues[ n ];
1841 rValue.Name = rProp.Name;
1842 rValue.Handle = rProp.Handle;
1844 if ( !bHadTitle && rProp.Name.equalsAsciiL(
1845 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1847 // Set new title instead of original.
1848 bHadTitle = sal_True;
1849 rValue.Value <<= rInfo.NewTitle;
1851 else
1852 rValue.Value = xRow->getObject(
1853 n + 1,
1854 uno::Reference< container::XNameAccess >() );
1856 rValue.State = beans::PropertyState_DIRECT_VALUE;
1858 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1860 // Add Additional Core Property.
1863 xTarget->addProperty( rProp.Name,
1864 rProp.Attributes,
1865 rValue.Value );
1867 catch ( beans::PropertyExistException const & )
1870 catch ( beans::IllegalTypeException const & )
1873 catch ( lang::IllegalArgumentException const & )
1879 // Set target values.
1880 xTarget->setPropertyValues( aValues, xEnv );
1883 //////////////////////////////////////////////////////////////////////
1884 // 3) Commit (insert) child.
1885 //////////////////////////////////////////////////////////////////////
1887 xTarget->insert( rInfo.NameClash, xEnv );
1889 //////////////////////////////////////////////////////////////////////
1890 // 4) Transfer (copy) children of source.
1891 //////////////////////////////////////////////////////////////////////
1893 if ( xSource->isFolder() )
1895 HierarchyEntry aFolder(
1896 m_xSMgr, m_pProvider, xId->getContentIdentifier() );
1897 HierarchyEntry::iterator it;
1899 while ( aFolder.next( it ) )
1901 const HierarchyEntryData& rResult = *it;
1903 rtl::OUString aChildId = xId->getContentIdentifier();
1904 if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() )
1905 aChildId += rtl::OUString::createFromAscii( "/" );
1907 aChildId += rResult.getName();
1909 ucb::TransferInfo aInfo;
1910 aInfo.MoveData = sal_False;
1911 aInfo.NewTitle = rtl::OUString();
1912 aInfo.SourceURL = aChildId;
1913 aInfo.NameClash = rInfo.NameClash;
1915 // Transfer child to target.
1916 xTarget->transfer( aInfo, xEnv );
1920 //////////////////////////////////////////////////////////////////////
1921 // 5) Destroy source ( when moving only ) .
1922 //////////////////////////////////////////////////////////////////////
1924 if ( rInfo.MoveData )
1926 xSource->destroy( sal_True, xEnv );
1928 // Remove all persistent data of source and its children.
1929 if ( !xSource->removeData() )
1931 uno::Any aProps
1932 = uno::makeAny(
1933 beans::PropertyValue(
1934 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1935 "Uri")),
1937 uno::makeAny(
1938 xSource->m_xIdentifier->
1939 getContentIdentifier()),
1940 beans::PropertyState_DIRECT_VALUE));
1941 ucbhelper::cancelCommandExecution(
1942 ucb::IOErrorCode_CANT_WRITE,
1943 uno::Sequence< uno::Any >(&aProps, 1),
1944 xEnv,
1945 rtl::OUString::createFromAscii(
1946 "Cannot remove persistent data of source object!" ),
1947 this );
1948 // Unreachable
1951 // Remove own and all children's Additional Core Properties.
1952 xSource->removeAdditionalPropertySet( sal_True );