Update ooo320-m1
[ooovba.git] / ucb / source / ucp / hierarchy / hierarchydata.cxx
blobeb88177691dd0b9828073a06ca4ee5f4bceefa96
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hierarchydata.cxx,v $
10 * $Revision: 1.28 $
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 /**************************************************************************
35 TODO
36 **************************************************************************
38 - HierarchyEntry::move
39 --> Rewrite to use XNamed ( once this is supported by config db api ).
41 *************************************************************************/
42 #include "hierarchydata.hxx"
44 #include <vector>
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>
54 #endif
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;
70 sal_Int32 pos;
71 iterator_Impl()
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 ];
82 switch ( c )
84 case '&':
85 rBuffer.appendAscii( "&amp;" );
86 break;
88 case '"':
89 rBuffer.appendAscii( "&quot;" );
90 break;
92 case '\'':
93 rBuffer.appendAscii( "&apos;" );
94 break;
96 case '<':
97 rBuffer.appendAscii( "&lt;" );
98 break;
100 case '>':
101 rBuffer.appendAscii( "&gt;" );
102 break;
104 default:
105 rBuffer.append( c );
106 break;
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 )
130 : m_xSMgr( rSMgr ),
131 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
132 m_bTriedToGetRootReadAccess( sal_False )
134 HierarchyUri aUri( rURL );
135 m_aServiceSpecifier = aUri.getService();
137 if ( pProvider )
139 m_xConfigProvider
140 = pProvider->getConfigProvider( m_aServiceSpecifier );
141 m_xRootReadAccess
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 );
153 else
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 );
169 return sal_False;
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 ) )
195 return sal_False;
197 rtl::OUString aValue;
199 // Get Title value.
200 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
201 >>= aValue ) )
203 OSL_ENSURE( sal_False,
204 "HierarchyEntry::getData - "
205 "Got no Title value!" );
206 return sal_False;
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 )
215 >>= aValue ) )
217 OSL_ENSURE( sal_False,
218 "HierarchyEntry::getData - "
219 "Got no TargetURL value!" );
220 return sal_False;
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
238 // not an error.
240 // Get Type value.
241 sal_Int32 nType = 0;
242 if ( xRootReadAccess->getByHierarchicalName( aTypePath )
243 >>= nType )
245 if ( nType == 0 )
247 rData.setType( HierarchyEntryData::LINK );
249 else if ( nType == 1 )
251 rData.setType( HierarchyEntryData::FOLDER );
253 else
255 OSL_ENSURE( sal_False,
256 "HierarchyEntry::getData - "
257 "Unknown Type value!" );
258 return sal_False;
263 rData.setName( m_aName );
264 return sal_True;
267 catch ( uno::RuntimeException const & )
269 throw;
271 catch ( container::NoSuchElementException const & )
273 // getByHierarchicalName
275 OSL_ENSURE( sal_False,
276 "HierarchyEntry::getData - caught NoSuchElementException!" );
278 return sal_False;
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 ),
292 uno::UNO_QUERY );
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( '/' );
302 if ( nPos != -1 )
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 );
311 bRoot = sal_False;
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 ) ),
326 aArguments ),
327 uno::UNO_QUERY );
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;
343 uno::Any aMyKey;
347 uno::Reference< container::XNameAccess > xNameAccess;
349 if ( bRoot )
351 xNameAccess = xParentNameAccess;
353 else
355 xParentNameAccess->getByName(
356 rtl::OUString::createFromAscii( "Children" ) )
357 >>= xNameAccess;
360 if ( xNameAccess->hasByName( m_aName ) )
361 aMyKey = xNameAccess->getByName( m_aName );
362 else
363 bExists = sal_False;
365 catch ( container::NoSuchElementException const & )
367 bExists = sal_False;
370 uno::Reference< container::XNameReplace > xNameReplace;
371 uno::Reference< container::XNameContainer > xContainer;
373 if ( bExists )
375 // Key exists. Replace values.
377 aMyKey >>= xNameReplace;
379 OSL_ENSURE( xNameReplace.is(),
380 "HierarchyEntry::setData - No name replace!" );
382 else
384 if ( !bCreate )
385 return sal_True;
387 // Key does not exist. Create / fill / insert it.
389 uno::Reference< lang::XSingleServiceFactory > xFac;
391 if ( bRoot )
393 // Special handling for children of root,
394 // which is not an entry. It's only a set
395 // of entries.
396 xFac = uno::Reference< lang::XSingleServiceFactory >(
397 xParentNameAccess, uno::UNO_QUERY );
399 else
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!" );
411 if ( xFac.is() )
413 xNameReplace
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() )
422 xContainer
423 = uno::Reference< container::XNameContainer >(
424 xFac, uno::UNO_QUERY );
426 OSL_ENSURE( xContainer.is(),
427 "HierarchyEntry::setData - No container!" );
432 if ( xNameReplace.is() )
434 // Set Title value.
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 ) )
448 aValue
449 = m_xOfficeInstDirs->makeRelocatableURL( aValue );
451 xNameReplace->replaceByName(
452 rtl::OUString::createFromAscii( "TargetURL" ),
453 uno::makeAny( aValue ) );
455 // Set Type value.
456 sal_Int32 nType
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 ) );
466 // Commit changes.
467 xBatch->commitChanges();
468 return sal_True;
473 catch ( uno::RuntimeException const & )
475 throw;
477 catch ( lang::IllegalArgumentException const & )
479 // replaceByName, insertByName
481 OSL_ENSURE(
482 sal_False,
483 "HierarchyEntry::setData - caught IllegalArgumentException!" );
485 catch ( container::NoSuchElementException const & )
487 // replaceByName, getByName
489 OSL_ENSURE(
490 sal_False,
491 "HierarchyEntry::setData - caught NoSuchElementException!" );
493 catch ( container::ElementExistException const & )
495 // insertByName
497 OSL_ENSURE(
498 sal_False,
499 "HierarchyEntry::setData - caught ElementExistException!" );
501 catch ( lang::WrappedTargetException const & )
503 // replaceByName, insertByName, getByName, commitChanges
505 OSL_ENSURE(
506 sal_False,
507 "HierarchyEntry::setData - caught WrappedTargetException!" );
509 catch ( uno::Exception const & )
511 // createInstance, createInstanceWithArguments
513 OSL_ENSURE(
514 sal_False,
515 "HierarchyEntry::setData - caught Exception!" );
518 return sal_False;
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 )
530 return sal_True;
532 #if 0
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
539 #else
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 );
548 else
550 OSL_ENSURE( sal_False, "HierarchyEntry::move - Invalid URL!" );
551 return sal_False;
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 ),
564 uno::UNO_QUERY );
566 if ( !m_xConfigProvider.is() )
567 return sal_False;
569 rtl::OUString aOldParentPath;
570 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
571 if ( nPos != -1 )
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( '/' );
584 if ( nPos != -1 )
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 ) ),
607 aArguments ),
608 uno::UNO_QUERY );
610 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
612 if ( !xOldParentBatch.is() )
613 return sal_False;
615 if ( aOldParentPath == aNewParentPath )
617 bDifferentParents = sal_False;
618 xNewParentBatch = xOldParentBatch;
620 else
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 ) ),
633 aArguments ),
634 uno::UNO_QUERY );
636 OSL_ENSURE(
637 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
639 if ( !xNewParentBatch.is() )
640 return sal_False;
643 catch ( uno::RuntimeException const & )
645 throw;
647 catch ( uno::Exception const & )
649 // createInstance, createInstanceWithArguments
651 OSL_ENSURE( sal_False, "HierarchyEntry::move - caught Exception!" );
652 return sal_False;
655 //////////////////////////////////////////////////////////////////////
656 // (1) Get entry...
657 //////////////////////////////////////////////////////////////////////
659 uno::Any aEntry;
660 uno::Reference< container::XNameAccess > xOldParentNameAccess;
661 uno::Reference< container::XNameContainer > xOldNameContainer;
665 xOldParentNameAccess
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() )
673 return sal_False;
675 if ( bOldRoot )
677 xOldNameContainer = uno::Reference< container::XNameContainer >(
678 xOldParentNameAccess, uno::UNO_QUERY );
680 else
682 xOldParentNameAccess->getByName(
683 rtl::OUString::createFromAscii( "Children" ) )
684 >>= xOldNameContainer;
687 aEntry = xOldNameContainer->getByName( m_aName );
689 catch ( container::NoSuchElementException const & )
691 // getByName
693 OSL_ENSURE( sal_False,
694 "HierarchyEntry::move - caught NoSuchElementException!" );
695 return sal_False;
697 catch ( lang::WrappedTargetException const & )
699 // getByName
701 OSL_ENSURE( sal_False,
702 "HierarchyEntry::move - caught WrappedTargetException!" );
703 return sal_False;
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!" );
721 return sal_False;
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() )
737 return sal_False;
739 uno::Reference< container::XNameAccess > xNewParentNameAccess;
740 if ( bDifferentParents )
741 xNewParentNameAccess
742 = uno::Reference< container::XNameAccess >(
743 xNewParentBatch, uno::UNO_QUERY );
744 else
745 xNewParentNameAccess = xOldParentNameAccess;
747 OSL_ENSURE( xNewParentNameAccess.is(),
748 "HierarchyEntry::move - No name access!" );
750 if ( !xNewParentNameAccess.is() )
751 return sal_False;
753 uno::Reference< container::XNameContainer > xNewNameContainer;
754 if ( bDifferentParents )
756 if ( bNewRoot )
758 xNewNameContainer
759 = uno::Reference< container::XNameContainer >(
760 xNewParentNameAccess, uno::UNO_QUERY );
762 else
764 xNewParentNameAccess->getByName(
765 rtl::OUString::createFromAscii( "Children" ) )
766 >>= xNewNameContainer;
769 else
770 xNewNameContainer = xOldNameContainer;
772 if ( !xNewNameContainer.is() )
773 return sal_False;
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
783 // instead.
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!" );
804 return sal_False;
806 catch ( lang::IllegalArgumentException const & )
808 // replaceByName, insertByName
810 OSL_ENSURE(
811 sal_False,
812 "HierarchyEntry::move - caught IllegalArgumentException!" );
813 return sal_False;
815 catch ( container::ElementExistException const & )
817 // insertByName
819 OSL_ENSURE( sal_False,
820 "HierarchyEntry::move - caught ElementExistException!" );
821 return sal_False;
823 catch ( lang::WrappedTargetException const & )
825 // replaceByName, insertByName, getByName
827 OSL_ENSURE( sal_False,
828 "HierarchyEntry::move - caught WrappedTargetException!" );
829 return sal_False;
832 #if 0
833 //////////////////////////////////////////////////////////////////////
834 // (4) Commit changes...
835 //////////////////////////////////////////////////////////////////////
839 xNewParentBatch->commitChanges();
841 if ( bDifferentParents )
842 xOldParentBatch->commitChanges();
844 catch ( lang::WrappedTargetException const & )
846 // commitChanges
848 OSL_ENSURE( sal_False,
849 "HierarchyEntry::move - caught WrappedTargetException!" );
850 return sal_False;
852 #endif
854 return sal_True;
855 #endif
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 ),
868 uno::UNO_QUERY );
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( '/' );
878 if ( nPos != -1 )
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 );
887 bRoot = sal_False;
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 ) ),
902 aArguments ),
903 uno::UNO_QUERY );
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;
918 if ( bRoot )
920 // Special handling for children of root,
921 // which is not an entry. It's only a set
922 // of entries.
923 xContainer = uno::Reference< container::XNameContainer >(
924 xParentNameAccess, uno::UNO_QUERY );
926 else
928 // Append new entry to parents child list,
929 // which is a set of entries.
930 xParentNameAccess->getByName(
931 rtl::OUString::createFromAscii( "Children" ) )
932 >>= xContainer;
935 OSL_ENSURE( xContainer.is(),
936 "HierarchyEntry::remove - No container!" );
938 if ( xContainer.is() )
940 xContainer->removeByName( m_aName );
941 xBatch->commitChanges();
942 return sal_True;
947 catch ( uno::RuntimeException const & )
949 throw;
951 catch ( container::NoSuchElementException const & )
953 // getByName, removeByName
955 OSL_ENSURE(
956 sal_False,
957 "HierarchyEntry::remove - caught NoSuchElementException!" );
959 catch ( lang::WrappedTargetException const & )
961 // getByName, commitChanges
963 OSL_ENSURE(
964 sal_False,
965 "HierarchyEntry::remove - caught WrappedTargetException!" );
967 catch ( uno::Exception const & )
969 // createInstance, createInstanceWithArguments
971 OSL_ENSURE( sal_False,
972 "HierarchyEntry::remove - caught Exception!" );
975 return sal_False;
978 //=========================================================================
979 sal_Bool HierarchyEntry::first( iterator& it )
981 osl::Guard< osl::Mutex > aGuard( m_aMutex );
983 if ( it.m_pImpl->pos == -1 )
985 // Init...
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 )
1002 >>= xNameAccess;
1004 else
1005 xNameAccess
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 & )
1028 throw;
1030 catch ( container::NoSuchElementException const& )
1032 // getByHierarchicalName
1034 OSL_ENSURE(
1035 sal_False,
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 )
1046 return sal_False;
1048 it.m_pImpl->pos = 0;
1049 return sal_True;
1052 //=========================================================================
1053 sal_Bool HierarchyEntry::next( iterator& it )
1055 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1057 if ( it.m_pImpl->pos == -1 )
1058 return first( it );
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();
1076 if ( nLen )
1078 rtl::OUStringBuffer aNewPath;
1079 aNewPath.appendAscii( "['" );
1081 sal_Int32 nStart = 0;
1082 sal_Int32 nEnd = aPath.indexOf( '/' );
1086 if ( nEnd == -1 )
1087 nEnd = nLen;
1089 rtl::OUString aToken = aPath.copy( nStart, nEnd - nStart );
1090 makeXMLName( aToken, aNewPath );
1092 if ( nEnd != nLen )
1094 aNewPath.appendAscii( "']/Children/['" );
1095 nStart = nEnd + 1;
1096 nEnd = aPath.indexOf( '/', nStart );
1098 else
1099 aNewPath.appendAscii( "']" );
1101 while ( nEnd != nLen );
1103 return aNewPath.makeStringAndClear();
1106 return aPath;
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() )
1129 m_xConfigProvider
1130 = uno::Reference< lang::XMultiServiceFactory >(
1131 m_xSMgr->createInstance( m_aServiceSpecifier ),
1132 uno::UNO_QUERY );
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;
1147 m_xRootReadAccess
1148 = uno::Reference< container::XHierarchicalNameAccess >(
1149 m_xConfigProvider->createInstanceWithArguments(
1150 rtl::OUString(
1151 RTL_CONSTASCII_USTRINGPARAM(
1152 READ_SERVICE_NAME ) ),
1153 aArguments ),
1154 uno::UNO_QUERY );
1157 catch ( uno::RuntimeException const & )
1159 throw;
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()
1190 delete m_pImpl;
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.
1236 // Get Type value.
1237 sal_Int32 nType = 0;
1238 if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType )
1240 if ( nType == 0 )
1242 m_pImpl->entry.setType( HierarchyEntryData::LINK );
1244 else if ( nType == 1 )
1246 m_pImpl->entry.setType( HierarchyEntryData::FOLDER );
1248 else
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