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