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