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