bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchydata.cxx
blob0cd59ac93c292ad84409f6f34da7374fd2a43b8a
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 <vector>
32 #include <osl/diagnose.h>
33 #include <rtl/ustrbuf.hxx>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
36 #include <com/sun/star/container/XNameContainer.hpp>
37 #include <com/sun/star/container/XNameReplace.hpp>
38 #include <com/sun/star/util/XChangesBatch.hpp>
39 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
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 : officeDirs( 0 ), pos( -1 /* before first */ ) {};
61 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.appendAscii( "&amp;" );
71 break;
73 case '"':
74 rBuffer.appendAscii( "&quot;" );
75 break;
77 case '\'':
78 rBuffer.appendAscii( "&apos;" );
79 break;
81 case '<':
82 rBuffer.appendAscii( "&lt;" );
83 break;
85 case '>':
86 rBuffer.appendAscii( "&gt;" );
87 break;
89 default:
90 rBuffer.append( c );
91 break;
99 // HierarchyEntry Implementation.
104 #define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess"
105 #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
107 // describe path of cfg entry
108 #define CFGPROPERTY_NODEPATH "nodepath"
111 HierarchyEntry::HierarchyEntry(
112 const uno::Reference< uno::XComponentContext >& rxContext,
113 HierarchyContentProvider* pProvider,
114 const OUString& rURL )
115 : m_xContext( rxContext ),
116 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
117 m_bTriedToGetRootReadAccess( false )
119 HierarchyUri aUri( rURL );
120 m_aServiceSpecifier = aUri.getService();
122 m_xConfigProvider
123 = pProvider->getConfigProvider( m_aServiceSpecifier );
124 m_xRootReadAccess
125 = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier );
127 // Note: do not init m_aPath in init list. createPathFromHierarchyURL
128 // needs m_xContext and m_aMutex.
129 m_aPath = createPathFromHierarchyURL( aUri );
131 // Extract language independent name from URL.
132 sal_Int32 nPos = rURL.lastIndexOf( '/' );
133 if ( nPos > HIERARCHY_URL_SCHEME_LENGTH )
134 m_aName = rURL.copy( nPos + 1 );
135 else
136 OSL_FAIL( "HierarchyEntry - Invalid URL!" );
140 bool HierarchyEntry::hasData()
142 osl::Guard< osl::Mutex > aGuard( m_aMutex );
143 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
144 = getRootReadAccess();
146 OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" );
148 if ( xRootReadAccess.is() )
149 return xRootReadAccess->hasByHierarchicalName( m_aPath );
151 return false;
155 bool HierarchyEntry::getData( HierarchyEntryData& rData )
159 osl::Guard< osl::Mutex > aGuard( m_aMutex );
161 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
162 = getRootReadAccess();
164 OSL_ENSURE( xRootReadAccess.is(),
165 "HierarchyEntry::getData - No root!" );
167 if ( xRootReadAccess.is() )
169 OUString aTitlePath = m_aPath;
170 aTitlePath += "/Title";
172 // Note: Avoid NoSuchElementExceptions, because exceptions are
173 // relatively 'expensive'. Checking for availability of
174 // title value is sufficient here, because if it is
175 // there, the other values will be available too.
176 if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) )
177 return false;
179 OUString aValue;
181 // Get Title value.
182 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
183 >>= aValue ) )
185 OSL_FAIL( "HierarchyEntry::getData - "
186 "Got no Title value!" );
187 return false;
190 rData.setTitle( aValue );
192 // Get TargetURL value.
193 OUString aTargetURLPath = m_aPath;
194 aTargetURLPath += "/TargetURL";
195 if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath )
196 >>= aValue ) )
198 OSL_FAIL( "HierarchyEntry::getData - "
199 "Got no TargetURL value!" );
200 return false;
203 // TargetURL property may contain a reference to the Office
204 // installation directory. To ensure a reloctable office
205 // installation, the path to the office installtion directory must
206 // never be stored directly. A placeholder is used instead. Replace
207 // it by actual installation directory.
208 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
209 aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue );
210 rData.setTargetURL( aValue );
212 OUString aTypePath = m_aPath;
213 aTypePath += "/Type";
214 if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) )
216 // Might not be present since it was introduced long after
217 // Title and TargetURL (#82433#)... So not getting it is
218 // not an error.
220 // Get Type value.
221 sal_Int32 nType = 0;
222 if ( xRootReadAccess->getByHierarchicalName( aTypePath )
223 >>= nType )
225 if ( nType == 0 )
227 rData.setType( HierarchyEntryData::LINK );
229 else if ( nType == 1 )
231 rData.setType( HierarchyEntryData::FOLDER );
233 else
235 OSL_FAIL( "HierarchyEntry::getData - "
236 "Unknown Type value!" );
237 return false;
242 rData.setName( m_aName );
243 return true;
246 catch ( uno::RuntimeException const & )
248 throw;
250 catch ( container::NoSuchElementException const & )
252 // getByHierarchicalName
254 OSL_FAIL( "HierarchyEntry::getData - caught NoSuchElementException!" );
256 return false;
260 bool HierarchyEntry::setData(
261 const HierarchyEntryData& rData, bool bCreate )
265 osl::Guard< osl::Mutex > aGuard( m_aMutex );
267 if ( !m_xConfigProvider.is() )
268 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
269 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
270 uno::UNO_QUERY );
272 if ( m_xConfigProvider.is() )
274 // Create parent's key. It must exist!
276 OUString aParentPath;
277 bool bRoot = true;
279 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
280 if ( nPos != -1 )
282 // Skip "/Children" segment of the path, too.
283 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
285 OSL_ENSURE( nPos != -1,
286 "HierarchyEntry::setData - Wrong path!" );
288 aParentPath += m_aPath.copy( 0, nPos );
289 bRoot = false;
292 uno::Sequence< uno::Any > aArguments( 1 );
293 beans::PropertyValue aProperty;
295 aProperty.Name = CFGPROPERTY_NODEPATH;
296 aProperty.Value <<= aParentPath;
297 aArguments[ 0 ] <<= aProperty;
299 uno::Reference< util::XChangesBatch > xBatch(
300 m_xConfigProvider->createInstanceWithArguments(
301 OUString( READWRITE_SERVICE_NAME ),
302 aArguments ),
303 uno::UNO_QUERY );
305 OSL_ENSURE( xBatch.is(),
306 "HierarchyEntry::setData - No batch!" );
308 uno::Reference< container::XNameAccess > xParentNameAccess(
309 xBatch, uno::UNO_QUERY );
311 OSL_ENSURE( xParentNameAccess.is(),
312 "HierarchyEntry::setData - No name access!" );
314 if ( xBatch.is() && xParentNameAccess.is() )
316 // Try to create own key. It must not exist!
318 bool bExists = true;
319 uno::Any aMyKey;
323 uno::Reference< container::XNameAccess > xNameAccess;
325 if ( bRoot )
327 xNameAccess = xParentNameAccess;
329 else
331 xParentNameAccess->getByName(
332 OUString("Children") )
333 >>= xNameAccess;
336 if ( xNameAccess->hasByName( m_aName ) )
337 aMyKey = xNameAccess->getByName( m_aName );
338 else
339 bExists = false;
341 catch ( container::NoSuchElementException const & )
343 bExists = false;
346 uno::Reference< container::XNameReplace > xNameReplace;
347 uno::Reference< container::XNameContainer > xContainer;
349 if ( bExists )
351 // Key exists. Replace values.
353 aMyKey >>= xNameReplace;
355 OSL_ENSURE( xNameReplace.is(),
356 "HierarchyEntry::setData - No name replace!" );
358 else
360 if ( !bCreate )
361 return true;
363 // Key does not exist. Create / fill / insert it.
365 uno::Reference< lang::XSingleServiceFactory > xFac;
367 if ( bRoot )
369 // Special handling for children of root,
370 // which is not an entry. It's only a set
371 // of entries.
372 xFac = uno::Reference< lang::XSingleServiceFactory >(
373 xParentNameAccess, uno::UNO_QUERY );
375 else
377 // Append new entry to parents child list,
378 // which is a set of entries.
379 xParentNameAccess->getByName(
380 OUString( "Children" ) ) >>= xFac;
383 OSL_ENSURE( xFac.is(),
384 "HierarchyEntry::setData - No factory!" );
386 if ( xFac.is() )
388 xNameReplace
389 = uno::Reference< container::XNameReplace >(
390 xFac->createInstance(), uno::UNO_QUERY );
392 OSL_ENSURE( xNameReplace.is(),
393 "HierarchyEntry::setData - No name replace!" );
395 if ( xNameReplace.is() )
397 xContainer
398 = uno::Reference< container::XNameContainer >(
399 xFac, uno::UNO_QUERY );
401 OSL_ENSURE( xContainer.is(),
402 "HierarchyEntry::setData - No container!" );
407 if ( xNameReplace.is() )
409 // Set Title value.
410 xNameReplace->replaceByName(
411 OUString("Title"),
412 uno::makeAny( rData.getTitle() ) );
414 // Set TargetURL value.
416 // TargetURL property may contain a reference to the Office
417 // installation directory. To ensure a reloctable office
418 // installation, the path to the office installtion
419 // directory must never be stored directly. Use a
420 // placeholder instead.
421 OUString aValue( rData.getTargetURL() );
422 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
423 aValue
424 = m_xOfficeInstDirs->makeRelocatableURL( aValue );
426 xNameReplace->replaceByName(
427 OUString("TargetURL"),
428 uno::makeAny( aValue ) );
430 // Set Type value.
431 sal_Int32 nType
432 = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
433 xNameReplace->replaceByName(
434 OUString("Type"),
435 uno::makeAny( nType ) );
437 if ( xContainer.is() )
438 xContainer->insertByName(
439 m_aName, uno::makeAny( xNameReplace ) );
441 // Commit changes.
442 xBatch->commitChanges();
443 return true;
448 catch ( lang::IllegalArgumentException const & )
450 // replaceByName, insertByName
452 OSL_FAIL(
453 "HierarchyEntry::setData - caught IllegalArgumentException!" );
455 catch ( uno::RuntimeException const & )
457 throw;
459 catch ( container::NoSuchElementException const & )
461 // replaceByName, getByName
463 OSL_FAIL(
464 "HierarchyEntry::setData - caught NoSuchElementException!" );
466 catch ( container::ElementExistException const & )
468 // insertByName
470 OSL_FAIL(
471 "HierarchyEntry::setData - caught ElementExistException!" );
473 catch ( lang::WrappedTargetException const & )
475 // replaceByName, insertByName, getByName, commitChanges
477 OSL_FAIL(
478 "HierarchyEntry::setData - caught WrappedTargetException!" );
480 catch ( uno::Exception const & )
482 // createInstance, createInstanceWithArguments
484 OSL_FAIL(
485 "HierarchyEntry::setData - caught Exception!" );
488 return false;
492 bool HierarchyEntry::move(
493 const OUString& rNewURL, const HierarchyEntryData& rData )
495 osl::Guard< osl::Mutex > aGuard( m_aMutex );
497 OUString aNewPath = createPathFromHierarchyURL( rNewURL );
499 if ( aNewPath == m_aPath )
500 return true;
502 bool bOldRoot = true;
503 uno::Reference< util::XChangesBatch > xOldParentBatch;
505 OUString aNewKey;
506 sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' );
507 if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH )
508 aNewKey = rNewURL.copy( nURLPos + 1 );
509 else
511 OSL_FAIL( "HierarchyEntry::move - Invalid URL!" );
512 return false;
515 bool bNewRoot = true;
516 uno::Reference< util::XChangesBatch > xNewParentBatch;
518 bool bDifferentParents = true;
522 if ( !m_xConfigProvider.is() )
523 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
524 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
525 uno::UNO_QUERY );
527 if ( !m_xConfigProvider.is() )
528 return false;
530 OUString aOldParentPath;
531 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
532 if ( nPos != -1 )
534 // Skip "/Children" segment of the path, too.
535 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
537 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
539 aOldParentPath += m_aPath.copy( 0, nPos );
540 bOldRoot = false;
543 OUString aNewParentPath;
544 nPos = aNewPath.lastIndexOf( '/' );
545 if ( nPos != -1 )
547 // Skip "/Children" segment of the path, too.
548 nPos = aNewPath.lastIndexOf( '/', nPos - 1 );
550 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
552 aNewParentPath += aNewPath.copy( 0, nPos );
553 bNewRoot = false;
556 uno::Sequence< uno::Any > aArguments( 1 );
557 beans::PropertyValue aProperty;
559 aProperty.Name = CFGPROPERTY_NODEPATH;
560 aProperty.Value <<= aOldParentPath;
561 aArguments[ 0 ] <<= aProperty;
563 xOldParentBatch = uno::Reference< util::XChangesBatch >(
564 m_xConfigProvider->createInstanceWithArguments(
565 OUString( READWRITE_SERVICE_NAME ),
566 aArguments ),
567 uno::UNO_QUERY );
569 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
571 if ( !xOldParentBatch.is() )
572 return false;
574 if ( aOldParentPath == aNewParentPath )
576 bDifferentParents = false;
577 xNewParentBatch = xOldParentBatch;
579 else
581 bDifferentParents = true;
583 aProperty.Name = CFGPROPERTY_NODEPATH;
584 aProperty.Value <<= aNewParentPath;
585 aArguments[ 0 ] <<= aProperty;
587 xNewParentBatch = uno::Reference< util::XChangesBatch >(
588 m_xConfigProvider->createInstanceWithArguments(
589 OUString( READWRITE_SERVICE_NAME ),
590 aArguments ),
591 uno::UNO_QUERY );
593 OSL_ENSURE(
594 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
596 if ( !xNewParentBatch.is() )
597 return false;
600 catch ( uno::RuntimeException const & )
602 throw;
604 catch ( uno::Exception const & )
606 // createInstance, createInstanceWithArguments
608 OSL_FAIL( "HierarchyEntry::move - caught Exception!" );
609 return false;
613 // (1) Get entry...
616 uno::Any aEntry;
617 uno::Reference< container::XNameAccess > xOldParentNameAccess;
618 uno::Reference< container::XNameContainer > xOldNameContainer;
622 xOldParentNameAccess
623 = uno::Reference< container::XNameAccess >(
624 xOldParentBatch, uno::UNO_QUERY );
626 OSL_ENSURE( xOldParentNameAccess.is(),
627 "HierarchyEntry::move - No name access!" );
629 if ( !xOldParentNameAccess.is() )
630 return false;
632 if ( bOldRoot )
634 xOldNameContainer = uno::Reference< container::XNameContainer >(
635 xOldParentNameAccess, uno::UNO_QUERY );
637 else
639 xOldParentNameAccess->getByName(
640 OUString("Children") )
641 >>= xOldNameContainer;
644 aEntry = xOldNameContainer->getByName( m_aName );
646 catch ( container::NoSuchElementException const & )
648 // getByName
650 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
651 return false;
653 catch ( lang::WrappedTargetException const & )
655 // getByName
657 OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
658 return false;
662 // (2) Remove entry... Note: Insert BEFORE remove does not work!
667 xOldNameContainer->removeByName( m_aName );
668 xOldParentBatch->commitChanges();
670 catch ( container::NoSuchElementException const & )
672 // getByName, removeByName
674 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
675 return false;
679 // (3) Insert entry at new parent...
684 uno::Reference< container::XNameReplace > xNewNameReplace;
685 aEntry >>= xNewNameReplace;
687 OSL_ENSURE( xNewNameReplace.is(),
688 "HierarchyEntry::move - No name replace!" );
690 if ( !xNewNameReplace.is() )
691 return false;
693 uno::Reference< container::XNameAccess > xNewParentNameAccess;
694 if ( bDifferentParents )
695 xNewParentNameAccess
696 = uno::Reference< container::XNameAccess >(
697 xNewParentBatch, uno::UNO_QUERY );
698 else
699 xNewParentNameAccess = xOldParentNameAccess;
701 OSL_ENSURE( xNewParentNameAccess.is(),
702 "HierarchyEntry::move - No name access!" );
704 if ( !xNewParentNameAccess.is() )
705 return false;
707 uno::Reference< container::XNameContainer > xNewNameContainer;
708 if ( bDifferentParents )
710 if ( bNewRoot )
712 xNewNameContainer
713 = uno::Reference< container::XNameContainer >(
714 xNewParentNameAccess, uno::UNO_QUERY );
716 else
718 xNewParentNameAccess->getByName(
719 OUString("Children") )
720 >>= xNewNameContainer;
723 else
724 xNewNameContainer = xOldNameContainer;
726 if ( !xNewNameContainer.is() )
727 return false;
729 xNewNameReplace->replaceByName(
730 OUString("Title"),
731 uno::makeAny( rData.getTitle() ) );
733 // TargetURL property may contain a reference to the Office
734 // installation directory. To ensure a reloctable office
735 // installation, the path to the office installtion
736 // directory must never be stored directly. Use a placeholder
737 // instead.
738 OUString aValue( rData.getTargetURL() );
739 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
740 aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue );
741 xNewNameReplace->replaceByName(
742 OUString("TargetURL"),
743 uno::makeAny( aValue ) );
744 sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
745 xNewNameReplace->replaceByName(
746 OUString("Type"),
747 uno::makeAny( nType ) );
749 xNewNameContainer->insertByName( aNewKey, aEntry );
750 xNewParentBatch->commitChanges();
752 catch ( container::NoSuchElementException const & )
754 // replaceByName, insertByName, getByName
756 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
757 return false;
759 catch ( lang::IllegalArgumentException const & )
761 // replaceByName, insertByName
763 OSL_FAIL(
764 "HierarchyEntry::move - caught IllegalArgumentException!" );
765 return false;
767 catch ( container::ElementExistException const & )
769 // insertByName
771 OSL_FAIL( "HierarchyEntry::move - caught ElementExistException!" );
772 return false;
774 catch ( lang::WrappedTargetException const & )
776 // replaceByName, insertByName, getByName
778 OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
779 return false;
782 return true;
786 bool HierarchyEntry::remove()
790 osl::Guard< osl::Mutex > aGuard( m_aMutex );
792 if ( !m_xConfigProvider.is() )
793 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
794 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
795 uno::UNO_QUERY );
797 if ( m_xConfigProvider.is() )
799 // Create parent's key. It must exist!
801 OUString aParentPath;
802 bool bRoot = true;
804 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
805 if ( nPos != -1 )
807 // Skip "/Children" segment of the path, too.
808 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
810 OSL_ENSURE( nPos != -1,
811 "HierarchyEntry::remove - Wrong path!" );
813 aParentPath += m_aPath.copy( 0, nPos );
814 bRoot = false;
817 uno::Sequence< uno::Any > aArguments( 1 );
818 beans::PropertyValue aProperty;
820 aProperty.Name = CFGPROPERTY_NODEPATH;
821 aProperty.Value <<= aParentPath;
822 aArguments[ 0 ] <<= aProperty;
824 uno::Reference< util::XChangesBatch > xBatch(
825 m_xConfigProvider->createInstanceWithArguments(
826 OUString( READWRITE_SERVICE_NAME ),
827 aArguments ),
828 uno::UNO_QUERY );
830 OSL_ENSURE( xBatch.is(),
831 "HierarchyEntry::remove - No batch!" );
833 uno::Reference< container::XNameAccess > xParentNameAccess(
834 xBatch, uno::UNO_QUERY );
836 OSL_ENSURE( xParentNameAccess.is(),
837 "HierarchyEntry::remove - No name access!" );
839 if ( xBatch.is() && xParentNameAccess.is() )
841 uno::Reference< container::XNameContainer > xContainer;
843 if ( bRoot )
845 // Special handling for children of root,
846 // which is not an entry. It's only a set
847 // of entries.
848 xContainer = uno::Reference< container::XNameContainer >(
849 xParentNameAccess, uno::UNO_QUERY );
851 else
853 // Append new entry to parents child list,
854 // which is a set of entries.
855 xParentNameAccess->getByName(
856 OUString("Children") )
857 >>= xContainer;
860 OSL_ENSURE( xContainer.is(),
861 "HierarchyEntry::remove - No container!" );
863 if ( xContainer.is() )
865 xContainer->removeByName( m_aName );
866 xBatch->commitChanges();
867 return true;
872 catch ( uno::RuntimeException const & )
874 throw;
876 catch ( container::NoSuchElementException const & )
878 // getByName, removeByName
880 OSL_FAIL(
881 "HierarchyEntry::remove - caught NoSuchElementException!" );
883 catch ( lang::WrappedTargetException const & )
885 // getByName, commitChanges
887 OSL_FAIL(
888 "HierarchyEntry::remove - caught WrappedTargetException!" );
890 catch ( uno::Exception const & )
892 // createInstance, createInstanceWithArguments
894 OSL_FAIL( "HierarchyEntry::remove - caught Exception!" );
897 return false;
901 bool HierarchyEntry::first( iterator& it )
903 osl::Guard< osl::Mutex > aGuard( m_aMutex );
905 if ( it.m_pImpl->pos == -1 )
907 // Init...
911 uno::Reference< container::XHierarchicalNameAccess >
912 xRootHierNameAccess = getRootReadAccess();
914 if ( xRootHierNameAccess.is() )
916 uno::Reference< container::XNameAccess > xNameAccess;
918 if ( !m_aPath.isEmpty() )
920 OUString aPath = m_aPath;
921 aPath += "/Children";
923 xRootHierNameAccess->getByHierarchicalName( aPath )
924 >>= xNameAccess;
926 else
927 xNameAccess
928 = uno::Reference< container::XNameAccess >(
929 xRootHierNameAccess, uno::UNO_QUERY );
931 OSL_ENSURE( xNameAccess.is(),
932 "HierarchyEntry::first - No name access!" );
934 if ( xNameAccess.is() )
935 it.m_pImpl->names = xNameAccess->getElementNames();
937 uno::Reference< container::XHierarchicalNameAccess >
938 xHierNameAccess( xNameAccess, uno::UNO_QUERY );
940 OSL_ENSURE( xHierNameAccess.is(),
941 "HierarchyEntry::first - No hier. name access!" );
943 it.m_pImpl->dir = xHierNameAccess;
945 it.m_pImpl->officeDirs = m_xOfficeInstDirs;
948 catch ( uno::RuntimeException const & )
950 throw;
952 catch ( container::NoSuchElementException const& )
954 // getByHierarchicalName
956 OSL_FAIL(
957 "HierarchyEntry::first - caught NoSuchElementException!" );
959 catch ( uno::Exception const & )
961 OSL_FAIL( "HierarchyEntry::first - caught Exception!" );
965 if ( it.m_pImpl->names.getLength() == 0 )
966 return false;
968 it.m_pImpl->pos = 0;
969 return true;
973 bool HierarchyEntry::next( iterator& it )
975 osl::Guard< osl::Mutex > aGuard( m_aMutex );
977 if ( it.m_pImpl->pos == -1 )
978 return first( it );
980 ++(it.m_pImpl->pos);
982 return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() );
986 OUString HierarchyEntry::createPathFromHierarchyURL(
987 const HierarchyUri& rURI )
989 // Transform path....
990 // folder/subfolder/subsubfolder
991 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
993 const OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash.
994 sal_Int32 nLen = aPath.getLength();
996 if ( nLen )
998 OUStringBuffer aNewPath;
999 aNewPath.appendAscii( "['" );
1001 sal_Int32 nStart = 0;
1002 sal_Int32 nEnd = aPath.indexOf( '/' );
1006 if ( nEnd == -1 )
1007 nEnd = nLen;
1009 OUString aToken = aPath.copy( nStart, nEnd - nStart );
1010 makeXMLName( aToken, aNewPath );
1012 if ( nEnd != nLen )
1014 aNewPath.appendAscii( "']/Children/['" );
1015 nStart = nEnd + 1;
1016 nEnd = aPath.indexOf( '/', nStart );
1018 else
1019 aNewPath.appendAscii( "']" );
1021 while ( nEnd != nLen );
1023 return aNewPath.makeStringAndClear();
1026 return aPath;
1030 uno::Reference< container::XHierarchicalNameAccess >
1031 HierarchyEntry::getRootReadAccess()
1033 if ( !m_xRootReadAccess.is() )
1035 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1036 if ( !m_xRootReadAccess.is() )
1038 if ( m_bTriedToGetRootReadAccess ) // #82494#
1040 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1041 "Unable to read any config data! -> #82494#" );
1042 return uno::Reference< container::XHierarchicalNameAccess >();
1047 if ( !m_xConfigProvider.is() )
1048 m_xConfigProvider
1049 = uno::Reference< lang::XMultiServiceFactory >(
1050 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
1051 uno::UNO_QUERY );
1053 if ( m_xConfigProvider.is() )
1055 // Create Root object.
1057 uno::Sequence< uno::Any > aArguments( 1 );
1058 beans::PropertyValue aProperty;
1059 aProperty.Name = CFGPROPERTY_NODEPATH;
1060 aProperty.Value <<= OUString(); // root path
1061 aArguments[ 0 ] <<= aProperty;
1063 m_bTriedToGetRootReadAccess = true;
1065 m_xRootReadAccess
1066 = uno::Reference< container::XHierarchicalNameAccess >(
1067 m_xConfigProvider->createInstanceWithArguments(
1068 OUString( READ_SERVICE_NAME ),
1069 aArguments ),
1070 uno::UNO_QUERY );
1073 catch ( uno::RuntimeException const & )
1075 throw;
1077 catch ( uno::Exception const & )
1079 // createInstance, createInstanceWithArguments
1081 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1082 "caught Exception!" );
1086 return m_xRootReadAccess;
1092 // HierarchyEntry::iterator Implementation.
1097 HierarchyEntry::iterator::iterator()
1099 m_pImpl = new iterator_Impl;
1103 HierarchyEntry::iterator::~iterator()
1105 delete m_pImpl;
1109 const HierarchyEntryData& HierarchyEntry::iterator::operator*() const
1111 if ( ( m_pImpl->pos != -1 )
1112 && ( m_pImpl->dir.is() )
1113 && ( m_pImpl->pos < m_pImpl->names.getLength() ) )
1117 OUStringBuffer aKey;
1118 aKey.appendAscii( "['" );
1119 makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey );
1120 aKey.appendAscii( "']" );
1122 OUString aTitle = aKey.makeStringAndClear();
1123 OUString aTargetURL = aTitle;
1124 OUString aType = aTitle;
1126 aTitle += "/Title";
1127 aTargetURL += "/TargetURL";
1128 aType += "/Type";
1130 OUString aValue;
1131 m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue;
1132 m_pImpl->entry.setTitle( aValue );
1134 m_pImpl->dir->getByHierarchicalName( aTargetURL ) >>= aValue;
1136 // TargetURL property may contain a reference to the Office
1137 // installation directory. To ensure a reloctable office
1138 // installation, the path to the office installtion directory must
1139 // never be stored directly. A placeholder is used instead. Replace
1140 // it by actual installation directory.
1141 if ( m_pImpl->officeDirs.is() && !aValue.isEmpty() )
1142 aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue );
1143 m_pImpl->entry.setTargetURL( aValue );
1145 if ( m_pImpl->dir->hasByHierarchicalName( aType ) )
1147 // Might not be present since it was introduced long
1148 // after Title and TargetURL (#82433#)... So not getting
1149 // it is not an error.
1151 // Get Type value.
1152 sal_Int32 nType = 0;
1153 if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType )
1155 if ( nType == 0 )
1157 m_pImpl->entry.setType( HierarchyEntryData::LINK );
1159 else if ( nType == 1 )
1161 m_pImpl->entry.setType( HierarchyEntryData::FOLDER );
1163 else
1165 OSL_FAIL( "HierarchyEntry::getData - "
1166 "Unknown Type value!" );
1171 m_pImpl->entry.setName(
1172 m_pImpl->names.getConstArray()[ m_pImpl->pos ] );
1174 catch ( container::NoSuchElementException const & )
1176 m_pImpl->entry = HierarchyEntryData();
1180 return m_pImpl->entry;
1183 } // namespace hierarchy_ucp
1185 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */