1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
23 **************************************************************************
25 - optimize transfer command. "Move" should be implementable much more
28 **************************************************************************
30 - Root Folder vs. 'normal' Folder
31 - root doesn't support command 'delete'
32 - root doesn't support command 'insert'
33 - root needs not created via XContentCreator - queryContent with root
34 folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0
37 *************************************************************************/
38 #include <osl/diagnose.h>
40 #include "osl/doublecheckedlocking.h"
41 #include <rtl/ustring.h>
42 #include <rtl/ustring.hxx>
43 #include <com/sun/star/beans/PropertyAttribute.hpp>
44 #include <com/sun/star/beans/PropertyState.hpp>
45 #include <com/sun/star/beans/PropertyValue.hpp>
46 #include <com/sun/star/beans/XPropertyAccess.hpp>
47 #include <com/sun/star/lang/IllegalAccessException.hpp>
48 #include <com/sun/star/sdbc/XRow.hpp>
49 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
50 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
51 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
52 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
53 #include <com/sun/star/ucb/NameClash.hpp>
54 #include <com/sun/star/ucb/NameClashException.hpp>
55 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
56 #include <com/sun/star/ucb/TransferInfo.hpp>
57 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
58 #include <com/sun/star/ucb/XCommandInfo.hpp>
59 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
60 #include <com/sun/star/uno/Any.hxx>
61 #include <com/sun/star/uno/Sequence.hxx>
62 #include <comphelper/processfactory.hxx>
63 #include <ucbhelper/contentidentifier.hxx>
64 #include <ucbhelper/propertyvalueset.hxx>
65 #include <ucbhelper/cancelcommandexecution.hxx>
66 #include "hierarchycontent.hxx"
67 #include "hierarchyprovider.hxx"
68 #include "dynamicresultset.hxx"
69 #include "hierarchyuri.hxx"
71 #include "../inc/urihelper.hxx"
73 using namespace com::sun::star
;
74 using namespace hierarchy_ucp
;
76 //=========================================================================
77 //=========================================================================
79 // HierarchyContent Implementation.
81 //=========================================================================
82 //=========================================================================
84 // static ( "virtual" ctor )
85 HierarchyContent
* HierarchyContent::create(
86 const uno::Reference
< uno::XComponentContext
>& rxContext
,
87 HierarchyContentProvider
* pProvider
,
88 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
90 // Fail, if content does not exist.
91 HierarchyContentProperties aProps
;
92 if ( !loadData( rxContext
, pProvider
, Identifier
, aProps
) )
95 return new HierarchyContent( rxContext
, pProvider
, Identifier
, aProps
);
98 //=========================================================================
99 // static ( "virtual" ctor )
100 HierarchyContent
* HierarchyContent::create(
101 const uno::Reference
< uno::XComponentContext
>& rxContext
,
102 HierarchyContentProvider
* pProvider
,
103 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
104 const ucb::ContentInfo
& Info
)
106 if ( Info
.Type
.isEmpty() )
109 if ( Info
.Type
!= HIERARCHY_FOLDER_CONTENT_TYPE
&& Info
.Type
!= HIERARCHY_LINK_CONTENT_TYPE
)
112 return new HierarchyContent( rxContext
, pProvider
, Identifier
, Info
);
115 //=========================================================================
116 HierarchyContent::HierarchyContent(
117 const uno::Reference
< uno::XComponentContext
>& rxContext
,
118 HierarchyContentProvider
* pProvider
,
119 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
120 const HierarchyContentProperties
& rProps
)
121 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
123 m_eState( PERSISTENT
),
124 m_pProvider( pProvider
),
125 m_bCheckedReadOnly( false ),
126 m_bIsReadOnly( true )
128 setKind( Identifier
);
131 //=========================================================================
132 HierarchyContent::HierarchyContent(
133 const uno::Reference
< uno::XComponentContext
>& rxContext
,
134 HierarchyContentProvider
* pProvider
,
135 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
136 const ucb::ContentInfo
& Info
)
137 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
138 m_aProps( Info
.Type
== HIERARCHY_FOLDER_CONTENT_TYPE
? HierarchyEntryData::FOLDER
: HierarchyEntryData::LINK
),
139 m_eState( TRANSIENT
),
140 m_pProvider( pProvider
),
141 m_bCheckedReadOnly( false ),
142 m_bIsReadOnly( true )
144 setKind( Identifier
);
147 //=========================================================================
149 HierarchyContent::~HierarchyContent()
153 //=========================================================================
155 // XInterface methods.
157 //=========================================================================
160 void SAL_CALL
HierarchyContent::acquire()
163 ContentImplHelper::acquire();
166 //=========================================================================
168 void SAL_CALL
HierarchyContent::release()
171 ContentImplHelper::release();
174 //=========================================================================
176 uno::Any SAL_CALL
HierarchyContent::queryInterface( const uno::Type
& rType
)
177 throw ( uno::RuntimeException
)
179 uno::Any aRet
= ContentImplHelper::queryInterface( rType
);
181 if ( !aRet
.hasValue() )
183 // Note: isReadOnly may be relative expensive. So avoid calling it
184 // unless it is really necessary.
185 aRet
= cppu::queryInterface(
186 rType
, static_cast< ucb::XContentCreator
* >( this ) );
187 if ( aRet
.hasValue() )
189 if ( !isFolder() || isReadOnly() )
197 //=========================================================================
199 // XTypeProvider methods.
201 //=========================================================================
203 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent
);
205 //=========================================================================
207 uno::Sequence
< uno::Type
> SAL_CALL
HierarchyContent::getTypes()
208 throw( uno::RuntimeException
)
210 cppu::OTypeCollection
* pCollection
= 0;
212 if ( isFolder() && !isReadOnly() )
214 static cppu::OTypeCollection
* pFolderTypes
= 0;
216 pCollection
= pFolderTypes
;
219 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
221 pCollection
= pFolderTypes
;
224 static cppu::OTypeCollection
aCollection(
225 CPPU_TYPE_REF( lang::XTypeProvider
),
226 CPPU_TYPE_REF( lang::XServiceInfo
),
227 CPPU_TYPE_REF( lang::XComponent
),
228 CPPU_TYPE_REF( ucb::XContent
),
229 CPPU_TYPE_REF( ucb::XCommandProcessor
),
230 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
231 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
232 CPPU_TYPE_REF( beans::XPropertyContainer
),
233 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
234 CPPU_TYPE_REF( container::XChild
),
235 CPPU_TYPE_REF( ucb::XContentCreator
) ); // !!
236 pCollection
= &aCollection
;
237 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
238 pFolderTypes
= pCollection
;
242 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
247 static cppu::OTypeCollection
* pDocumentTypes
= 0;
249 pCollection
= pDocumentTypes
;
252 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
254 pCollection
= pDocumentTypes
;
257 static cppu::OTypeCollection
aCollection(
258 CPPU_TYPE_REF( lang::XTypeProvider
),
259 CPPU_TYPE_REF( lang::XServiceInfo
),
260 CPPU_TYPE_REF( lang::XComponent
),
261 CPPU_TYPE_REF( ucb::XContent
),
262 CPPU_TYPE_REF( ucb::XCommandProcessor
),
263 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
264 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
265 CPPU_TYPE_REF( beans::XPropertyContainer
),
266 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
267 CPPU_TYPE_REF( container::XChild
) );
268 pCollection
= &aCollection
;
269 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
270 pDocumentTypes
= pCollection
;
274 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
278 return (*pCollection
).getTypes();
281 //=========================================================================
283 // XServiceInfo methods.
285 //=========================================================================
288 rtl::OUString SAL_CALL
HierarchyContent::getImplementationName()
289 throw( uno::RuntimeException
)
291 return rtl::OUString( "com.sun.star.comp.ucb.HierarchyContent" );
294 //=========================================================================
296 uno::Sequence
< rtl::OUString
> SAL_CALL
297 HierarchyContent::getSupportedServiceNames()
298 throw( uno::RuntimeException
)
300 uno::Sequence
< rtl::OUString
> aSNS( 1 );
302 if ( m_eKind
== LINK
)
303 aSNS
.getArray()[ 0 ] = rtl::OUString( HIERARCHY_LINK_CONTENT_SERVICE_NAME
);
304 else if ( m_eKind
== FOLDER
)
305 aSNS
.getArray()[ 0 ] = rtl::OUString( HIERARCHY_FOLDER_CONTENT_SERVICE_NAME
);
307 aSNS
.getArray()[ 0 ] = rtl::OUString( HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME
);
312 //=========================================================================
316 //=========================================================================
319 rtl::OUString SAL_CALL
HierarchyContent::getContentType()
320 throw( uno::RuntimeException
)
322 return m_aProps
.getContentType();
325 //=========================================================================
327 uno::Reference
< ucb::XContentIdentifier
> SAL_CALL
328 HierarchyContent::getIdentifier()
329 throw( uno::RuntimeException
)
332 if ( m_eState
== TRANSIENT
)
334 // Transient contents have no identifier.
335 return uno::Reference
< ucb::XContentIdentifier
>();
338 return ContentImplHelper::getIdentifier();
341 //=========================================================================
343 // XCommandProcessor methods.
345 //=========================================================================
348 uno::Any SAL_CALL
HierarchyContent::execute(
349 const ucb::Command
& aCommand
,
350 sal_Int32
/*CommandId*/,
351 const uno::Reference
< ucb::XCommandEnvironment
>& Environment
)
352 throw( uno::Exception
,
353 ucb::CommandAbortedException
,
354 uno::RuntimeException
)
358 if ( aCommand
.Name
== "getPropertyValues" )
360 //////////////////////////////////////////////////////////////////
362 //////////////////////////////////////////////////////////////////
364 uno::Sequence
< beans::Property
> Properties
;
365 if ( !( aCommand
.Argument
>>= Properties
) )
367 ucbhelper::cancelCommandExecution(
368 uno::makeAny( lang::IllegalArgumentException(
369 rtl::OUString( "Wrong argument type!" ),
370 static_cast< cppu::OWeakObject
* >( this ),
376 aRet
<<= getPropertyValues( Properties
);
378 else if ( aCommand
.Name
== "setPropertyValues" )
380 //////////////////////////////////////////////////////////////////
382 //////////////////////////////////////////////////////////////////
384 uno::Sequence
< beans::PropertyValue
> aProperties
;
385 if ( !( aCommand
.Argument
>>= aProperties
) )
387 ucbhelper::cancelCommandExecution(
388 uno::makeAny( lang::IllegalArgumentException(
389 rtl::OUString( "Wrong argument type!" ),
390 static_cast< cppu::OWeakObject
* >( this ),
396 if ( !aProperties
.getLength() )
398 ucbhelper::cancelCommandExecution(
399 uno::makeAny( lang::IllegalArgumentException(
400 rtl::OUString( "No properties!" ),
401 static_cast< cppu::OWeakObject
* >( this ),
407 aRet
<<= setPropertyValues( aProperties
, Environment
);
409 else if ( aCommand
.Name
== "getPropertySetInfo" )
411 //////////////////////////////////////////////////////////////////
412 // getPropertySetInfo
413 //////////////////////////////////////////////////////////////////
415 aRet
<<= getPropertySetInfo( Environment
);
417 else if ( aCommand
.Name
== "getCommandInfo" )
419 //////////////////////////////////////////////////////////////////
421 //////////////////////////////////////////////////////////////////
423 aRet
<<= getCommandInfo( Environment
);
425 else if ( aCommand
.Name
== "open" && isFolder() )
427 //////////////////////////////////////////////////////////////////
428 // open command for a folder content
429 //////////////////////////////////////////////////////////////////
431 ucb::OpenCommandArgument2 aOpenCommand
;
432 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
434 ucbhelper::cancelCommandExecution(
435 uno::makeAny( lang::IllegalArgumentException(
436 rtl::OUString( "Wrong argument type!" ),
437 static_cast< cppu::OWeakObject
* >( this ),
443 uno::Reference
< ucb::XDynamicResultSet
> xSet
444 = new DynamicResultSet( m_xContext
, this, aOpenCommand
);
447 else if ( aCommand
.Name
== "insert" && ( m_eKind
!= ROOT
) && !isReadOnly() )
449 //////////////////////////////////////////////////////////////////
451 // ( Not available at root folder )
452 //////////////////////////////////////////////////////////////////
454 ucb::InsertCommandArgument aArg
;
455 if ( !( aCommand
.Argument
>>= aArg
) )
457 ucbhelper::cancelCommandExecution(
458 uno::makeAny( lang::IllegalArgumentException(
459 rtl::OUString( "Wrong argument type!" ),
460 static_cast< cppu::OWeakObject
* >( this ),
466 sal_Int32 nNameClash
= aArg
.ReplaceExisting
467 ? ucb::NameClash::OVERWRITE
468 : ucb::NameClash::ERROR
;
469 insert( nNameClash
, Environment
);
471 else if ( aCommand
.Name
== "delete" && ( m_eKind
!= ROOT
) && !isReadOnly() )
473 //////////////////////////////////////////////////////////////////
475 // ( Not available at root folder )
476 //////////////////////////////////////////////////////////////////
478 sal_Bool bDeletePhysical
= sal_False
;
479 aCommand
.Argument
>>= bDeletePhysical
;
480 destroy( bDeletePhysical
, Environment
);
482 // Remove own and all children's persistent data.
487 beans::PropertyValue(
488 rtl::OUString( "Uri"),
490 uno::makeAny(m_xIdentifier
->
491 getContentIdentifier()),
492 beans::PropertyState_DIRECT_VALUE
));
493 ucbhelper::cancelCommandExecution(
494 ucb::IOErrorCode_CANT_WRITE
,
495 uno::Sequence
< uno::Any
>(&aProps
, 1),
497 rtl::OUString( "Cannot remove persistent data!" ),
502 // Remove own and all children's Additional Core Properties.
503 removeAdditionalPropertySet( sal_True
);
505 else if ( aCommand
.Name
== "transfer" && isFolder() && !isReadOnly() )
507 //////////////////////////////////////////////////////////////////
509 // ( Not available at link objects )
510 //////////////////////////////////////////////////////////////////
512 ucb::TransferInfo aInfo
;
513 if ( !( aCommand
.Argument
>>= aInfo
) )
515 OSL_FAIL( "Wrong argument type!" );
516 ucbhelper::cancelCommandExecution(
517 uno::makeAny( lang::IllegalArgumentException(
518 rtl::OUString( "Wrong argument type!" ),
519 static_cast< cppu::OWeakObject
* >( this ),
525 transfer( aInfo
, Environment
);
527 else if ( aCommand
.Name
== "createNewContent" && isFolder() && !isReadOnly() )
529 //////////////////////////////////////////////////////////////////
531 // ( Not available at link objects )
532 //////////////////////////////////////////////////////////////////
534 ucb::ContentInfo aInfo
;
535 if ( !( aCommand
.Argument
>>= aInfo
) )
537 OSL_FAIL( "Wrong argument type!" );
538 ucbhelper::cancelCommandExecution(
539 uno::makeAny( lang::IllegalArgumentException(
540 rtl::OUString( "Wrong argument type!" ),
541 static_cast< cppu::OWeakObject
* >( this ),
547 aRet
<<= createNewContent( aInfo
);
551 //////////////////////////////////////////////////////////////////
552 // Unsupported command
553 //////////////////////////////////////////////////////////////////
555 ucbhelper::cancelCommandExecution(
556 uno::makeAny( ucb::UnsupportedCommandException(
558 static_cast< cppu::OWeakObject
* >( this ) ) ),
566 //=========================================================================
568 void SAL_CALL
HierarchyContent::abort( sal_Int32
/*CommandId*/ )
569 throw( uno::RuntimeException
)
571 // @@@ Generally, no action takes much time...
574 //=========================================================================
576 // XContentCreator methods.
578 //=========================================================================
581 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
582 HierarchyContent::queryCreatableContentsInfo()
583 throw( uno::RuntimeException
)
585 return m_aProps
.getCreatableContentsInfo();
588 //=========================================================================
590 uno::Reference
< ucb::XContent
> SAL_CALL
591 HierarchyContent::createNewContent( const ucb::ContentInfo
& Info
)
592 throw( uno::RuntimeException
)
596 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
598 if ( Info
.Type
.isEmpty() )
599 return uno::Reference
< ucb::XContent
>();
601 sal_Bool bCreateFolder
= Info
.Type
== HIERARCHY_FOLDER_CONTENT_TYPE
;
603 if ( !bCreateFolder
&& Info
.Type
!= HIERARCHY_LINK_CONTENT_TYPE
)
604 return uno::Reference
< ucb::XContent
>();
606 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
608 OSL_ENSURE( !aURL
.isEmpty(),
609 "HierarchyContent::createNewContent - empty identifier!" );
611 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
612 aURL
+= rtl::OUString("/");
615 aURL
+= rtl::OUString("New_Folder");
617 aURL
+= rtl::OUString("New_Link");
619 uno::Reference
< ucb::XContentIdentifier
> xId
620 = new ::ucbhelper::ContentIdentifier( aURL
);
622 return create( m_xContext
, m_pProvider
, xId
, Info
);
626 OSL_FAIL( "createNewContent called on non-folder object!" );
627 return uno::Reference
< ucb::XContent
>();
631 //=========================================================================
633 rtl::OUString
HierarchyContent::getParentURL()
635 HierarchyUri
aUri( m_xIdentifier
->getContentIdentifier() );
636 return aUri
.getParentUri();
639 //=========================================================================
641 sal_Bool
HierarchyContent::hasData(
642 const uno::Reference
< uno::XComponentContext
>& rxContext
,
643 HierarchyContentProvider
* pProvider
,
644 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
646 rtl::OUString aURL
= Identifier
->getContentIdentifier();
648 // Am I a root folder?
649 HierarchyUri
aUri( aURL
);
650 if ( aUri
.isRootFolder() )
652 // hasData must always return 'true' for root folder
653 // even if no persistent data exist!!!
657 return HierarchyEntry( rxContext
, pProvider
, aURL
).hasData();
660 //=========================================================================
662 sal_Bool
HierarchyContent::loadData(
663 const uno::Reference
< uno::XComponentContext
>& rxContext
,
664 HierarchyContentProvider
* pProvider
,
665 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
666 HierarchyContentProperties
& rProps
)
668 rtl::OUString aURL
= Identifier
->getContentIdentifier();
670 // Am I a root folder?
671 HierarchyUri
aUri( aURL
);
672 if ( aUri
.isRootFolder() )
674 rProps
= HierarchyContentProperties( HierarchyEntryData::FOLDER
);
678 HierarchyEntry
aEntry( rxContext
, pProvider
, aURL
);
679 HierarchyEntryData aData
;
680 if ( !aEntry
.getData( aData
) )
683 rProps
= HierarchyContentProperties( aData
);
688 //=========================================================================
689 sal_Bool
HierarchyContent::storeData()
691 HierarchyEntry
aEntry(
692 m_xContext
, m_pProvider
, m_xIdentifier
->getContentIdentifier() );
693 return aEntry
.setData( m_aProps
.getHierarchyEntryData(), sal_True
);
696 //=========================================================================
697 sal_Bool
HierarchyContent::renameData(
698 const uno::Reference
< ucb::XContentIdentifier
>& xOldId
,
699 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
701 HierarchyEntry
aEntry(
702 m_xContext
, m_pProvider
, xOldId
->getContentIdentifier() );
703 return aEntry
.move( xNewId
->getContentIdentifier(),
704 m_aProps
.getHierarchyEntryData() );
707 //=========================================================================
708 sal_Bool
HierarchyContent::removeData()
710 HierarchyEntry
aEntry(
711 m_xContext
, m_pProvider
, m_xIdentifier
->getContentIdentifier() );
712 return aEntry
.remove();
715 //=========================================================================
716 void HierarchyContent::setKind(
717 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
)
719 if ( m_aProps
.getIsFolder() )
721 // Am I a root folder?
722 HierarchyUri
aUri( Identifier
->getContentIdentifier() );
723 if ( aUri
.isRootFolder() )
732 //=========================================================================
733 bool HierarchyContent::isReadOnly()
735 if ( !m_bCheckedReadOnly
)
737 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
738 if ( !m_bCheckedReadOnly
)
740 m_bCheckedReadOnly
= true;
741 m_bIsReadOnly
= true;
743 HierarchyUri
aUri( m_xIdentifier
->getContentIdentifier() );
744 uno::Reference
< lang::XMultiServiceFactory
> xConfigProv
745 = m_pProvider
->getConfigProvider( aUri
.getService() );
746 if ( xConfigProv
.is() )
748 uno::Sequence
< rtl::OUString
> aNames
749 = xConfigProv
->getAvailableServiceNames();
750 sal_Int32 nCount
= aNames
.getLength();
751 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
753 if ( aNames
[ n
] == "com.sun.star.ucb.HierarchyDataReadWriteAccess" )
755 m_bIsReadOnly
= false;
763 return m_bIsReadOnly
;
766 //=========================================================================
767 uno::Reference
< ucb::XContentIdentifier
>
768 HierarchyContent::makeNewIdentifier( const rtl::OUString
& rTitle
)
770 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
772 // Assemble new content identifier...
773 HierarchyUri
aUri( m_xIdentifier
->getContentIdentifier() );
774 rtl::OUString aNewURL
= aUri
.getParentUri();
775 aNewURL
+= rtl::OUString("/");
776 aNewURL
+= ::ucb_impl::urihelper::encodeSegment( rTitle
);
778 return uno::Reference
< ucb::XContentIdentifier
>(
779 new ::ucbhelper::ContentIdentifier( aNewURL
) );
782 //=========================================================================
783 void HierarchyContent::queryChildren( HierarchyContentRefList
& rChildren
)
785 if ( ( m_eKind
!= FOLDER
) && ( m_eKind
!= ROOT
) )
788 // Obtain a list with a snapshot of all currently instanciated contents
789 // from provider and extract the contents which are direct children
792 ::ucbhelper::ContentRefList aAllContents
;
793 m_xProvider
->queryExistingContents( aAllContents
);
795 rtl::OUString aURL
= m_xIdentifier
->getContentIdentifier();
796 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
798 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
800 // No trailing slash found. Append.
801 aURL
+= rtl::OUString("/");
804 sal_Int32 nLen
= aURL
.getLength();
806 ::ucbhelper::ContentRefList::const_iterator it
= aAllContents
.begin();
807 ::ucbhelper::ContentRefList::const_iterator end
= aAllContents
.end();
811 ::ucbhelper::ContentImplHelperRef xChild
= (*it
);
812 rtl::OUString aChildURL
813 = xChild
->getIdentifier()->getContentIdentifier();
815 // Is aURL a prefix of aChildURL?
816 if ( ( aChildURL
.getLength() > nLen
) &&
817 ( aChildURL
.compareTo( aURL
, nLen
) == 0 ) )
819 sal_Int32 nPos
= nLen
;
820 nPos
= aChildURL
.indexOf( '/', nPos
);
822 if ( ( nPos
== -1 ) ||
823 ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
825 // No further slashes/ only a final slash. It's a child!
828 static_cast< HierarchyContent
* >( xChild
.get() ) ) );
835 //=========================================================================
836 sal_Bool
HierarchyContent::exchangeIdentity(
837 const uno::Reference
< ucb::XContentIdentifier
>& xNewId
)
842 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
844 uno::Reference
< ucb::XContent
> xThis
= this;
846 // Already persistent?
847 if ( m_eState
!= PERSISTENT
)
849 OSL_FAIL( "HierarchyContent::exchangeIdentity - Not persistent!" );
853 // Am I the root folder?
854 if ( m_eKind
== ROOT
)
856 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
857 "Not supported by root folder!" );
861 // Exchange own identitity.
863 // Fail, if a content with given id already exists.
864 if ( !hasData( xNewId
) )
866 rtl::OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
869 if ( exchange( xNewId
) )
871 if ( m_eKind
== FOLDER
)
873 // Process instanciated children...
875 HierarchyContentRefList aChildren
;
876 queryChildren( aChildren
);
878 HierarchyContentRefList::const_iterator it
= aChildren
.begin();
879 HierarchyContentRefList::const_iterator end
= aChildren
.end();
883 HierarchyContentRef xChild
= (*it
);
885 // Create new content identifier for the child...
886 uno::Reference
< ucb::XContentIdentifier
> xOldChildId
887 = xChild
->getIdentifier();
888 rtl::OUString aOldChildURL
889 = xOldChildId
->getContentIdentifier();
890 rtl::OUString aNewChildURL
891 = aOldChildURL
.replaceAt(
894 xNewId
->getContentIdentifier() );
895 uno::Reference
< ucb::XContentIdentifier
> xNewChildId
896 = new ::ucbhelper::ContentIdentifier( aNewChildURL
);
898 if ( !xChild
->exchangeIdentity( xNewChildId
) )
908 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
909 "Panic! Cannot exchange identity!" );
913 //=========================================================================
915 uno::Reference
< sdbc::XRow
> HierarchyContent::getPropertyValues(
916 const uno::Reference
< uno::XComponentContext
>& rxContext
,
917 const uno::Sequence
< beans::Property
>& rProperties
,
918 const HierarchyContentProperties
& rData
,
919 HierarchyContentProvider
* pProvider
,
920 const rtl::OUString
& rContentId
)
922 // Note: Empty sequence means "get values of all supported properties".
924 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
925 = new ::ucbhelper::PropertyValueSet( rxContext
);
927 sal_Int32 nCount
= rProperties
.getLength();
930 uno::Reference
< beans::XPropertySet
> xAdditionalPropSet
;
931 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
933 const beans::Property
* pProps
= rProperties
.getConstArray();
934 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
936 const beans::Property
& rProp
= pProps
[ n
];
938 // Process Core properties.
940 if ( rProp
.Name
== "ContentType" )
942 xRow
->appendString ( rProp
, rData
.getContentType() );
944 else if ( rProp
.Name
== "Title" )
946 xRow
->appendString ( rProp
, rData
.getTitle() );
948 else if ( rProp
.Name
== "IsDocument" )
950 xRow
->appendBoolean( rProp
, rData
.getIsDocument() );
952 else if ( rProp
.Name
== "IsFolder" )
954 xRow
->appendBoolean( rProp
, rData
.getIsFolder() );
956 else if ( rProp
.Name
== "CreatableContentsInfo" )
959 rProp
, uno::makeAny( rData
.getCreatableContentsInfo() ) );
961 else if ( rProp
.Name
== "TargetURL" )
963 // TargetURL is only supported by links.
965 if ( rData
.getIsDocument() )
966 xRow
->appendString( rProp
, rData
.getTargetURL() );
968 xRow
->appendVoid( rProp
);
972 // Not a Core Property! Maybe it's an Additional Core Property?!
974 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
977 = uno::Reference
< beans::XPropertySet
>(
978 pProvider
->getAdditionalPropertySet( rContentId
,
981 bTriedToGetAdditonalPropSet
= sal_True
;
984 if ( xAdditionalPropSet
.is() )
986 if ( !xRow
->appendPropertySetValue(
990 // Append empty entry.
991 xRow
->appendVoid( rProp
);
996 // Append empty entry.
997 xRow
->appendVoid( rProp
);
1004 // Append all Core Properties.
1005 xRow
->appendString (
1006 beans::Property( rtl::OUString("ContentType"),
1008 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1009 beans::PropertyAttribute::BOUND
1010 | beans::PropertyAttribute::READONLY
),
1011 rData
.getContentType() );
1012 xRow
->appendString (
1013 beans::Property( rtl::OUString("Title"),
1015 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1016 // @@@ Might actually be read-only!
1017 beans::PropertyAttribute::BOUND
),
1019 xRow
->appendBoolean(
1020 beans::Property( rtl::OUString("IsDocument"),
1022 getCppuBooleanType(),
1023 beans::PropertyAttribute::BOUND
1024 | beans::PropertyAttribute::READONLY
),
1025 rData
.getIsDocument() );
1026 xRow
->appendBoolean(
1027 beans::Property( rtl::OUString("IsFolder"),
1029 getCppuBooleanType(),
1030 beans::PropertyAttribute::BOUND
1031 | beans::PropertyAttribute::READONLY
),
1032 rData
.getIsFolder() );
1034 if ( rData
.getIsDocument() )
1036 beans::Property( rtl::OUString("TargetURL"),
1039 static_cast< const rtl::OUString
* >( 0 ) ),
1040 // @@@ Might actually be read-only!
1041 beans::PropertyAttribute::BOUND
),
1042 rData
.getTargetURL() );
1045 rtl::OUString("CreatableContentsInfo"),
1047 getCppuType( static_cast<
1048 const uno::Sequence
< ucb::ContentInfo
> * >( 0 ) ),
1049 beans::PropertyAttribute::BOUND
1050 | beans::PropertyAttribute::READONLY
),
1051 uno::makeAny( rData
.getCreatableContentsInfo() ) );
1053 // Append all Additional Core Properties.
1055 uno::Reference
< beans::XPropertySet
> xSet(
1056 pProvider
->getAdditionalPropertySet( rContentId
, sal_False
),
1058 xRow
->appendPropertySet( xSet
);
1061 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
1064 //=========================================================================
1065 uno::Reference
< sdbc::XRow
> HierarchyContent::getPropertyValues(
1066 const uno::Sequence
< beans::Property
>& rProperties
)
1068 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1069 return getPropertyValues( m_xContext
,
1073 m_xIdentifier
->getContentIdentifier() );
1076 //=========================================================================
1077 uno::Sequence
< uno::Any
> HierarchyContent::setPropertyValues(
1078 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1079 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1080 throw( uno::Exception
)
1082 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1084 uno::Sequence
< uno::Any
> aRet( rValues
.getLength() );
1085 uno::Sequence
< beans::PropertyChangeEvent
> aChanges( rValues
.getLength() );
1086 sal_Int32 nChanged
= 0;
1088 beans::PropertyChangeEvent aEvent
;
1089 aEvent
.Source
= static_cast< cppu::OWeakObject
* >( this );
1090 aEvent
.Further
= sal_False
;
1091 // aEvent.PropertyName =
1092 aEvent
.PropertyHandle
= -1;
1093 // aEvent.OldValue =
1094 // aEvent.NewValue =
1096 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1097 sal_Int32 nCount
= rValues
.getLength();
1099 uno::Reference
< ucb::XPersistentPropertySet
> xAdditionalPropSet
;
1100 sal_Bool bTriedToGetAdditonalPropSet
= sal_False
;
1102 sal_Bool bExchange
= sal_False
;
1103 rtl::OUString aOldTitle
;
1104 rtl::OUString aOldName
;
1105 sal_Int32 nTitlePos
= -1;
1107 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1109 const beans::PropertyValue
& rValue
= pValues
[ n
];
1111 if ( rValue
.Name
== "ContentType" )
1113 // Read-only property!
1114 aRet
[ n
] <<= lang::IllegalAccessException(
1115 rtl::OUString( "Property is read-only!" ),
1116 static_cast< cppu::OWeakObject
* >( this ) );
1118 else if ( rValue
.Name
== "IsDocument" )
1120 // Read-only property!
1121 aRet
[ n
] <<= lang::IllegalAccessException(
1122 rtl::OUString( "Property is read-only!" ),
1123 static_cast< cppu::OWeakObject
* >( this ) );
1125 else if ( rValue
.Name
== "IsFolder" )
1127 // Read-only property!
1128 aRet
[ n
] <<= lang::IllegalAccessException(
1129 rtl::OUString( "Property is read-only!" ),
1130 static_cast< cppu::OWeakObject
* >( this ) );
1132 else if ( rValue
.Name
== "CreatableContentsInfo" )
1134 // Read-only property!
1135 aRet
[ n
] <<= lang::IllegalAccessException(
1136 rtl::OUString( "Property is read-only!" ),
1137 static_cast< cppu::OWeakObject
* >( this ) );
1139 else if ( rValue
.Name
== "Title" )
1143 aRet
[ n
] <<= lang::IllegalAccessException(
1144 rtl::OUString( "Property is read-only!" ),
1145 static_cast< cppu::OWeakObject
* >( this ) );
1149 rtl::OUString aNewValue
;
1150 if ( rValue
.Value
>>= aNewValue
)
1153 if ( !aNewValue
.isEmpty() )
1155 if ( aNewValue
!= m_aProps
.getTitle() )
1157 // modified title -> modified URL -> exchange !
1158 if ( m_eState
== PERSISTENT
)
1159 bExchange
= sal_True
;
1161 aOldTitle
= m_aProps
.getTitle();
1162 aOldName
= m_aProps
.getName();
1164 m_aProps
.setTitle( aNewValue
);
1166 ::ucb_impl::urihelper::encodeSegment(
1169 // property change event will be set later...
1171 // remember position within sequence of values
1172 // (for error handling).
1178 aRet
[ n
] <<= lang::IllegalArgumentException(
1179 rtl::OUString( "Empty title not allowed!" ),
1180 static_cast< cppu::OWeakObject
* >( this ),
1186 aRet
[ n
] <<= beans::IllegalTypeException(
1187 rtl::OUString( "Property value has wrong type!" ),
1188 static_cast< cppu::OWeakObject
* >( this ) );
1192 else if ( rValue
.Name
== "TargetURL" )
1196 aRet
[ n
] <<= lang::IllegalAccessException(
1197 rtl::OUString( "Property is read-only!" ),
1198 static_cast< cppu::OWeakObject
* >( this ) );
1202 // TargetURL is only supported by links.
1204 if ( m_eKind
== LINK
)
1206 rtl::OUString aNewValue
;
1207 if ( rValue
.Value
>>= aNewValue
)
1209 // No empty target URL's!
1210 if ( !aNewValue
.isEmpty() )
1212 if ( aNewValue
!= m_aProps
.getTargetURL() )
1214 aEvent
.PropertyName
= rValue
.Name
;
1216 = uno::makeAny( m_aProps
.getTargetURL() );
1218 = uno::makeAny( aNewValue
);
1220 aChanges
.getArray()[ nChanged
] = aEvent
;
1222 m_aProps
.setTargetURL( aNewValue
);
1228 aRet
[ n
] <<= lang::IllegalArgumentException(
1229 rtl::OUString( "Empty target URL not allowed!" ),
1230 static_cast< cppu::OWeakObject
* >( this ),
1236 aRet
[ n
] <<= beans::IllegalTypeException(
1237 rtl::OUString( "Property value has wrong type!" ),
1238 static_cast< cppu::OWeakObject
* >( this ) );
1243 aRet
[ n
] <<= beans::UnknownPropertyException(
1244 rtl::OUString( "TargetURL only supported by links!" ),
1245 static_cast< cppu::OWeakObject
* >( this ) );
1251 // Not a Core Property! Maybe it's an Additional Core Property?!
1253 if ( !bTriedToGetAdditonalPropSet
&& !xAdditionalPropSet
.is() )
1255 xAdditionalPropSet
= getAdditionalPropertySet( sal_False
);
1256 bTriedToGetAdditonalPropSet
= sal_True
;
1259 if ( xAdditionalPropSet
.is() )
1263 uno::Any aOldValue
= xAdditionalPropSet
->getPropertyValue(
1265 if ( aOldValue
!= rValue
.Value
)
1267 xAdditionalPropSet
->setPropertyValue(
1268 rValue
.Name
, rValue
.Value
);
1270 aEvent
.PropertyName
= rValue
.Name
;
1271 aEvent
.OldValue
= aOldValue
;
1272 aEvent
.NewValue
= rValue
.Value
;
1274 aChanges
.getArray()[ nChanged
] = aEvent
;
1278 catch ( beans::UnknownPropertyException
const & e
)
1282 catch ( lang::WrappedTargetException
const & e
)
1286 catch ( beans::PropertyVetoException
const & e
)
1290 catch ( lang::IllegalArgumentException
const & e
)
1297 aRet
[ n
] <<= uno::Exception(
1298 rtl::OUString( "No property set for storing the value!" ),
1299 static_cast< cppu::OWeakObject
* >( this ) );
1306 uno::Reference
< ucb::XContentIdentifier
> xOldId
1308 uno::Reference
< ucb::XContentIdentifier
> xNewId
1309 = makeNewIdentifier( m_aProps
.getTitle() );
1312 if ( exchangeIdentity( xNewId
) )
1314 // Adapt persistent data.
1315 renameData( xOldId
, xNewId
);
1317 // Adapt Additional Core Properties.
1318 renameAdditionalPropertySet( xOldId
->getContentIdentifier(),
1319 xNewId
->getContentIdentifier(),
1325 m_aProps
.setTitle( aOldTitle
);
1326 m_aProps
.setName ( aOldName
);
1328 aOldTitle
= aOldName
= rtl::OUString();
1331 aRet
[ nTitlePos
] <<= uno::Exception(
1332 rtl::OUString("Exchange failed!"),
1333 static_cast< cppu::OWeakObject
* >( this ) );
1337 if ( !aOldTitle
.isEmpty() )
1339 aEvent
.PropertyName
= rtl::OUString("Title");
1340 aEvent
.OldValue
= uno::makeAny( aOldTitle
);
1341 aEvent
.NewValue
= uno::makeAny( m_aProps
.getTitle() );
1343 aChanges
.getArray()[ nChanged
] = aEvent
;
1349 // Save changes, if content was already made persistent.
1350 if ( !bExchange
&& ( m_eState
== PERSISTENT
) )
1356 beans::PropertyValue(
1357 rtl::OUString( "Uri"),
1359 uno::makeAny(m_xIdentifier
->
1360 getContentIdentifier()),
1361 beans::PropertyState_DIRECT_VALUE
));
1362 ucbhelper::cancelCommandExecution(
1363 ucb::IOErrorCode_CANT_WRITE
,
1364 uno::Sequence
< uno::Any
>(&aProps
, 1),
1366 rtl::OUString( "Cannot store persistent data!" ),
1372 aChanges
.realloc( nChanged
);
1375 notifyPropertiesChange( aChanges
);
1381 //=========================================================================
1382 void HierarchyContent::insert( sal_Int32 nNameClashResolve
,
1383 const uno::Reference
<
1384 ucb::XCommandEnvironment
> & xEnv
)
1385 throw( uno::Exception
)
1387 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1389 // Am I the root folder?
1390 if ( m_eKind
== ROOT
)
1392 ucbhelper::cancelCommandExecution(
1393 uno::makeAny( ucb::UnsupportedCommandException(
1394 rtl::OUString( "Not supported by root folder!" ),
1395 static_cast< cppu::OWeakObject
* >( this ) ) ),
1400 // Check, if all required properties were set.
1401 if ( m_aProps
.getTitle().isEmpty() )
1403 uno::Sequence
< rtl::OUString
> aProps( 1 );
1404 aProps
[ 0 ] = rtl::OUString("Title");
1405 ucbhelper::cancelCommandExecution(
1406 uno::makeAny( ucb::MissingPropertiesException(
1408 static_cast< cppu::OWeakObject
* >( this ),
1414 // Assemble new content identifier...
1416 uno::Reference
< ucb::XContentIdentifier
> xId
1417 = makeNewIdentifier( m_aProps
.getTitle() );
1419 // Handle possible name clash...
1421 switch ( nNameClashResolve
)
1424 case ucb::NameClash::ERROR
:
1425 if ( hasData( xId
) )
1427 ucbhelper::cancelCommandExecution(
1429 ucb::NameClashException(
1431 static_cast< cppu::OWeakObject
* >( this ),
1432 task::InteractionClassification_ERROR
,
1433 m_aProps
.getTitle() ) ),
1439 // replace existing object.
1440 case ucb::NameClash::OVERWRITE
:
1443 // "invent" a new valid title.
1444 case ucb::NameClash::RENAME
:
1445 if ( hasData( xId
) )
1451 rtl::OUString aNewId
= xId
->getContentIdentifier();
1452 aNewId
+= rtl::OUString("_");
1453 aNewId
+= rtl::OUString::valueOf( ++nTry
);
1454 xId
= new ::ucbhelper::ContentIdentifier( aNewId
);
1456 while ( hasData( xId
) && ( nTry
< 1000 ) );
1460 ucbhelper::cancelCommandExecution(
1462 ucb::UnsupportedNameClashException(
1463 rtl::OUString( "Unable to resolve name clash!" ),
1464 static_cast< cppu::OWeakObject
* >( this ),
1465 nNameClashResolve
) ),
1471 rtl::OUString
aNewTitle( m_aProps
.getTitle() );
1472 aNewTitle
+= rtl::OUString("_");
1473 aNewTitle
+= rtl::OUString::valueOf( nTry
);
1474 m_aProps
.setTitle( aNewTitle
);
1479 case ucb::NameClash::KEEP
: // deprecated
1480 case ucb::NameClash::ASK
:
1482 if ( hasData( xId
) )
1484 ucbhelper::cancelCommandExecution(
1486 ucb::UnsupportedNameClashException(
1488 static_cast< cppu::OWeakObject
* >( this ),
1489 nNameClashResolve
) ),
1496 // Identifier changed?
1497 sal_Bool bNewId
= ( xId
->getContentIdentifier()
1498 != m_xIdentifier
->getContentIdentifier() );
1499 m_xIdentifier
= xId
;
1504 = uno::makeAny(beans::PropertyValue(
1505 rtl::OUString( "Uri"),
1507 uno::makeAny(m_xIdentifier
->
1508 getContentIdentifier()),
1509 beans::PropertyState_DIRECT_VALUE
));
1510 ucbhelper::cancelCommandExecution(
1511 ucb::IOErrorCode_CANT_WRITE
,
1512 uno::Sequence
< uno::Any
>(&aProps
, 1),
1514 rtl::OUString("Cannot store persistent data!"),
1519 m_eState
= PERSISTENT
;
1528 //=========================================================================
1529 void HierarchyContent::destroy( sal_Bool bDeletePhysical
,
1530 const uno::Reference
<
1531 ucb::XCommandEnvironment
> & xEnv
)
1532 throw( uno::Exception
)
1534 // @@@ take care about bDeletePhysical -> trashcan support
1536 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1538 uno::Reference
< ucb::XContent
> xThis
= this;
1541 if ( m_eState
!= PERSISTENT
)
1543 ucbhelper::cancelCommandExecution(
1544 uno::makeAny( ucb::UnsupportedCommandException(
1545 rtl::OUString( "Not persistent!" ),
1546 static_cast< cppu::OWeakObject
* >( this ) ) ),
1551 // Am I the root folder?
1552 if ( m_eKind
== ROOT
)
1554 ucbhelper::cancelCommandExecution(
1555 uno::makeAny( ucb::UnsupportedCommandException(
1556 rtl::OUString( "Not supported by root folder!" ),
1557 static_cast< cppu::OWeakObject
* >( this ) ) ),
1567 if ( m_eKind
== FOLDER
)
1569 // Process instanciated children...
1571 HierarchyContentRefList aChildren
;
1572 queryChildren( aChildren
);
1574 HierarchyContentRefList::const_iterator it
= aChildren
.begin();
1575 HierarchyContentRefList::const_iterator end
= aChildren
.end();
1579 (*it
)->destroy( bDeletePhysical
, xEnv
);
1585 //=========================================================================
1586 void HierarchyContent::transfer(
1587 const ucb::TransferInfo
& rInfo
,
1588 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1589 throw( uno::Exception
)
1591 osl::ClearableGuard
< osl::Mutex
> aGuard( m_aMutex
);
1594 if ( m_eState
!= PERSISTENT
)
1596 ucbhelper::cancelCommandExecution(
1597 uno::makeAny( ucb::UnsupportedCommandException(
1598 rtl::OUString( "Not persistent!" ),
1599 static_cast< cppu::OWeakObject
* >( this ) ) ),
1604 // Is source a hierarchy content?
1605 if ( ( rInfo
.SourceURL
.getLength() < HIERARCHY_URL_SCHEME_LENGTH
+ 2 ) ||
1606 ( rInfo
.SourceURL
.compareToAscii( HIERARCHY_URL_SCHEME
":/",
1607 HIERARCHY_URL_SCHEME_LENGTH
+ 2 )
1610 ucbhelper::cancelCommandExecution(
1611 uno::makeAny( ucb::InteractiveBadTransferURLException(
1613 static_cast< cppu::OWeakObject
* >( this ) ) ),
1618 // Is source not a parent of me / not me?
1619 rtl::OUString aId
= m_xIdentifier
->getContentIdentifier();
1620 sal_Int32 nPos
= aId
.lastIndexOf( '/' );
1621 if ( nPos
!= ( aId
.getLength() - 1 ) )
1623 // No trailing slash found. Append.
1624 aId
+= rtl::OUString("/");
1627 if ( rInfo
.SourceURL
.getLength() <= aId
.getLength() )
1630 rInfo
.SourceURL
, rInfo
.SourceURL
.getLength() ) == 0 )
1633 = uno::makeAny(beans::PropertyValue(
1634 rtl::OUString( "Uri"),
1636 uno::makeAny(rInfo
.SourceURL
),
1637 beans::PropertyState_DIRECT_VALUE
));
1638 ucbhelper::cancelCommandExecution(
1639 ucb::IOErrorCode_RECURSIVE
,
1640 uno::Sequence
< uno::Any
>(&aProps
, 1),
1642 rtl::OUString( "Target is equal to or is a child of source!" ),
1648 //////////////////////////////////////////////////////////////////////
1649 // 0) Obtain content object for source.
1650 //////////////////////////////////////////////////////////////////////
1652 uno::Reference
< ucb::XContentIdentifier
> xId
1653 = new ::ucbhelper::ContentIdentifier( rInfo
.SourceURL
);
1655 // Note: The static cast is okay here, because its sure that
1656 // m_xProvider is always the HierarchyContentProvider.
1657 rtl::Reference
< HierarchyContent
> xSource
;
1661 xSource
= static_cast< HierarchyContent
* >(
1662 m_xProvider
->queryContent( xId
).get() );
1664 catch ( ucb::IllegalIdentifierException
const & )
1669 if ( !xSource
.is() )
1672 = uno::makeAny(beans::PropertyValue(
1673 rtl::OUString( "Uri"),
1675 uno::makeAny(xId
->getContentIdentifier()),
1676 beans::PropertyState_DIRECT_VALUE
));
1677 ucbhelper::cancelCommandExecution(
1678 ucb::IOErrorCode_CANT_READ
,
1679 uno::Sequence
< uno::Any
>(&aProps
, 1),
1681 rtl::OUString( "Cannot instanciate source object!" ),
1686 //////////////////////////////////////////////////////////////////////
1687 // 1) Create new child content.
1688 //////////////////////////////////////////////////////////////////////
1690 rtl::OUString aType
= xSource
->isFolder()
1691 ? rtl::OUString( HIERARCHY_FOLDER_CONTENT_TYPE
)
1692 : rtl::OUString( HIERARCHY_LINK_CONTENT_TYPE
);
1693 ucb::ContentInfo aContentInfo
;
1694 aContentInfo
.Type
= aType
;
1695 aContentInfo
.Attributes
= 0;
1697 // Note: The static cast is okay here, because its sure that
1698 // createNewContent always creates a HierarchyContent.
1699 rtl::Reference
< HierarchyContent
> xTarget
1700 = static_cast< HierarchyContent
* >(
1701 createNewContent( aContentInfo
).get() );
1702 if ( !xTarget
.is() )
1705 = uno::makeAny(beans::PropertyValue(
1706 rtl::OUString( "Folder"),
1709 beans::PropertyState_DIRECT_VALUE
));
1710 ucbhelper::cancelCommandExecution(
1711 ucb::IOErrorCode_CANT_CREATE
,
1712 uno::Sequence
< uno::Any
>(&aProps
, 1),
1714 rtl::OUString( "XContentCreator::createNewContent failed!" ),
1719 //////////////////////////////////////////////////////////////////////
1720 // 2) Copy data from source content to child content.
1721 //////////////////////////////////////////////////////////////////////
1723 uno::Sequence
< beans::Property
> aSourceProps
1724 = xSource
->getPropertySetInfo( xEnv
)->getProperties();
1725 sal_Int32 nCount
= aSourceProps
.getLength();
1729 sal_Bool bHadTitle
= rInfo
.NewTitle
.isEmpty();
1731 // Get all source values.
1732 uno::Reference
< sdbc::XRow
> xRow
1733 = xSource
->getPropertyValues( aSourceProps
);
1735 uno::Sequence
< beans::PropertyValue
> aValues( nCount
);
1736 beans::PropertyValue
* pValues
= aValues
.getArray();
1738 const beans::Property
* pProps
= aSourceProps
.getConstArray();
1739 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1741 const beans::Property
& rProp
= pProps
[ n
];
1742 beans::PropertyValue
& rValue
= pValues
[ n
];
1744 rValue
.Name
= rProp
.Name
;
1745 rValue
.Handle
= rProp
.Handle
;
1747 if ( !bHadTitle
&& rProp
.Name
== "Title" )
1749 // Set new title instead of original.
1750 bHadTitle
= sal_True
;
1751 rValue
.Value
<<= rInfo
.NewTitle
;
1754 rValue
.Value
= xRow
->getObject(
1756 uno::Reference
< container::XNameAccess
>() );
1758 rValue
.State
= beans::PropertyState_DIRECT_VALUE
;
1760 if ( rProp
.Attributes
& beans::PropertyAttribute::REMOVABLE
)
1762 // Add Additional Core Property.
1765 xTarget
->addProperty( rProp
.Name
,
1769 catch ( beans::PropertyExistException
const & )
1772 catch ( beans::IllegalTypeException
const & )
1775 catch ( lang::IllegalArgumentException
const & )
1781 // Set target values.
1782 xTarget
->setPropertyValues( aValues
, xEnv
);
1785 //////////////////////////////////////////////////////////////////////
1786 // 3) Commit (insert) child.
1787 //////////////////////////////////////////////////////////////////////
1789 xTarget
->insert( rInfo
.NameClash
, xEnv
);
1791 //////////////////////////////////////////////////////////////////////
1792 // 4) Transfer (copy) children of source.
1793 //////////////////////////////////////////////////////////////////////
1795 if ( xSource
->isFolder() )
1797 HierarchyEntry
aFolder(
1798 m_xContext
, m_pProvider
, xId
->getContentIdentifier() );
1799 HierarchyEntry::iterator it
;
1801 while ( aFolder
.next( it
) )
1803 const HierarchyEntryData
& rResult
= *it
;
1805 rtl::OUString aChildId
= xId
->getContentIdentifier();
1806 if ( ( aChildId
.lastIndexOf( '/' ) + 1 ) != aChildId
.getLength() )
1807 aChildId
+= rtl::OUString("/");
1809 aChildId
+= rResult
.getName();
1811 ucb::TransferInfo aInfo
;
1812 aInfo
.MoveData
= sal_False
;
1813 aInfo
.NewTitle
= rtl::OUString();
1814 aInfo
.SourceURL
= aChildId
;
1815 aInfo
.NameClash
= rInfo
.NameClash
;
1817 // Transfer child to target.
1818 xTarget
->transfer( aInfo
, xEnv
);
1822 //////////////////////////////////////////////////////////////////////
1823 // 5) Destroy source ( when moving only ) .
1824 //////////////////////////////////////////////////////////////////////
1826 if ( rInfo
.MoveData
)
1828 xSource
->destroy( sal_True
, xEnv
);
1830 // Remove all persistent data of source and its children.
1831 if ( !xSource
->removeData() )
1835 beans::PropertyValue(
1836 rtl::OUString( "Uri"),
1839 xSource
->m_xIdentifier
->
1840 getContentIdentifier()),
1841 beans::PropertyState_DIRECT_VALUE
));
1842 ucbhelper::cancelCommandExecution(
1843 ucb::IOErrorCode_CANT_WRITE
,
1844 uno::Sequence
< uno::Any
>(&aProps
, 1),
1846 rtl::OUString( "Cannot remove persistent data of source object!" ),
1851 // Remove own and all children's Additional Core Properties.
1852 xSource
->removeAdditionalPropertySet( sal_True
);
1856 //=========================================================================
1857 //=========================================================================
1859 // HierarchyContentProperties Implementation.
1861 //=========================================================================
1862 //=========================================================================
1864 uno::Sequence
< ucb::ContentInfo
>
1865 HierarchyContentProperties::getCreatableContentsInfo() const
1867 if ( getIsFolder() )
1869 uno::Sequence
< ucb::ContentInfo
> aSeq( 2 );
1872 aSeq
.getArray()[ 0 ].Type
1873 = rtl::OUString( HIERARCHY_FOLDER_CONTENT_TYPE
);
1874 aSeq
.getArray()[ 0 ].Attributes
1875 = ucb::ContentInfoAttribute::KIND_FOLDER
;
1877 uno::Sequence
< beans::Property
> aFolderProps( 1 );
1878 aFolderProps
.getArray()[ 0 ] = beans::Property(
1879 rtl::OUString("Title"),
1881 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1882 beans::PropertyAttribute::BOUND
);
1883 aSeq
.getArray()[ 0 ].Properties
= aFolderProps
;
1886 aSeq
.getArray()[ 1 ].Type
1887 = rtl::OUString( HIERARCHY_LINK_CONTENT_TYPE
);
1888 aSeq
.getArray()[ 1 ].Attributes
1889 = ucb::ContentInfoAttribute::KIND_LINK
;
1891 uno::Sequence
< beans::Property
> aLinkProps( 2 );
1892 aLinkProps
.getArray()[ 0 ] = beans::Property(
1893 rtl::OUString("Title"),
1895 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1896 beans::PropertyAttribute::BOUND
);
1897 aLinkProps
.getArray()[ 1 ] = beans::Property(
1898 rtl::OUString("TargetURL"),
1900 getCppuType( static_cast< const rtl::OUString
* >( 0 ) ),
1901 beans::PropertyAttribute::BOUND
);
1902 aSeq
.getArray()[ 1 ].Properties
= aLinkProps
;
1908 return uno::Sequence
< ucb::ContentInfo
>( 0 );
1912 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */