Bump version to 24.04.3.4
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchydata.cxx
blob6b7e0d857e54cce63aff06b8eca45108e96afbb9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
22 TODO
23 **************************************************************************
25 - HierarchyEntry::move
26 --> Rewrite to use XNamed ( once this is supported by config db api ).
28 *************************************************************************/
29 #include "hierarchydata.hxx"
31 #include <comphelper/diagnose_ex.hxx>
32 #include <rtl/ustrbuf.hxx>
33 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/container/XNameReplace.hpp>
36 #include <com/sun/star/util/XChangesBatch.hpp>
37 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
38 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
39 #include <comphelper/propertysequence.hxx>
40 #include <utility>
41 #include "hierarchyprovider.hxx"
42 #include "hierarchyuri.hxx"
44 using namespace com::sun::star;
46 namespace hierarchy_ucp
50 static void makeXMLName( std::u16string_view rIn, OUStringBuffer & rBuffer )
52 size_t nCount = rIn.size();
53 for ( size_t n = 0; n < nCount; ++n )
55 const sal_Unicode c = rIn[ n ];
56 switch ( c )
58 case '&':
59 rBuffer.append( "&amp;" );
60 break;
62 case '"':
63 rBuffer.append( "&quot;" );
64 break;
66 case '\'':
67 rBuffer.append( "&apos;" );
68 break;
70 case '<':
71 rBuffer.append( "&lt;" );
72 break;
74 case '>':
75 rBuffer.append( "&gt;" );
76 break;
78 default:
79 rBuffer.append( c );
80 break;
86 // HierarchyEntry Implementation.
89 constexpr OUStringLiteral READ_SERVICE_NAME = u"com.sun.star.ucb.HierarchyDataReadAccess";
90 constexpr OUString READWRITE_SERVICE_NAME = u"com.sun.star.ucb.HierarchyDataReadWriteAccess"_ustr;
92 // describe path of cfg entry
93 constexpr OUString CFGPROPERTY_NODEPATH = u"nodepath"_ustr;
96 HierarchyEntry::HierarchyEntry(
97 uno::Reference< uno::XComponentContext > xContext,
98 HierarchyContentProvider* pProvider,
99 const OUString& rURL )
100 : m_xContext(std::move( xContext )),
101 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
102 m_bTriedToGetRootReadAccess( false )
104 HierarchyUri aUri( rURL );
105 m_aServiceSpecifier = aUri.getService();
107 m_xConfigProvider
108 = pProvider->getConfigProvider( m_aServiceSpecifier );
109 m_xRootReadAccess
110 = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier );
112 // Note: do not init m_aPath in init list. createPathFromHierarchyURL
113 // needs m_xContext and m_aMutex.
114 m_aPath = createPathFromHierarchyURL( aUri );
116 // Extract language independent name from URL.
117 sal_Int32 nPos = rURL.lastIndexOf( '/' );
118 if ( nPos > HIERARCHY_URL_SCHEME_LENGTH )
119 m_aName = rURL.copy( nPos + 1 );
120 else
121 OSL_FAIL( "HierarchyEntry - Invalid URL!" );
125 bool HierarchyEntry::hasData()
127 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
128 = getRootReadAccess();
130 OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" );
132 if ( xRootReadAccess.is() )
133 return xRootReadAccess->hasByHierarchicalName( m_aPath );
135 return false;
139 bool HierarchyEntry::getData( HierarchyEntryData& rData )
143 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
144 = getRootReadAccess();
146 OSL_ENSURE( xRootReadAccess.is(),
147 "HierarchyEntry::getData - No root!" );
149 if ( xRootReadAccess.is() )
151 OUString aTitlePath = m_aPath + "/Title";
153 // Note: Avoid NoSuchElementExceptions, because exceptions are
154 // relatively 'expensive'. Checking for availability of
155 // title value is sufficient here, because if it is
156 // there, the other values will be available too.
157 if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) )
158 return false;
160 OUString aValue;
162 // Get Title value.
163 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
164 >>= aValue ) )
166 OSL_FAIL( "HierarchyEntry::getData - "
167 "Got no Title value!" );
168 return false;
171 rData.setTitle( aValue );
173 // Get TargetURL value.
174 OUString aTargetURLPath = m_aPath + "/TargetURL";
175 if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath )
176 >>= aValue ) )
178 OSL_FAIL( "HierarchyEntry::getData - "
179 "Got no TargetURL value!" );
180 return false;
183 // TargetURL property may contain a reference to the Office
184 // installation directory. To ensure a reloctable office
185 // installation, the path to the office installation directory must
186 // never be stored directly. A placeholder is used instead. Replace
187 // it by actual installation directory.
188 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
189 aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue );
190 rData.setTargetURL( aValue );
192 OUString aTypePath = m_aPath + "/Type";
193 if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) )
195 // Might not be present since it was introduced long after
196 // Title and TargetURL (#82433#)... So not getting it is
197 // not an error.
199 // Get Type value.
200 sal_Int32 nType = 0;
201 if ( xRootReadAccess->getByHierarchicalName( aTypePath )
202 >>= nType )
204 if ( nType == 0 )
206 rData.setType( HierarchyEntryData::LINK );
208 else if ( nType == 1 )
210 rData.setType( HierarchyEntryData::FOLDER );
212 else
214 OSL_FAIL( "HierarchyEntry::getData - "
215 "Unknown Type value!" );
216 return false;
221 rData.setName( m_aName );
222 return true;
225 catch ( uno::RuntimeException const & )
227 throw;
229 catch ( container::NoSuchElementException const & )
231 // getByHierarchicalName
233 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
235 return false;
239 bool HierarchyEntry::setData( const HierarchyEntryData& rData )
243 std::unique_lock aGuard( m_aMutex );
245 if ( !m_xConfigProvider.is() )
246 m_xConfigProvider.set(
247 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
248 uno::UNO_QUERY );
250 if ( m_xConfigProvider.is() )
252 // Create parent's key. It must exist!
254 OUString aParentPath;
255 bool bRoot = true;
257 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
258 if ( nPos != -1 )
260 // Skip "/Children" segment of the path, too.
261 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
263 OSL_ENSURE( nPos != -1,
264 "HierarchyEntry::setData - Wrong path!" );
266 aParentPath += m_aPath.subView( 0, nPos );
267 bRoot = false;
270 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
272 {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)}
273 }));
275 uno::Reference< util::XChangesBatch > xBatch(
276 m_xConfigProvider->createInstanceWithArguments(
277 READWRITE_SERVICE_NAME,
278 aArguments ),
279 uno::UNO_QUERY );
281 OSL_ENSURE( xBatch.is(),
282 "HierarchyEntry::setData - No batch!" );
284 uno::Reference< container::XNameAccess > xParentNameAccess(
285 xBatch, uno::UNO_QUERY );
287 OSL_ENSURE( xParentNameAccess.is(),
288 "HierarchyEntry::setData - No name access!" );
290 if ( xBatch.is() && xParentNameAccess.is() )
292 // Try to create own key. It must not exist!
294 bool bExists = true;
295 uno::Any aMyKey;
299 uno::Reference< container::XNameAccess > xNameAccess;
301 if ( bRoot )
303 xNameAccess = xParentNameAccess;
305 else
307 xParentNameAccess->getByName("Children") >>= xNameAccess;
310 if ( xNameAccess->hasByName( m_aName ) )
311 aMyKey = xNameAccess->getByName( m_aName );
312 else
313 bExists = false;
315 catch ( container::NoSuchElementException const & )
317 bExists = false;
320 uno::Reference< container::XNameReplace > xNameReplace;
321 uno::Reference< container::XNameContainer > xContainer;
323 if ( bExists )
325 // Key exists. Replace values.
327 aMyKey >>= xNameReplace;
329 OSL_ENSURE( xNameReplace.is(),
330 "HierarchyEntry::setData - No name replace!" );
332 else
334 // Key does not exist. Create / fill / insert it.
336 uno::Reference< lang::XSingleServiceFactory > xFac;
338 if ( bRoot )
340 // Special handling for children of root,
341 // which is not an entry. It's only a set
342 // of entries.
343 xFac.set( xParentNameAccess, uno::UNO_QUERY );
345 else
347 // Append new entry to parents child list,
348 // which is a set of entries.
349 xParentNameAccess->getByName("Children") >>= xFac;
352 OSL_ENSURE( xFac.is(),
353 "HierarchyEntry::setData - No factory!" );
355 if ( xFac.is() )
357 xNameReplace.set( xFac->createInstance(), uno::UNO_QUERY );
359 OSL_ENSURE( xNameReplace.is(),
360 "HierarchyEntry::setData - No name replace!" );
362 if ( xNameReplace.is() )
364 xContainer.set( xFac, uno::UNO_QUERY );
366 OSL_ENSURE( xContainer.is(),
367 "HierarchyEntry::setData - No container!" );
372 if ( xNameReplace.is() )
374 // Set Title value.
375 xNameReplace->replaceByName(
376 "Title",
377 uno::Any( rData.getTitle() ) );
379 // Set TargetURL value.
381 // TargetURL property may contain a reference to the Office
382 // installation directory. To ensure a reloctable office
383 // installation, the path to the office installation
384 // directory must never be stored directly. Use a
385 // placeholder instead.
386 OUString aValue( rData.getTargetURL() );
387 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
388 aValue
389 = m_xOfficeInstDirs->makeRelocatableURL( aValue );
391 xNameReplace->replaceByName(
392 "TargetURL",
393 uno::Any( aValue ) );
395 // Set Type value.
396 sal_Int32 nType
397 = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
398 xNameReplace->replaceByName(
399 "Type",
400 uno::Any( nType ) );
402 if ( xContainer.is() )
403 xContainer->insertByName(
404 m_aName, uno::Any( xNameReplace ) );
406 // Commit changes.
407 xBatch->commitChanges();
408 return true;
413 catch ( lang::IllegalArgumentException const & )
415 // replaceByName, insertByName
417 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
419 catch ( uno::RuntimeException const & )
421 throw;
423 catch ( container::NoSuchElementException const & )
425 // replaceByName, getByName
427 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
429 catch ( container::ElementExistException const & )
431 // insertByName
433 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
435 catch ( lang::WrappedTargetException const & )
437 // replaceByName, insertByName, getByName, commitChanges
439 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
441 catch ( uno::Exception const & )
443 // createInstance, createInstanceWithArguments
445 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
448 return false;
452 bool HierarchyEntry::move(
453 const OUString& rNewURL, const HierarchyEntryData& rData )
455 OUString aNewPath = createPathFromHierarchyURL( HierarchyUri(rNewURL) );
457 std::unique_lock aGuard( m_aMutex );
459 if ( aNewPath == m_aPath )
460 return true;
462 bool bOldRoot = true;
463 uno::Reference< util::XChangesBatch > xOldParentBatch;
465 OUString aNewKey;
466 sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' );
467 if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH )
468 aNewKey = rNewURL.copy( nURLPos + 1 );
469 else
471 OSL_FAIL( "HierarchyEntry::move - Invalid URL!" );
472 return false;
475 bool bNewRoot = true;
476 uno::Reference< util::XChangesBatch > xNewParentBatch;
478 bool bDifferentParents = true;
482 if ( !m_xConfigProvider.is() )
483 m_xConfigProvider.set(
484 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
485 uno::UNO_QUERY );
487 if ( !m_xConfigProvider.is() )
488 return false;
490 OUString aOldParentPath;
491 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
492 if ( nPos != -1 )
494 // Skip "/Children" segment of the path, too.
495 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
497 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
499 aOldParentPath += m_aPath.subView( 0, nPos );
500 bOldRoot = false;
503 OUString aNewParentPath;
504 nPos = aNewPath.lastIndexOf( '/' );
505 if ( nPos != -1 )
507 // Skip "/Children" segment of the path, too.
508 nPos = aNewPath.lastIndexOf( '/', nPos - 1 );
510 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
512 aNewParentPath += aNewPath.subView( 0, nPos );
513 bNewRoot = false;
516 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
518 {CFGPROPERTY_NODEPATH, uno::Any(aOldParentPath)}
519 }));
521 xOldParentBatch.set(
522 m_xConfigProvider->createInstanceWithArguments(
523 READWRITE_SERVICE_NAME,
524 aArguments ),
525 uno::UNO_QUERY );
527 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
529 if ( !xOldParentBatch.is() )
530 return false;
532 if ( aOldParentPath == aNewParentPath )
534 bDifferentParents = false;
535 xNewParentBatch = xOldParentBatch;
537 else
539 bDifferentParents = true;
541 uno::Sequence<uno::Any> aArguments2(comphelper::InitAnyPropertySequence(
543 {CFGPROPERTY_NODEPATH, uno::Any(aNewParentPath)}
544 }));
546 xNewParentBatch.set(
547 m_xConfigProvider->createInstanceWithArguments(
548 READWRITE_SERVICE_NAME,
549 aArguments2 ),
550 uno::UNO_QUERY );
552 OSL_ENSURE(
553 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
555 if ( !xNewParentBatch.is() )
556 return false;
559 catch ( uno::RuntimeException const & )
561 throw;
563 catch ( uno::Exception const & )
565 // createInstance, createInstanceWithArguments
567 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
568 return false;
572 // (1) Get entry...
575 uno::Any aEntry;
576 uno::Reference< container::XNameAccess > xOldParentNameAccess;
577 uno::Reference< container::XNameContainer > xOldNameContainer;
581 xOldParentNameAccess.set( xOldParentBatch, uno::UNO_QUERY );
583 OSL_ENSURE( xOldParentNameAccess.is(),
584 "HierarchyEntry::move - No name access!" );
586 if ( !xOldParentNameAccess.is() )
587 return false;
589 if ( bOldRoot )
591 xOldNameContainer.set( xOldParentNameAccess, uno::UNO_QUERY );
593 else
595 xOldParentNameAccess->getByName("Children") >>= xOldNameContainer;
598 aEntry = xOldNameContainer->getByName( m_aName );
600 catch ( container::NoSuchElementException const & )
602 // getByName
604 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
605 return false;
607 catch ( lang::WrappedTargetException const & )
609 // getByName
611 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
612 return false;
616 // (2) Remove entry... Note: Insert BEFORE remove does not work!
621 xOldNameContainer->removeByName( m_aName );
622 xOldParentBatch->commitChanges();
624 catch ( container::NoSuchElementException const & )
626 // getByName, removeByName
628 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
629 return false;
633 // (3) Insert entry at new parent...
638 uno::Reference< container::XNameReplace > xNewNameReplace;
639 aEntry >>= xNewNameReplace;
641 OSL_ENSURE( xNewNameReplace.is(),
642 "HierarchyEntry::move - No name replace!" );
644 if ( !xNewNameReplace.is() )
645 return false;
647 uno::Reference< container::XNameAccess > xNewParentNameAccess;
648 if ( bDifferentParents )
649 xNewParentNameAccess.set( xNewParentBatch, uno::UNO_QUERY );
650 else
651 xNewParentNameAccess = xOldParentNameAccess;
653 OSL_ENSURE( xNewParentNameAccess.is(),
654 "HierarchyEntry::move - No name access!" );
656 if ( !xNewParentNameAccess.is() )
657 return false;
659 uno::Reference< container::XNameContainer > xNewNameContainer;
660 if ( bDifferentParents )
662 if ( bNewRoot )
664 xNewNameContainer.set( xNewParentNameAccess, uno::UNO_QUERY );
666 else
668 xNewParentNameAccess->getByName("Children") >>= xNewNameContainer;
671 else
672 xNewNameContainer = xOldNameContainer;
674 if ( !xNewNameContainer.is() )
675 return false;
677 xNewNameReplace->replaceByName(
678 "Title",
679 uno::Any( rData.getTitle() ) );
681 // TargetURL property may contain a reference to the Office
682 // installation directory. To ensure a reloctable office
683 // installation, the path to the office installation
684 // directory must never be stored directly. Use a placeholder
685 // instead.
686 OUString aValue( rData.getTargetURL() );
687 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
688 aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue );
689 xNewNameReplace->replaceByName(
690 "TargetURL",
691 uno::Any( aValue ) );
692 sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
693 xNewNameReplace->replaceByName(
694 "Type",
695 uno::Any( nType ) );
697 xNewNameContainer->insertByName( aNewKey, aEntry );
698 xNewParentBatch->commitChanges();
700 catch ( container::NoSuchElementException const & )
702 // replaceByName, insertByName, getByName
704 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
705 return false;
707 catch ( lang::IllegalArgumentException const & )
709 // replaceByName, insertByName
711 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
712 return false;
714 catch ( container::ElementExistException const & )
716 // insertByName
718 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
719 return false;
721 catch ( lang::WrappedTargetException const & )
723 // replaceByName, insertByName, getByName
725 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
726 return false;
729 return true;
733 bool HierarchyEntry::remove()
737 std::unique_lock aGuard( m_aMutex );
739 if ( !m_xConfigProvider.is() )
740 m_xConfigProvider.set(
741 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
742 uno::UNO_QUERY );
744 if ( m_xConfigProvider.is() )
746 // Create parent's key. It must exist!
748 OUString aParentPath;
749 bool bRoot = true;
751 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
752 if ( nPos != -1 )
754 // Skip "/Children" segment of the path, too.
755 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
757 OSL_ENSURE( nPos != -1,
758 "HierarchyEntry::remove - Wrong path!" );
760 aParentPath += m_aPath.subView( 0, nPos );
761 bRoot = false;
764 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
766 {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)}
767 }));
769 uno::Reference< util::XChangesBatch > xBatch(
770 m_xConfigProvider->createInstanceWithArguments(
771 READWRITE_SERVICE_NAME,
772 aArguments ),
773 uno::UNO_QUERY );
775 OSL_ENSURE( xBatch.is(),
776 "HierarchyEntry::remove - No batch!" );
778 uno::Reference< container::XNameAccess > xParentNameAccess(
779 xBatch, uno::UNO_QUERY );
781 OSL_ENSURE( xParentNameAccess.is(),
782 "HierarchyEntry::remove - No name access!" );
784 if ( xBatch.is() && xParentNameAccess.is() )
786 uno::Reference< container::XNameContainer > xContainer;
788 if ( bRoot )
790 // Special handling for children of root,
791 // which is not an entry. It's only a set
792 // of entries.
793 xContainer.set( xParentNameAccess, uno::UNO_QUERY );
795 else
797 // Append new entry to parents child list,
798 // which is a set of entries.
799 xParentNameAccess->getByName("Children") >>= xContainer;
802 OSL_ENSURE( xContainer.is(),
803 "HierarchyEntry::remove - No container!" );
805 if ( xContainer.is() )
807 xContainer->removeByName( m_aName );
808 xBatch->commitChanges();
809 return true;
814 catch ( uno::RuntimeException const & )
816 throw;
818 catch ( container::NoSuchElementException const & )
820 // getByName, removeByName
822 OSL_FAIL(
823 "HierarchyEntry::remove - caught NoSuchElementException!" );
825 catch ( lang::WrappedTargetException const & )
827 // getByName, commitChanges
829 OSL_FAIL(
830 "HierarchyEntry::remove - caught WrappedTargetException!" );
832 catch ( uno::Exception const & )
834 // createInstance, createInstanceWithArguments
836 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
839 return false;
843 bool HierarchyEntry::first( iterator & it )
845 if ( it.pos == -1 )
847 // Init...
851 uno::Reference< container::XHierarchicalNameAccess >
852 xRootHierNameAccess = getRootReadAccess();
854 if ( xRootHierNameAccess.is() )
856 uno::Reference< container::XNameAccess > xNameAccess;
858 if ( !m_aPath.isEmpty() )
860 OUString aPath = m_aPath + "/Children";
862 xRootHierNameAccess->getByHierarchicalName( aPath )
863 >>= xNameAccess;
865 else
866 xNameAccess.set( xRootHierNameAccess, uno::UNO_QUERY );
868 OSL_ENSURE( xNameAccess.is(),
869 "HierarchyEntry::first - No name access!" );
871 if ( xNameAccess.is() )
872 it.names = xNameAccess->getElementNames();
874 uno::Reference< container::XHierarchicalNameAccess >
875 xHierNameAccess( xNameAccess, uno::UNO_QUERY );
877 OSL_ENSURE( xHierNameAccess.is(),
878 "HierarchyEntry::first - No hier. name access!" );
880 it.dir = xHierNameAccess;
882 it.officeDirs = m_xOfficeInstDirs;
885 catch ( uno::RuntimeException const & )
887 throw;
889 catch ( container::NoSuchElementException const& )
891 // getByHierarchicalName
893 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
895 catch ( uno::Exception const & )
897 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
901 if ( !it.names.hasElements() )
902 return false;
904 it.pos = 0;
905 return true;
909 bool HierarchyEntry::next( iterator& it )
911 if ( it.pos == -1 )
912 return first( it );
914 ++it.pos;
916 return ( it.pos < it.names.getLength() );
920 OUString HierarchyEntry::createPathFromHierarchyURL(
921 const HierarchyUri& rURI )
923 // Transform path...
924 // folder/subfolder/subsubfolder
925 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
927 const OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash.
928 sal_Int32 nLen = aPath.getLength();
930 if ( nLen )
932 OUStringBuffer aNewPath( "['" );
934 sal_Int32 nStart = 0;
935 sal_Int32 nEnd = aPath.indexOf( '/' );
939 if ( nEnd == -1 )
940 nEnd = nLen;
942 OUString aToken = aPath.copy( nStart, nEnd - nStart );
943 makeXMLName( aToken, aNewPath );
945 if ( nEnd != nLen )
947 aNewPath.append( "']/Children/['" );
948 nStart = nEnd + 1;
949 nEnd = aPath.indexOf( '/', nStart );
951 else
952 aNewPath.append( "']" );
954 while ( nEnd != nLen );
956 return aNewPath.makeStringAndClear();
959 return aPath;
963 uno::Reference< container::XHierarchicalNameAccess >
964 HierarchyEntry::getRootReadAccess()
966 if ( !m_xRootReadAccess.is() )
968 std::unique_lock aGuard( m_aMutex );
969 if ( !m_xRootReadAccess.is() )
971 if ( m_bTriedToGetRootReadAccess )
973 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
974 "Unable to read any config data! -> #82494#" );
975 return uno::Reference< container::XHierarchicalNameAccess >();
980 if ( !m_xConfigProvider.is() )
981 m_xConfigProvider.set(
982 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
983 uno::UNO_QUERY );
985 if ( m_xConfigProvider.is() )
987 // Create Root object.
989 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
991 {CFGPROPERTY_NODEPATH, uno::Any(OUString())} // root path
992 }));
994 m_bTriedToGetRootReadAccess = true;
996 m_xRootReadAccess.set(
997 m_xConfigProvider->createInstanceWithArguments(
998 READ_SERVICE_NAME,
999 aArguments ),
1000 uno::UNO_QUERY );
1003 catch ( uno::RuntimeException const & )
1005 throw;
1007 catch ( uno::Exception const & )
1009 // createInstance, createInstanceWithArguments
1011 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
1015 return m_xRootReadAccess;
1019 // HierarchyEntry::iterator Implementation.
1022 const HierarchyEntryData& HierarchyEntry::iterator::operator*()
1024 if ( ( pos != -1 )
1025 && ( dir.is() )
1026 && ( pos < names.getLength() ) )
1030 OUStringBuffer aKey( "['" );
1031 makeXMLName( names.getConstArray()[ pos ], aKey );
1032 aKey.append( "']" );
1034 OUString aTitle = aKey.makeStringAndClear();
1035 OUString aTargetURL = aTitle;
1036 OUString aType = aTitle;
1038 aTitle += "/Title";
1039 aTargetURL += "/TargetURL";
1040 aType += "/Type";
1042 OUString aValue;
1043 dir->getByHierarchicalName( aTitle ) >>= aValue;
1044 entry.setTitle( aValue );
1046 dir->getByHierarchicalName( aTargetURL ) >>= aValue;
1048 // TargetURL property may contain a reference to the Office
1049 // installation directory. To ensure a reloctable office
1050 // installation, the path to the office installation directory must
1051 // never be stored directly. A placeholder is used instead. Replace
1052 // it by actual installation directory.
1053 if ( officeDirs.is() && !aValue.isEmpty() )
1054 aValue = officeDirs->makeAbsoluteURL( aValue );
1055 entry.setTargetURL( aValue );
1057 if ( dir->hasByHierarchicalName( aType ) )
1059 // Might not be present since it was introduced long
1060 // after Title and TargetURL (#82433#)... So not getting
1061 // it is not an error.
1063 // Get Type value.
1064 sal_Int32 nType = 0;
1065 if ( dir->getByHierarchicalName( aType ) >>= nType )
1067 if ( nType == 0 )
1069 entry.setType( HierarchyEntryData::LINK );
1071 else if ( nType == 1 )
1073 entry.setType( HierarchyEntryData::FOLDER );
1075 else
1077 OSL_FAIL( "HierarchyEntry::getData - "
1078 "Unknown Type value!" );
1083 entry.setName(
1084 names.getConstArray()[ pos ] );
1086 catch ( container::NoSuchElementException const & )
1088 entry = HierarchyEntryData();
1092 return entry;
1095 } // namespace hierarchy_ucp
1097 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */