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 "hierarchycontent.hxx"
69#include "hierarchyprovider.hxx"
70#include "dynamicresultset.hxx"
71#include "hierarchyuri.hxx"
72
73#include "../inc/urihelper.hxx"
74
75using namespace com::sun::star;
76using namespace hierarchy_ucp;
77
78
79// HierarchyContent Implementation.
80
81
82// static ( "virtual" ctor )
83rtl::Reference<HierarchyContent> HierarchyContent::create(
84 const uno::Reference< uno::XComponentContext >& rxContext,
85 HierarchyContentProvider* pProvider,
86 const uno::Reference< ucb::XContentIdentifier >& Identifier )
87{
88 // Fail, if content does not exist.
90 if ( !loadData( rxContext, pProvider, Identifier, aProps ) )
91 return nullptr;
92
93 return new HierarchyContent( rxContext, pProvider, Identifier, aProps );
94}
95
96
97// static ( "virtual" ctor )
99 const uno::Reference< uno::XComponentContext >& rxContext,
100 HierarchyContentProvider* pProvider,
101 const uno::Reference< ucb::XContentIdentifier >& Identifier,
102 const ucb::ContentInfo& Info )
103{
104 if ( Info.Type.isEmpty() )
105 return nullptr;
106
108 return nullptr;
109
110 return new HierarchyContent( rxContext, pProvider, Identifier, Info );
111}
112
113
115 const uno::Reference< uno::XComponentContext >& rxContext,
116 HierarchyContentProvider* pProvider,
117 const uno::Reference< ucb::XContentIdentifier >& Identifier,
118 const HierarchyContentProperties& rProps )
119: ContentImplHelper( rxContext, pProvider, Identifier ),
120 m_aProps( rProps ),
121 m_eState( PERSISTENT ),
122 m_pProvider( pProvider ),
123 m_bCheckedReadOnly( false ),
124 m_bIsReadOnly( true )
125{
126 setKind( Identifier );
127}
128
129
130HierarchyContent::HierarchyContent(
131 const uno::Reference< uno::XComponentContext >& rxContext,
132 HierarchyContentProvider* pProvider,
133 const uno::Reference< ucb::XContentIdentifier >& Identifier,
134 const ucb::ContentInfo& Info )
135 : ContentImplHelper( rxContext, pProvider, Identifier ),
137 m_eState( TRANSIENT ),
138 m_pProvider( pProvider ),
139 m_bCheckedReadOnly( false ),
140 m_bIsReadOnly( true )
141{
142 setKind( Identifier );
143}
144
145
146// virtual
147HierarchyContent::~HierarchyContent()
148{
149}
150
151
152// XInterface methods.
153
154
155// virtual
157 noexcept
158{
159 ContentImplHelper::acquire();
160}
161
162
163// virtual
165 noexcept
166{
167 ContentImplHelper::release();
168}
169
170
171// virtual
173{
174 uno::Any aRet = ContentImplHelper::queryInterface( rType );
175
176 if ( !aRet.hasValue() )
177 {
178 // Note: isReadOnly may be relative expensive. So avoid calling it
179 // unless it is really necessary.
181 rType, static_cast< ucb::XContentCreator * >( this ) );
182 if ( aRet.hasValue() )
183 {
184 if ( !isFolder() || isReadOnly() )
185 return uno::Any();
186 }
187 }
188
189 return aRet;
190}
191
192
193// XTypeProvider methods.
194
195
197
198
199// virtual
200uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes()
201{
202 if ( isFolder() && !isReadOnly() )
203 {
204 static cppu::OTypeCollection s_aFolderTypes(
205 CPPU_TYPE_REF( lang::XTypeProvider ),
206 CPPU_TYPE_REF( lang::XServiceInfo ),
207 CPPU_TYPE_REF( lang::XComponent ),
208 CPPU_TYPE_REF( ucb::XContent ),
209 CPPU_TYPE_REF( ucb::XCommandProcessor ),
210 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
211 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
212 CPPU_TYPE_REF( beans::XPropertyContainer ),
213 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
214 CPPU_TYPE_REF( container::XChild ),
215 CPPU_TYPE_REF( ucb::XContentCreator ) );
216
217
218 return s_aFolderTypes.getTypes();
219 }
220 else
221 {
222 static cppu::OTypeCollection s_aDocumentTypes(
223 CPPU_TYPE_REF( lang::XTypeProvider ),
224 CPPU_TYPE_REF( lang::XServiceInfo ),
225 CPPU_TYPE_REF( lang::XComponent ),
226 CPPU_TYPE_REF( ucb::XContent ),
227 CPPU_TYPE_REF( ucb::XCommandProcessor ),
228 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
229 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
230 CPPU_TYPE_REF( beans::XPropertyContainer ),
231 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
232 CPPU_TYPE_REF( container::XChild ) );
233
234 return s_aDocumentTypes.getTypes();
235 }
236}
237
238
239// XServiceInfo methods.
240
241
242// virtual
244{
245 return "com.sun.star.comp.ucb.HierarchyContent";
246}
247
248
249// virtual
250uno::Sequence< OUString > SAL_CALL
252{
253 uno::Sequence< OUString > aSNS( 1 );
254
255 if ( m_eKind == LINK )
256 aSNS.getArray()[ 0 ] = "com.sun.star.ucb.HierarchyLinkContent";
257 else if ( m_eKind == FOLDER )
258 aSNS.getArray()[ 0 ] = "com.sun.star.ucb.HierarchyFolderContent";
259 else
260 aSNS.getArray()[ 0 ] = "com.sun.star.ucb.HierarchyRootFolderContent";
261
262 return aSNS;
263}
264
265
266// XContent methods.
267
268
269// virtual
271{
272 return m_aProps.getContentType();
273}
274
275
276// virtual
277uno::Reference< ucb::XContentIdentifier > SAL_CALL
279{
280 // Transient?
281 if ( m_eState == TRANSIENT )
282 {
283 // Transient contents have no identifier.
284 return uno::Reference< ucb::XContentIdentifier >();
285 }
286
287 return ContentImplHelper::getIdentifier();
288}
289
290
291// XCommandProcessor methods.
292
293
294// virtual
296 const ucb::Command& aCommand,
297 sal_Int32 /*CommandId*/,
298 const uno::Reference< ucb::XCommandEnvironment >& Environment )
299{
300 uno::Any aRet;
301
302 if ( aCommand.Name == "getPropertyValues" )
303 {
304
305 // getPropertyValues
306
307
308 uno::Sequence< beans::Property > Properties;
309 if ( !( aCommand.Argument >>= Properties ) )
310 {
312 uno::Any( lang::IllegalArgumentException(
313 "Wrong argument type!",
314 static_cast< cppu::OWeakObject * >( this ),
315 -1 ) ),
316 Environment );
317 // Unreachable
318 }
319
320 aRet <<= getPropertyValues( Properties );
321 }
322 else if ( aCommand.Name == "setPropertyValues" )
323 {
324
325 // setPropertyValues
326
327
328 uno::Sequence< beans::PropertyValue > aProperties;
329 if ( !( aCommand.Argument >>= aProperties ) )
330 {
332 uno::Any( lang::IllegalArgumentException(
333 "Wrong argument type!",
334 static_cast< cppu::OWeakObject * >( this ),
335 -1 ) ),
336 Environment );
337 // Unreachable
338 }
339
340 if ( !aProperties.hasElements() )
341 {
343 uno::Any( lang::IllegalArgumentException(
344 "No properties!",
345 static_cast< cppu::OWeakObject * >( this ),
346 -1 ) ),
347 Environment );
348 // Unreachable
349 }
350
352 }
353 else if ( aCommand.Name == "getPropertySetInfo" )
354 {
355
356 // getPropertySetInfo
357
358
360 }
361 else if ( aCommand.Name == "getCommandInfo" )
362 {
363
364 // getCommandInfo
365
366
367 aRet <<= getCommandInfo( Environment );
368 }
369 else if ( aCommand.Name == "open" && isFolder() )
370 {
371
372 // open command for a folder content
373
374
375 ucb::OpenCommandArgument2 aOpenCommand;
376 if ( !( aCommand.Argument >>= aOpenCommand ) )
377 {
379 uno::Any( lang::IllegalArgumentException(
380 "Wrong argument type!",
381 static_cast< cppu::OWeakObject * >( this ),
382 -1 ) ),
383 Environment );
384 // Unreachable
385 }
386
387 uno::Reference< ucb::XDynamicResultSet > xSet
388 = new DynamicResultSet( m_xContext, this, aOpenCommand );
389 aRet <<= xSet;
390 }
391 else if ( aCommand.Name == "insert" && ( m_eKind != ROOT ) && !isReadOnly() )
392 {
393
394 // insert
395 // ( Not available at root folder )
396
397
398 ucb::InsertCommandArgument aArg;
399 if ( !( aCommand.Argument >>= aArg ) )
400 {
402 uno::Any( lang::IllegalArgumentException(
403 "Wrong argument type!",
404 static_cast< cppu::OWeakObject * >( this ),
405 -1 ) ),
406 Environment );
407 // Unreachable
408 }
409
410 sal_Int32 nNameClash = aArg.ReplaceExisting
411 ? ucb::NameClash::OVERWRITE
412 : ucb::NameClash::ERROR;
413 insert( nNameClash, Environment );
414 }
415 else if ( aCommand.Name == "delete" && ( m_eKind != ROOT ) && !isReadOnly() )
416 {
417
418 // delete
419 // ( Not available at root folder )
420
421
422 bool bDeletePhysical = false;
423 aCommand.Argument >>= bDeletePhysical;
424 destroy( bDeletePhysical, Environment );
425
426 // Remove own and all children's persistent data.
427 if ( !removeData() )
428 {
429 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
430 {
431 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
432 }));
434 ucb::IOErrorCode_CANT_WRITE,
435 aArgs,
437 "Cannot remove persistent data!",
438 this );
439 // Unreachable
440 }
441
442 // Remove own and all children's Additional Core Properties.
444 }
445 else if ( aCommand.Name == "transfer" && isFolder() && !isReadOnly() )
446 {
447
448 // transfer
449 // ( Not available at link objects )
450
451
452 ucb::TransferInfo aInfo;
453 if ( !( aCommand.Argument >>= aInfo ) )
454 {
455 OSL_FAIL( "Wrong argument type!" );
457 uno::Any( lang::IllegalArgumentException(
458 "Wrong argument type!",
459 static_cast< cppu::OWeakObject * >( this ),
460 -1 ) ),
461 Environment );
462 // Unreachable
463 }
464
465 transfer( aInfo, Environment );
466 }
467 else if ( aCommand.Name == "createNewContent" && isFolder() && !isReadOnly() )
468 {
469
470 // createNewContent
471 // ( Not available at link objects )
472
473
474 ucb::ContentInfo aInfo;
475 if ( !( aCommand.Argument >>= aInfo ) )
476 {
477 OSL_FAIL( "Wrong argument type!" );
479 uno::Any( lang::IllegalArgumentException(
480 "Wrong argument type!",
481 static_cast< cppu::OWeakObject * >( this ),
482 -1 ) ),
483 Environment );
484 // Unreachable
485 }
486
487 aRet <<= createNewContent( aInfo );
488 }
489 else
490 {
491
492 // Unsupported command
493
494
496 uno::Any( ucb::UnsupportedCommandException(
497 OUString(),
498 static_cast< cppu::OWeakObject * >( this ) ) ),
499 Environment );
500 // Unreachable
501 }
502
503 return aRet;
504}
505
506
507// virtual
508void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ )
509{
510 // @@@ Generally, no action takes much time...
511}
512
513
514// XContentCreator methods.
515
516
517// virtual
518uno::Sequence< ucb::ContentInfo > SAL_CALL
520{
522}
523
524
525// virtual
526uno::Reference< ucb::XContent > SAL_CALL
527HierarchyContent::createNewContent( const ucb::ContentInfo& Info )
528{
529 if ( isFolder() )
530 {
531 osl::Guard< osl::Mutex > aGuard( m_aMutex );
532
533 if ( Info.Type.isEmpty() )
534 return uno::Reference< ucb::XContent >();
535
536 bool bCreateFolder = Info.Type == HIERARCHY_FOLDER_CONTENT_TYPE;
537
538 if ( !bCreateFolder && Info.Type != HIERARCHY_LINK_CONTENT_TYPE )
539 return uno::Reference< ucb::XContent >();
540
541 OUString aURL = m_xIdentifier->getContentIdentifier();
542
543 OSL_ENSURE( !aURL.isEmpty(),
544 "HierarchyContent::createNewContent - empty identifier!" );
545
546 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
547 aURL += "/";
548
549 if ( bCreateFolder )
550 aURL += "New_Folder";
551 else
552 aURL += "New_Link";
553
554 uno::Reference< ucb::XContentIdentifier > xId
555 = new ::ucbhelper::ContentIdentifier( aURL );
556
557 return create( m_xContext, m_pProvider, xId, Info );
558 }
559 else
560 {
561 OSL_FAIL( "createNewContent called on non-folder object!" );
562 return uno::Reference< ucb::XContent >();
563 }
564}
565
566
567// virtual
569{
570 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
571 return aUri.getParentUri();
572}
573
574
575//static
577 const uno::Reference< uno::XComponentContext >& rxContext,
578 HierarchyContentProvider* pProvider,
579 const uno::Reference< ucb::XContentIdentifier >& Identifier )
580{
581 OUString aURL = Identifier->getContentIdentifier();
582
583 // Am I a root folder?
584 HierarchyUri aUri( aURL );
585 if ( aUri.isRootFolder() )
586 {
587 // hasData must always return 'true' for root folder
588 // even if no persistent data exist!!!
589 return true;
590 }
591
592 return HierarchyEntry( rxContext, pProvider, aURL ).hasData();
593}
594
595
596//static
598 const uno::Reference< uno::XComponentContext >& rxContext,
599 HierarchyContentProvider* pProvider,
600 const uno::Reference< ucb::XContentIdentifier >& Identifier,
602{
603 OUString aURL = Identifier->getContentIdentifier();
604
605 // Am I a root folder?
606 HierarchyUri aUri( aURL );
607 if ( aUri.isRootFolder() )
608 {
610 }
611 else
612 {
613 HierarchyEntry aEntry( rxContext, pProvider, aURL );
615 if ( !aEntry.getData( aData ) )
616 return false;
617
619 }
620 return true;
621}
622
623
625{
626 HierarchyEntry aEntry(
627 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
628 return aEntry.setData( m_aProps.getHierarchyEntryData() );
629}
630
631
633 const uno::Reference< ucb::XContentIdentifier >& xOldId,
634 const uno::Reference< ucb::XContentIdentifier >& xNewId )
635{
636 HierarchyEntry aEntry(
637 m_xContext, m_pProvider, xOldId->getContentIdentifier() );
638 aEntry.move( xNewId->getContentIdentifier(),
640}
641
642
644{
645 HierarchyEntry aEntry(
646 m_xContext, m_pProvider, m_xIdentifier->getContentIdentifier() );
647 return aEntry.remove();
648}
649
650
652 const uno::Reference< ucb::XContentIdentifier >& Identifier )
653{
654 if ( m_aProps.getIsFolder() )
655 {
656 // Am I a root folder?
657 HierarchyUri aUri( Identifier->getContentIdentifier() );
658 if ( aUri.isRootFolder() )
659 m_eKind = ROOT;
660 else
661 m_eKind = FOLDER;
662 }
663 else
664 m_eKind = LINK;
665}
666
667
669{
670 if ( !m_bCheckedReadOnly )
671 {
672 osl::Guard< osl::Mutex > aGuard( m_aMutex );
673 if ( !m_bCheckedReadOnly )
674 {
675 m_bCheckedReadOnly = true;
676 m_bIsReadOnly = true;
677
678 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
679 uno::Reference< lang::XMultiServiceFactory > xConfigProv
681 if ( xConfigProv.is() )
682 {
683 uno::Sequence< OUString > aNames
684 = xConfigProv->getAvailableServiceNames();
685 m_bIsReadOnly = comphelper::findValue(aNames, "com.sun.star.ucb.HierarchyDataReadWriteAccess") == -1;
686 }
687 }
688 }
689
690 return m_bIsReadOnly;
691}
692
693
694uno::Reference< ucb::XContentIdentifier >
695HierarchyContent::makeNewIdentifier( const OUString& rTitle )
696{
697 osl::Guard< osl::Mutex > aGuard( m_aMutex );
698
699 // Assemble new content identifier...
700 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() );
701 OUString aNewURL = aUri.getParentUri() + "/";
702 aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle );
703
704 return uno::Reference< ucb::XContentIdentifier >(
705 new ::ucbhelper::ContentIdentifier( aNewURL ) );
706}
707
708
710{
711 if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) )
712 return;
713
714 // Obtain a list with a snapshot of all currently instantiated contents
715 // from provider and extract the contents which are direct children
716 // of this content.
717
718 ::ucbhelper::ContentRefList aAllContents;
719 m_xProvider->queryExistingContents( aAllContents );
720
721 OUString aURL = m_xIdentifier->getContentIdentifier();
722 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
723
724 if ( nURLPos != ( aURL.getLength() - 1 ) )
725 {
726 // No trailing slash found. Append.
727 aURL += "/";
728 }
729
730 sal_Int32 nLen = aURL.getLength();
731
732 for ( const auto& rContent : aAllContents )
733 {
734 ::ucbhelper::ContentImplHelperRef xChild = rContent;
735 OUString aChildURL
736 = xChild->getIdentifier()->getContentIdentifier();
737
738 // Is aURL a prefix of aChildURL?
739 if ( ( aChildURL.getLength() > nLen ) &&
740 ( aChildURL.startsWith( aURL ) ) )
741 {
742 sal_Int32 nPos = aChildURL.indexOf( '/', nLen );
743
744 if ( ( nPos == -1 ) ||
745 ( nPos == ( aChildURL.getLength() - 1 ) ) )
746 {
747 // No further slashes/ only a final slash. It's a child!
748 rChildren.emplace_back(
749 static_cast< HierarchyContent * >( xChild.get() ) );
750 }
751 }
752 }
753}
754
755
757 const uno::Reference< ucb::XContentIdentifier >& xNewId )
758{
759 if ( !xNewId.is() )
760 return false;
761
762 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
763
764 uno::Reference< ucb::XContent > xThis = this;
765
766 // Already persistent?
767 if ( m_eState != PERSISTENT )
768 {
769 OSL_FAIL( "HierarchyContent::exchangeIdentity - Not persistent!" );
770 return false;
771 }
772
773 // Am I the root folder?
774 if ( m_eKind == ROOT )
775 {
776 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
777 "Not supported by root folder!" );
778 return false;
779 }
780
781 // Exchange own identity.
782
783 // Fail, if a content with given id already exists.
784 if ( !hasData( xNewId ) )
785 {
786 OUString aOldURL = m_xIdentifier->getContentIdentifier();
787
788 aGuard.clear();
789 if ( exchange( xNewId ) )
790 {
791 if ( m_eKind == FOLDER )
792 {
793 // Process instantiated children...
794
796 queryChildren( aChildren );
797
798 for ( const auto& rChild : aChildren )
799 {
800 HierarchyContentRef xChild = rChild;
801
802 // Create new content identifier for the child...
803 uno::Reference< ucb::XContentIdentifier > xOldChildId
804 = xChild->getIdentifier();
805 OUString aOldChildURL
806 = xOldChildId->getContentIdentifier();
807 OUString aNewChildURL
808 = aOldChildURL.replaceAt(
809 0,
810 aOldURL.getLength(),
811 xNewId->getContentIdentifier() );
812 uno::Reference< ucb::XContentIdentifier > xNewChildId
813 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
814
815 if ( !xChild->exchangeIdentity( xNewChildId ) )
816 return false;
817 }
818 }
819 return true;
820 }
821 }
822
823 OSL_FAIL( "HierarchyContent::exchangeIdentity - "
824 "Panic! Cannot exchange identity!" );
825 return false;
826}
827
828
829// static
830uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
831 const uno::Reference< uno::XComponentContext >& rxContext,
832 const uno::Sequence< beans::Property >& rProperties,
833 const HierarchyContentProperties& rData,
834 HierarchyContentProvider* pProvider,
835 const OUString& rContentId )
836{
837 // Note: Empty sequence means "get values of all supported properties".
838
840 = new ::ucbhelper::PropertyValueSet( rxContext );
841
842 if ( rProperties.hasElements() )
843 {
844 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
845 bool bTriedToGetAdditionalPropSet = false;
846
847 for ( const beans::Property& rProp : rProperties )
848 {
849 // Process Core properties.
850
851 if ( rProp.Name == "ContentType" )
852 {
853 xRow->appendString ( rProp, rData.getContentType() );
854 }
855 else if ( rProp.Name == "Title" )
856 {
857 xRow->appendString ( rProp, rData.getTitle() );
858 }
859 else if ( rProp.Name == "IsDocument" )
860 {
861 xRow->appendBoolean( rProp, rData.getIsDocument() );
862 }
863 else if ( rProp.Name == "IsFolder" )
864 {
865 xRow->appendBoolean( rProp, rData.getIsFolder() );
866 }
867 else if ( rProp.Name == "CreatableContentsInfo" )
868 {
869 xRow->appendObject(
870 rProp, uno::Any( rData.getCreatableContentsInfo() ) );
871 }
872 else if ( rProp.Name == "TargetURL" )
873 {
874 // TargetURL is only supported by links.
875
876 if ( rData.getIsDocument() )
877 xRow->appendString( rProp, rData.getTargetURL() );
878 else
879 xRow->appendVoid( rProp );
880 }
881 else
882 {
883 // Not a Core Property! Maybe it's an Additional Core Property?!
884
885 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
886 {
887 xAdditionalPropSet =
888 pProvider->getAdditionalPropertySet( rContentId,
889 false );
890 bTriedToGetAdditionalPropSet = true;
891 }
892
893 if ( xAdditionalPropSet.is() )
894 {
895 if ( !xRow->appendPropertySetValue(
896 xAdditionalPropSet,
897 rProp ) )
898 {
899 // Append empty entry.
900 xRow->appendVoid( rProp );
901 }
902 }
903 else
904 {
905 // Append empty entry.
906 xRow->appendVoid( rProp );
907 }
908 }
909 }
910 }
911 else
912 {
913 // Append all Core Properties.
914 xRow->appendString (
915 beans::Property( "ContentType",
916 -1,
918 beans::PropertyAttribute::BOUND
919 | beans::PropertyAttribute::READONLY ),
920 rData.getContentType() );
921 xRow->appendString (
922 beans::Property( "Title",
923 -1,
925 // @@@ Might actually be read-only!
926 beans::PropertyAttribute::BOUND ),
927 rData.getTitle() );
928 xRow->appendBoolean(
929 beans::Property( "IsDocument",
930 -1,
932 beans::PropertyAttribute::BOUND
933 | beans::PropertyAttribute::READONLY ),
934 rData.getIsDocument() );
935 xRow->appendBoolean(
936 beans::Property( "IsFolder",
937 -1,
939 beans::PropertyAttribute::BOUND
940 | beans::PropertyAttribute::READONLY ),
941 rData.getIsFolder() );
942
943 if ( rData.getIsDocument() )
944 xRow->appendString(
945 beans::Property( "TargetURL",
946 -1,
948 // @@@ Might actually be read-only!
949 beans::PropertyAttribute::BOUND ),
950 rData.getTargetURL() );
951 xRow->appendObject(
952 beans::Property(
953 "CreatableContentsInfo",
954 -1,
955 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
956 beans::PropertyAttribute::BOUND
957 | beans::PropertyAttribute::READONLY ),
958 uno::Any( rData.getCreatableContentsInfo() ) );
959
960 // Append all Additional Core Properties.
961
962 uno::Reference< beans::XPropertySet > xSet =
963 pProvider->getAdditionalPropertySet( rContentId, false );
964 xRow->appendPropertySet( xSet );
965 }
966
967 return xRow;
968}
969
970
971uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues(
972 const uno::Sequence< beans::Property >& rProperties )
973{
974 osl::Guard< osl::Mutex > aGuard( m_aMutex );
976 rProperties,
977 m_aProps,
979 m_xIdentifier->getContentIdentifier() );
980}
981
982
983uno::Sequence< uno::Any > HierarchyContent::setPropertyValues(
984 const uno::Sequence< beans::PropertyValue >& rValues,
985 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
986{
987 osl::ResettableGuard< osl::Mutex > aGuard( m_aMutex );
988
989 uno::Sequence< uno::Any > aRet( rValues.getLength() );
990 auto aRetRange = asNonConstRange(aRet);
991 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
992 sal_Int32 nChanged = 0;
993
994 beans::PropertyChangeEvent aEvent;
995 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
996 aEvent.Further = false;
997// aEvent.PropertyName =
998 aEvent.PropertyHandle = -1;
999// aEvent.OldValue =
1000// aEvent.NewValue =
1001
1002 const beans::PropertyValue* pValues = rValues.getConstArray();
1003 sal_Int32 nCount = rValues.getLength();
1004
1005 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1006 bool bTriedToGetAdditionalPropSet = false;
1007
1008 bool bExchange = false;
1009 OUString aOldTitle;
1010 OUString aOldName;
1011 sal_Int32 nTitlePos = -1;
1012
1013 for ( sal_Int32 n = 0; n < nCount; ++n )
1014 {
1015 const beans::PropertyValue& rValue = pValues[ n ];
1016
1017 if ( rValue.Name == "ContentType" )
1018 {
1019 // Read-only property!
1020 aRetRange[ n ] <<= lang::IllegalAccessException(
1021 "Property is read-only!",
1022 static_cast< cppu::OWeakObject * >( this ) );
1023 }
1024 else if ( rValue.Name == "IsDocument" )
1025 {
1026 // Read-only property!
1027 aRetRange[ n ] <<= lang::IllegalAccessException(
1028 "Property is read-only!",
1029 static_cast< cppu::OWeakObject * >( this ) );
1030 }
1031 else if ( rValue.Name == "IsFolder" )
1032 {
1033 // Read-only property!
1034 aRetRange[ n ] <<= lang::IllegalAccessException(
1035 "Property is read-only!",
1036 static_cast< cppu::OWeakObject * >( this ) );
1037 }
1038 else if ( rValue.Name == "CreatableContentsInfo" )
1039 {
1040 // Read-only property!
1041 aRetRange[ n ] <<= lang::IllegalAccessException(
1042 "Property is read-only!",
1043 static_cast< cppu::OWeakObject * >( this ) );
1044 }
1045 else if ( rValue.Name == "Title" )
1046 {
1047 if ( isReadOnly() )
1048 {
1049 aRetRange[ n ] <<= lang::IllegalAccessException(
1050 "Property is read-only!",
1051 static_cast< cppu::OWeakObject * >( this ) );
1052 }
1053 else
1054 {
1055 OUString aNewValue;
1056 if ( rValue.Value >>= aNewValue )
1057 {
1058 // No empty titles!
1059 if ( !aNewValue.isEmpty() )
1060 {
1061 if ( aNewValue != m_aProps.getTitle() )
1062 {
1063 // modified title -> modified URL -> exchange !
1064 if ( m_eState == PERSISTENT )
1065 bExchange = true;
1066
1067 aOldTitle = m_aProps.getTitle();
1068 aOldName = m_aProps.getName();
1069
1070 m_aProps.setTitle( aNewValue );
1073 aNewValue ) );
1074
1075 // property change event will be set later...
1076
1077 // remember position within sequence of values
1078 // (for error handling).
1079 nTitlePos = n;
1080 }
1081 }
1082 else
1083 {
1084 aRetRange[ n ] <<= lang::IllegalArgumentException(
1085 "Empty title not allowed!",
1086 static_cast< cppu::OWeakObject * >( this ),
1087 -1 );
1088 }
1089 }
1090 else
1091 {
1092 aRetRange[ n ] <<= beans::IllegalTypeException(
1093 "Property value has wrong type!",
1094 static_cast< cppu::OWeakObject * >( this ) );
1095 }
1096 }
1097 }
1098 else if ( rValue.Name == "TargetURL" )
1099 {
1100 if ( isReadOnly() )
1101 {
1102 aRetRange[ n ] <<= lang::IllegalAccessException(
1103 "Property is read-only!",
1104 static_cast< cppu::OWeakObject * >( this ) );
1105 }
1106 else
1107 {
1108 // TargetURL is only supported by links.
1109
1110 if ( m_eKind == LINK )
1111 {
1112 OUString aNewValue;
1113 if ( rValue.Value >>= aNewValue )
1114 {
1115 // No empty target URL's!
1116 if ( !aNewValue.isEmpty() )
1117 {
1118 if ( aNewValue != m_aProps.getTargetURL() )
1119 {
1120 aEvent.PropertyName = rValue.Name;
1121 aEvent.OldValue <<= m_aProps.getTargetURL();
1122 aEvent.NewValue <<= aNewValue;
1123
1124 aChanges.getArray()[ nChanged ] = aEvent;
1125
1126 m_aProps.setTargetURL( aNewValue );
1127 nChanged++;
1128 }
1129 }
1130 else
1131 {
1132 aRetRange[ n ] <<= lang::IllegalArgumentException(
1133 "Empty target URL not allowed!",
1134 static_cast< cppu::OWeakObject * >( this ),
1135 -1 );
1136 }
1137 }
1138 else
1139 {
1140 aRetRange[ n ] <<= beans::IllegalTypeException(
1141 "Property value has wrong type!",
1142 static_cast< cppu::OWeakObject * >( this ) );
1143 }
1144 }
1145 else
1146 {
1147 aRetRange[ n ] <<= beans::UnknownPropertyException(
1148 "TargetURL only supported by links!",
1149 static_cast< cppu::OWeakObject * >( this ) );
1150 }
1151 }
1152 }
1153 else
1154 {
1155 // Not a Core Property! Maybe it's an Additional Core Property?!
1156
1157 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1158 {
1159 xAdditionalPropSet = getAdditionalPropertySet( false );
1160 bTriedToGetAdditionalPropSet = true;
1161 }
1162
1163 if ( xAdditionalPropSet.is() )
1164 {
1165 try
1166 {
1167 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1168 rValue.Name );
1169 if ( aOldValue != rValue.Value )
1170 {
1171 xAdditionalPropSet->setPropertyValue(
1172 rValue.Name, rValue.Value );
1173
1174 aEvent.PropertyName = rValue.Name;
1175 aEvent.OldValue = aOldValue;
1176 aEvent.NewValue = rValue.Value;
1177
1178 aChanges.getArray()[ nChanged ] = aEvent;
1179 nChanged++;
1180 }
1181 }
1182 catch ( beans::UnknownPropertyException const & e )
1183 {
1184 aRetRange[ n ] <<= e;
1185 }
1186 catch ( lang::WrappedTargetException const & e )
1187 {
1188 aRetRange[ n ] <<= e;
1189 }
1190 catch ( beans::PropertyVetoException const & e )
1191 {
1192 aRetRange[ n ] <<= e;
1193 }
1194 catch ( lang::IllegalArgumentException const & e )
1195 {
1196 aRetRange[ n ] <<= e;
1197 }
1198 }
1199 else
1200 {
1201 aRetRange[ n ] <<= uno::Exception(
1202 "No property set for storing the value!",
1203 static_cast< cppu::OWeakObject * >( this ) );
1204 }
1205 }
1206 }
1207
1208 if ( bExchange )
1209 {
1210 uno::Reference< ucb::XContentIdentifier > xOldId
1211 = m_xIdentifier;
1212 uno::Reference< ucb::XContentIdentifier > xNewId
1214
1215 aGuard.clear();
1216 if ( exchangeIdentity( xNewId ) )
1217 {
1218 // Adapt persistent data.
1219 renameData( xOldId, xNewId );
1220
1221 // Adapt Additional Core Properties.
1222 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1223 xNewId->getContentIdentifier() );
1224 }
1225 else
1226 {
1227 // Roll-back.
1228 m_aProps.setTitle( aOldTitle );
1229 m_aProps.setName ( aOldName );
1230
1231 aOldTitle.clear();
1232 aOldName.clear();
1233
1234 // Set error .
1235 aRetRange[ nTitlePos ] <<= uno::Exception(
1236 "Exchange failed!",
1237 static_cast< cppu::OWeakObject * >( this ) );
1238 }
1239 aGuard.reset();
1240 }
1241
1242 if ( !aOldTitle.isEmpty() )
1243 {
1244 aEvent.PropertyName = "Title";
1245 aEvent.OldValue <<= aOldTitle;
1246 aEvent.NewValue <<= m_aProps.getTitle();
1247
1248 aChanges.getArray()[ nChanged ] = aEvent;
1249 nChanged++;
1250 }
1251
1252 if ( nChanged > 0 )
1253 {
1254 // Save changes, if content was already made persistent.
1255 if ( !bExchange && ( m_eState == PERSISTENT ) )
1256 {
1257 if ( !storeData() )
1258 {
1259 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1260 {
1261 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1262 }));
1264 ucb::IOErrorCode_CANT_WRITE,
1265 aArgs,
1266 xEnv,
1267 "Cannot store persistent data!",
1268 this );
1269 // Unreachable
1270 }
1271 }
1272
1273 aChanges.realloc( nChanged );
1274
1275 aGuard.clear();
1276 notifyPropertiesChange( aChanges );
1277 }
1278
1279 return aRet;
1280}
1281
1282
1283void HierarchyContent::insert( sal_Int32 nNameClashResolve,
1284 const uno::Reference<
1285 ucb::XCommandEnvironment > & xEnv )
1286{
1287 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1288
1289 // Am I the root folder?
1290 if ( m_eKind == ROOT )
1291 {
1293 uno::Any( ucb::UnsupportedCommandException(
1294 "Not supported by root folder!",
1295 static_cast< cppu::OWeakObject * >( this ) ) ),
1296 xEnv );
1297 // Unreachable
1298 }
1299
1300 // Check, if all required properties were set.
1301 if ( m_aProps.getTitle().isEmpty() )
1302 {
1303 uno::Sequence<OUString> aProps { "Title" };
1305 uno::Any( ucb::MissingPropertiesException(
1306 OUString(),
1307 static_cast< cppu::OWeakObject * >( this ),
1308 aProps ) ),
1309 xEnv );
1310 // Unreachable
1311 }
1312
1313 // Assemble new content identifier...
1314
1315 uno::Reference< ucb::XContentIdentifier > xId
1317
1318 // Handle possible name clash...
1319
1320 switch ( nNameClashResolve )
1321 {
1322 // fail.
1323 case ucb::NameClash::ERROR:
1324 if ( hasData( xId ) )
1325 {
1327 uno::Any(
1328 ucb::NameClashException(
1329 OUString(),
1330 static_cast< cppu::OWeakObject * >( this ),
1331 task::InteractionClassification_ERROR,
1332 m_aProps.getTitle() ) ),
1333 xEnv );
1334 // Unreachable
1335 }
1336 break;
1337
1338 // replace existing object.
1339 case ucb::NameClash::OVERWRITE:
1340 break;
1341
1342 // "invent" a new valid title.
1343 case ucb::NameClash::RENAME:
1344 if ( hasData( xId ) )
1345 {
1346 sal_Int32 nTry = 0;
1347
1348 do
1349 {
1350 OUString aNewId = xId->getContentIdentifier() + "_";
1351 aNewId += 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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ),
1385 nNameClashResolve ) ),
1386 xEnv );
1387 // Unreachable
1388 }
1389 break;
1390 }
1391
1392 // Identifier changed?
1393 bool bNewId = ( xId->getContentIdentifier()
1394 != m_xIdentifier->getContentIdentifier() );
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 static_cast< cppu::OWeakObject * >( this ) ) ),
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 static_cast< cppu::OWeakObject * >( this ) ) ),
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 static_cast< cppu::OWeakObject * >( this ) ) ),
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 static_cast< cppu::OWeakObject * >( this ) ) ),
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)
HierarchyContent(const css::uno::Reference< css::uno::XComponentContext > &rxContext, HierarchyContentProvider *pProvider, const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier, const HierarchyContentProperties &rProps)
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
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
css::uno::Reference< css::ucb::XPersistentPropertySet > getAdditionalPropertySet(const OUString &rKey, bool bCreate)
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)
Reference< XRow > xRow
Reference< XContentIdentifier > xId
OUString aId
const ContentProperties & rData
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