1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hierarchycontent.cxx,v $
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 /**************************************************************************
36 **************************************************************************
38 - optimize transfer command. "Move" should be implementable much more
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
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
) )
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() )
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
) ) )
128 // Fail, if content does exist.
129 if ( hasData( rxSMgr
, pProvider
, Identifier
) )
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
),
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 //=========================================================================
173 HierarchyContent::~HierarchyContent()
177 //=========================================================================
179 // XInterface methods.
181 //=========================================================================
184 void SAL_CALL
HierarchyContent::acquire()
187 ContentImplHelper::acquire();
190 //=========================================================================
192 void SAL_CALL
HierarchyContent::release()
195 ContentImplHelper::release();
198 //=========================================================================
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() )
221 //=========================================================================
223 // XTypeProvider methods.
225 //=========================================================================
227 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent
);
229 //=========================================================================
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
;
243 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
245 pCollection
= pFolderTypes
;
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
;
266 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
271 static cppu::OTypeCollection
* pDocumentTypes
= 0;
273 pCollection
= pDocumentTypes
;
276 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
278 pCollection
= pDocumentTypes
;
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
;
298 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
302 return (*pCollection
).getTypes();
305 //=========================================================================
307 // XServiceInfo methods.
309 //=========================================================================
312 rtl::OUString SAL_CALL
HierarchyContent::getImplementationName()
313 throw( uno::RuntimeException
)
315 return rtl::OUString::createFromAscii(
316 "com.sun.star.comp.ucb.HierarchyContent" );
319 //=========================================================================
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
);
334 aSNS
.getArray()[ 0 ] = rtl::OUString::createFromAscii(
335 HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME
);
340 //=========================================================================
344 //=========================================================================
347 rtl::OUString SAL_CALL
HierarchyContent::getContentType()
348 throw( uno::RuntimeException
)
350 return m_aProps
.getContentType();
353 //=========================================================================
355 uno::Reference
< ucb::XContentIdentifier
> SAL_CALL
356 HierarchyContent::getIdentifier()
357 throw( uno::RuntimeException
)
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 //=========================================================================
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
)
386 if ( aCommand
.Name
.equalsAsciiL(
387 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
389 //////////////////////////////////////////////////////////////////
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 ),
406 aRet
<<= getPropertyValues( Properties
);
408 else if ( aCommand
.Name
.equalsAsciiL(
409 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
411 //////////////////////////////////////////////////////////////////
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 ),
428 if ( !aProperties
.getLength() )
430 ucbhelper::cancelCommandExecution(
431 uno::makeAny( lang::IllegalArgumentException(
432 rtl::OUString::createFromAscii(
434 static_cast< cppu::OWeakObject
* >( this ),
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 //////////////////////////////////////////////////////////////////
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 ),
480 uno::Reference
< ucb::XDynamicResultSet
> xSet
481 = new DynamicResultSet( m_xSMgr
, this, aOpenCommand
);
484 else if ( ( m_eKind
!= ROOT
) && !isReadOnly() &&
485 aCommand
.Name
.equalsAsciiL(
486 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
488 //////////////////////////////////////////////////////////////////
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 ),
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 //////////////////////////////////////////////////////////////////
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.
529 beans::PropertyValue(
530 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
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),
540 rtl::OUString::createFromAscii(
541 "Cannot remove persistent data!" ),
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 //////////////////////////////////////////////////////////////////
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 ),
572 transfer( aInfo
, Environment
);
576 //////////////////////////////////////////////////////////////////
577 // Unsupported command
578 //////////////////////////////////////////////////////////////////
580 ucbhelper::cancelCommandExecution(
581 uno::makeAny( ucb::UnsupportedCommandException(
583 static_cast< cppu::OWeakObject
* >( this ) ) ),
591 //=========================================================================
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 //=========================================================================
606 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
607 HierarchyContent::queryCreatableContentsInfo()
608 throw( uno::RuntimeException
)
612 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
614 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
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
;
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
;
653 OSL_ENSURE( sal_False
,
654 "queryCreatableContentsInfo called on non-folder object!" );
656 return uno::Sequence
< ucb::ContentInfo
>( 0 );
660 //=========================================================================
662 uno::Reference
< ucb::XContent
> SAL_CALL
663 HierarchyContent::createNewContent( const ucb::ContentInfo
& Info
)
664 throw( uno::RuntimeException
)
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( "/" );
691 aURL
+= rtl::OUString::createFromAscii( "New_Folder" );
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
);
702 OSL_ENSURE( sal_False
,
703 "createNewContent called on non-folder object!" );
704 return uno::Reference
< ucb::XContent
>();
708 //=========================================================================
710 rtl::OUString
HierarchyContent::getParentURL()
712 HierarchyUri
aUri( m_xIdentifier
->getContentIdentifier() );
713 return aUri
.getParentUri();
716 //=========================================================================
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!!!
734 return HierarchyEntry( rxSMgr
, pProvider
, aURL
).hasData();
737 //=========================================================================
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
);
755 HierarchyEntry
aEntry( rxSMgr
, pProvider
, aURL
);
756 HierarchyEntryData aData
;
757 if ( !aEntry
.getData( aData
) )
760 rProps
= HierarchyContentProperties( aData
);
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() )
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"
835 m_bIsReadOnly
= false;
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
) )
868 // Obtain a list with a snapshot of all currently instanciated contents
869 // from provider and extract the contents which are direct children
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();
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!
908 static_cast< HierarchyContent
* >( xChild
.get() ) ) );
915 //=========================================================================
916 sal_Bool
HierarchyContent::exchangeIdentity(
917 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
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!" );
934 // Am I the root folder?
935 if ( m_eKind
== ROOT
)
937 OSL_ENSURE( sal_False
, "HierarchyContent::exchangeIdentity - "
938 "Not supported by root folder!" );
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();
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();
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(
975 xNewId
->getContentIdentifier() );
976 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
977 = new ::ucbhelper::ContentIdentifier(
978 m_xSMgr
, aNewChildURL
);
980 if ( !xChild
->exchangeIdentity( xNewChildId
) )
990 OSL_ENSURE( sal_False
,
991 "HierarchyContent::exchangeIdentity - "
992 "Panic! Cannot exchange identity!" );
996 //=========================================================================
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();
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() );
1051 xRow
->appendVoid( rProp
);
1055 // Not a Core Property! Maybe it's an Additional Core Property?!
1057 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1060 = uno::Reference
< beans::XPropertySet
>(
1061 pProvider
->getAdditionalPropertySet( rContentId
,
1064 bTriedToGetAdditonalPropSet
= sal_True
;
1067 if ( xAdditionalPropSet
.is() )
1069 if ( !xRow
->appendPropertySetValue(
1073 // Append empty entry.
1074 xRow
->appendVoid( rProp
);
1079 // Append empty entry.
1080 xRow
->appendVoid( rProp
);
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
),
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() )
1119 beans::Property( rtl::OUString::createFromAscii( "TargetURL" ),
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
),
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
,
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" ) ) )
1217 aRet
[ n
] <<= lang::IllegalAccessException(
1218 rtl::OUString::createFromAscii(
1219 "Property is read-only!" ),
1220 static_cast< cppu::OWeakObject
* >( this ) );
1224 rtl::OUString aNewValue
;
1225 if ( rValue
.Value
>>= aNewValue
)
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
);
1241 ::ucb_impl::urihelper::encodeSegment(
1244 // property change event will be set later...
1246 // remember position within sequence of values
1247 // (for error handling).
1253 aRet
[ n
] <<= lang::IllegalArgumentException(
1254 rtl::OUString::createFromAscii(
1255 "Empty title not allowed!" ),
1256 static_cast< cppu::OWeakObject
* >( this ),
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" ) ) )
1274 aRet
[ n
] <<= lang::IllegalAccessException(
1275 rtl::OUString::createFromAscii(
1276 "Property is read-only!" ),
1277 static_cast< cppu::OWeakObject
* >( this ) );
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
;
1295 = uno::makeAny( m_aProps
.getTargetURL() );
1297 = uno::makeAny( aNewValue
);
1299 aChanges
.getArray()[ nChanged
] = aEvent
;
1301 m_aProps
.setTargetURL( aNewValue
);
1307 aRet
[ n
] <<= lang::IllegalArgumentException(
1308 rtl::OUString::createFromAscii(
1309 "Empty target URL not allowed!" ),
1310 static_cast< cppu::OWeakObject
* >( this ),
1316 aRet
[ n
] <<= beans::IllegalTypeException(
1317 rtl::OUString::createFromAscii(
1318 "Property value has wrong type!" ),
1319 static_cast< cppu::OWeakObject
* >( this ) );
1324 aRet
[ n
] <<= beans::UnknownPropertyException(
1325 rtl::OUString::createFromAscii(
1326 "TargetURL only supported by links!" ),
1327 static_cast< cppu::OWeakObject
* >( this ) );
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(
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
;
1360 catch ( beans::UnknownPropertyException
const & e
)
1364 catch ( lang::WrappedTargetException
const & e
)
1368 catch ( beans::PropertyVetoException
const & e
)
1372 catch ( lang::IllegalArgumentException
const & e
)
1379 aRet
[ n
] <<= uno::Exception(
1380 rtl::OUString::createFromAscii(
1381 "No property set for storing the value!" ),
1382 static_cast< cppu::OWeakObject
* >( this ) );
1389 uno::Reference
< ucb::XContentIdentifier
> xOldId
1391 uno::Reference
< ucb::XContentIdentifier
> xNewId
1392 = makeNewIdentifier( m_aProps
.getTitle() );
1395 if ( exchangeIdentity( xNewId
) )
1397 // Adapt persistent data.
1398 renameData( xOldId
, xNewId
);
1400 // Adapt Additional Core Properties.
1401 renameAdditionalPropertySet( xOldId
->getContentIdentifier(),
1402 xNewId
->getContentIdentifier(),
1408 m_aProps
.setTitle( aOldTitle
);
1409 m_aProps
.setName ( aOldName
);
1411 aOldTitle
= aOldName
= rtl::OUString();
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
;
1432 // Save changes, if content was already made persistent.
1433 if ( !bExchange
&& ( m_eState
== PERSISTENT
) )
1439 beans::PropertyValue(
1440 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
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),
1450 rtl::OUString::createFromAscii(
1451 "Cannot store persistent data!" ),
1457 aChanges
.realloc( nChanged
);
1460 notifyPropertiesChange( aChanges
);
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 ) ) ),
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(
1494 static_cast< cppu::OWeakObject
* >( this ),
1500 // Assemble new content identifier...
1502 uno::Reference
< ucb::XContentIdentifier
> xId
1503 = makeNewIdentifier( m_aProps
.getTitle() );
1505 // Handle possible name clash...
1507 switch ( nNameClashResolve
)
1510 case ucb::NameClash::ERROR
:
1511 if ( hasData( xId
) )
1513 ucbhelper::cancelCommandExecution(
1515 ucb::NameClashException(
1517 static_cast< cppu::OWeakObject
* >( this ),
1518 task::InteractionClassification_ERROR
,
1519 m_aProps
.getTitle() ) ),
1525 // replace existing object.
1526 case ucb::NameClash::OVERWRITE
:
1529 // "invent" a new valid title.
1530 case ucb::NameClash::RENAME
:
1531 if ( hasData( xId
) )
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 ) );
1546 ucbhelper::cancelCommandExecution(
1548 ucb::UnsupportedNameClashException(
1549 rtl::OUString::createFromAscii(
1550 "Unable to resolve name clash!" ),
1551 static_cast< cppu::OWeakObject
* >( this ),
1552 nNameClashResolve
) ),
1558 rtl::OUString
aNewTitle( m_aProps
.getTitle() );
1559 aNewTitle
+= rtl::OUString::createFromAscii( "_" );
1560 aNewTitle
+= rtl::OUString::valueOf( nTry
);
1561 m_aProps
.setTitle( aNewTitle
);
1566 case ucb::NameClash::KEEP
: // deprecated
1567 case ucb::NameClash::ASK
:
1569 if ( hasData( xId
) )
1571 ucbhelper::cancelCommandExecution(
1573 ucb::UnsupportedNameClashException(
1575 static_cast< cppu::OWeakObject
* >( this ),
1576 nNameClashResolve
) ),
1583 // Identifier changed?
1584 sal_Bool bNewId
= ( xId
->getContentIdentifier()
1585 != m_xIdentifier
->getContentIdentifier() );
1586 m_xIdentifier
= xId
;
1591 = uno::makeAny(beans::PropertyValue(
1592 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
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),
1602 rtl::OUString::createFromAscii( "Cannot store persistent data!" ),
1607 m_eState
= PERSISTENT
;
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;
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 ) ) ),
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 ) ) ),
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();
1669 (*it
)->destroy( bDeletePhysical
, xEnv
);
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
);
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 ) ) ),
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 )
1701 ucbhelper::cancelCommandExecution(
1702 uno::makeAny( ucb::InteractiveBadTransferURLException(
1704 static_cast< cppu::OWeakObject
* >( this ) ) ),
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() )
1721 rInfo
.SourceURL
, rInfo
.SourceURL
.getLength() ) == 0 )
1724 = uno::makeAny(beans::PropertyValue(
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),
1734 rtl::OUString::createFromAscii(
1735 "Target is equal to or is a child of source!" ),
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 & )
1762 if ( !xSource
.is() )
1765 = uno::makeAny(beans::PropertyValue(
1766 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
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),
1775 rtl::OUString::createFromAscii(
1776 "Cannot instanciate source object!" ),
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() )
1800 = uno::makeAny(beans::PropertyValue(
1801 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1805 beans::PropertyState_DIRECT_VALUE
));
1806 ucbhelper::cancelCommandExecution(
1807 ucb::IOErrorCode_CANT_CREATE
,
1808 uno::Sequence
< uno::Any
>(&aProps
, 1),
1810 rtl::OUString::createFromAscii(
1811 "XContentCreator::createNewContent failed!" ),
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();
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
;
1852 rValue
.Value
= xRow
->getObject(
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
,
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() )
1933 beans::PropertyValue(
1934 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
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),
1945 rtl::OUString::createFromAscii(
1946 "Cannot remove persistent data of source object!" ),
1951 // Remove own and all children's Additional Core Properties.
1952 xSource
->removeAdditionalPropertySet( sal_True
);