Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchydata.cxx
blob0f78cd033707988415d398ce6c937fc9ff1e29a5
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 <osl/diagnose.h>
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 "hierarchyprovider.hxx"
41 #include "hierarchyuri.hxx"
43 using namespace com::sun::star;
45 namespace hierarchy_ucp
49 struct HierarchyEntry::iterator_Impl
51 HierarchyEntryData entry;
52 uno::Reference< container::XHierarchicalNameAccess > dir;
53 uno::Reference< util::XOfficeInstallationDirectories > officeDirs;
54 uno::Sequence< OUString> names;
55 sal_Int32 pos;
56 iterator_Impl()
57 : pos( -1 /* before first */ ) {};
61 static void makeXMLName( const OUString & rIn, OUStringBuffer & rBuffer )
63 sal_Int32 nCount = rIn.getLength();
64 for ( sal_Int32 n = 0; n < nCount; ++n )
66 const sal_Unicode c = rIn[ n ];
67 switch ( c )
69 case '&':
70 rBuffer.append( "&amp;" );
71 break;
73 case '"':
74 rBuffer.append( "&quot;" );
75 break;
77 case '\'':
78 rBuffer.append( "&apos;" );
79 break;
81 case '<':
82 rBuffer.append( "&lt;" );
83 break;
85 case '>':
86 rBuffer.append( "&gt;" );
87 break;
89 default:
90 rBuffer.append( c );
91 break;
97 // HierarchyEntry Implementation.
100 #define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess"
101 #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
103 // describe path of cfg entry
104 #define CFGPROPERTY_NODEPATH "nodepath"
107 HierarchyEntry::HierarchyEntry(
108 const uno::Reference< uno::XComponentContext >& rxContext,
109 HierarchyContentProvider* pProvider,
110 const OUString& rURL )
111 : m_xContext( rxContext ),
112 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
113 m_bTriedToGetRootReadAccess( false )
115 HierarchyUri aUri( rURL );
116 m_aServiceSpecifier = aUri.getService();
118 m_xConfigProvider
119 = pProvider->getConfigProvider( m_aServiceSpecifier );
120 m_xRootReadAccess
121 = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier );
123 // Note: do not init m_aPath in init list. createPathFromHierarchyURL
124 // needs m_xContext and m_aMutex.
125 m_aPath = createPathFromHierarchyURL( aUri );
127 // Extract language independent name from URL.
128 sal_Int32 nPos = rURL.lastIndexOf( '/' );
129 if ( nPos > HIERARCHY_URL_SCHEME_LENGTH )
130 m_aName = rURL.copy( nPos + 1 );
131 else
132 OSL_FAIL( "HierarchyEntry - Invalid URL!" );
136 bool HierarchyEntry::hasData()
138 osl::Guard< osl::Mutex > aGuard( m_aMutex );
139 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
140 = getRootReadAccess();
142 OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" );
144 if ( xRootReadAccess.is() )
145 return xRootReadAccess->hasByHierarchicalName( m_aPath );
147 return false;
151 bool HierarchyEntry::getData( HierarchyEntryData& rData )
155 osl::Guard< osl::Mutex > aGuard( m_aMutex );
157 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
158 = getRootReadAccess();
160 OSL_ENSURE( xRootReadAccess.is(),
161 "HierarchyEntry::getData - No root!" );
163 if ( xRootReadAccess.is() )
165 OUString aTitlePath = m_aPath + "/Title";
167 // Note: Avoid NoSuchElementExceptions, because exceptions are
168 // relatively 'expensive'. Checking for availability of
169 // title value is sufficient here, because if it is
170 // there, the other values will be available too.
171 if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) )
172 return false;
174 OUString aValue;
176 // Get Title value.
177 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
178 >>= aValue ) )
180 OSL_FAIL( "HierarchyEntry::getData - "
181 "Got no Title value!" );
182 return false;
185 rData.setTitle( aValue );
187 // Get TargetURL value.
188 OUString aTargetURLPath = m_aPath + "/TargetURL";
189 if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath )
190 >>= aValue ) )
192 OSL_FAIL( "HierarchyEntry::getData - "
193 "Got no TargetURL value!" );
194 return false;
197 // TargetURL property may contain a reference to the Office
198 // installation directory. To ensure a reloctable office
199 // installation, the path to the office installation directory must
200 // never be stored directly. A placeholder is used instead. Replace
201 // it by actual installation directory.
202 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
203 aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue );
204 rData.setTargetURL( aValue );
206 OUString aTypePath = m_aPath + "/Type";
207 if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) )
209 // Might not be present since it was introduced long after
210 // Title and TargetURL (#82433#)... So not getting it is
211 // not an error.
213 // Get Type value.
214 sal_Int32 nType = 0;
215 if ( xRootReadAccess->getByHierarchicalName( aTypePath )
216 >>= nType )
218 if ( nType == 0 )
220 rData.setType( HierarchyEntryData::LINK );
222 else if ( nType == 1 )
224 rData.setType( HierarchyEntryData::FOLDER );
226 else
228 OSL_FAIL( "HierarchyEntry::getData - "
229 "Unknown Type value!" );
230 return false;
235 rData.setName( m_aName );
236 return true;
239 catch ( uno::RuntimeException const & )
241 throw;
243 catch ( container::NoSuchElementException const & )
245 // getByHierarchicalName
247 OSL_FAIL( "HierarchyEntry::getData - caught NoSuchElementException!" );
249 return false;
253 bool HierarchyEntry::setData( const HierarchyEntryData& rData )
257 osl::Guard< osl::Mutex > aGuard( m_aMutex );
259 if ( !m_xConfigProvider.is() )
260 m_xConfigProvider.set(
261 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
262 uno::UNO_QUERY );
264 if ( m_xConfigProvider.is() )
266 // Create parent's key. It must exist!
268 OUString aParentPath;
269 bool bRoot = true;
271 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
272 if ( nPos != -1 )
274 // Skip "/Children" segment of the path, too.
275 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
277 OSL_ENSURE( nPos != -1,
278 "HierarchyEntry::setData - Wrong path!" );
280 aParentPath += m_aPath.copy( 0, nPos );
281 bRoot = false;
284 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
286 {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)}
287 }));
289 uno::Reference< util::XChangesBatch > xBatch(
290 m_xConfigProvider->createInstanceWithArguments(
291 READWRITE_SERVICE_NAME,
292 aArguments ),
293 uno::UNO_QUERY );
295 OSL_ENSURE( xBatch.is(),
296 "HierarchyEntry::setData - No batch!" );
298 uno::Reference< container::XNameAccess > xParentNameAccess(
299 xBatch, uno::UNO_QUERY );
301 OSL_ENSURE( xParentNameAccess.is(),
302 "HierarchyEntry::setData - No name access!" );
304 if ( xBatch.is() && xParentNameAccess.is() )
306 // Try to create own key. It must not exist!
308 bool bExists = true;
309 uno::Any aMyKey;
313 uno::Reference< container::XNameAccess > xNameAccess;
315 if ( bRoot )
317 xNameAccess = xParentNameAccess;
319 else
321 xParentNameAccess->getByName("Children") >>= xNameAccess;
324 if ( xNameAccess->hasByName( m_aName ) )
325 aMyKey = xNameAccess->getByName( m_aName );
326 else
327 bExists = false;
329 catch ( container::NoSuchElementException const & )
331 bExists = false;
334 uno::Reference< container::XNameReplace > xNameReplace;
335 uno::Reference< container::XNameContainer > xContainer;
337 if ( bExists )
339 // Key exists. Replace values.
341 aMyKey >>= xNameReplace;
343 OSL_ENSURE( xNameReplace.is(),
344 "HierarchyEntry::setData - No name replace!" );
346 else
348 // Key does not exist. Create / fill / insert it.
350 uno::Reference< lang::XSingleServiceFactory > xFac;
352 if ( bRoot )
354 // Special handling for children of root,
355 // which is not an entry. It's only a set
356 // of entries.
357 xFac.set( xParentNameAccess, uno::UNO_QUERY );
359 else
361 // Append new entry to parents child list,
362 // which is a set of entries.
363 xParentNameAccess->getByName("Children") >>= xFac;
366 OSL_ENSURE( xFac.is(),
367 "HierarchyEntry::setData - No factory!" );
369 if ( xFac.is() )
371 xNameReplace.set( xFac->createInstance(), uno::UNO_QUERY );
373 OSL_ENSURE( xNameReplace.is(),
374 "HierarchyEntry::setData - No name replace!" );
376 if ( xNameReplace.is() )
378 xContainer.set( xFac, uno::UNO_QUERY );
380 OSL_ENSURE( xContainer.is(),
381 "HierarchyEntry::setData - No container!" );
386 if ( xNameReplace.is() )
388 // Set Title value.
389 xNameReplace->replaceByName(
390 "Title",
391 uno::makeAny( rData.getTitle() ) );
393 // Set TargetURL value.
395 // TargetURL property may contain a reference to the Office
396 // installation directory. To ensure a reloctable office
397 // installation, the path to the office installation
398 // directory must never be stored directly. Use a
399 // placeholder instead.
400 OUString aValue( rData.getTargetURL() );
401 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
402 aValue
403 = m_xOfficeInstDirs->makeRelocatableURL( aValue );
405 xNameReplace->replaceByName(
406 "TargetURL",
407 uno::makeAny( aValue ) );
409 // Set Type value.
410 sal_Int32 nType
411 = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
412 xNameReplace->replaceByName(
413 "Type",
414 uno::makeAny( nType ) );
416 if ( xContainer.is() )
417 xContainer->insertByName(
418 m_aName, uno::makeAny( xNameReplace ) );
420 // Commit changes.
421 xBatch->commitChanges();
422 return true;
427 catch ( lang::IllegalArgumentException const & )
429 // replaceByName, insertByName
431 OSL_FAIL(
432 "HierarchyEntry::setData - caught IllegalArgumentException!" );
434 catch ( uno::RuntimeException const & )
436 throw;
438 catch ( container::NoSuchElementException const & )
440 // replaceByName, getByName
442 OSL_FAIL(
443 "HierarchyEntry::setData - caught NoSuchElementException!" );
445 catch ( container::ElementExistException const & )
447 // insertByName
449 OSL_FAIL(
450 "HierarchyEntry::setData - caught ElementExistException!" );
452 catch ( lang::WrappedTargetException const & )
454 // replaceByName, insertByName, getByName, commitChanges
456 OSL_FAIL(
457 "HierarchyEntry::setData - caught WrappedTargetException!" );
459 catch ( uno::Exception const & )
461 // createInstance, createInstanceWithArguments
463 OSL_FAIL(
464 "HierarchyEntry::setData - caught Exception!" );
467 return false;
471 bool HierarchyEntry::move(
472 const OUString& rNewURL, const HierarchyEntryData& rData )
474 osl::Guard< osl::Mutex > aGuard( m_aMutex );
476 OUString aNewPath = createPathFromHierarchyURL( HierarchyUri(rNewURL) );
478 if ( aNewPath == m_aPath )
479 return true;
481 bool bOldRoot = true;
482 uno::Reference< util::XChangesBatch > xOldParentBatch;
484 OUString aNewKey;
485 sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' );
486 if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH )
487 aNewKey = rNewURL.copy( nURLPos + 1 );
488 else
490 OSL_FAIL( "HierarchyEntry::move - Invalid URL!" );
491 return false;
494 bool bNewRoot = true;
495 uno::Reference< util::XChangesBatch > xNewParentBatch;
497 bool bDifferentParents = true;
501 if ( !m_xConfigProvider.is() )
502 m_xConfigProvider.set(
503 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
504 uno::UNO_QUERY );
506 if ( !m_xConfigProvider.is() )
507 return false;
509 OUString aOldParentPath;
510 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
511 if ( nPos != -1 )
513 // Skip "/Children" segment of the path, too.
514 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
516 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
518 aOldParentPath += m_aPath.copy( 0, nPos );
519 bOldRoot = false;
522 OUString aNewParentPath;
523 nPos = aNewPath.lastIndexOf( '/' );
524 if ( nPos != -1 )
526 // Skip "/Children" segment of the path, too.
527 nPos = aNewPath.lastIndexOf( '/', nPos - 1 );
529 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
531 aNewParentPath += aNewPath.copy( 0, nPos );
532 bNewRoot = false;
535 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
537 {CFGPROPERTY_NODEPATH, uno::Any(aOldParentPath)}
538 }));
540 xOldParentBatch.set(
541 m_xConfigProvider->createInstanceWithArguments(
542 READWRITE_SERVICE_NAME,
543 aArguments ),
544 uno::UNO_QUERY );
546 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
548 if ( !xOldParentBatch.is() )
549 return false;
551 if ( aOldParentPath == aNewParentPath )
553 bDifferentParents = false;
554 xNewParentBatch = xOldParentBatch;
556 else
558 bDifferentParents = true;
560 uno::Sequence<uno::Any> aArguments2(comphelper::InitAnyPropertySequence(
562 {CFGPROPERTY_NODEPATH, uno::Any(aNewParentPath)}
563 }));
565 xNewParentBatch.set(
566 m_xConfigProvider->createInstanceWithArguments(
567 READWRITE_SERVICE_NAME,
568 aArguments2 ),
569 uno::UNO_QUERY );
571 OSL_ENSURE(
572 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
574 if ( !xNewParentBatch.is() )
575 return false;
578 catch ( uno::RuntimeException const & )
580 throw;
582 catch ( uno::Exception const & )
584 // createInstance, createInstanceWithArguments
586 OSL_FAIL( "HierarchyEntry::move - caught Exception!" );
587 return false;
591 // (1) Get entry...
594 uno::Any aEntry;
595 uno::Reference< container::XNameAccess > xOldParentNameAccess;
596 uno::Reference< container::XNameContainer > xOldNameContainer;
600 xOldParentNameAccess.set( xOldParentBatch, uno::UNO_QUERY );
602 OSL_ENSURE( xOldParentNameAccess.is(),
603 "HierarchyEntry::move - No name access!" );
605 if ( !xOldParentNameAccess.is() )
606 return false;
608 if ( bOldRoot )
610 xOldNameContainer.set( xOldParentNameAccess, uno::UNO_QUERY );
612 else
614 xOldParentNameAccess->getByName("Children") >>= xOldNameContainer;
617 aEntry = xOldNameContainer->getByName( m_aName );
619 catch ( container::NoSuchElementException const & )
621 // getByName
623 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
624 return false;
626 catch ( lang::WrappedTargetException const & )
628 // getByName
630 OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
631 return false;
635 // (2) Remove entry... Note: Insert BEFORE remove does not work!
640 xOldNameContainer->removeByName( m_aName );
641 xOldParentBatch->commitChanges();
643 catch ( container::NoSuchElementException const & )
645 // getByName, removeByName
647 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
648 return false;
652 // (3) Insert entry at new parent...
657 uno::Reference< container::XNameReplace > xNewNameReplace;
658 aEntry >>= xNewNameReplace;
660 OSL_ENSURE( xNewNameReplace.is(),
661 "HierarchyEntry::move - No name replace!" );
663 if ( !xNewNameReplace.is() )
664 return false;
666 uno::Reference< container::XNameAccess > xNewParentNameAccess;
667 if ( bDifferentParents )
668 xNewParentNameAccess.set( xNewParentBatch, uno::UNO_QUERY );
669 else
670 xNewParentNameAccess = xOldParentNameAccess;
672 OSL_ENSURE( xNewParentNameAccess.is(),
673 "HierarchyEntry::move - No name access!" );
675 if ( !xNewParentNameAccess.is() )
676 return false;
678 uno::Reference< container::XNameContainer > xNewNameContainer;
679 if ( bDifferentParents )
681 if ( bNewRoot )
683 xNewNameContainer.set( xNewParentNameAccess, uno::UNO_QUERY );
685 else
687 xNewParentNameAccess->getByName("Children") >>= xNewNameContainer;
690 else
691 xNewNameContainer = xOldNameContainer;
693 if ( !xNewNameContainer.is() )
694 return false;
696 xNewNameReplace->replaceByName(
697 "Title",
698 uno::makeAny( rData.getTitle() ) );
700 // TargetURL property may contain a reference to the Office
701 // installation directory. To ensure a reloctable office
702 // installation, the path to the office installation
703 // directory must never be stored directly. Use a placeholder
704 // instead.
705 OUString aValue( rData.getTargetURL() );
706 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
707 aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue );
708 xNewNameReplace->replaceByName(
709 "TargetURL",
710 uno::makeAny( aValue ) );
711 sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
712 xNewNameReplace->replaceByName(
713 "Type",
714 uno::makeAny( nType ) );
716 xNewNameContainer->insertByName( aNewKey, aEntry );
717 xNewParentBatch->commitChanges();
719 catch ( container::NoSuchElementException const & )
721 // replaceByName, insertByName, getByName
723 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
724 return false;
726 catch ( lang::IllegalArgumentException const & )
728 // replaceByName, insertByName
730 OSL_FAIL(
731 "HierarchyEntry::move - caught IllegalArgumentException!" );
732 return false;
734 catch ( container::ElementExistException const & )
736 // insertByName
738 OSL_FAIL( "HierarchyEntry::move - caught ElementExistException!" );
739 return false;
741 catch ( lang::WrappedTargetException const & )
743 // replaceByName, insertByName, getByName
745 OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
746 return false;
749 return true;
753 bool HierarchyEntry::remove()
757 osl::Guard< osl::Mutex > aGuard( m_aMutex );
759 if ( !m_xConfigProvider.is() )
760 m_xConfigProvider.set(
761 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
762 uno::UNO_QUERY );
764 if ( m_xConfigProvider.is() )
766 // Create parent's key. It must exist!
768 OUString aParentPath;
769 bool bRoot = true;
771 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
772 if ( nPos != -1 )
774 // Skip "/Children" segment of the path, too.
775 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
777 OSL_ENSURE( nPos != -1,
778 "HierarchyEntry::remove - Wrong path!" );
780 aParentPath += m_aPath.copy( 0, nPos );
781 bRoot = false;
784 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
786 {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)}
787 }));
789 uno::Reference< util::XChangesBatch > xBatch(
790 m_xConfigProvider->createInstanceWithArguments(
791 READWRITE_SERVICE_NAME,
792 aArguments ),
793 uno::UNO_QUERY );
795 OSL_ENSURE( xBatch.is(),
796 "HierarchyEntry::remove - No batch!" );
798 uno::Reference< container::XNameAccess > xParentNameAccess(
799 xBatch, uno::UNO_QUERY );
801 OSL_ENSURE( xParentNameAccess.is(),
802 "HierarchyEntry::remove - No name access!" );
804 if ( xBatch.is() && xParentNameAccess.is() )
806 uno::Reference< container::XNameContainer > xContainer;
808 if ( bRoot )
810 // Special handling for children of root,
811 // which is not an entry. It's only a set
812 // of entries.
813 xContainer.set( xParentNameAccess, uno::UNO_QUERY );
815 else
817 // Append new entry to parents child list,
818 // which is a set of entries.
819 xParentNameAccess->getByName("Children") >>= xContainer;
822 OSL_ENSURE( xContainer.is(),
823 "HierarchyEntry::remove - No container!" );
825 if ( xContainer.is() )
827 xContainer->removeByName( m_aName );
828 xBatch->commitChanges();
829 return true;
834 catch ( uno::RuntimeException const & )
836 throw;
838 catch ( container::NoSuchElementException const & )
840 // getByName, removeByName
842 OSL_FAIL(
843 "HierarchyEntry::remove - caught NoSuchElementException!" );
845 catch ( lang::WrappedTargetException const & )
847 // getByName, commitChanges
849 OSL_FAIL(
850 "HierarchyEntry::remove - caught WrappedTargetException!" );
852 catch ( uno::Exception const & )
854 // createInstance, createInstanceWithArguments
856 OSL_FAIL( "HierarchyEntry::remove - caught Exception!" );
859 return false;
863 bool HierarchyEntry::first( iterator const & it )
865 osl::Guard< osl::Mutex > aGuard( m_aMutex );
867 if ( it.m_pImpl->pos == -1 )
869 // Init...
873 uno::Reference< container::XHierarchicalNameAccess >
874 xRootHierNameAccess = getRootReadAccess();
876 if ( xRootHierNameAccess.is() )
878 uno::Reference< container::XNameAccess > xNameAccess;
880 if ( !m_aPath.isEmpty() )
882 OUString aPath = m_aPath + "/Children";
884 xRootHierNameAccess->getByHierarchicalName( aPath )
885 >>= xNameAccess;
887 else
888 xNameAccess.set( xRootHierNameAccess, uno::UNO_QUERY );
890 OSL_ENSURE( xNameAccess.is(),
891 "HierarchyEntry::first - No name access!" );
893 if ( xNameAccess.is() )
894 it.m_pImpl->names = xNameAccess->getElementNames();
896 uno::Reference< container::XHierarchicalNameAccess >
897 xHierNameAccess( xNameAccess, uno::UNO_QUERY );
899 OSL_ENSURE( xHierNameAccess.is(),
900 "HierarchyEntry::first - No hier. name access!" );
902 it.m_pImpl->dir = xHierNameAccess;
904 it.m_pImpl->officeDirs = m_xOfficeInstDirs;
907 catch ( uno::RuntimeException const & )
909 throw;
911 catch ( container::NoSuchElementException const& )
913 // getByHierarchicalName
915 OSL_FAIL(
916 "HierarchyEntry::first - caught NoSuchElementException!" );
918 catch ( uno::Exception const & )
920 OSL_FAIL( "HierarchyEntry::first - caught Exception!" );
924 if ( !it.m_pImpl->names.hasElements() )
925 return false;
927 it.m_pImpl->pos = 0;
928 return true;
932 bool HierarchyEntry::next( iterator const & it )
934 osl::Guard< osl::Mutex > aGuard( m_aMutex );
936 if ( it.m_pImpl->pos == -1 )
937 return first( it );
939 ++(it.m_pImpl->pos);
941 return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() );
945 OUString HierarchyEntry::createPathFromHierarchyURL(
946 const HierarchyUri& rURI )
948 // Transform path...
949 // folder/subfolder/subsubfolder
950 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
952 const OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash.
953 sal_Int32 nLen = aPath.getLength();
955 if ( nLen )
957 OUStringBuffer aNewPath;
958 aNewPath.append( "['" );
960 sal_Int32 nStart = 0;
961 sal_Int32 nEnd = aPath.indexOf( '/' );
965 if ( nEnd == -1 )
966 nEnd = nLen;
968 OUString aToken = aPath.copy( nStart, nEnd - nStart );
969 makeXMLName( aToken, aNewPath );
971 if ( nEnd != nLen )
973 aNewPath.append( "']/Children/['" );
974 nStart = nEnd + 1;
975 nEnd = aPath.indexOf( '/', nStart );
977 else
978 aNewPath.append( "']" );
980 while ( nEnd != nLen );
982 return aNewPath.makeStringAndClear();
985 return aPath;
989 uno::Reference< container::XHierarchicalNameAccess >
990 HierarchyEntry::getRootReadAccess()
992 if ( !m_xRootReadAccess.is() )
994 osl::Guard< osl::Mutex > aGuard( m_aMutex );
995 if ( !m_xRootReadAccess.is() )
997 if ( m_bTriedToGetRootReadAccess )
999 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1000 "Unable to read any config data! -> #82494#" );
1001 return uno::Reference< container::XHierarchicalNameAccess >();
1006 if ( !m_xConfigProvider.is() )
1007 m_xConfigProvider.set(
1008 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
1009 uno::UNO_QUERY );
1011 if ( m_xConfigProvider.is() )
1013 // Create Root object.
1015 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
1017 {CFGPROPERTY_NODEPATH, uno::Any(OUString())} // root path
1018 }));
1020 m_bTriedToGetRootReadAccess = true;
1022 m_xRootReadAccess.set(
1023 m_xConfigProvider->createInstanceWithArguments(
1024 READ_SERVICE_NAME,
1025 aArguments ),
1026 uno::UNO_QUERY );
1029 catch ( uno::RuntimeException const & )
1031 throw;
1033 catch ( uno::Exception const & )
1035 // createInstance, createInstanceWithArguments
1037 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1038 "caught Exception!" );
1042 return m_xRootReadAccess;
1046 // HierarchyEntry::iterator Implementation.
1049 HierarchyEntry::iterator::iterator()
1050 : m_pImpl( new iterator_Impl )
1055 HierarchyEntry::iterator::~iterator()
1060 const HierarchyEntryData& HierarchyEntry::iterator::operator*() const
1062 if ( ( m_pImpl->pos != -1 )
1063 && ( m_pImpl->dir.is() )
1064 && ( m_pImpl->pos < m_pImpl->names.getLength() ) )
1068 OUStringBuffer aKey;
1069 aKey.append( "['" );
1070 makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey );
1071 aKey.append( "']" );
1073 OUString aTitle = aKey.makeStringAndClear();
1074 OUString aTargetURL = aTitle;
1075 OUString aType = aTitle;
1077 aTitle += "/Title";
1078 aTargetURL += "/TargetURL";
1079 aType += "/Type";
1081 OUString aValue;
1082 m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue;
1083 m_pImpl->entry.setTitle( aValue );
1085 m_pImpl->dir->getByHierarchicalName( aTargetURL ) >>= aValue;
1087 // TargetURL property may contain a reference to the Office
1088 // installation directory. To ensure a reloctable office
1089 // installation, the path to the office installation directory must
1090 // never be stored directly. A placeholder is used instead. Replace
1091 // it by actual installation directory.
1092 if ( m_pImpl->officeDirs.is() && !aValue.isEmpty() )
1093 aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue );
1094 m_pImpl->entry.setTargetURL( aValue );
1096 if ( m_pImpl->dir->hasByHierarchicalName( aType ) )
1098 // Might not be present since it was introduced long
1099 // after Title and TargetURL (#82433#)... So not getting
1100 // it is not an error.
1102 // Get Type value.
1103 sal_Int32 nType = 0;
1104 if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType )
1106 if ( nType == 0 )
1108 m_pImpl->entry.setType( HierarchyEntryData::LINK );
1110 else if ( nType == 1 )
1112 m_pImpl->entry.setType( HierarchyEntryData::FOLDER );
1114 else
1116 OSL_FAIL( "HierarchyEntry::getData - "
1117 "Unknown Type value!" );
1122 m_pImpl->entry.setName(
1123 m_pImpl->names.getConstArray()[ m_pImpl->pos ] );
1125 catch ( container::NoSuchElementException const & )
1127 m_pImpl->entry = HierarchyEntryData();
1131 return m_pImpl->entry;
1134 } // namespace hierarchy_ucp
1136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */