1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hierarchydata.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
36 **************************************************************************
38 - HierarchyEntry::move
39 --> Rewrite to use XNamed ( once this is supported by config db api ).
41 *************************************************************************/
42 #include "hierarchydata.hxx"
45 #include <osl/diagnose.h>
46 #include <rtl/ustrbuf.hxx>
47 #include <com/sun/star/beans/PropertyValue.hpp>
48 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
49 #include <com/sun/star/container/XNameContainer.hpp>
50 #include <com/sun/star/container/XNameReplace.hpp>
51 #include <com/sun/star/util/XChangesBatch.hpp>
52 #ifndef _COM_SUN_STAR_UTIL_XOFFICEINSTALLTIONDIRECTORIES_HPP_
53 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
55 #include "hierarchyprovider.hxx"
56 #include "hierarchyuri.hxx"
58 using namespace com::sun::star
;
60 namespace hierarchy_ucp
63 //=========================================================================
64 struct HierarchyEntry::iterator_Impl
66 HierarchyEntryData entry
;
67 uno::Reference
< container::XHierarchicalNameAccess
> dir
;
68 uno::Reference
< util::XOfficeInstallationDirectories
> officeDirs
;
69 uno::Sequence
< rtl::OUString
> names
;
72 : officeDirs( 0 ), pos( -1 /* before first */ ) {};
75 //=========================================================================
76 void makeXMLName( const rtl::OUString
& rIn
, rtl::OUStringBuffer
& rBuffer
)
78 sal_Int32 nCount
= rIn
.getLength();
79 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
81 const sal_Unicode c
= rIn
.getStr()[ n
];
85 rBuffer
.appendAscii( "&" );
89 rBuffer
.appendAscii( """ );
93 rBuffer
.appendAscii( "'" );
97 rBuffer
.appendAscii( "<" );
101 rBuffer
.appendAscii( ">" );
111 //=========================================================================
112 //=========================================================================
114 // HierarchyEntry Implementation.
116 //=========================================================================
117 //=========================================================================
119 #define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess"
120 #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
122 // describe path of cfg entry
123 #define CFGPROPERTY_NODEPATH "nodepath"
125 //=========================================================================
126 HierarchyEntry::HierarchyEntry(
127 const uno::Reference
< lang::XMultiServiceFactory
>& rSMgr
,
128 HierarchyContentProvider
* pProvider
,
129 const rtl::OUString
& rURL
)
131 m_xOfficeInstDirs( pProvider
->getOfficeInstallationDirectories() ),
132 m_bTriedToGetRootReadAccess( sal_False
)
134 HierarchyUri
aUri( rURL
);
135 m_aServiceSpecifier
= aUri
.getService();
140 = pProvider
->getConfigProvider( m_aServiceSpecifier
);
142 = pProvider
->getRootConfigReadNameAccess( m_aServiceSpecifier
);
145 // Note: do not init m_aPath in init list. createPathFromHierarchyURL
146 // needs m_xSMgr and m_aMutex.
147 m_aPath
= createPathFromHierarchyURL( aUri
);
149 // Extract language independent name from URL.
150 sal_Int32 nPos
= rURL
.lastIndexOf( '/' );
151 if ( nPos
> HIERARCHY_URL_SCHEME_LENGTH
)
152 m_aName
= rURL
.copy( nPos
+ 1 );
154 OSL_ENSURE( sal_False
, "HierarchyEntry - Invalid URL!" );
157 //=========================================================================
158 sal_Bool
HierarchyEntry::hasData()
160 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
161 uno::Reference
< container::XHierarchicalNameAccess
> xRootReadAccess
162 = getRootReadAccess();
164 OSL_ENSURE( xRootReadAccess
.is(), "HierarchyEntry::hasData - No root!" );
166 if ( xRootReadAccess
.is() )
167 return xRootReadAccess
->hasByHierarchicalName( m_aPath
);
172 //=========================================================================
173 sal_Bool
HierarchyEntry::getData( HierarchyEntryData
& rData
)
177 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
179 uno::Reference
< container::XHierarchicalNameAccess
> xRootReadAccess
180 = getRootReadAccess();
182 OSL_ENSURE( xRootReadAccess
.is(),
183 "HierarchyEntry::getData - No root!" );
185 if ( xRootReadAccess
.is() )
187 rtl::OUString aTitlePath
= m_aPath
;
188 aTitlePath
+= rtl::OUString::createFromAscii( "/Title" );
190 // Note: Avoid NoSuchElementExceptions, because exceptions are
191 // relatively 'expensive'. Checking for availability of
192 // title value is sufficient here, because if it is
193 // there, the other values will be available too.
194 if ( !xRootReadAccess
->hasByHierarchicalName( aTitlePath
) )
197 rtl::OUString aValue
;
200 if ( !( xRootReadAccess
->getByHierarchicalName( aTitlePath
)
203 OSL_ENSURE( sal_False
,
204 "HierarchyEntry::getData - "
205 "Got no Title value!" );
209 rData
.setTitle( aValue
);
211 // Get TargetURL value.
212 rtl::OUString aTargetURLPath
= m_aPath
;
213 aTargetURLPath
+= rtl::OUString::createFromAscii( "/TargetURL" );
214 if ( !( xRootReadAccess
->getByHierarchicalName( aTargetURLPath
)
217 OSL_ENSURE( sal_False
,
218 "HierarchyEntry::getData - "
219 "Got no TargetURL value!" );
223 // TargetURL property may contain a reference to the Office
224 // installation directory. To ensure a reloctable office
225 // installation, the path to the office installtion directory must
226 // never be stored directly. A placeholder is used instead. Replace
227 // it by actual installation directory.
228 if ( m_xOfficeInstDirs
.is() && ( aValue
.getLength() > 0 ) )
229 aValue
= m_xOfficeInstDirs
->makeAbsoluteURL( aValue
);
230 rData
.setTargetURL( aValue
);
232 rtl::OUString aTypePath
= m_aPath
;
233 aTypePath
+= rtl::OUString::createFromAscii( "/Type" );
234 if ( xRootReadAccess
->hasByHierarchicalName( aTypePath
) )
236 // Might not be present since it was introduced long after
237 // Title and TargetURL (#82433#)... So not getting it is
242 if ( xRootReadAccess
->getByHierarchicalName( aTypePath
)
247 rData
.setType( HierarchyEntryData::LINK
);
249 else if ( nType
== 1 )
251 rData
.setType( HierarchyEntryData::FOLDER
);
255 OSL_ENSURE( sal_False
,
256 "HierarchyEntry::getData - "
257 "Unknown Type value!" );
263 rData
.setName( m_aName
);
267 catch ( uno::RuntimeException
const & )
271 catch ( container::NoSuchElementException
const & )
273 // getByHierarchicalName
275 OSL_ENSURE( sal_False
,
276 "HierarchyEntry::getData - caught NoSuchElementException!" );
281 //=========================================================================
282 sal_Bool
HierarchyEntry::setData(
283 const HierarchyEntryData
& rData
, sal_Bool bCreate
)
287 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
289 if ( !m_xConfigProvider
.is() )
290 m_xConfigProvider
= uno::Reference
< lang::XMultiServiceFactory
>(
291 m_xSMgr
->createInstance( m_aServiceSpecifier
),
294 if ( m_xConfigProvider
.is() )
296 // Create parent's key. It must exist!
298 rtl::OUString aParentPath
;
299 sal_Bool bRoot
= sal_True
;
301 sal_Int32 nPos
= m_aPath
.lastIndexOf( '/' );
304 // Skip "/Children" segment of the path, too.
305 nPos
= m_aPath
.lastIndexOf( '/', nPos
- 1 );
307 OSL_ENSURE( nPos
!= -1,
308 "HierarchyEntry::setData - Wrong path!" );
310 aParentPath
+= m_aPath
.copy( 0, nPos
);
314 uno::Sequence
< uno::Any
> aArguments( 1 );
315 beans::PropertyValue aProperty
;
317 aProperty
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
318 CFGPROPERTY_NODEPATH
) );
319 aProperty
.Value
<<= aParentPath
;
320 aArguments
[ 0 ] <<= aProperty
;
322 uno::Reference
< util::XChangesBatch
> xBatch(
323 m_xConfigProvider
->createInstanceWithArguments(
324 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
325 READWRITE_SERVICE_NAME
) ),
329 OSL_ENSURE( xBatch
.is(),
330 "HierarchyEntry::setData - No batch!" );
332 uno::Reference
< container::XNameAccess
> xParentNameAccess(
333 xBatch
, uno::UNO_QUERY
);
335 OSL_ENSURE( xParentNameAccess
.is(),
336 "HierarchyEntry::setData - No name access!" );
338 if ( xBatch
.is() && xParentNameAccess
.is() )
340 // Try to create own key. It must not exist!
342 sal_Bool bExists
= sal_True
;
347 uno::Reference
< container::XNameAccess
> xNameAccess
;
351 xNameAccess
= xParentNameAccess
;
355 xParentNameAccess
->getByName(
356 rtl::OUString::createFromAscii( "Children" ) )
360 if ( xNameAccess
->hasByName( m_aName
) )
361 aMyKey
= xNameAccess
->getByName( m_aName
);
365 catch ( container::NoSuchElementException
const & )
370 uno::Reference
< container::XNameReplace
> xNameReplace
;
371 uno::Reference
< container::XNameContainer
> xContainer
;
375 // Key exists. Replace values.
377 aMyKey
>>= xNameReplace
;
379 OSL_ENSURE( xNameReplace
.is(),
380 "HierarchyEntry::setData - No name replace!" );
387 // Key does not exist. Create / fill / insert it.
389 uno::Reference
< lang::XSingleServiceFactory
> xFac
;
393 // Special handling for children of root,
394 // which is not an entry. It's only a set
396 xFac
= uno::Reference
< lang::XSingleServiceFactory
>(
397 xParentNameAccess
, uno::UNO_QUERY
);
401 // Append new entry to parents child list,
402 // which is a set of entries.
403 xParentNameAccess
->getByName(
404 rtl::OUString::createFromAscii(
405 "Children" ) ) >>= xFac
;
408 OSL_ENSURE( xFac
.is(),
409 "HierarchyEntry::setData - No factory!" );
414 = uno::Reference
< container::XNameReplace
>(
415 xFac
->createInstance(), uno::UNO_QUERY
);
417 OSL_ENSURE( xNameReplace
.is(),
418 "HierarchyEntry::setData - No name replace!" );
420 if ( xNameReplace
.is() )
423 = uno::Reference
< container::XNameContainer
>(
424 xFac
, uno::UNO_QUERY
);
426 OSL_ENSURE( xContainer
.is(),
427 "HierarchyEntry::setData - No container!" );
432 if ( xNameReplace
.is() )
435 xNameReplace
->replaceByName(
436 rtl::OUString::createFromAscii( "Title" ),
437 uno::makeAny( rData
.getTitle() ) );
439 // Set TargetURL value.
441 // TargetURL property may contain a reference to the Office
442 // installation directory. To ensure a reloctable office
443 // installation, the path to the office installtion
444 // directory must never be stored directly. Use a
445 // placeholder instead.
446 rtl::OUString
aValue( rData
.getTargetURL() );
447 if ( m_xOfficeInstDirs
.is() && ( aValue
.getLength() > 0 ) )
449 = m_xOfficeInstDirs
->makeRelocatableURL( aValue
);
451 xNameReplace
->replaceByName(
452 rtl::OUString::createFromAscii( "TargetURL" ),
453 uno::makeAny( aValue
) );
457 = rData
.getType() == HierarchyEntryData::LINK
? 0 : 1;
458 xNameReplace
->replaceByName(
459 rtl::OUString::createFromAscii( "Type" ),
460 uno::makeAny( nType
) );
462 if ( xContainer
.is() )
463 xContainer
->insertByName(
464 m_aName
, uno::makeAny( xNameReplace
) );
467 xBatch
->commitChanges();
473 catch ( uno::RuntimeException
const & )
477 catch ( lang::IllegalArgumentException
const & )
479 // replaceByName, insertByName
483 "HierarchyEntry::setData - caught IllegalArgumentException!" );
485 catch ( container::NoSuchElementException
const & )
487 // replaceByName, getByName
491 "HierarchyEntry::setData - caught NoSuchElementException!" );
493 catch ( container::ElementExistException
const & )
499 "HierarchyEntry::setData - caught ElementExistException!" );
501 catch ( lang::WrappedTargetException
const & )
503 // replaceByName, insertByName, getByName, commitChanges
507 "HierarchyEntry::setData - caught WrappedTargetException!" );
509 catch ( uno::Exception
const & )
511 // createInstance, createInstanceWithArguments
515 "HierarchyEntry::setData - caught Exception!" );
521 //=========================================================================
522 sal_Bool
HierarchyEntry::move(
523 const rtl::OUString
& rNewURL
, const HierarchyEntryData
& rData
)
525 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
527 rtl::OUString aNewPath
= createPathFromHierarchyURL( rNewURL
);
529 if ( aNewPath
== m_aPath
)
533 // In the "near future"... ( not yet implemented in config db )
535 - get update access
for m_aPath
536 - update access
-> XNamed
537 - xNamed::setName( newName
)
538 - updateaccess commit
541 sal_Bool bOldRoot
= sal_True
;
542 uno::Reference
< util::XChangesBatch
> xOldParentBatch
;
544 rtl::OUString aNewKey
;
545 sal_Int32 nURLPos
= rNewURL
.lastIndexOf( '/' );
546 if ( nURLPos
> HIERARCHY_URL_SCHEME_LENGTH
)
547 aNewKey
= rNewURL
.copy( nURLPos
+ 1 );
550 OSL_ENSURE( sal_False
, "HierarchyEntry::move - Invalid URL!" );
554 sal_Bool bNewRoot
= sal_True
;
555 uno::Reference
< util::XChangesBatch
> xNewParentBatch
;
557 sal_Bool bDifferentParents
= sal_True
;
561 if ( !m_xConfigProvider
.is() )
562 m_xConfigProvider
= uno::Reference
< lang::XMultiServiceFactory
>(
563 m_xSMgr
->createInstance( m_aServiceSpecifier
),
566 if ( !m_xConfigProvider
.is() )
569 rtl::OUString aOldParentPath
;
570 sal_Int32 nPos
= m_aPath
.lastIndexOf( '/' );
573 // Skip "/Children" segment of the path, too.
574 nPos
= m_aPath
.lastIndexOf( '/', nPos
- 1 );
576 OSL_ENSURE( nPos
!= -1, "HierarchyEntry::move - Wrong path!" );
578 aOldParentPath
+= m_aPath
.copy( 0, nPos
);
579 bOldRoot
= sal_False
;
582 rtl::OUString aNewParentPath
;
583 nPos
= aNewPath
.lastIndexOf( '/' );
586 // Skip "/Children" segment of the path, too.
587 nPos
= aNewPath
.lastIndexOf( '/', nPos
- 1 );
589 OSL_ENSURE( nPos
!= -1, "HierarchyEntry::move - Wrong path!" );
591 aNewParentPath
+= aNewPath
.copy( 0, nPos
);
592 bNewRoot
= sal_False
;
595 uno::Sequence
< uno::Any
> aArguments( 1 );
596 beans::PropertyValue aProperty
;
598 aProperty
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
599 CFGPROPERTY_NODEPATH
) );
600 aProperty
.Value
<<= aOldParentPath
;
601 aArguments
[ 0 ] <<= aProperty
;
603 xOldParentBatch
= uno::Reference
< util::XChangesBatch
>(
604 m_xConfigProvider
->createInstanceWithArguments(
605 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
606 READWRITE_SERVICE_NAME
) ),
610 OSL_ENSURE( xOldParentBatch
.is(), "HierarchyEntry::move - No batch!" );
612 if ( !xOldParentBatch
.is() )
615 if ( aOldParentPath
== aNewParentPath
)
617 bDifferentParents
= sal_False
;
618 xNewParentBatch
= xOldParentBatch
;
622 bDifferentParents
= sal_True
;
624 aProperty
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
625 CFGPROPERTY_NODEPATH
) );
626 aProperty
.Value
<<= aNewParentPath
;
627 aArguments
[ 0 ] <<= aProperty
;
629 xNewParentBatch
= uno::Reference
< util::XChangesBatch
>(
630 m_xConfigProvider
->createInstanceWithArguments(
631 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
632 READWRITE_SERVICE_NAME
) ),
637 xNewParentBatch
.is(), "HierarchyEntry::move - No batch!" );
639 if ( !xNewParentBatch
.is() )
643 catch ( uno::RuntimeException
const & )
647 catch ( uno::Exception
const & )
649 // createInstance, createInstanceWithArguments
651 OSL_ENSURE( sal_False
, "HierarchyEntry::move - caught Exception!" );
655 //////////////////////////////////////////////////////////////////////
657 //////////////////////////////////////////////////////////////////////
660 uno::Reference
< container::XNameAccess
> xOldParentNameAccess
;
661 uno::Reference
< container::XNameContainer
> xOldNameContainer
;
666 = uno::Reference
< container::XNameAccess
>(
667 xOldParentBatch
, uno::UNO_QUERY
);
669 OSL_ENSURE( xOldParentNameAccess
.is(),
670 "HierarchyEntry::move - No name access!" );
672 if ( !xOldParentNameAccess
.is() )
677 xOldNameContainer
= uno::Reference
< container::XNameContainer
>(
678 xOldParentNameAccess
, uno::UNO_QUERY
);
682 xOldParentNameAccess
->getByName(
683 rtl::OUString::createFromAscii( "Children" ) )
684 >>= xOldNameContainer
;
687 aEntry
= xOldNameContainer
->getByName( m_aName
);
689 catch ( container::NoSuchElementException
const & )
693 OSL_ENSURE( sal_False
,
694 "HierarchyEntry::move - caught NoSuchElementException!" );
697 catch ( lang::WrappedTargetException
const & )
701 OSL_ENSURE( sal_False
,
702 "HierarchyEntry::move - caught WrappedTargetException!" );
706 //////////////////////////////////////////////////////////////////////
707 // (2) Remove entry... Note: Insert BEFORE remove does not work!
708 //////////////////////////////////////////////////////////////////////
712 xOldNameContainer
->removeByName( m_aName
);
713 xOldParentBatch
->commitChanges();
715 catch ( container::NoSuchElementException
const & )
717 // getByName, removeByName
719 OSL_ENSURE( sal_False
,
720 "HierarchyEntry::move - caught NoSuchElementException!" );
724 //////////////////////////////////////////////////////////////////////
725 // (3) Insert entry at new parent...
726 //////////////////////////////////////////////////////////////////////
730 uno::Reference
< container::XNameReplace
> xNewNameReplace
;
731 aEntry
>>= xNewNameReplace
;
733 OSL_ENSURE( xNewNameReplace
.is(),
734 "HierarchyEntry::move - No name replace!" );
736 if ( !xNewNameReplace
.is() )
739 uno::Reference
< container::XNameAccess
> xNewParentNameAccess
;
740 if ( bDifferentParents
)
742 = uno::Reference
< container::XNameAccess
>(
743 xNewParentBatch
, uno::UNO_QUERY
);
745 xNewParentNameAccess
= xOldParentNameAccess
;
747 OSL_ENSURE( xNewParentNameAccess
.is(),
748 "HierarchyEntry::move - No name access!" );
750 if ( !xNewParentNameAccess
.is() )
753 uno::Reference
< container::XNameContainer
> xNewNameContainer
;
754 if ( bDifferentParents
)
759 = uno::Reference
< container::XNameContainer
>(
760 xNewParentNameAccess
, uno::UNO_QUERY
);
764 xNewParentNameAccess
->getByName(
765 rtl::OUString::createFromAscii( "Children" ) )
766 >>= xNewNameContainer
;
770 xNewNameContainer
= xOldNameContainer
;
772 if ( !xNewNameContainer
.is() )
775 xNewNameReplace
->replaceByName(
776 rtl::OUString::createFromAscii( "Title" ),
777 uno::makeAny( rData
.getTitle() ) );
779 // TargetURL property may contain a reference to the Office
780 // installation directory. To ensure a reloctable office
781 // installation, the path to the office installtion
782 // directory must never be stored directly. Use a placeholder
784 rtl::OUString
aValue( rData
.getTargetURL() );
785 if ( m_xOfficeInstDirs
.is() && ( aValue
.getLength() > 0 ) )
786 aValue
= m_xOfficeInstDirs
->makeRelocatableURL( aValue
);
787 xNewNameReplace
->replaceByName(
788 rtl::OUString::createFromAscii( "TargetURL" ),
789 uno::makeAny( aValue
) );
790 sal_Int32 nType
= rData
.getType() == HierarchyEntryData::LINK
? 0 : 1;
791 xNewNameReplace
->replaceByName(
792 rtl::OUString::createFromAscii( "Type" ),
793 uno::makeAny( nType
) );
795 xNewNameContainer
->insertByName( aNewKey
, aEntry
);
796 xNewParentBatch
->commitChanges();
798 catch ( container::NoSuchElementException
const & )
800 // replaceByName, insertByName, getByName
802 OSL_ENSURE( sal_False
,
803 "HierarchyEntry::move - caught NoSuchElementException!" );
806 catch ( lang::IllegalArgumentException
const & )
808 // replaceByName, insertByName
812 "HierarchyEntry::move - caught IllegalArgumentException!" );
815 catch ( container::ElementExistException
const & )
819 OSL_ENSURE( sal_False
,
820 "HierarchyEntry::move - caught ElementExistException!" );
823 catch ( lang::WrappedTargetException
const & )
825 // replaceByName, insertByName, getByName
827 OSL_ENSURE( sal_False
,
828 "HierarchyEntry::move - caught WrappedTargetException!" );
833 //////////////////////////////////////////////////////////////////////
834 // (4) Commit changes...
835 //////////////////////////////////////////////////////////////////////
839 xNewParentBatch
->commitChanges();
841 if ( bDifferentParents
)
842 xOldParentBatch
->commitChanges();
844 catch ( lang::WrappedTargetException
const & )
848 OSL_ENSURE( sal_False
,
849 "HierarchyEntry::move - caught WrappedTargetException!" );
858 //=========================================================================
859 sal_Bool
HierarchyEntry::remove()
863 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
865 if ( !m_xConfigProvider
.is() )
866 m_xConfigProvider
= uno::Reference
< lang::XMultiServiceFactory
>(
867 m_xSMgr
->createInstance( m_aServiceSpecifier
),
870 if ( m_xConfigProvider
.is() )
872 // Create parent's key. It must exist!
874 rtl::OUString aParentPath
;
875 sal_Bool bRoot
= sal_True
;
877 sal_Int32 nPos
= m_aPath
.lastIndexOf( '/' );
880 // Skip "/Children" segment of the path, too.
881 nPos
= m_aPath
.lastIndexOf( '/', nPos
- 1 );
883 OSL_ENSURE( nPos
!= -1,
884 "HierarchyEntry::remove - Wrong path!" );
886 aParentPath
+= m_aPath
.copy( 0, nPos
);
890 uno::Sequence
< uno::Any
> aArguments( 1 );
891 beans::PropertyValue aProperty
;
893 aProperty
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
894 CFGPROPERTY_NODEPATH
) );
895 aProperty
.Value
<<= aParentPath
;
896 aArguments
[ 0 ] <<= aProperty
;
898 uno::Reference
< util::XChangesBatch
> xBatch(
899 m_xConfigProvider
->createInstanceWithArguments(
900 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
901 READWRITE_SERVICE_NAME
) ),
905 OSL_ENSURE( xBatch
.is(),
906 "HierarchyEntry::remove - No batch!" );
908 uno::Reference
< container::XNameAccess
> xParentNameAccess(
909 xBatch
, uno::UNO_QUERY
);
911 OSL_ENSURE( xParentNameAccess
.is(),
912 "HierarchyEntry::remove - No name access!" );
914 if ( xBatch
.is() && xParentNameAccess
.is() )
916 uno::Reference
< container::XNameContainer
> xContainer
;
920 // Special handling for children of root,
921 // which is not an entry. It's only a set
923 xContainer
= uno::Reference
< container::XNameContainer
>(
924 xParentNameAccess
, uno::UNO_QUERY
);
928 // Append new entry to parents child list,
929 // which is a set of entries.
930 xParentNameAccess
->getByName(
931 rtl::OUString::createFromAscii( "Children" ) )
935 OSL_ENSURE( xContainer
.is(),
936 "HierarchyEntry::remove - No container!" );
938 if ( xContainer
.is() )
940 xContainer
->removeByName( m_aName
);
941 xBatch
->commitChanges();
947 catch ( uno::RuntimeException
const & )
951 catch ( container::NoSuchElementException
const & )
953 // getByName, removeByName
957 "HierarchyEntry::remove - caught NoSuchElementException!" );
959 catch ( lang::WrappedTargetException
const & )
961 // getByName, commitChanges
965 "HierarchyEntry::remove - caught WrappedTargetException!" );
967 catch ( uno::Exception
const & )
969 // createInstance, createInstanceWithArguments
971 OSL_ENSURE( sal_False
,
972 "HierarchyEntry::remove - caught Exception!" );
978 //=========================================================================
979 sal_Bool
HierarchyEntry::first( iterator
& it
)
981 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
983 if ( it
.m_pImpl
->pos
== -1 )
989 uno::Reference
< container::XHierarchicalNameAccess
>
990 xRootHierNameAccess
= getRootReadAccess();
992 if ( xRootHierNameAccess
.is() )
994 uno::Reference
< container::XNameAccess
> xNameAccess
;
996 if ( m_aPath
.getLength() > 0 )
998 rtl::OUString aPath
= m_aPath
;
999 aPath
+= rtl::OUString::createFromAscii( "/Children" );
1001 xRootHierNameAccess
->getByHierarchicalName( aPath
)
1006 = uno::Reference
< container::XNameAccess
>(
1007 xRootHierNameAccess
, uno::UNO_QUERY
);
1009 OSL_ENSURE( xNameAccess
.is(),
1010 "HierarchyEntry::first - No name access!" );
1012 if ( xNameAccess
.is() )
1013 it
.m_pImpl
->names
= xNameAccess
->getElementNames();
1015 uno::Reference
< container::XHierarchicalNameAccess
>
1016 xHierNameAccess( xNameAccess
, uno::UNO_QUERY
);
1018 OSL_ENSURE( xHierNameAccess
.is(),
1019 "HierarchyEntry::first - No hier. name access!" );
1021 it
.m_pImpl
->dir
= xHierNameAccess
;
1023 it
.m_pImpl
->officeDirs
= m_xOfficeInstDirs
;
1026 catch ( uno::RuntimeException
const & )
1030 catch ( container::NoSuchElementException
const& )
1032 // getByHierarchicalName
1036 "HierarchyEntry::first - caught NoSuchElementException!" );
1038 catch ( uno::Exception
const & )
1040 OSL_ENSURE( sal_False
,
1041 "HierarchyEntry::first - caught Exception!" );
1045 if ( it
.m_pImpl
->names
.getLength() == 0 )
1048 it
.m_pImpl
->pos
= 0;
1052 //=========================================================================
1053 sal_Bool
HierarchyEntry::next( iterator
& it
)
1055 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1057 if ( it
.m_pImpl
->pos
== -1 )
1060 ++(it
.m_pImpl
->pos
);
1062 return ( it
.m_pImpl
->pos
< it
.m_pImpl
->names
.getLength() );
1065 //=========================================================================
1066 rtl::OUString
HierarchyEntry::createPathFromHierarchyURL(
1067 const HierarchyUri
& rURI
)
1069 // Transform path....
1070 // folder/subfolder/subsubfolder
1071 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
1073 const rtl::OUString aPath
= rURI
.getPath().copy( 1 ); // skip leading slash.
1074 sal_Int32 nLen
= aPath
.getLength();
1078 rtl::OUStringBuffer aNewPath
;
1079 aNewPath
.appendAscii( "['" );
1081 sal_Int32 nStart
= 0;
1082 sal_Int32 nEnd
= aPath
.indexOf( '/' );
1089 rtl::OUString aToken
= aPath
.copy( nStart
, nEnd
- nStart
);
1090 makeXMLName( aToken
, aNewPath
);
1094 aNewPath
.appendAscii( "']/Children/['" );
1096 nEnd
= aPath
.indexOf( '/', nStart
);
1099 aNewPath
.appendAscii( "']" );
1101 while ( nEnd
!= nLen
);
1103 return aNewPath
.makeStringAndClear();
1109 //=========================================================================
1110 uno::Reference
< container::XHierarchicalNameAccess
>
1111 HierarchyEntry::getRootReadAccess()
1113 if ( !m_xRootReadAccess
.is() )
1115 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1116 if ( !m_xRootReadAccess
.is() )
1118 if ( m_bTriedToGetRootReadAccess
) // #82494#
1120 OSL_ENSURE( sal_False
,
1121 "HierarchyEntry::getRootReadAccess - "
1122 "Unable to read any config data! -> #82494#" );
1123 return uno::Reference
< container::XHierarchicalNameAccess
>();
1128 if ( !m_xConfigProvider
.is() )
1130 = uno::Reference
< lang::XMultiServiceFactory
>(
1131 m_xSMgr
->createInstance( m_aServiceSpecifier
),
1134 if ( m_xConfigProvider
.is() )
1136 // Create Root object.
1138 uno::Sequence
< uno::Any
> aArguments( 1 );
1139 beans::PropertyValue aProperty
;
1140 aProperty
.Name
= rtl::OUString(
1141 RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH
) );
1142 aProperty
.Value
<<= rtl::OUString(); // root path
1143 aArguments
[ 0 ] <<= aProperty
;
1145 m_bTriedToGetRootReadAccess
= sal_True
;
1148 = uno::Reference
< container::XHierarchicalNameAccess
>(
1149 m_xConfigProvider
->createInstanceWithArguments(
1151 RTL_CONSTASCII_USTRINGPARAM(
1152 READ_SERVICE_NAME
) ),
1157 catch ( uno::RuntimeException
const & )
1161 catch ( uno::Exception
const & )
1163 // createInstance, createInstanceWithArguments
1165 OSL_ENSURE( sal_False
,
1166 "HierarchyEntry::getRootReadAccess - "
1167 "caught Exception!" );
1171 return m_xRootReadAccess
;
1174 //=========================================================================
1175 //=========================================================================
1177 // HierarchyEntry::iterator Implementation.
1179 //=========================================================================
1180 //=========================================================================
1182 HierarchyEntry::iterator::iterator()
1184 m_pImpl
= new iterator_Impl
;
1187 //=========================================================================
1188 HierarchyEntry::iterator::~iterator()
1193 //=========================================================================
1194 const HierarchyEntryData
& HierarchyEntry::iterator::operator*() const
1196 if ( ( m_pImpl
->pos
!= -1 )
1197 && ( m_pImpl
->dir
.is() )
1198 && ( m_pImpl
->pos
< m_pImpl
->names
.getLength() ) )
1202 rtl::OUStringBuffer aKey
;
1203 aKey
.appendAscii( "['" );
1204 makeXMLName( m_pImpl
->names
.getConstArray()[ m_pImpl
->pos
], aKey
);
1205 aKey
.appendAscii( "']" );
1207 rtl::OUString aTitle
= aKey
.makeStringAndClear();
1208 rtl::OUString aTargetURL
= aTitle
;
1209 rtl::OUString aType
= aTitle
;
1211 aTitle
+= rtl::OUString::createFromAscii( "/Title" );
1212 aTargetURL
+= rtl::OUString::createFromAscii( "/TargetURL" );
1213 aType
+= rtl::OUString::createFromAscii( "/Type" );
1215 rtl::OUString aValue
;
1216 m_pImpl
->dir
->getByHierarchicalName( aTitle
) >>= aValue
;
1217 m_pImpl
->entry
.setTitle( aValue
);
1219 m_pImpl
->dir
->getByHierarchicalName( aTargetURL
) >>= aValue
;
1221 // TargetURL property may contain a reference to the Office
1222 // installation directory. To ensure a reloctable office
1223 // installation, the path to the office installtion directory must
1224 // never be stored directly. A placeholder is used instead. Replace
1225 // it by actual installation directory.
1226 if ( m_pImpl
->officeDirs
.is() && ( aValue
.getLength() > 0 ) )
1227 aValue
= m_pImpl
->officeDirs
->makeAbsoluteURL( aValue
);
1228 m_pImpl
->entry
.setTargetURL( aValue
);
1230 if ( m_pImpl
->dir
->hasByHierarchicalName( aType
) )
1232 // Might not be present since it was introduced long
1233 // after Title and TargetURL (#82433#)... So not getting
1234 // it is not an error.
1237 sal_Int32 nType
= 0;
1238 if ( m_pImpl
->dir
->getByHierarchicalName( aType
) >>= nType
)
1242 m_pImpl
->entry
.setType( HierarchyEntryData::LINK
);
1244 else if ( nType
== 1 )
1246 m_pImpl
->entry
.setType( HierarchyEntryData::FOLDER
);
1250 OSL_ENSURE( sal_False
,
1251 "HierarchyEntry::getData - "
1252 "Unknown Type value!" );
1257 m_pImpl
->entry
.setName(
1258 m_pImpl
->names
.getConstArray()[ m_pImpl
->pos
] );
1260 catch ( container::NoSuchElementException
const & )
1262 m_pImpl
->entry
= HierarchyEntryData();
1266 return m_pImpl
->entry
;
1269 } // namespace hierarchy_ucp