Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / hierarchy / hierarchydata.cxx
blob63a90ad8ea4c9dc459c3a7f4d376ccb3f19859ad
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
31 TODO
32 **************************************************************************
34 - HierarchyEntry::move
35 --> Rewrite to use XNamed ( once this is supported by config db api ).
37 *************************************************************************/
38 #include "hierarchydata.hxx"
40 #include <vector>
41 #include <osl/diagnose.h>
42 #include <rtl/ustrbuf.hxx>
43 #include <com/sun/star/beans/PropertyValue.hpp>
44 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
45 #include <com/sun/star/container/XNameContainer.hpp>
46 #include <com/sun/star/container/XNameReplace.hpp>
47 #include <com/sun/star/util/XChangesBatch.hpp>
48 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
49 #include "hierarchyprovider.hxx"
50 #include "hierarchyuri.hxx"
52 using namespace com::sun::star;
54 namespace hierarchy_ucp
57 //=========================================================================
58 struct HierarchyEntry::iterator_Impl
60 HierarchyEntryData entry;
61 uno::Reference< container::XHierarchicalNameAccess > dir;
62 uno::Reference< util::XOfficeInstallationDirectories > officeDirs;
63 uno::Sequence< rtl::OUString> names;
64 sal_Int32 pos;
65 iterator_Impl()
66 : officeDirs( 0 ), pos( -1 /* before first */ ) {};
69 //=========================================================================
70 void makeXMLName( const rtl::OUString & rIn, rtl::OUStringBuffer & rBuffer )
72 sal_Int32 nCount = rIn.getLength();
73 for ( sal_Int32 n = 0; n < nCount; ++n )
75 const sal_Unicode c = rIn.getStr()[ n ];
76 switch ( c )
78 case '&':
79 rBuffer.appendAscii( "&amp;" );
80 break;
82 case '"':
83 rBuffer.appendAscii( "&quot;" );
84 break;
86 case '\'':
87 rBuffer.appendAscii( "&apos;" );
88 break;
90 case '<':
91 rBuffer.appendAscii( "&lt;" );
92 break;
94 case '>':
95 rBuffer.appendAscii( "&gt;" );
96 break;
98 default:
99 rBuffer.append( c );
100 break;
105 //=========================================================================
106 //=========================================================================
108 // HierarchyEntry Implementation.
110 //=========================================================================
111 //=========================================================================
113 #define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess"
114 #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
116 // describe path of cfg entry
117 #define CFGPROPERTY_NODEPATH "nodepath"
119 //=========================================================================
120 HierarchyEntry::HierarchyEntry(
121 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
122 HierarchyContentProvider* pProvider,
123 const rtl::OUString& rURL )
124 : m_xSMgr( rSMgr ),
125 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
126 m_bTriedToGetRootReadAccess( sal_False )
128 HierarchyUri aUri( rURL );
129 m_aServiceSpecifier = aUri.getService();
131 if ( pProvider )
133 m_xConfigProvider
134 = pProvider->getConfigProvider( m_aServiceSpecifier );
135 m_xRootReadAccess
136 = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier );
139 // Note: do not init m_aPath in init list. createPathFromHierarchyURL
140 // needs m_xSMgr and m_aMutex.
141 m_aPath = createPathFromHierarchyURL( aUri );
143 // Extract language independent name from URL.
144 sal_Int32 nPos = rURL.lastIndexOf( '/' );
145 if ( nPos > HIERARCHY_URL_SCHEME_LENGTH )
146 m_aName = rURL.copy( nPos + 1 );
147 else
148 OSL_FAIL( "HierarchyEntry - Invalid URL!" );
151 //=========================================================================
152 sal_Bool HierarchyEntry::hasData()
154 osl::Guard< osl::Mutex > aGuard( m_aMutex );
155 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
156 = getRootReadAccess();
158 OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" );
160 if ( xRootReadAccess.is() )
161 return xRootReadAccess->hasByHierarchicalName( m_aPath );
163 return sal_False;
166 //=========================================================================
167 sal_Bool HierarchyEntry::getData( HierarchyEntryData& rData )
171 osl::Guard< osl::Mutex > aGuard( m_aMutex );
173 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
174 = getRootReadAccess();
176 OSL_ENSURE( xRootReadAccess.is(),
177 "HierarchyEntry::getData - No root!" );
179 if ( xRootReadAccess.is() )
181 rtl::OUString aTitlePath = m_aPath;
182 aTitlePath += rtl::OUString("/Title");
184 // Note: Avoid NoSuchElementExceptions, because exceptions are
185 // relatively 'expensive'. Checking for availability of
186 // title value is sufficient here, because if it is
187 // there, the other values will be available too.
188 if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) )
189 return sal_False;
191 rtl::OUString aValue;
193 // Get Title value.
194 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
195 >>= aValue ) )
197 OSL_FAIL( "HierarchyEntry::getData - "
198 "Got no Title value!" );
199 return sal_False;
202 rData.setTitle( aValue );
204 // Get TargetURL value.
205 rtl::OUString aTargetURLPath = m_aPath;
206 aTargetURLPath += rtl::OUString("/TargetURL");
207 if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath )
208 >>= aValue ) )
210 OSL_FAIL( "HierarchyEntry::getData - "
211 "Got no TargetURL value!" );
212 return sal_False;
215 // TargetURL property may contain a reference to the Office
216 // installation directory. To ensure a reloctable office
217 // installation, the path to the office installtion directory must
218 // never be stored directly. A placeholder is used instead. Replace
219 // it by actual installation directory.
220 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
221 aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue );
222 rData.setTargetURL( aValue );
224 rtl::OUString aTypePath = m_aPath;
225 aTypePath += rtl::OUString("/Type");
226 if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) )
228 // Might not be present since it was introduced long after
229 // Title and TargetURL (#82433#)... So not getting it is
230 // not an error.
232 // Get Type value.
233 sal_Int32 nType = 0;
234 if ( xRootReadAccess->getByHierarchicalName( aTypePath )
235 >>= nType )
237 if ( nType == 0 )
239 rData.setType( HierarchyEntryData::LINK );
241 else if ( nType == 1 )
243 rData.setType( HierarchyEntryData::FOLDER );
245 else
247 OSL_FAIL( "HierarchyEntry::getData - "
248 "Unknown Type value!" );
249 return sal_False;
254 rData.setName( m_aName );
255 return sal_True;
258 catch ( uno::RuntimeException const & )
260 throw;
262 catch ( container::NoSuchElementException const & )
264 // getByHierarchicalName
266 OSL_FAIL( "HierarchyEntry::getData - caught NoSuchElementException!" );
268 return sal_False;
271 //=========================================================================
272 sal_Bool HierarchyEntry::setData(
273 const HierarchyEntryData& rData, sal_Bool bCreate )
277 osl::Guard< osl::Mutex > aGuard( m_aMutex );
279 if ( !m_xConfigProvider.is() )
280 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
281 m_xSMgr->createInstance( m_aServiceSpecifier ),
282 uno::UNO_QUERY );
284 if ( m_xConfigProvider.is() )
286 // Create parent's key. It must exist!
288 rtl::OUString aParentPath;
289 sal_Bool bRoot = sal_True;
291 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
292 if ( nPos != -1 )
294 // Skip "/Children" segment of the path, too.
295 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
297 OSL_ENSURE( nPos != -1,
298 "HierarchyEntry::setData - Wrong path!" );
300 aParentPath += m_aPath.copy( 0, nPos );
301 bRoot = sal_False;
304 uno::Sequence< uno::Any > aArguments( 1 );
305 beans::PropertyValue aProperty;
307 aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
308 aProperty.Value <<= aParentPath;
309 aArguments[ 0 ] <<= aProperty;
311 uno::Reference< util::XChangesBatch > xBatch(
312 m_xConfigProvider->createInstanceWithArguments(
313 rtl::OUString( READWRITE_SERVICE_NAME ),
314 aArguments ),
315 uno::UNO_QUERY );
317 OSL_ENSURE( xBatch.is(),
318 "HierarchyEntry::setData - No batch!" );
320 uno::Reference< container::XNameAccess > xParentNameAccess(
321 xBatch, uno::UNO_QUERY );
323 OSL_ENSURE( xParentNameAccess.is(),
324 "HierarchyEntry::setData - No name access!" );
326 if ( xBatch.is() && xParentNameAccess.is() )
328 // Try to create own key. It must not exist!
330 sal_Bool bExists = sal_True;
331 uno::Any aMyKey;
335 uno::Reference< container::XNameAccess > xNameAccess;
337 if ( bRoot )
339 xNameAccess = xParentNameAccess;
341 else
343 xParentNameAccess->getByName(
344 rtl::OUString("Children") )
345 >>= xNameAccess;
348 if ( xNameAccess->hasByName( m_aName ) )
349 aMyKey = xNameAccess->getByName( m_aName );
350 else
351 bExists = sal_False;
353 catch ( container::NoSuchElementException const & )
355 bExists = sal_False;
358 uno::Reference< container::XNameReplace > xNameReplace;
359 uno::Reference< container::XNameContainer > xContainer;
361 if ( bExists )
363 // Key exists. Replace values.
365 aMyKey >>= xNameReplace;
367 OSL_ENSURE( xNameReplace.is(),
368 "HierarchyEntry::setData - No name replace!" );
370 else
372 if ( !bCreate )
373 return sal_True;
375 // Key does not exist. Create / fill / insert it.
377 uno::Reference< lang::XSingleServiceFactory > xFac;
379 if ( bRoot )
381 // Special handling for children of root,
382 // which is not an entry. It's only a set
383 // of entries.
384 xFac = uno::Reference< lang::XSingleServiceFactory >(
385 xParentNameAccess, uno::UNO_QUERY );
387 else
389 // Append new entry to parents child list,
390 // which is a set of entries.
391 xParentNameAccess->getByName(
392 rtl::OUString( "Children" ) ) >>= xFac;
395 OSL_ENSURE( xFac.is(),
396 "HierarchyEntry::setData - No factory!" );
398 if ( xFac.is() )
400 xNameReplace
401 = uno::Reference< container::XNameReplace >(
402 xFac->createInstance(), uno::UNO_QUERY );
404 OSL_ENSURE( xNameReplace.is(),
405 "HierarchyEntry::setData - No name replace!" );
407 if ( xNameReplace.is() )
409 xContainer
410 = uno::Reference< container::XNameContainer >(
411 xFac, uno::UNO_QUERY );
413 OSL_ENSURE( xContainer.is(),
414 "HierarchyEntry::setData - No container!" );
419 if ( xNameReplace.is() )
421 // Set Title value.
422 xNameReplace->replaceByName(
423 rtl::OUString("Title"),
424 uno::makeAny( rData.getTitle() ) );
426 // Set TargetURL value.
428 // TargetURL property may contain a reference to the Office
429 // installation directory. To ensure a reloctable office
430 // installation, the path to the office installtion
431 // directory must never be stored directly. Use a
432 // placeholder instead.
433 rtl::OUString aValue( rData.getTargetURL() );
434 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
435 aValue
436 = m_xOfficeInstDirs->makeRelocatableURL( aValue );
438 xNameReplace->replaceByName(
439 rtl::OUString("TargetURL"),
440 uno::makeAny( aValue ) );
442 // Set Type value.
443 sal_Int32 nType
444 = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
445 xNameReplace->replaceByName(
446 rtl::OUString("Type"),
447 uno::makeAny( nType ) );
449 if ( xContainer.is() )
450 xContainer->insertByName(
451 m_aName, uno::makeAny( xNameReplace ) );
453 // Commit changes.
454 xBatch->commitChanges();
455 return sal_True;
460 catch ( uno::RuntimeException const & )
462 throw;
464 catch ( lang::IllegalArgumentException const & )
466 // replaceByName, insertByName
468 OSL_FAIL(
469 "HierarchyEntry::setData - caught IllegalArgumentException!" );
471 catch ( container::NoSuchElementException const & )
473 // replaceByName, getByName
475 OSL_FAIL(
476 "HierarchyEntry::setData - caught NoSuchElementException!" );
478 catch ( container::ElementExistException const & )
480 // insertByName
482 OSL_FAIL(
483 "HierarchyEntry::setData - caught ElementExistException!" );
485 catch ( lang::WrappedTargetException const & )
487 // replaceByName, insertByName, getByName, commitChanges
489 OSL_FAIL(
490 "HierarchyEntry::setData - caught WrappedTargetException!" );
492 catch ( uno::Exception const & )
494 // createInstance, createInstanceWithArguments
496 OSL_FAIL(
497 "HierarchyEntry::setData - caught Exception!" );
500 return sal_False;
503 //=========================================================================
504 sal_Bool HierarchyEntry::move(
505 const rtl::OUString& rNewURL, const HierarchyEntryData& rData )
507 osl::Guard< osl::Mutex > aGuard( m_aMutex );
509 rtl::OUString aNewPath = createPathFromHierarchyURL( rNewURL );
511 if ( aNewPath == m_aPath )
512 return sal_True;
514 sal_Bool bOldRoot = sal_True;
515 uno::Reference< util::XChangesBatch > xOldParentBatch;
517 rtl::OUString aNewKey;
518 sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' );
519 if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH )
520 aNewKey = rNewURL.copy( nURLPos + 1 );
521 else
523 OSL_FAIL( "HierarchyEntry::move - Invalid URL!" );
524 return sal_False;
527 sal_Bool bNewRoot = sal_True;
528 uno::Reference< util::XChangesBatch > xNewParentBatch;
530 sal_Bool bDifferentParents = sal_True;
534 if ( !m_xConfigProvider.is() )
535 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
536 m_xSMgr->createInstance( m_aServiceSpecifier ),
537 uno::UNO_QUERY );
539 if ( !m_xConfigProvider.is() )
540 return sal_False;
542 rtl::OUString aOldParentPath;
543 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
544 if ( nPos != -1 )
546 // Skip "/Children" segment of the path, too.
547 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
549 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
551 aOldParentPath += m_aPath.copy( 0, nPos );
552 bOldRoot = sal_False;
555 rtl::OUString aNewParentPath;
556 nPos = aNewPath.lastIndexOf( '/' );
557 if ( nPos != -1 )
559 // Skip "/Children" segment of the path, too.
560 nPos = aNewPath.lastIndexOf( '/', nPos - 1 );
562 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
564 aNewParentPath += aNewPath.copy( 0, nPos );
565 bNewRoot = sal_False;
568 uno::Sequence< uno::Any > aArguments( 1 );
569 beans::PropertyValue aProperty;
571 aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
572 aProperty.Value <<= aOldParentPath;
573 aArguments[ 0 ] <<= aProperty;
575 xOldParentBatch = uno::Reference< util::XChangesBatch >(
576 m_xConfigProvider->createInstanceWithArguments(
577 rtl::OUString( READWRITE_SERVICE_NAME ),
578 aArguments ),
579 uno::UNO_QUERY );
581 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
583 if ( !xOldParentBatch.is() )
584 return sal_False;
586 if ( aOldParentPath == aNewParentPath )
588 bDifferentParents = sal_False;
589 xNewParentBatch = xOldParentBatch;
591 else
593 bDifferentParents = sal_True;
595 aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
596 aProperty.Value <<= aNewParentPath;
597 aArguments[ 0 ] <<= aProperty;
599 xNewParentBatch = uno::Reference< util::XChangesBatch >(
600 m_xConfigProvider->createInstanceWithArguments(
601 rtl::OUString( READWRITE_SERVICE_NAME ),
602 aArguments ),
603 uno::UNO_QUERY );
605 OSL_ENSURE(
606 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
608 if ( !xNewParentBatch.is() )
609 return sal_False;
612 catch ( uno::RuntimeException const & )
614 throw;
616 catch ( uno::Exception const & )
618 // createInstance, createInstanceWithArguments
620 OSL_FAIL( "HierarchyEntry::move - caught Exception!" );
621 return sal_False;
624 //////////////////////////////////////////////////////////////////////
625 // (1) Get entry...
626 //////////////////////////////////////////////////////////////////////
628 uno::Any aEntry;
629 uno::Reference< container::XNameAccess > xOldParentNameAccess;
630 uno::Reference< container::XNameContainer > xOldNameContainer;
634 xOldParentNameAccess
635 = uno::Reference< container::XNameAccess >(
636 xOldParentBatch, uno::UNO_QUERY );
638 OSL_ENSURE( xOldParentNameAccess.is(),
639 "HierarchyEntry::move - No name access!" );
641 if ( !xOldParentNameAccess.is() )
642 return sal_False;
644 if ( bOldRoot )
646 xOldNameContainer = uno::Reference< container::XNameContainer >(
647 xOldParentNameAccess, uno::UNO_QUERY );
649 else
651 xOldParentNameAccess->getByName(
652 rtl::OUString("Children") )
653 >>= xOldNameContainer;
656 aEntry = xOldNameContainer->getByName( m_aName );
658 catch ( container::NoSuchElementException const & )
660 // getByName
662 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
663 return sal_False;
665 catch ( lang::WrappedTargetException const & )
667 // getByName
669 OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
670 return sal_False;
673 //////////////////////////////////////////////////////////////////////
674 // (2) Remove entry... Note: Insert BEFORE remove does not work!
675 //////////////////////////////////////////////////////////////////////
679 xOldNameContainer->removeByName( m_aName );
680 xOldParentBatch->commitChanges();
682 catch ( container::NoSuchElementException const & )
684 // getByName, removeByName
686 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
687 return sal_False;
690 //////////////////////////////////////////////////////////////////////
691 // (3) Insert entry at new parent...
692 //////////////////////////////////////////////////////////////////////
696 uno::Reference< container::XNameReplace > xNewNameReplace;
697 aEntry >>= xNewNameReplace;
699 OSL_ENSURE( xNewNameReplace.is(),
700 "HierarchyEntry::move - No name replace!" );
702 if ( !xNewNameReplace.is() )
703 return sal_False;
705 uno::Reference< container::XNameAccess > xNewParentNameAccess;
706 if ( bDifferentParents )
707 xNewParentNameAccess
708 = uno::Reference< container::XNameAccess >(
709 xNewParentBatch, uno::UNO_QUERY );
710 else
711 xNewParentNameAccess = xOldParentNameAccess;
713 OSL_ENSURE( xNewParentNameAccess.is(),
714 "HierarchyEntry::move - No name access!" );
716 if ( !xNewParentNameAccess.is() )
717 return sal_False;
719 uno::Reference< container::XNameContainer > xNewNameContainer;
720 if ( bDifferentParents )
722 if ( bNewRoot )
724 xNewNameContainer
725 = uno::Reference< container::XNameContainer >(
726 xNewParentNameAccess, uno::UNO_QUERY );
728 else
730 xNewParentNameAccess->getByName(
731 rtl::OUString("Children") )
732 >>= xNewNameContainer;
735 else
736 xNewNameContainer = xOldNameContainer;
738 if ( !xNewNameContainer.is() )
739 return sal_False;
741 xNewNameReplace->replaceByName(
742 rtl::OUString("Title"),
743 uno::makeAny( rData.getTitle() ) );
745 // TargetURL property may contain a reference to the Office
746 // installation directory. To ensure a reloctable office
747 // installation, the path to the office installtion
748 // directory must never be stored directly. Use a placeholder
749 // instead.
750 rtl::OUString aValue( rData.getTargetURL() );
751 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
752 aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue );
753 xNewNameReplace->replaceByName(
754 rtl::OUString("TargetURL"),
755 uno::makeAny( aValue ) );
756 sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
757 xNewNameReplace->replaceByName(
758 rtl::OUString("Type"),
759 uno::makeAny( nType ) );
761 xNewNameContainer->insertByName( aNewKey, aEntry );
762 xNewParentBatch->commitChanges();
764 catch ( container::NoSuchElementException const & )
766 // replaceByName, insertByName, getByName
768 OSL_FAIL( "HierarchyEntry::move - caught NoSuchElementException!" );
769 return sal_False;
771 catch ( lang::IllegalArgumentException const & )
773 // replaceByName, insertByName
775 OSL_FAIL(
776 "HierarchyEntry::move - caught IllegalArgumentException!" );
777 return sal_False;
779 catch ( container::ElementExistException const & )
781 // insertByName
783 OSL_FAIL( "HierarchyEntry::move - caught ElementExistException!" );
784 return sal_False;
786 catch ( lang::WrappedTargetException const & )
788 // replaceByName, insertByName, getByName
790 OSL_FAIL( "HierarchyEntry::move - caught WrappedTargetException!" );
791 return sal_False;
794 return sal_True;
797 //=========================================================================
798 sal_Bool HierarchyEntry::remove()
802 osl::Guard< osl::Mutex > aGuard( m_aMutex );
804 if ( !m_xConfigProvider.is() )
805 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
806 m_xSMgr->createInstance( m_aServiceSpecifier ),
807 uno::UNO_QUERY );
809 if ( m_xConfigProvider.is() )
811 // Create parent's key. It must exist!
813 rtl::OUString aParentPath;
814 sal_Bool bRoot = sal_True;
816 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
817 if ( nPos != -1 )
819 // Skip "/Children" segment of the path, too.
820 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
822 OSL_ENSURE( nPos != -1,
823 "HierarchyEntry::remove - Wrong path!" );
825 aParentPath += m_aPath.copy( 0, nPos );
826 bRoot = sal_False;
829 uno::Sequence< uno::Any > aArguments( 1 );
830 beans::PropertyValue aProperty;
832 aProperty.Name = rtl::OUString( CFGPROPERTY_NODEPATH );
833 aProperty.Value <<= aParentPath;
834 aArguments[ 0 ] <<= aProperty;
836 uno::Reference< util::XChangesBatch > xBatch(
837 m_xConfigProvider->createInstanceWithArguments(
838 rtl::OUString( READWRITE_SERVICE_NAME ),
839 aArguments ),
840 uno::UNO_QUERY );
842 OSL_ENSURE( xBatch.is(),
843 "HierarchyEntry::remove - No batch!" );
845 uno::Reference< container::XNameAccess > xParentNameAccess(
846 xBatch, uno::UNO_QUERY );
848 OSL_ENSURE( xParentNameAccess.is(),
849 "HierarchyEntry::remove - No name access!" );
851 if ( xBatch.is() && xParentNameAccess.is() )
853 uno::Reference< container::XNameContainer > xContainer;
855 if ( bRoot )
857 // Special handling for children of root,
858 // which is not an entry. It's only a set
859 // of entries.
860 xContainer = uno::Reference< container::XNameContainer >(
861 xParentNameAccess, uno::UNO_QUERY );
863 else
865 // Append new entry to parents child list,
866 // which is a set of entries.
867 xParentNameAccess->getByName(
868 rtl::OUString("Children") )
869 >>= xContainer;
872 OSL_ENSURE( xContainer.is(),
873 "HierarchyEntry::remove - No container!" );
875 if ( xContainer.is() )
877 xContainer->removeByName( m_aName );
878 xBatch->commitChanges();
879 return sal_True;
884 catch ( uno::RuntimeException const & )
886 throw;
888 catch ( container::NoSuchElementException const & )
890 // getByName, removeByName
892 OSL_FAIL(
893 "HierarchyEntry::remove - caught NoSuchElementException!" );
895 catch ( lang::WrappedTargetException const & )
897 // getByName, commitChanges
899 OSL_FAIL(
900 "HierarchyEntry::remove - caught WrappedTargetException!" );
902 catch ( uno::Exception const & )
904 // createInstance, createInstanceWithArguments
906 OSL_FAIL( "HierarchyEntry::remove - caught Exception!" );
909 return sal_False;
912 //=========================================================================
913 sal_Bool HierarchyEntry::first( iterator& it )
915 osl::Guard< osl::Mutex > aGuard( m_aMutex );
917 if ( it.m_pImpl->pos == -1 )
919 // Init...
923 uno::Reference< container::XHierarchicalNameAccess >
924 xRootHierNameAccess = getRootReadAccess();
926 if ( xRootHierNameAccess.is() )
928 uno::Reference< container::XNameAccess > xNameAccess;
930 if ( !m_aPath.isEmpty() )
932 rtl::OUString aPath = m_aPath;
933 aPath += rtl::OUString("/Children");
935 xRootHierNameAccess->getByHierarchicalName( aPath )
936 >>= xNameAccess;
938 else
939 xNameAccess
940 = uno::Reference< container::XNameAccess >(
941 xRootHierNameAccess, uno::UNO_QUERY );
943 OSL_ENSURE( xNameAccess.is(),
944 "HierarchyEntry::first - No name access!" );
946 if ( xNameAccess.is() )
947 it.m_pImpl->names = xNameAccess->getElementNames();
949 uno::Reference< container::XHierarchicalNameAccess >
950 xHierNameAccess( xNameAccess, uno::UNO_QUERY );
952 OSL_ENSURE( xHierNameAccess.is(),
953 "HierarchyEntry::first - No hier. name access!" );
955 it.m_pImpl->dir = xHierNameAccess;
957 it.m_pImpl->officeDirs = m_xOfficeInstDirs;
960 catch ( uno::RuntimeException const & )
962 throw;
964 catch ( container::NoSuchElementException const& )
966 // getByHierarchicalName
968 OSL_FAIL(
969 "HierarchyEntry::first - caught NoSuchElementException!" );
971 catch ( uno::Exception const & )
973 OSL_FAIL( "HierarchyEntry::first - caught Exception!" );
977 if ( it.m_pImpl->names.getLength() == 0 )
978 return sal_False;
980 it.m_pImpl->pos = 0;
981 return sal_True;
984 //=========================================================================
985 sal_Bool HierarchyEntry::next( iterator& it )
987 osl::Guard< osl::Mutex > aGuard( m_aMutex );
989 if ( it.m_pImpl->pos == -1 )
990 return first( it );
992 ++(it.m_pImpl->pos);
994 return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() );
997 //=========================================================================
998 rtl::OUString HierarchyEntry::createPathFromHierarchyURL(
999 const HierarchyUri& rURI )
1001 // Transform path....
1002 // folder/subfolder/subsubfolder
1003 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
1005 const rtl::OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash.
1006 sal_Int32 nLen = aPath.getLength();
1008 if ( nLen )
1010 rtl::OUStringBuffer aNewPath;
1011 aNewPath.appendAscii( "['" );
1013 sal_Int32 nStart = 0;
1014 sal_Int32 nEnd = aPath.indexOf( '/' );
1018 if ( nEnd == -1 )
1019 nEnd = nLen;
1021 rtl::OUString aToken = aPath.copy( nStart, nEnd - nStart );
1022 makeXMLName( aToken, aNewPath );
1024 if ( nEnd != nLen )
1026 aNewPath.appendAscii( "']/Children/['" );
1027 nStart = nEnd + 1;
1028 nEnd = aPath.indexOf( '/', nStart );
1030 else
1031 aNewPath.appendAscii( "']" );
1033 while ( nEnd != nLen );
1035 return aNewPath.makeStringAndClear();
1038 return aPath;
1041 //=========================================================================
1042 uno::Reference< container::XHierarchicalNameAccess >
1043 HierarchyEntry::getRootReadAccess()
1045 if ( !m_xRootReadAccess.is() )
1047 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1048 if ( !m_xRootReadAccess.is() )
1050 if ( m_bTriedToGetRootReadAccess ) // #82494#
1052 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1053 "Unable to read any config data! -> #82494#" );
1054 return uno::Reference< container::XHierarchicalNameAccess >();
1059 if ( !m_xConfigProvider.is() )
1060 m_xConfigProvider
1061 = uno::Reference< lang::XMultiServiceFactory >(
1062 m_xSMgr->createInstance( m_aServiceSpecifier ),
1063 uno::UNO_QUERY );
1065 if ( m_xConfigProvider.is() )
1067 // Create Root object.
1069 uno::Sequence< uno::Any > aArguments( 1 );
1070 beans::PropertyValue aProperty;
1071 aProperty.Name = rtl::OUString(
1072 CFGPROPERTY_NODEPATH );
1073 aProperty.Value <<= rtl::OUString(); // root path
1074 aArguments[ 0 ] <<= aProperty;
1076 m_bTriedToGetRootReadAccess = sal_True;
1078 m_xRootReadAccess
1079 = uno::Reference< container::XHierarchicalNameAccess >(
1080 m_xConfigProvider->createInstanceWithArguments(
1081 rtl::OUString( READ_SERVICE_NAME ),
1082 aArguments ),
1083 uno::UNO_QUERY );
1086 catch ( uno::RuntimeException const & )
1088 throw;
1090 catch ( uno::Exception const & )
1092 // createInstance, createInstanceWithArguments
1094 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
1095 "caught Exception!" );
1099 return m_xRootReadAccess;
1102 //=========================================================================
1103 //=========================================================================
1105 // HierarchyEntry::iterator Implementation.
1107 //=========================================================================
1108 //=========================================================================
1110 HierarchyEntry::iterator::iterator()
1112 m_pImpl = new iterator_Impl;
1115 //=========================================================================
1116 HierarchyEntry::iterator::~iterator()
1118 delete m_pImpl;
1121 //=========================================================================
1122 const HierarchyEntryData& HierarchyEntry::iterator::operator*() const
1124 if ( ( m_pImpl->pos != -1 )
1125 && ( m_pImpl->dir.is() )
1126 && ( m_pImpl->pos < m_pImpl->names.getLength() ) )
1130 rtl::OUStringBuffer aKey;
1131 aKey.appendAscii( "['" );
1132 makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey );
1133 aKey.appendAscii( "']" );
1135 rtl::OUString aTitle = aKey.makeStringAndClear();
1136 rtl::OUString aTargetURL = aTitle;
1137 rtl::OUString aType = aTitle;
1139 aTitle += rtl::OUString("/Title");
1140 aTargetURL += rtl::OUString("/TargetURL");
1141 aType += rtl::OUString("/Type");
1143 rtl::OUString aValue;
1144 m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue;
1145 m_pImpl->entry.setTitle( aValue );
1147 m_pImpl->dir->getByHierarchicalName( aTargetURL ) >>= aValue;
1149 // TargetURL property may contain a reference to the Office
1150 // installation directory. To ensure a reloctable office
1151 // installation, the path to the office installtion directory must
1152 // never be stored directly. A placeholder is used instead. Replace
1153 // it by actual installation directory.
1154 if ( m_pImpl->officeDirs.is() && !aValue.isEmpty() )
1155 aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue );
1156 m_pImpl->entry.setTargetURL( aValue );
1158 if ( m_pImpl->dir->hasByHierarchicalName( aType ) )
1160 // Might not be present since it was introduced long
1161 // after Title and TargetURL (#82433#)... So not getting
1162 // it is not an error.
1164 // Get Type value.
1165 sal_Int32 nType = 0;
1166 if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType )
1168 if ( nType == 0 )
1170 m_pImpl->entry.setType( HierarchyEntryData::LINK );
1172 else if ( nType == 1 )
1174 m_pImpl->entry.setType( HierarchyEntryData::FOLDER );
1176 else
1178 OSL_FAIL( "HierarchyEntry::getData - "
1179 "Unknown Type value!" );
1184 m_pImpl->entry.setName(
1185 m_pImpl->names.getConstArray()[ m_pImpl->pos ] );
1187 catch ( container::NoSuchElementException const & )
1189 m_pImpl->entry = HierarchyEntryData();
1193 return m_pImpl->entry;
1196 } // namespace hierarchy_ucp
1198 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */