xref: /trunk/main/ucb/source/ucp/hierarchy/hierarchycontent.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_hier.hxx"
26 
27 /**************************************************************************
28                                 TODO
29  **************************************************************************
30 
31  - optimize transfer command. "Move" should be implementable much more
32    efficient!
33 
34  **************************************************************************
35 
36  - Root Folder vs. 'normal' Folder
37     - root doesn't support command 'delete'
38     - root doesn't support command 'insert'
39     - root needs not created via XContentCreator - queryContent with root
40       folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0
41     - root has no parent.
42 
43  *************************************************************************/
44 #include <osl/diagnose.h>
45 
46 #include "osl/doublecheckedlocking.h"
47 #include <rtl/ustring.h>
48 #include <rtl/ustring.hxx>
49 #include <com/sun/star/beans/PropertyAttribute.hpp>
50 #include <com/sun/star/beans/PropertyState.hpp>
51 #include <com/sun/star/beans/PropertyValue.hpp>
52 #include <com/sun/star/beans/XPropertyAccess.hpp>
53 #include <com/sun/star/lang/IllegalAccessException.hpp>
54 #include <com/sun/star/sdbc/XRow.hpp>
55 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
56 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
57 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
58 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
59 #include <com/sun/star/ucb/NameClash.hpp>
60 #include <com/sun/star/ucb/NameClashException.hpp>
61 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
62 #include <com/sun/star/ucb/TransferInfo.hpp>
63 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
64 #include <com/sun/star/ucb/XCommandInfo.hpp>
65 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
66 #include <com/sun/star/uno/Any.hxx>
67 #include <com/sun/star/uno/Sequence.hxx>
68 #include <ucbhelper/contentidentifier.hxx>
69 #include <ucbhelper/propertyvalueset.hxx>
70 #include <ucbhelper/cancelcommandexecution.hxx>
71 #include "hierarchycontent.hxx"
72 #include "hierarchyprovider.hxx"
73 #include "dynamicresultset.hxx"
74 #include "hierarchyuri.hxx"
75 
76 #include "../inc/urihelper.hxx"
77 
78 using namespace com::sun::star;
79 using namespace hierarchy_ucp;
80 
81 //=========================================================================
82 //=========================================================================
83 //
84 // HierarchyContent Implementation.
85 //
86 //=========================================================================
87 //=========================================================================
88 
89 // static ( "virtual" ctor )
create(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,HierarchyContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier)90 HierarchyContent* HierarchyContent::create(
91             const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
92             HierarchyContentProvider* pProvider,
93             const uno::Reference< ucb::XContentIdentifier >& Identifier )
94 {
95     // Fail, if content does not exist.
96     HierarchyContentProperties aProps;
97     if ( !loadData( rxSMgr, pProvider, Identifier, aProps ) )
98         return 0;
99 
100     return new HierarchyContent( rxSMgr, pProvider, Identifier, aProps );
101 }
102 
103 //=========================================================================
104 // static ( "virtual" ctor )
create(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,HierarchyContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,const ucb::ContentInfo & Info)105 HierarchyContent* HierarchyContent::create(
106             const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
107             HierarchyContentProvider* pProvider,
108             const uno::Reference< ucb::XContentIdentifier >& Identifier,
109             const ucb::ContentInfo& Info )
110 {
111     if ( !Info.Type.getLength() )
112         return 0;
113 
114     if ( !Info.Type.equalsAsciiL(
115             RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) &&
116          !Info.Type.equalsAsciiL(
117             RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) )
118         return 0;
119 
120 #if 0
121     // Fail, if content does exist.
122     if ( hasData( rxSMgr, pProvider, Identifier ) )
123         return 0;
124 #endif
125 
126     return new HierarchyContent( rxSMgr, pProvider, Identifier, Info );
127 }
128 
129 //=========================================================================
HierarchyContent(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,HierarchyContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,const HierarchyContentProperties & rProps)130 HierarchyContent::HierarchyContent(
131             const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
132             HierarchyContentProvider* pProvider,
133             const uno::Reference< ucb::XContentIdentifier >& Identifier,
134             const HierarchyContentProperties& rProps )
135 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
136   m_aProps( rProps ),
137   m_eState( PERSISTENT ),
138   m_pProvider( pProvider ),
139   m_bCheckedReadOnly( false ),
140   m_bIsReadOnly( true )
141 {
142     setKind( Identifier );
143 }
144 
145 //=========================================================================
HierarchyContent(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,HierarchyContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,const ucb::ContentInfo & Info)146 HierarchyContent::HierarchyContent(
147             const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
148             HierarchyContentProvider* pProvider,
149             const uno::Reference< ucb::XContentIdentifier >& Identifier,
150             const ucb::ContentInfo& Info )
151   : ContentImplHelper( rxSMgr, pProvider, Identifier ),
152   m_aProps( Info.Type.equalsAsciiL(
153                 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) )
154             ? HierarchyEntryData::FOLDER
155             : HierarchyEntryData::LINK ),
156   m_eState( TRANSIENT ),
157   m_pProvider( pProvider ),
158   m_bCheckedReadOnly( false ),
159   m_bIsReadOnly( true )
160 {
161     setKind( Identifier );
162 }
163 
164 //=========================================================================
165 // virtual
~HierarchyContent()166 HierarchyContent::~HierarchyContent()
167 {
168 }
169 
170 //=========================================================================
171 //
172 // XInterface methods.
173 //
174 //=========================================================================
175 
176 // virtual
acquire()177 void SAL_CALL HierarchyContent::acquire()
178     throw( )
179 {
180     ContentImplHelper::acquire();
181 }
182 
183 //=========================================================================
184 // virtual
release()185 void SAL_CALL HierarchyContent::release()
186     throw( )
187 {
188     ContentImplHelper::release();
189 }
190 
191 //=========================================================================
192 // virtual
queryInterface(const uno::Type & rType)193 uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType )
194 {
195     uno::Any aRet = ContentImplHelper::queryInterface( rType );
196 
197     if ( !aRet.hasValue() )
198     {
199         // Note: isReadOnly may be relative expensive. So avoid calling it
200         //       unless it is really necessary.
201         aRet = cppu::queryInterface(
202                 rType, static_cast< ucb::XContentCreator * >( this ) );
203         if ( aRet.hasValue() )
204         {
205             if ( !isFolder() || isReadOnly() )
206                 return uno::Any();
207         }
208     }
209 
210     return aRet;
211 }
212 
213 //=========================================================================
214 //
215 // XTypeProvider methods.
216 //
217 //=========================================================================
218 
219 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent );
220 
221 //=========================================================================
222 // virtual
getTypes()223 uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes()
224 {
225     cppu::OTypeCollection * pCollection = 0;
226 
227     if ( isFolder() && !isReadOnly() )
228     {
229         static cppu::OTypeCollection* pFolderTypes = 0;
230 
231         pCollection = pFolderTypes;
232         if ( !pCollection )
233         {
234             osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
235 
236             pCollection = pFolderTypes;
237             if ( !pCollection )
238             {
239                 static cppu::OTypeCollection aCollection(
240                     CPPU_TYPE_REF( lang::XTypeProvider ),
241                     CPPU_TYPE_REF( lang::XServiceInfo ),
242                     CPPU_TYPE_REF( lang::XComponent ),
243                     CPPU_TYPE_REF( ucb::XContent ),
244                     CPPU_TYPE_REF( ucb::XCommandProcessor ),
245                     CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
246                     CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
247                     CPPU_TYPE_REF( beans::XPropertyContainer ),
248                     CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
249                     CPPU_TYPE_REF( container::XChild ),
250                     CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
251                 pCollection = &aCollection;
252                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
253                 pFolderTypes = pCollection;
254             }
255         }
256         else {
257             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
258         }
259     }
260     else
261     {
262         static cppu::OTypeCollection* pDocumentTypes = 0;
263 
264         pCollection = pDocumentTypes;
265         if ( !pCollection )
266         {
267             osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
268 
269             pCollection = pDocumentTypes;
270             if ( !pCollection )
271             {
272                 static cppu::OTypeCollection aCollection(
273                     CPPU_TYPE_REF( lang::XTypeProvider ),
274                     CPPU_TYPE_REF( lang::XServiceInfo ),
275                     CPPU_TYPE_REF( lang::XComponent ),
276                     CPPU_TYPE_REF( ucb::XContent ),
277                     CPPU_TYPE_REF( ucb::XCommandProcessor ),
278                     CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
279                     CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
280                     CPPU_TYPE_REF( beans::XPropertyContainer ),
281                     CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
282                     CPPU_TYPE_REF( container::XChild ) );
283                 pCollection = &aCollection;
284                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
285                 pDocumentTypes = pCollection;
286             }
287         }
288         else {
289             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
290         }
291     }
292 
293     return (*pCollection).getTypes();
294 }
295 
296 //=========================================================================
297 //
298 // XServiceInfo methods.
299 //
300 //=========================================================================
301 
302 // virtual
getImplementationName()303 rtl::OUString SAL_CALL HierarchyContent::getImplementationName()
304 {
305     return rtl::OUString::createFromAscii(
306                             "com.sun.star.comp.ucb.HierarchyContent" );
307 }
308 
309 //=========================================================================
310 // virtual
311 uno::Sequence< rtl::OUString > SAL_CALL
getSupportedServiceNames()312 HierarchyContent::getSupportedServiceNames()
313 {
314     uno::Sequence< rtl::OUString > aSNS( 1 );
315 
316     if ( m_eKind == LINK )
317         aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
318                                 HIERARCHY_LINK_CONTENT_SERVICE_NAME );
319     else if ( m_eKind == FOLDER )
320         aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
321                                 HIERARCHY_FOLDER_CONTENT_SERVICE_NAME );
322     else
323         aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
324                                 HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME );
325 
326     return aSNS;
327 }
328 
329 //=========================================================================
330 //
331 // XContent methods.
332 //
333 //=========================================================================
334 
335 // virtual
getContentType()336 rtl::OUString SAL_CALL HierarchyContent::getContentType()
337 {
338     return m_aProps.getContentType();
339 }
340 
341 //=========================================================================
342 // virtual
343 uno::Reference< ucb::XContentIdentifier > SAL_CALL
getIdentifier()344 HierarchyContent::getIdentifier()
345 {
346     // Transient?
347     if ( m_eState == TRANSIENT )
348     {
349         // Transient contents have no identifier.
350         return uno::Reference< ucb::XContentIdentifier >();
351     }
352 
353     return ContentImplHelper::getIdentifier();
354 }
355 
356 //=========================================================================
357 //
358 // XCommandProcessor methods.
359 //
360 //=========================================================================
361 
362 // virtual
execute(const ucb::Command & aCommand,sal_Int32,const uno::Reference<ucb::XCommandEnvironment> & Environment)363 uno::Any SAL_CALL HierarchyContent::execute(
364         const ucb::Command& aCommand,
365         sal_Int32 /*CommandId*/,
366         const uno::Reference< ucb::XCommandEnvironment >& Environment )
367 {
368     uno::Any aRet;
369 
370     if ( aCommand.Name.equalsAsciiL(
371             RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
372     {
373         //////////////////////////////////////////////////////////////////
374         // getPropertyValues
375         //////////////////////////////////////////////////////////////////
376 
377         uno::Sequence< beans::Property > Properties;
378         if ( !( aCommand.Argument >>= Properties ) )
379         {
380             ucbhelper::cancelCommandExecution(
381                 uno::makeAny( lang::IllegalArgumentException(
382                                     rtl::OUString::createFromAscii(
383                                         "Wrong argument type!" ),
384                                     static_cast< cppu::OWeakObject * >( this ),
385                                     -1 ) ),
386                 Environment );
387             // Unreachable
388         }
389 
390         aRet <<= getPropertyValues( Properties );
391     }
392     else if ( aCommand.Name.equalsAsciiL(
393                 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
394     {
395         //////////////////////////////////////////////////////////////////
396         // setPropertyValues
397         //////////////////////////////////////////////////////////////////
398 
399         uno::Sequence< beans::PropertyValue > aProperties;
400         if ( !( aCommand.Argument >>= aProperties ) )
401         {
402             ucbhelper::cancelCommandExecution(
403                 uno::makeAny( lang::IllegalArgumentException(
404                                     rtl::OUString::createFromAscii(
405                                         "Wrong argument type!" ),
406                                     static_cast< cppu::OWeakObject * >( this ),
407                                     -1 ) ),
408                 Environment );
409             // Unreachable
410         }
411 
412         if ( !aProperties.getLength() )
413         {
414             ucbhelper::cancelCommandExecution(
415                 uno::makeAny( lang::IllegalArgumentException(
416                                     rtl::OUString::createFromAscii(
417                                         "No properties!" ),
418                                     static_cast< cppu::OWeakObject * >( this ),
419                                     -1 ) ),
420                 Environment );
421             // Unreachable
422         }
423 
424         aRet <<= setPropertyValues( aProperties, Environment );
425     }
426     else if ( aCommand.Name.equalsAsciiL(
427                 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
428     {
429         //////////////////////////////////////////////////////////////////
430         // getPropertySetInfo
431         //////////////////////////////////////////////////////////////////
432 
433         aRet <<= getPropertySetInfo( Environment );
434     }
435     else if ( aCommand.Name.equalsAsciiL(
436                 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
437     {
438         //////////////////////////////////////////////////////////////////
439         // getCommandInfo
440         //////////////////////////////////////////////////////////////////
441 
442         aRet <<= getCommandInfo( Environment );
443     }
444     else if ( aCommand.Name.equalsAsciiL(
445                   RTL_CONSTASCII_STRINGPARAM( "open" ) ) && isFolder() )
446     {
447         //////////////////////////////////////////////////////////////////
448         // open command for a folder content
449         //////////////////////////////////////////////////////////////////
450 
451         ucb::OpenCommandArgument2 aOpenCommand;
452         if ( !( aCommand.Argument >>= aOpenCommand ) )
453         {
454             ucbhelper::cancelCommandExecution(
455                 uno::makeAny( lang::IllegalArgumentException(
456                                     rtl::OUString::createFromAscii(
457                                         "Wrong argument type!" ),
458                                     static_cast< cppu::OWeakObject * >( this ),
459                                     -1 ) ),
460                 Environment );
461             // Unreachable
462         }
463 
464         uno::Reference< ucb::XDynamicResultSet > xSet
465                 = new DynamicResultSet( m_xSMgr, this, aOpenCommand );
466         aRet <<= xSet;
467     }
468     else if ( aCommand.Name.equalsAsciiL(
469                   RTL_CONSTASCII_STRINGPARAM( "insert" ) ) &&
470               ( m_eKind != ROOT ) && !isReadOnly() )
471     {
472         //////////////////////////////////////////////////////////////////
473         // insert
474         //  ( Not available at root folder )
475         //////////////////////////////////////////////////////////////////
476 
477         ucb::InsertCommandArgument aArg;
478         if ( !( aCommand.Argument >>= aArg ) )
479         {
480             ucbhelper::cancelCommandExecution(
481                 uno::makeAny( lang::IllegalArgumentException(
482                                     rtl::OUString::createFromAscii(
483                                         "Wrong argument type!" ),
484                                     static_cast< cppu::OWeakObject * >( this ),
485                                     -1 ) ),
486                 Environment );
487             // Unreachable
488         }
489 
490         sal_Int32 nNameClash = aArg.ReplaceExisting
491                              ? ucb::NameClash::OVERWRITE
492                              : ucb::NameClash::ERROR;
493         insert( nNameClash, Environment );
494     }
495     else if ( aCommand.Name.equalsAsciiL(
496                   RTL_CONSTASCII_STRINGPARAM( "delete" ) ) &&
497               ( m_eKind != ROOT ) && !isReadOnly() )
498     {
499         //////////////////////////////////////////////////////////////////
500         // delete
501         //  ( Not available at root folder )
502         //////////////////////////////////////////////////////////////////
503 
504         sal_Bool bDeletePhysical = sal_False;
505         aCommand.Argument >>= bDeletePhysical;
506         destroy( bDeletePhysical, Environment );
507 
508         // Remove own and all children's persistent data.
509         if ( !removeData() )
510         {
511             uno::Any aProps
512                 = uno::makeAny(
513                          beans::PropertyValue(
514                              rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
515                                                "Uri")),
516                              -1,
517                              uno::makeAny(m_xIdentifier->
518                                               getContentIdentifier()),
519                              beans::PropertyState_DIRECT_VALUE));
520             ucbhelper::cancelCommandExecution(
521                 ucb::IOErrorCode_CANT_WRITE,
522                 uno::Sequence< uno::Any >(&aProps, 1),
523                 Environment,
524                 rtl::OUString::createFromAscii(
525                     "Cannot remove persistent data!" ),
526                 this );
527             // Unreachable
528         }
529 
530         // Remove own and all children's Additional Core Properties.
531         removeAdditionalPropertySet( sal_True );
532     }
533     else if ( aCommand.Name.equalsAsciiL(
534                   RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) &&
535               isFolder() && !isReadOnly() )
536     {
537         //////////////////////////////////////////////////////////////////
538         // transfer
539         //      ( Not available at link objects )
540         //////////////////////////////////////////////////////////////////
541 
542         ucb::TransferInfo aInfo;
543         if ( !( aCommand.Argument >>= aInfo ) )
544         {
545             OSL_ENSURE( sal_False, "Wrong argument type!" );
546             ucbhelper::cancelCommandExecution(
547                 uno::makeAny( lang::IllegalArgumentException(
548                                     rtl::OUString::createFromAscii(
549                                         "Wrong argument type!" ),
550                                     static_cast< cppu::OWeakObject * >( this ),
551                                     -1 ) ),
552                 Environment );
553             // Unreachable
554         }
555 
556         transfer( aInfo, Environment );
557     }
558     else if ( aCommand.Name.equalsAsciiL(
559                   RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) &&
560               isFolder() && !isReadOnly() )
561     {
562         //////////////////////////////////////////////////////////////////
563         // createNewContent
564         //      ( Not available at link objects )
565         //////////////////////////////////////////////////////////////////
566 
567         ucb::ContentInfo aInfo;
568         if ( !( aCommand.Argument >>= aInfo ) )
569         {
570             OSL_ENSURE( sal_False, "Wrong argument type!" );
571             ucbhelper::cancelCommandExecution(
572                 uno::makeAny( lang::IllegalArgumentException(
573                                     rtl::OUString::createFromAscii(
574                                         "Wrong argument type!" ),
575                                     static_cast< cppu::OWeakObject * >( this ),
576                                     -1 ) ),
577                 Environment );
578             // Unreachable
579         }
580 
581         aRet <<= createNewContent( aInfo );
582     }
583     else
584     {
585         //////////////////////////////////////////////////////////////////
586         // Unsupported command
587         //////////////////////////////////////////////////////////////////
588 
589         ucbhelper::cancelCommandExecution(
590             uno::makeAny( ucb::UnsupportedCommandException(
591                                 rtl::OUString(),
592                                 static_cast< cppu::OWeakObject * >( this ) ) ),
593             Environment );
594         // Unreachable
595     }
596 
597     return aRet;
598 }
599 
600 //=========================================================================
601 // virtual
abort(sal_Int32)602 void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ )
603 {
604     // @@@ Generally, no action takes much time...
605 }
606 
607 //=========================================================================
608 //
609 // XContentCreator methods.
610 //
611 //=========================================================================
612 
613 // virtual
614 uno::Sequence< ucb::ContentInfo > SAL_CALL
queryCreatableContentsInfo()615 HierarchyContent::queryCreatableContentsInfo()
616 {
617     return m_aProps.getCreatableContentsInfo();
618 }
619 
620 //=========================================================================
621 // virtual
622 uno::Reference< ucb::XContent > SAL_CALL
createNewContent(const ucb::ContentInfo & Info)623 HierarchyContent::createNewContent( const ucb::ContentInfo& Info )
624 {
625     if ( isFolder() )
626     {
627         osl::Guard< osl::Mutex > aGuard( m_aMutex );
628 
629         if ( !Info.Type.getLength() )
630             return uno::Reference< ucb::XContent >();
631 
632         sal_Bool bCreateFolder =
633             Info.Type.equalsAsciiL(
634                 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) );
635 
636         if ( !bCreateFolder &&
637              !Info.Type.equalsAsciiL(
638                 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) )
639             return uno::Reference< ucb::XContent >();
640 
641         rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
642 
643         OSL_ENSURE( aURL.getLength() > 0,
644                     "HierarchyContent::createNewContent - empty identifier!" );
645 
646         if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
647             aURL += rtl::OUString::createFromAscii( "/" );
648 
649         if ( bCreateFolder )
650             aURL += rtl::OUString::createFromAscii( "New_Folder" );
651         else
652             aURL += rtl::OUString::createFromAscii( "New_Link" );
653 
654         uno::Reference< ucb::XContentIdentifier > xId
655             = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
656 
657         return create( m_xSMgr, m_pProvider, xId, Info );
658     }
659     else
660     {
661         OSL_ENSURE( sal_False,
662                     "createNewContent called on non-folder object!" );
663         return uno::Reference< ucb::XContent >();
664     }
665 }
666 
667 //=========================================================================
668 // virtual
getParentURL()669 rtl::OUString HierarchyContent::getParentURL()
670 {
671     HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
672     return aUri.getParentUri();
673 }
674 
675 //=========================================================================
676 //static
hasData(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,HierarchyContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier)677 sal_Bool HierarchyContent::hasData(
678             const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
679             HierarchyContentProvider* pProvider,
680             const uno::Reference< ucb::XContentIdentifier >& Identifier )
681 {
682     rtl::OUString aURL = Identifier->getContentIdentifier();
683 
684     // Am I a root folder?
685     HierarchyUri aUri( aURL );
686     if ( aUri.isRootFolder() )
687     {
688         // hasData must always return 'true' for root folder
689         // even if no persistent data exist!!!
690         return sal_True;
691     }
692 
693     return HierarchyEntry( rxSMgr, pProvider, aURL ).hasData();
694 }
695 
696 //=========================================================================
697 //static
loadData(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,HierarchyContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,HierarchyContentProperties & rProps)698 sal_Bool HierarchyContent::loadData(
699             const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
700             HierarchyContentProvider* pProvider,
701             const uno::Reference< ucb::XContentIdentifier >& Identifier,
702             HierarchyContentProperties& rProps )
703 {
704     rtl::OUString aURL = Identifier->getContentIdentifier();
705 
706     // Am I a root folder?
707     HierarchyUri aUri( aURL );
708     if ( aUri.isRootFolder() )
709     {
710         rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER );
711     }
712     else
713     {
714         HierarchyEntry aEntry( rxSMgr, pProvider, aURL );
715         HierarchyEntryData aData;
716         if ( !aEntry.getData( aData ) )
717             return sal_False;
718 
719         rProps = HierarchyContentProperties( aData );
720     }
721     return sal_True;
722 }
723 
724 //=========================================================================
storeData()725 sal_Bool HierarchyContent::storeData()
726 {
727     HierarchyEntry aEntry(
728             m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() );
729     return aEntry.setData( m_aProps.getHierarchyEntryData(), sal_True );
730 }
731 
732 //=========================================================================
renameData(const uno::Reference<ucb::XContentIdentifier> & xOldId,const uno::Reference<ucb::XContentIdentifier> & xNewId)733 sal_Bool HierarchyContent::renameData(
734             const uno::Reference< ucb::XContentIdentifier >& xOldId,
735             const uno::Reference< ucb::XContentIdentifier >& xNewId )
736 {
737     HierarchyEntry aEntry(
738             m_xSMgr, m_pProvider, xOldId->getContentIdentifier() );
739     return aEntry.move( xNewId->getContentIdentifier(),
740                         m_aProps.getHierarchyEntryData() );
741 }
742 
743 //=========================================================================
removeData()744 sal_Bool HierarchyContent::removeData()
745 {
746     HierarchyEntry aEntry(
747         m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() );
748     return aEntry.remove();
749 }
750 
751 //=========================================================================
setKind(const uno::Reference<ucb::XContentIdentifier> & Identifier)752 void HierarchyContent::setKind(
753             const uno::Reference< ucb::XContentIdentifier >& Identifier )
754 {
755     if ( m_aProps.getIsFolder() )
756     {
757         // Am I a root folder?
758         HierarchyUri aUri( Identifier->getContentIdentifier() );
759         if ( aUri.isRootFolder() )
760             m_eKind = ROOT;
761         else
762             m_eKind = FOLDER;
763     }
764     else
765         m_eKind = LINK;
766 }
767 
768 //=========================================================================
isReadOnly()769 bool HierarchyContent::isReadOnly()
770 {
771     if ( !m_bCheckedReadOnly )
772     {
773         osl::Guard< osl::Mutex > aGuard( m_aMutex );
774         if ( !m_bCheckedReadOnly )
775         {
776             m_bCheckedReadOnly = true;
777             m_bIsReadOnly      = true;
778 
779             HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
780             uno::Reference< lang::XMultiServiceFactory > xConfigProv
781                 = m_pProvider->getConfigProvider( aUri.getService() );
782             if ( xConfigProv.is() )
783             {
784                 uno::Sequence< rtl::OUString > aNames
785                     = xConfigProv->getAvailableServiceNames();
786                 sal_Int32 nCount = aNames.getLength();
787                 for ( sal_Int32 n = 0; n < nCount; ++n )
788                 {
789                     if ( aNames[ n ].equalsAsciiL(
790                             RTL_CONSTASCII_STRINGPARAM(
791                                 "com.sun.star.ucb.HierarchyDataReadWriteAccess"
792                              ) ) )
793                     {
794                         m_bIsReadOnly = false;
795                         break;
796                     }
797                 }
798             }
799         }
800     }
801 
802     return m_bIsReadOnly;
803 }
804 
805 //=========================================================================
806 uno::Reference< ucb::XContentIdentifier >
makeNewIdentifier(const rtl::OUString & rTitle)807 HierarchyContent::makeNewIdentifier( const rtl::OUString& rTitle )
808 {
809     osl::Guard< osl::Mutex > aGuard( m_aMutex );
810 
811     // Assemble new content identifier...
812     HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
813     rtl::OUString aNewURL = aUri.getParentUri();
814     aNewURL += rtl::OUString::createFromAscii( "/" );
815     aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle );
816 
817     return uno::Reference< ucb::XContentIdentifier >(
818         new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ) );
819 }
820 
821 //=========================================================================
queryChildren(HierarchyContentRefList & rChildren)822 void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren )
823 {
824     if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) )
825         return;
826 
827     // Obtain a list with a snapshot of all currently instantiated contents
828     // from provider and extract the contents which are direct children
829     // of this content.
830 
831     ::ucbhelper::ContentRefList aAllContents;
832     m_xProvider->queryExistingContents( aAllContents );
833 
834     rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
835     sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
836 
837     if ( nURLPos != ( aURL.getLength() - 1 ) )
838     {
839         // No trailing slash found. Append.
840         aURL += rtl::OUString::createFromAscii( "/" );
841     }
842 
843     sal_Int32 nLen = aURL.getLength();
844 
845     ::ucbhelper::ContentRefList::const_iterator it  = aAllContents.begin();
846     ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
847 
848     while ( it != end )
849     {
850         ::ucbhelper::ContentImplHelperRef xChild = (*it);
851         rtl::OUString aChildURL
852             = xChild->getIdentifier()->getContentIdentifier();
853 
854         // Is aURL a prefix of aChildURL?
855         if ( ( aChildURL.getLength() > nLen ) &&
856              ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
857         {
858             sal_Int32 nPos = nLen;
859             nPos = aChildURL.indexOf( '/', nPos );
860 
861             if ( ( nPos == -1 ) ||
862                  ( nPos == ( aChildURL.getLength() - 1 ) ) )
863             {
864                 // No further slashes/ only a final slash. It's a child!
865                 rChildren.push_back(
866                     HierarchyContentRef(
867                         static_cast< HierarchyContent * >( xChild.get() ) ) );
868             }
869         }
870         ++it;
871     }
872 }
873 
874 //=========================================================================
exchangeIdentity(const uno::Reference<ucb::XContentIdentifier> & xNewId)875 sal_Bool HierarchyContent::exchangeIdentity(
876             const uno::Reference< ucb::XContentIdentifier >& xNewId )
877 {
878     if ( !xNewId.is() )
879         return sal_False;
880 
881     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
882 
883     uno::Reference< ucb::XContent > xThis = this;
884 
885     // Already persistent?
886     if ( m_eState != PERSISTENT )
887     {
888         OSL_ENSURE( sal_False,
889                     "HierarchyContent::exchangeIdentity - Not persistent!" );
890         return sal_False;
891     }
892 
893     // Am I the root folder?
894     if ( m_eKind == ROOT )
895     {
896         OSL_ENSURE( sal_False, "HierarchyContent::exchangeIdentity - "
897                                "Not supported by root folder!" );
898         return sal_False;
899     }
900 
901     // Exchange own identitity.
902 
903     // Fail, if a content with given id already exists.
904     if ( !hasData( xNewId ) )
905     {
906         rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
907 
908         aGuard.clear();
909         if ( exchange( xNewId ) )
910         {
911             if ( m_eKind == FOLDER )
912             {
913                 // Process instantiated children...
914 
915                 HierarchyContentRefList aChildren;
916                 queryChildren( aChildren );
917 
918                 HierarchyContentRefList::const_iterator it  = aChildren.begin();
919                 HierarchyContentRefList::const_iterator end = aChildren.end();
920 
921                 while ( it != end )
922                 {
923                     HierarchyContentRef xChild = (*it);
924 
925                     // Create new content identifier for the child...
926                     uno::Reference< ucb::XContentIdentifier > xOldChildId
927                                                     = xChild->getIdentifier();
928                     rtl::OUString aOldChildURL
929                         = xOldChildId->getContentIdentifier();
930                     rtl::OUString aNewChildURL
931                         = aOldChildURL.replaceAt(
932                                         0,
933                                         aOldURL.getLength(),
934                                         xNewId->getContentIdentifier() );
935                     uno::Reference< ucb::XContentIdentifier > xNewChildId
936                         = new ::ucbhelper::ContentIdentifier(
937                             m_xSMgr, aNewChildURL );
938 
939                     if ( !xChild->exchangeIdentity( xNewChildId ) )
940                         return sal_False;
941 
942                     ++it;
943                 }
944             }
945             return sal_True;
946         }
947     }
948 
949     OSL_ENSURE( sal_False,
950                 "HierarchyContent::exchangeIdentity - "
951                 "Panic! Cannot exchange identity!" );
952     return sal_False;
953 }
954 
955 //=========================================================================
956 // static
getPropertyValues(const uno::Reference<lang::XMultiServiceFactory> & rSMgr,const uno::Sequence<beans::Property> & rProperties,const HierarchyContentProperties & rData,HierarchyContentProvider * pProvider,const rtl::OUString & rContentId)957 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
958                 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
959                 const uno::Sequence< beans::Property >& rProperties,
960                 const HierarchyContentProperties& rData,
961                 HierarchyContentProvider* pProvider,
962                 const rtl::OUString& rContentId )
963 {
964     // Note: Empty sequence means "get values of all supported properties".
965 
966     rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
967         = new ::ucbhelper::PropertyValueSet( rSMgr );
968 
969     sal_Int32 nCount = rProperties.getLength();
970     if ( nCount )
971     {
972         uno::Reference< beans::XPropertySet > xAdditionalPropSet;
973         sal_Bool bTriedToGetAdditonalPropSet = sal_False;
974 
975         const beans::Property* pProps = rProperties.getConstArray();
976         for ( sal_Int32 n = 0; n < nCount; ++n )
977         {
978             const beans::Property& rProp = pProps[ n ];
979 
980             // Process Core properties.
981 
982             if ( rProp.Name.equalsAsciiL(
983                         RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
984             {
985                 xRow->appendString ( rProp, rData.getContentType() );
986             }
987             else if ( rProp.Name.equalsAsciiL(
988                         RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
989             {
990                 xRow->appendString ( rProp, rData.getTitle() );
991             }
992             else if ( rProp.Name.equalsAsciiL(
993                         RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
994             {
995                 xRow->appendBoolean( rProp, rData.getIsDocument() );
996             }
997             else if ( rProp.Name.equalsAsciiL(
998                         RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
999             {
1000                 xRow->appendBoolean( rProp, rData.getIsFolder() );
1001             }
1002             else if ( rProp.Name.equalsAsciiL(
1003                         RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
1004             {
1005                 xRow->appendObject(
1006                     rProp, uno::makeAny( rData.getCreatableContentsInfo() ) );
1007             }
1008             else if ( rProp.Name.equalsAsciiL(
1009                         RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) )
1010             {
1011                 // TargetURL is only supported by links.
1012 
1013                 if ( rData.getIsDocument() )
1014                     xRow->appendString( rProp, rData.getTargetURL() );
1015                 else
1016                     xRow->appendVoid( rProp );
1017             }
1018             else
1019             {
1020                 // Not a Core Property! Maybe it's an Additional Core Property?!
1021 
1022                 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1023                 {
1024                     xAdditionalPropSet
1025                         = uno::Reference< beans::XPropertySet >(
1026                             pProvider->getAdditionalPropertySet( rContentId,
1027                                                                  sal_False ),
1028                             uno::UNO_QUERY );
1029                     bTriedToGetAdditonalPropSet = sal_True;
1030                 }
1031 
1032                 if ( xAdditionalPropSet.is() )
1033                 {
1034                     if ( !xRow->appendPropertySetValue(
1035                                                 xAdditionalPropSet,
1036                                                 rProp ) )
1037                     {
1038                         // Append empty entry.
1039                         xRow->appendVoid( rProp );
1040                     }
1041                 }
1042                 else
1043                 {
1044                     // Append empty entry.
1045                     xRow->appendVoid( rProp );
1046                 }
1047             }
1048         }
1049     }
1050     else
1051     {
1052         // Append all Core Properties.
1053         xRow->appendString (
1054             beans::Property( rtl::OUString::createFromAscii( "ContentType" ),
1055                       -1,
1056                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1057                       beans::PropertyAttribute::BOUND
1058                         | beans::PropertyAttribute::READONLY ),
1059             rData.getContentType() );
1060         xRow->appendString (
1061             beans::Property( rtl::OUString::createFromAscii( "Title" ),
1062                       -1,
1063                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1064                           // @@@ Might actually be read-only!
1065                       beans::PropertyAttribute::BOUND ),
1066             rData.getTitle() );
1067         xRow->appendBoolean(
1068             beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
1069                       -1,
1070                       getCppuBooleanType(),
1071                       beans::PropertyAttribute::BOUND
1072                         | beans::PropertyAttribute::READONLY ),
1073             rData.getIsDocument() );
1074         xRow->appendBoolean(
1075             beans::Property( rtl::OUString::createFromAscii( "IsFolder" ),
1076                       -1,
1077                       getCppuBooleanType(),
1078                       beans::PropertyAttribute::BOUND
1079                         | beans::PropertyAttribute::READONLY ),
1080             rData.getIsFolder() );
1081 
1082         if ( rData.getIsDocument() )
1083             xRow->appendString(
1084                 beans::Property( rtl::OUString::createFromAscii( "TargetURL" ),
1085                           -1,
1086                           getCppuType(
1087                             static_cast< const rtl::OUString * >( 0 ) ),
1088                           // @@@ Might actually be read-only!
1089                           beans::PropertyAttribute::BOUND ),
1090                 rData.getTargetURL() );
1091         xRow->appendObject(
1092             beans::Property(
1093                 rtl::OUString::createFromAscii( "CreatableContentsInfo" ),
1094                 -1,
1095                 getCppuType( static_cast<
1096                         const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
1097                 beans::PropertyAttribute::BOUND
1098                 | beans::PropertyAttribute::READONLY ),
1099             uno::makeAny( rData.getCreatableContentsInfo() ) );
1100 
1101         // Append all Additional Core Properties.
1102 
1103         uno::Reference< beans::XPropertySet > xSet(
1104             pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1105             uno::UNO_QUERY );
1106         xRow->appendPropertySet( xSet );
1107     }
1108 
1109     return uno::Reference< sdbc::XRow >( xRow.get() );
1110 }
1111 
1112 //=========================================================================
getPropertyValues(const uno::Sequence<beans::Property> & rProperties)1113 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
1114                         const uno::Sequence< beans::Property >& rProperties )
1115 {
1116     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1117     return getPropertyValues( m_xSMgr,
1118                               rProperties,
1119                               m_aProps,
1120                               m_pProvider,
1121                               m_xIdentifier->getContentIdentifier() );
1122 }
1123 
1124 //=========================================================================
setPropertyValues(const uno::Sequence<beans::PropertyValue> & rValues,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1125 uno::Sequence< uno::Any > HierarchyContent::setPropertyValues(
1126         const uno::Sequence< beans::PropertyValue >& rValues,
1127         const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1128 {
1129     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1130 
1131     uno::Sequence< uno::Any > aRet( rValues.getLength() );
1132     uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1133     sal_Int32 nChanged = 0;
1134 
1135     beans::PropertyChangeEvent aEvent;
1136     aEvent.Source         = static_cast< cppu::OWeakObject * >( this );
1137     aEvent.Further        = sal_False;
1138 //    aEvent.PropertyName   =
1139     aEvent.PropertyHandle = -1;
1140 //    aEvent.OldValue       =
1141 //    aEvent.NewValue       =
1142 
1143     const beans::PropertyValue* pValues = rValues.getConstArray();
1144     sal_Int32 nCount = rValues.getLength();
1145 
1146     uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1147     sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1148 
1149     sal_Bool bExchange = sal_False;
1150     rtl::OUString aOldTitle;
1151     rtl::OUString aOldName;
1152     sal_Int32 nTitlePos = -1;
1153 
1154     for ( sal_Int32 n = 0; n < nCount; ++n )
1155     {
1156         const beans::PropertyValue& rValue = pValues[ n ];
1157 
1158         if ( rValue.Name.equalsAsciiL(
1159                     RTL_CONSTASCII_STRINGPARAM(  "ContentType" ) ) )
1160         {
1161             // Read-only property!
1162             aRet[ n ] <<= lang::IllegalAccessException(
1163                             rtl::OUString::createFromAscii(
1164                                 "Property is read-only!" ),
1165                             static_cast< cppu::OWeakObject * >( this ) );
1166         }
1167         else if ( rValue.Name.equalsAsciiL(
1168                     RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1169         {
1170             // Read-only property!
1171             aRet[ n ] <<= lang::IllegalAccessException(
1172                             rtl::OUString::createFromAscii(
1173                                 "Property is read-only!" ),
1174                             static_cast< cppu::OWeakObject * >( this ) );
1175         }
1176         else if ( rValue.Name.equalsAsciiL(
1177                     RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1178         {
1179             // Read-only property!
1180             aRet[ n ] <<= lang::IllegalAccessException(
1181                             rtl::OUString::createFromAscii(
1182                                 "Property is read-only!" ),
1183                             static_cast< cppu::OWeakObject * >( this ) );
1184         }
1185         else if ( rValue.Name.equalsAsciiL(
1186                     RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
1187         {
1188             // Read-only property!
1189             aRet[ n ] <<= lang::IllegalAccessException(
1190                             rtl::OUString::createFromAscii(
1191                                 "Property is read-only!" ),
1192                             static_cast< cppu::OWeakObject * >( this ) );
1193         }
1194         else if ( rValue.Name.equalsAsciiL(
1195                     RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1196         {
1197             if ( isReadOnly() )
1198             {
1199                 aRet[ n ] <<= lang::IllegalAccessException(
1200                                 rtl::OUString::createFromAscii(
1201                                     "Property is read-only!" ),
1202                                 static_cast< cppu::OWeakObject * >( this ) );
1203             }
1204             else
1205             {
1206                 rtl::OUString aNewValue;
1207                 if ( rValue.Value >>= aNewValue )
1208                 {
1209                     // No empty titles!
1210                     if ( aNewValue.getLength() > 0 )
1211                     {
1212                         if ( aNewValue != m_aProps.getTitle() )
1213                         {
1214                             // modified title -> modified URL -> exchange !
1215                             if ( m_eState == PERSISTENT )
1216                                 bExchange = sal_True;
1217 
1218                             aOldTitle = m_aProps.getTitle();
1219                             aOldName  = m_aProps.getName();
1220 
1221                             m_aProps.setTitle( aNewValue );
1222                             m_aProps.setName(
1223                                 ::ucb_impl::urihelper::encodeSegment(
1224                                     aNewValue ) );
1225 
1226                             // property change event will be set later...
1227 
1228                             // remember position within sequence of values
1229                             // (for error handling).
1230                             nTitlePos = n;
1231                         }
1232                     }
1233                     else
1234                     {
1235                         aRet[ n ] <<= lang::IllegalArgumentException(
1236                                     rtl::OUString::createFromAscii(
1237                                             "Empty title not allowed!" ),
1238                                     static_cast< cppu::OWeakObject * >( this ),
1239                                     -1 );
1240                     }
1241                 }
1242                 else
1243                 {
1244                     aRet[ n ] <<= beans::IllegalTypeException(
1245                                 rtl::OUString::createFromAscii(
1246                                         "Property value has wrong type!" ),
1247                                 static_cast< cppu::OWeakObject * >( this ) );
1248                 }
1249             }
1250         }
1251         else if ( rValue.Name.equalsAsciiL(
1252                     RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) )
1253         {
1254             if ( isReadOnly() )
1255             {
1256                 aRet[ n ] <<= lang::IllegalAccessException(
1257                                 rtl::OUString::createFromAscii(
1258                                     "Property is read-only!" ),
1259                                 static_cast< cppu::OWeakObject * >( this ) );
1260             }
1261             else
1262             {
1263                 // TargetURL is only supported by links.
1264 
1265                 if ( m_eKind == LINK )
1266                 {
1267                     rtl::OUString aNewValue;
1268                     if ( rValue.Value >>= aNewValue )
1269                     {
1270                         // No empty target URL's!
1271                         if ( aNewValue.getLength() > 0 )
1272                         {
1273                             if ( aNewValue != m_aProps.getTargetURL() )
1274                             {
1275                                 aEvent.PropertyName = rValue.Name;
1276                                 aEvent.OldValue
1277                                     = uno::makeAny( m_aProps.getTargetURL() );
1278                                 aEvent.NewValue
1279                                     = uno::makeAny( aNewValue );
1280 
1281                                 aChanges.getArray()[ nChanged ] = aEvent;
1282 
1283                                 m_aProps.setTargetURL( aNewValue );
1284                                 nChanged++;
1285                             }
1286                         }
1287                         else
1288                         {
1289                             aRet[ n ] <<= lang::IllegalArgumentException(
1290                                     rtl::OUString::createFromAscii(
1291                                             "Empty target URL not allowed!" ),
1292                                     static_cast< cppu::OWeakObject * >( this ),
1293                                     -1 );
1294                         }
1295                     }
1296                     else
1297                     {
1298                         aRet[ n ] <<= beans::IllegalTypeException(
1299                                 rtl::OUString::createFromAscii(
1300                                         "Property value has wrong type!" ),
1301                                 static_cast< cppu::OWeakObject * >( this ) );
1302                     }
1303                 }
1304                 else
1305                 {
1306                     aRet[ n ] <<= beans::UnknownPropertyException(
1307                                 rtl::OUString::createFromAscii(
1308                                     "TargetURL only supported by links!" ),
1309                                 static_cast< cppu::OWeakObject * >( this ) );
1310                 }
1311             }
1312         }
1313         else
1314         {
1315             // Not a Core Property! Maybe it's an Additional Core Property?!
1316 
1317             if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1318             {
1319                 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1320                 bTriedToGetAdditonalPropSet = sal_True;
1321             }
1322 
1323             if ( xAdditionalPropSet.is() )
1324             {
1325                 try
1326                 {
1327                     uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1328                                                                 rValue.Name );
1329                     if ( aOldValue != rValue.Value )
1330                     {
1331                         xAdditionalPropSet->setPropertyValue(
1332                                                 rValue.Name, rValue.Value );
1333 
1334                         aEvent.PropertyName = rValue.Name;
1335                         aEvent.OldValue     = aOldValue;
1336                         aEvent.NewValue     = rValue.Value;
1337 
1338                         aChanges.getArray()[ nChanged ] = aEvent;
1339                         nChanged++;
1340                     }
1341                 }
1342                 catch ( beans::UnknownPropertyException const & e )
1343                 {
1344                     aRet[ n ] <<= e;
1345                 }
1346                 catch ( lang::WrappedTargetException const & e )
1347                 {
1348                     aRet[ n ] <<= e;
1349                 }
1350                 catch ( beans::PropertyVetoException const & e )
1351                 {
1352                     aRet[ n ] <<= e;
1353                 }
1354                 catch ( lang::IllegalArgumentException const & e )
1355                 {
1356                     aRet[ n ] <<= e;
1357                 }
1358             }
1359             else
1360             {
1361                 aRet[ n ] <<= uno::Exception(
1362                                 rtl::OUString::createFromAscii(
1363                                     "No property set for storing the value!" ),
1364                                 static_cast< cppu::OWeakObject * >( this ) );
1365             }
1366         }
1367     }
1368 
1369     if ( bExchange )
1370     {
1371         uno::Reference< ucb::XContentIdentifier > xOldId
1372             = m_xIdentifier;
1373         uno::Reference< ucb::XContentIdentifier > xNewId
1374             = makeNewIdentifier( m_aProps.getTitle() );
1375 
1376         aGuard.clear();
1377         if ( exchangeIdentity( xNewId ) )
1378         {
1379             // Adapt persistent data.
1380             renameData( xOldId, xNewId );
1381 
1382             // Adapt Additional Core Properties.
1383             renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1384                                          xNewId->getContentIdentifier(),
1385                                          sal_True );
1386         }
1387         else
1388         {
1389             // Roll-back.
1390             m_aProps.setTitle( aOldTitle );
1391             m_aProps.setName ( aOldName );
1392 
1393             aOldTitle = aOldName = rtl::OUString();
1394 
1395             // Set error .
1396             aRet[ nTitlePos ] <<= uno::Exception(
1397                     rtl::OUString::createFromAscii( "Exchange failed!" ),
1398                     static_cast< cppu::OWeakObject * >( this ) );
1399         }
1400     }
1401 
1402     if ( aOldTitle.getLength() )
1403     {
1404         aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" );
1405         aEvent.OldValue     = uno::makeAny( aOldTitle );
1406         aEvent.NewValue     = uno::makeAny( m_aProps.getTitle() );
1407 
1408         aChanges.getArray()[ nChanged ] = aEvent;
1409         nChanged++;
1410     }
1411 
1412     if ( nChanged > 0 )
1413     {
1414         // Save changes, if content was already made persistent.
1415         if ( !bExchange && ( m_eState == PERSISTENT ) )
1416         {
1417             if ( !storeData() )
1418             {
1419                 uno::Any aProps
1420                     = uno::makeAny(
1421                              beans::PropertyValue(
1422                                  rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1423                                      "Uri")),
1424                                  -1,
1425                                  uno::makeAny(m_xIdentifier->
1426                                                   getContentIdentifier()),
1427                                  beans::PropertyState_DIRECT_VALUE));
1428                 ucbhelper::cancelCommandExecution(
1429                     ucb::IOErrorCode_CANT_WRITE,
1430                     uno::Sequence< uno::Any >(&aProps, 1),
1431                     xEnv,
1432                     rtl::OUString::createFromAscii(
1433                         "Cannot store persistent data!" ),
1434                     this );
1435                 // Unreachable
1436             }
1437         }
1438 
1439         aChanges.realloc( nChanged );
1440 
1441         aGuard.clear();
1442         notifyPropertiesChange( aChanges );
1443     }
1444 
1445     return aRet;
1446 }
1447 
1448 //=========================================================================
insert(sal_Int32 nNameClashResolve,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1449 void HierarchyContent::insert( sal_Int32 nNameClashResolve,
1450                                const uno::Reference<
1451                                     ucb::XCommandEnvironment > & xEnv )
1452 {
1453     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1454 
1455     // Am I the root folder?
1456     if ( m_eKind == ROOT )
1457     {
1458         ucbhelper::cancelCommandExecution(
1459             uno::makeAny( ucb::UnsupportedCommandException(
1460                                 rtl::OUString::createFromAscii(
1461                                     "Not supported by root folder!" ),
1462                                 static_cast< cppu::OWeakObject * >( this ) ) ),
1463             xEnv );
1464         // Unreachable
1465     }
1466 
1467     // Check, if all required properties were set.
1468     if ( m_aProps.getTitle().getLength() == 0 )
1469     {
1470         uno::Sequence< rtl::OUString > aProps( 1 );
1471         aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" );
1472         ucbhelper::cancelCommandExecution(
1473             uno::makeAny( ucb::MissingPropertiesException(
1474                                 rtl::OUString(),
1475                                 static_cast< cppu::OWeakObject * >( this ),
1476                                 aProps ) ),
1477             xEnv );
1478         // Unreachable
1479     }
1480 
1481     // Assemble new content identifier...
1482 
1483     uno::Reference< ucb::XContentIdentifier > xId
1484         = makeNewIdentifier( m_aProps.getTitle() );
1485 
1486     // Handle possible name clash...
1487 
1488     switch ( nNameClashResolve )
1489     {
1490         // fail.
1491         case ucb::NameClash::ERROR:
1492             if ( hasData( xId ) )
1493             {
1494                 ucbhelper::cancelCommandExecution(
1495                     uno::makeAny(
1496                         ucb::NameClashException(
1497                             rtl::OUString(),
1498                             static_cast< cppu::OWeakObject * >( this ),
1499                             task::InteractionClassification_ERROR,
1500                             m_aProps.getTitle() ) ),
1501                     xEnv );
1502                 // Unreachable
1503             }
1504             break;
1505 
1506         // replace existing object.
1507         case ucb::NameClash::OVERWRITE:
1508             break;
1509 
1510         // "invent" a new valid title.
1511         case ucb::NameClash::RENAME:
1512             if ( hasData( xId ) )
1513             {
1514                 sal_Int32 nTry = 0;
1515 
1516                 do
1517                 {
1518                     rtl::OUString aNewId = xId->getContentIdentifier();
1519                     aNewId += rtl::OUString::createFromAscii( "_" );
1520                     aNewId += rtl::OUString::valueOf( ++nTry );
1521                     xId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewId );
1522                 }
1523                 while ( hasData( xId ) && ( nTry < 1000 ) );
1524 
1525                 if ( nTry == 1000 )
1526                 {
1527                     ucbhelper::cancelCommandExecution(
1528                         uno::makeAny(
1529                             ucb::UnsupportedNameClashException(
1530                                 rtl::OUString::createFromAscii(
1531                                     "Unable to resolve name clash!" ),
1532                                 static_cast< cppu::OWeakObject * >( this ),
1533                                 nNameClashResolve ) ),
1534                     xEnv );
1535                 // Unreachable
1536                 }
1537                 else
1538                 {
1539                     rtl::OUString aNewTitle( m_aProps.getTitle() );
1540                     aNewTitle += rtl::OUString::createFromAscii( "_" );
1541                     aNewTitle += rtl::OUString::valueOf( nTry );
1542                     m_aProps.setTitle( aNewTitle );
1543                 }
1544             }
1545             break;
1546 
1547         case ucb::NameClash::KEEP: // deprecated
1548         case ucb::NameClash::ASK:
1549         default:
1550             if ( hasData( xId ) )
1551             {
1552                 ucbhelper::cancelCommandExecution(
1553                     uno::makeAny(
1554                         ucb::UnsupportedNameClashException(
1555                                 rtl::OUString(),
1556                                 static_cast< cppu::OWeakObject * >( this ),
1557                                 nNameClashResolve ) ),
1558                     xEnv );
1559                 // Unreachable
1560             }
1561             break;
1562     }
1563 
1564     // Identifier changed?
1565     sal_Bool bNewId = ( xId->getContentIdentifier()
1566                             != m_xIdentifier->getContentIdentifier() );
1567     m_xIdentifier = xId;
1568 
1569     if ( !storeData() )
1570     {
1571         uno::Any aProps
1572             = uno::makeAny(beans::PropertyValue(
1573                                   rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1574                                                     "Uri")),
1575                                   -1,
1576                                   uno::makeAny(m_xIdentifier->
1577                                                    getContentIdentifier()),
1578                                   beans::PropertyState_DIRECT_VALUE));
1579         ucbhelper::cancelCommandExecution(
1580             ucb::IOErrorCode_CANT_WRITE,
1581             uno::Sequence< uno::Any >(&aProps, 1),
1582             xEnv,
1583             rtl::OUString::createFromAscii( "Cannot store persistent data!" ),
1584             this );
1585         // Unreachable
1586     }
1587 
1588     m_eState = PERSISTENT;
1589 
1590     if ( bNewId )
1591     {
1592         aGuard.clear();
1593         inserted();
1594     }
1595 }
1596 
1597 //=========================================================================
destroy(sal_Bool bDeletePhysical,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1598 void HierarchyContent::destroy( sal_Bool bDeletePhysical,
1599                                 const uno::Reference<
1600                                     ucb::XCommandEnvironment > & xEnv )
1601 {
1602     // @@@ take care about bDeletePhysical -> trashcan support
1603 
1604     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1605 
1606     uno::Reference< ucb::XContent > xThis = this;
1607 
1608     // Persistent?
1609     if ( m_eState != PERSISTENT )
1610     {
1611         ucbhelper::cancelCommandExecution(
1612             uno::makeAny( ucb::UnsupportedCommandException(
1613                                 rtl::OUString::createFromAscii(
1614                                     "Not persistent!" ),
1615                                 static_cast< cppu::OWeakObject * >( this ) ) ),
1616             xEnv );
1617         // Unreachable
1618     }
1619 
1620     // Am I the root folder?
1621     if ( m_eKind == ROOT )
1622     {
1623         ucbhelper::cancelCommandExecution(
1624             uno::makeAny( ucb::UnsupportedCommandException(
1625                                 rtl::OUString::createFromAscii(
1626                                     "Not supported by root folder!" ),
1627                                 static_cast< cppu::OWeakObject * >( this ) ) ),
1628             xEnv );
1629         // Unreachable
1630     }
1631 
1632     m_eState = DEAD;
1633 
1634     aGuard.clear();
1635     deleted();
1636 
1637     if ( m_eKind == FOLDER )
1638     {
1639         // Process instantiated children...
1640 
1641         HierarchyContentRefList aChildren;
1642         queryChildren( aChildren );
1643 
1644         HierarchyContentRefList::const_iterator it  = aChildren.begin();
1645         HierarchyContentRefList::const_iterator end = aChildren.end();
1646 
1647         while ( it != end )
1648         {
1649             (*it)->destroy( bDeletePhysical, xEnv );
1650             ++it;
1651         }
1652     }
1653 }
1654 
1655 //=========================================================================
transfer(const ucb::TransferInfo & rInfo,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1656 void HierarchyContent::transfer(
1657             const ucb::TransferInfo& rInfo,
1658             const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1659 {
1660     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1661 
1662     // Persistent?
1663     if ( m_eState != PERSISTENT )
1664     {
1665         ucbhelper::cancelCommandExecution(
1666             uno::makeAny( ucb::UnsupportedCommandException(
1667                                 rtl::OUString::createFromAscii(
1668                                     "Not persistent!" ),
1669                                 static_cast< cppu::OWeakObject * >( this ) ) ),
1670             xEnv );
1671         // Unreachable
1672     }
1673 
1674     // Is source a hierarchy content?
1675     if ( ( rInfo.SourceURL.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 2 ) ||
1676          ( rInfo.SourceURL.compareToAscii( HIERARCHY_URL_SCHEME ":/",
1677                                            HIERARCHY_URL_SCHEME_LENGTH + 2 )
1678             != 0 ) )
1679     {
1680         ucbhelper::cancelCommandExecution(
1681             uno::makeAny( ucb::InteractiveBadTransferURLException(
1682                             rtl::OUString(),
1683                             static_cast< cppu::OWeakObject * >( this ) ) ),
1684             xEnv );
1685         // Unreachable
1686     }
1687 
1688     // Is source not a parent of me / not me?
1689     rtl::OUString aId = m_xIdentifier->getContentIdentifier();
1690     sal_Int32 nPos = aId.lastIndexOf( '/' );
1691     if ( nPos != ( aId.getLength() - 1 ) )
1692     {
1693         // No trailing slash found. Append.
1694         aId += rtl::OUString::createFromAscii( "/" );
1695     }
1696 
1697     if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1698     {
1699         if ( aId.compareTo(
1700                 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
1701         {
1702             uno::Any aProps
1703                 = uno::makeAny(beans::PropertyValue(
1704                                       rtl::OUString(
1705                                           RTL_CONSTASCII_USTRINGPARAM("Uri")),
1706                                       -1,
1707                                       uno::makeAny(rInfo.SourceURL),
1708                                       beans::PropertyState_DIRECT_VALUE));
1709             ucbhelper::cancelCommandExecution(
1710                 ucb::IOErrorCode_RECURSIVE,
1711                 uno::Sequence< uno::Any >(&aProps, 1),
1712                 xEnv,
1713                 rtl::OUString::createFromAscii(
1714                     "Target is equal to or is a child of source!" ),
1715                 this );
1716             // Unreachable
1717         }
1718     }
1719 
1720     //////////////////////////////////////////////////////////////////////
1721     // 0) Obtain content object for source.
1722     //////////////////////////////////////////////////////////////////////
1723 
1724     uno::Reference< ucb::XContentIdentifier > xId
1725         = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL );
1726 
1727     // Note: The static cast is okay here, because its sure that
1728     //       m_xProvider is always the HierarchyContentProvider.
1729     rtl::Reference< HierarchyContent > xSource;
1730 
1731     try
1732     {
1733         xSource = static_cast< HierarchyContent * >(
1734                         m_xProvider->queryContent( xId ).get() );
1735     }
1736     catch ( ucb::IllegalIdentifierException const & )
1737     {
1738         // queryContent
1739     }
1740 
1741     if ( !xSource.is() )
1742     {
1743         uno::Any aProps
1744             = uno::makeAny(beans::PropertyValue(
1745                                   rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1746                                       "Uri")),
1747                                   -1,
1748                                   uno::makeAny(xId->getContentIdentifier()),
1749                                   beans::PropertyState_DIRECT_VALUE));
1750         ucbhelper::cancelCommandExecution(
1751             ucb::IOErrorCode_CANT_READ,
1752             uno::Sequence< uno::Any >(&aProps, 1),
1753             xEnv,
1754             rtl::OUString::createFromAscii(
1755                 "Cannot instantiate source object!" ),
1756             this );
1757         // Unreachable
1758     }
1759 
1760     //////////////////////////////////////////////////////////////////////
1761     // 1) Create new child content.
1762     //////////////////////////////////////////////////////////////////////
1763 
1764     rtl::OUString aType = xSource->isFolder()
1765         ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE )
1766         : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE );
1767     ucb::ContentInfo aContentInfo;
1768     aContentInfo.Type = aType;
1769     aContentInfo.Attributes = 0;
1770 
1771     // Note: The static cast is okay here, because its sure that
1772     //       createNewContent always creates a HierarchyContent.
1773     rtl::Reference< HierarchyContent > xTarget
1774         = static_cast< HierarchyContent * >(
1775             createNewContent( aContentInfo ).get() );
1776     if ( !xTarget.is() )
1777     {
1778         uno::Any aProps
1779             = uno::makeAny(beans::PropertyValue(
1780                                   rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1781                                       "Folder")),
1782                                   -1,
1783                                   uno::makeAny(aId),
1784                                   beans::PropertyState_DIRECT_VALUE));
1785         ucbhelper::cancelCommandExecution(
1786             ucb::IOErrorCode_CANT_CREATE,
1787             uno::Sequence< uno::Any >(&aProps, 1),
1788             xEnv,
1789             rtl::OUString::createFromAscii(
1790                 "XContentCreator::createNewContent failed!" ),
1791             this );
1792         // Unreachable
1793     }
1794 
1795     //////////////////////////////////////////////////////////////////////
1796     // 2) Copy data from source content to child content.
1797     //////////////////////////////////////////////////////////////////////
1798 
1799     uno::Sequence< beans::Property > aSourceProps
1800                     = xSource->getPropertySetInfo( xEnv )->getProperties();
1801     sal_Int32 nCount = aSourceProps.getLength();
1802 
1803     if ( nCount )
1804     {
1805         sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 );
1806 
1807         // Get all source values.
1808         uno::Reference< sdbc::XRow > xRow
1809             = xSource->getPropertyValues( aSourceProps );
1810 
1811         uno::Sequence< beans::PropertyValue > aValues( nCount );
1812         beans::PropertyValue* pValues = aValues.getArray();
1813 
1814         const beans::Property* pProps = aSourceProps.getConstArray();
1815         for ( sal_Int32 n = 0; n < nCount; ++n )
1816         {
1817             const beans::Property& rProp  = pProps[ n ];
1818             beans::PropertyValue&  rValue = pValues[ n ];
1819 
1820             rValue.Name   = rProp.Name;
1821             rValue.Handle = rProp.Handle;
1822 
1823             if ( !bHadTitle && rProp.Name.equalsAsciiL(
1824                                 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1825             {
1826                 // Set new title instead of original.
1827                 bHadTitle = sal_True;
1828                 rValue.Value <<= rInfo.NewTitle;
1829             }
1830             else
1831                 rValue.Value = xRow->getObject(
1832                                 n + 1,
1833                                 uno::Reference< container::XNameAccess >() );
1834 
1835             rValue.State = beans::PropertyState_DIRECT_VALUE;
1836 
1837             if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1838             {
1839                 // Add Additional Core Property.
1840                 try
1841                 {
1842                     xTarget->addProperty( rProp.Name,
1843                                           rProp.Attributes,
1844                                           rValue.Value );
1845                 }
1846                 catch ( beans::PropertyExistException const & )
1847                 {
1848                 }
1849                 catch ( beans::IllegalTypeException const & )
1850                 {
1851                 }
1852                 catch ( lang::IllegalArgumentException const & )
1853                 {
1854                 }
1855             }
1856         }
1857 
1858         // Set target values.
1859         xTarget->setPropertyValues( aValues, xEnv );
1860     }
1861 
1862     //////////////////////////////////////////////////////////////////////
1863     // 3) Commit (insert) child.
1864     //////////////////////////////////////////////////////////////////////
1865 
1866     xTarget->insert( rInfo.NameClash, xEnv );
1867 
1868     //////////////////////////////////////////////////////////////////////
1869     // 4) Transfer (copy) children of source.
1870     //////////////////////////////////////////////////////////////////////
1871 
1872     if ( xSource->isFolder() )
1873     {
1874         HierarchyEntry aFolder(
1875             m_xSMgr, m_pProvider, xId->getContentIdentifier() );
1876         HierarchyEntry::iterator it;
1877 
1878         while ( aFolder.next( it ) )
1879         {
1880             const HierarchyEntryData& rResult = *it;
1881 
1882             rtl::OUString aChildId = xId->getContentIdentifier();
1883             if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() )
1884                 aChildId += rtl::OUString::createFromAscii( "/" );
1885 
1886             aChildId += rResult.getName();
1887 
1888             ucb::TransferInfo aInfo;
1889             aInfo.MoveData  = sal_False;
1890             aInfo.NewTitle  = rtl::OUString();
1891             aInfo.SourceURL = aChildId;
1892             aInfo.NameClash = rInfo.NameClash;
1893 
1894             // Transfer child to target.
1895             xTarget->transfer( aInfo, xEnv );
1896         }
1897     }
1898 
1899     //////////////////////////////////////////////////////////////////////
1900     // 5) Destroy source ( when moving only ) .
1901     //////////////////////////////////////////////////////////////////////
1902 
1903     if ( rInfo.MoveData )
1904     {
1905         xSource->destroy( sal_True, xEnv );
1906 
1907         // Remove all persistent data of source and its children.
1908         if ( !xSource->removeData() )
1909         {
1910             uno::Any aProps
1911                 = uno::makeAny(
1912                          beans::PropertyValue(
1913                              rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1914                                                "Uri")),
1915                              -1,
1916                              uno::makeAny(
1917                                  xSource->m_xIdentifier->
1918                                               getContentIdentifier()),
1919                              beans::PropertyState_DIRECT_VALUE));
1920             ucbhelper::cancelCommandExecution(
1921                 ucb::IOErrorCode_CANT_WRITE,
1922                 uno::Sequence< uno::Any >(&aProps, 1),
1923                 xEnv,
1924                 rtl::OUString::createFromAscii(
1925                     "Cannot remove persistent data of source object!" ),
1926                 this );
1927             // Unreachable
1928         }
1929 
1930         // Remove own and all children's Additional Core Properties.
1931         xSource->removeAdditionalPropertySet( sal_True );
1932     }
1933 }
1934 
1935 //=========================================================================
1936 //=========================================================================
1937 //
1938 // HierarchyContentProperties Implementation.
1939 //
1940 //=========================================================================
1941 //=========================================================================
1942 
1943 uno::Sequence< ucb::ContentInfo >
getCreatableContentsInfo() const1944 HierarchyContentProperties::getCreatableContentsInfo() const
1945 {
1946     if ( getIsFolder() )
1947     {
1948         uno::Sequence< ucb::ContentInfo > aSeq( 2 );
1949 
1950         // Folder.
1951         aSeq.getArray()[ 0 ].Type
1952             = rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE );
1953         aSeq.getArray()[ 0 ].Attributes
1954             = ucb::ContentInfoAttribute::KIND_FOLDER;
1955 
1956         uno::Sequence< beans::Property > aFolderProps( 1 );
1957         aFolderProps.getArray()[ 0 ] = beans::Property(
1958                     rtl::OUString::createFromAscii( "Title" ),
1959                     -1,
1960                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1961                     beans::PropertyAttribute::BOUND );
1962         aSeq.getArray()[ 0 ].Properties = aFolderProps;
1963 
1964         // Link.
1965         aSeq.getArray()[ 1 ].Type
1966             = rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE );
1967         aSeq.getArray()[ 1 ].Attributes
1968             = ucb::ContentInfoAttribute::KIND_LINK;
1969 
1970         uno::Sequence< beans::Property > aLinkProps( 2 );
1971         aLinkProps.getArray()[ 0 ] = beans::Property(
1972                     rtl::OUString::createFromAscii( "Title" ),
1973                     -1,
1974                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1975                     beans::PropertyAttribute::BOUND );
1976         aLinkProps.getArray()[ 1 ] = beans::Property(
1977                     rtl::OUString::createFromAscii( "TargetURL" ),
1978                     -1,
1979                     getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1980                     beans::PropertyAttribute::BOUND );
1981         aSeq.getArray()[ 1 ].Properties = aLinkProps;
1982 
1983         return aSeq;
1984     }
1985     else
1986     {
1987         return uno::Sequence< ucb::ContentInfo >( 0 );
1988     }
1989 }
1990