LibreOffice Module ucb (master) 1
hierarchydata.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21/**************************************************************************
22 TODO
23 **************************************************************************
24
25 - HierarchyEntry::move
26 --> Rewrite to use XNamed ( once this is supported by config db api ).
27
28 *************************************************************************/
29#include "hierarchydata.hxx"
30
32#include <rtl/ustrbuf.hxx>
33#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
34#include <com/sun/star/container/XNameContainer.hpp>
35#include <com/sun/star/container/XNameReplace.hpp>
36#include <com/sun/star/util/XChangesBatch.hpp>
37#include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
38#include <com/sun/star/lang/XSingleServiceFactory.hpp>
40#include <utility>
41#include "hierarchyprovider.hxx"
42#include "hierarchyuri.hxx"
43
44using namespace com::sun::star;
45
46namespace hierarchy_ucp
47{
48
49
50static void makeXMLName( std::u16string_view rIn, OUStringBuffer & rBuffer )
51{
52 size_t nCount = rIn.size();
53 for ( size_t n = 0; n < nCount; ++n )
54 {
55 const sal_Unicode c = rIn[ n ];
56 switch ( c )
57 {
58 case '&':
59 rBuffer.append( "&amp;" );
60 break;
61
62 case '"':
63 rBuffer.append( "&quot;" );
64 break;
65
66 case '\'':
67 rBuffer.append( "&apos;" );
68 break;
69
70 case '<':
71 rBuffer.append( "&lt;" );
72 break;
73
74 case '>':
75 rBuffer.append( "&gt;" );
76 break;
77
78 default:
79 rBuffer.append( c );
80 break;
81 }
82 }
83}
84
85
86// HierarchyEntry Implementation.
87
88
89constexpr OUStringLiteral READ_SERVICE_NAME = u"com.sun.star.ucb.HierarchyDataReadAccess";
90constexpr OUStringLiteral READWRITE_SERVICE_NAME = u"com.sun.star.ucb.HierarchyDataReadWriteAccess";
91
92// describe path of cfg entry
93constexpr OUStringLiteral CFGPROPERTY_NODEPATH = u"nodepath";
94
95
97 uno::Reference< uno::XComponentContext > xContext,
98 HierarchyContentProvider* pProvider,
99 const OUString& rURL )
100: m_xContext(std::move( xContext )),
101 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
102 m_bTriedToGetRootReadAccess( false )
103{
104 HierarchyUri aUri( rURL );
106
111
112 // Note: do not init m_aPath in init list. createPathFromHierarchyURL
113 // needs m_xContext and m_aMutex.
115
116 // Extract language independent name from URL.
117 sal_Int32 nPos = rURL.lastIndexOf( '/' );
119 m_aName = rURL.copy( nPos + 1 );
120 else
121 OSL_FAIL( "HierarchyEntry - Invalid URL!" );
122}
123
124
126{
127 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
129
130 OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" );
131
132 if ( xRootReadAccess.is() )
133 return xRootReadAccess->hasByHierarchicalName( m_aPath );
134
135 return false;
136}
137
138
140{
141 try
142 {
143 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
145
146 OSL_ENSURE( xRootReadAccess.is(),
147 "HierarchyEntry::getData - No root!" );
148
149 if ( xRootReadAccess.is() )
150 {
151 OUString aTitlePath = m_aPath + "/Title";
152
153 // Note: Avoid NoSuchElementExceptions, because exceptions are
154 // relatively 'expensive'. Checking for availability of
155 // title value is sufficient here, because if it is
156 // there, the other values will be available too.
157 if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) )
158 return false;
159
160 OUString aValue;
161
162 // Get Title value.
163 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
164 >>= aValue ) )
165 {
166 OSL_FAIL( "HierarchyEntry::getData - "
167 "Got no Title value!" );
168 return false;
169 }
170
171 rData.setTitle( aValue );
172
173 // Get TargetURL value.
174 OUString aTargetURLPath = m_aPath + "/TargetURL";
175 if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath )
176 >>= aValue ) )
177 {
178 OSL_FAIL( "HierarchyEntry::getData - "
179 "Got no TargetURL value!" );
180 return false;
181 }
182
183 // TargetURL property may contain a reference to the Office
184 // installation directory. To ensure a reloctable office
185 // installation, the path to the office installation directory must
186 // never be stored directly. A placeholder is used instead. Replace
187 // it by actual installation directory.
188 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
189 aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue );
190 rData.setTargetURL( aValue );
191
192 OUString aTypePath = m_aPath + "/Type";
193 if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) )
194 {
195 // Might not be present since it was introduced long after
196 // Title and TargetURL (#82433#)... So not getting it is
197 // not an error.
198
199 // Get Type value.
200 sal_Int32 nType = 0;
201 if ( xRootReadAccess->getByHierarchicalName( aTypePath )
202 >>= nType )
203 {
204 if ( nType == 0 )
205 {
207 }
208 else if ( nType == 1 )
209 {
211 }
212 else
213 {
214 OSL_FAIL( "HierarchyEntry::getData - "
215 "Unknown Type value!" );
216 return false;
217 }
218 }
219 }
220
221 rData.setName( m_aName );
222 return true;
223 }
224 }
225 catch ( uno::RuntimeException const & )
226 {
227 throw;
228 }
229 catch ( container::NoSuchElementException const & )
230 {
231 // getByHierarchicalName
232
233 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
234 }
235 return false;
236}
237
238
240{
241 try
242 {
243 std::unique_lock aGuard( m_aMutex );
244
245 if ( !m_xConfigProvider.is() )
247 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
248 uno::UNO_QUERY );
249
250 if ( m_xConfigProvider.is() )
251 {
252 // Create parent's key. It must exist!
253
254 OUString aParentPath;
255 bool bRoot = true;
256
257 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
258 if ( nPos != -1 )
259 {
260 // Skip "/Children" segment of the path, too.
261 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
262
263 OSL_ENSURE( nPos != -1,
264 "HierarchyEntry::setData - Wrong path!" );
265
266 aParentPath += m_aPath.subView( 0, nPos );
267 bRoot = false;
268 }
269
270 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
271 {
272 {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)}
273 }));
274
275 uno::Reference< util::XChangesBatch > xBatch(
276 m_xConfigProvider->createInstanceWithArguments(
278 aArguments ),
279 uno::UNO_QUERY );
280
281 OSL_ENSURE( xBatch.is(),
282 "HierarchyEntry::setData - No batch!" );
283
284 uno::Reference< container::XNameAccess > xParentNameAccess(
285 xBatch, uno::UNO_QUERY );
286
287 OSL_ENSURE( xParentNameAccess.is(),
288 "HierarchyEntry::setData - No name access!" );
289
290 if ( xBatch.is() && xParentNameAccess.is() )
291 {
292 // Try to create own key. It must not exist!
293
294 bool bExists = true;
295 uno::Any aMyKey;
296
297 try
298 {
299 uno::Reference< container::XNameAccess > xNameAccess;
300
301 if ( bRoot )
302 {
303 xNameAccess = xParentNameAccess;
304 }
305 else
306 {
307 xParentNameAccess->getByName("Children") >>= xNameAccess;
308 }
309
310 if ( xNameAccess->hasByName( m_aName ) )
311 aMyKey = xNameAccess->getByName( m_aName );
312 else
313 bExists = false;
314 }
315 catch ( container::NoSuchElementException const & )
316 {
317 bExists = false;
318 }
319
320 uno::Reference< container::XNameReplace > xNameReplace;
321 uno::Reference< container::XNameContainer > xContainer;
322
323 if ( bExists )
324 {
325 // Key exists. Replace values.
326
327 aMyKey >>= xNameReplace;
328
329 OSL_ENSURE( xNameReplace.is(),
330 "HierarchyEntry::setData - No name replace!" );
331 }
332 else
333 {
334 // Key does not exist. Create / fill / insert it.
335
336 uno::Reference< lang::XSingleServiceFactory > xFac;
337
338 if ( bRoot )
339 {
340 // Special handling for children of root,
341 // which is not an entry. It's only a set
342 // of entries.
343 xFac.set( xParentNameAccess, uno::UNO_QUERY );
344 }
345 else
346 {
347 // Append new entry to parents child list,
348 // which is a set of entries.
349 xParentNameAccess->getByName("Children") >>= xFac;
350 }
351
352 OSL_ENSURE( xFac.is(),
353 "HierarchyEntry::setData - No factory!" );
354
355 if ( xFac.is() )
356 {
357 xNameReplace.set( xFac->createInstance(), uno::UNO_QUERY );
358
359 OSL_ENSURE( xNameReplace.is(),
360 "HierarchyEntry::setData - No name replace!" );
361
362 if ( xNameReplace.is() )
363 {
364 xContainer.set( xFac, uno::UNO_QUERY );
365
366 OSL_ENSURE( xContainer.is(),
367 "HierarchyEntry::setData - No container!" );
368 }
369 }
370 }
371
372 if ( xNameReplace.is() )
373 {
374 // Set Title value.
375 xNameReplace->replaceByName(
376 "Title",
377 uno::Any( rData.getTitle() ) );
378
379 // Set TargetURL value.
380
381 // TargetURL property may contain a reference to the Office
382 // installation directory. To ensure a reloctable office
383 // installation, the path to the office installation
384 // directory must never be stored directly. Use a
385 // placeholder instead.
386 OUString aValue( rData.getTargetURL() );
387 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
388 aValue
389 = m_xOfficeInstDirs->makeRelocatableURL( aValue );
390
391 xNameReplace->replaceByName(
392 "TargetURL",
393 uno::Any( aValue ) );
394
395 // Set Type value.
396 sal_Int32 nType
397 = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
398 xNameReplace->replaceByName(
399 "Type",
400 uno::Any( nType ) );
401
402 if ( xContainer.is() )
403 xContainer->insertByName(
404 m_aName, uno::Any( xNameReplace ) );
405
406 // Commit changes.
407 xBatch->commitChanges();
408 return true;
409 }
410 }
411 }
412 }
413 catch ( lang::IllegalArgumentException const & )
414 {
415 // replaceByName, insertByName
416
417 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
418 }
419 catch ( uno::RuntimeException const & )
420 {
421 throw;
422 }
423 catch ( container::NoSuchElementException const & )
424 {
425 // replaceByName, getByName
426
427 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
428 }
429 catch ( container::ElementExistException const & )
430 {
431 // insertByName
432
433 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
434 }
435 catch ( lang::WrappedTargetException const & )
436 {
437 // replaceByName, insertByName, getByName, commitChanges
438
439 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
440 }
441 catch ( uno::Exception const & )
442 {
443 // createInstance, createInstanceWithArguments
444
445 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
446 }
447
448 return false;
449}
450
451
453 const OUString& rNewURL, const HierarchyEntryData& rData )
454{
455 OUString aNewPath = createPathFromHierarchyURL( HierarchyUri(rNewURL) );
456
457 std::unique_lock aGuard( m_aMutex );
458
459 if ( aNewPath == m_aPath )
460 return true;
461
462 bool bOldRoot = true;
463 uno::Reference< util::XChangesBatch > xOldParentBatch;
464
465 OUString aNewKey;
466 sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' );
467 if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH )
468 aNewKey = rNewURL.copy( nURLPos + 1 );
469 else
470 {
471 OSL_FAIL( "HierarchyEntry::move - Invalid URL!" );
472 return false;
473 }
474
475 bool bNewRoot = true;
476 uno::Reference< util::XChangesBatch > xNewParentBatch;
477
478 bool bDifferentParents = true;
479
480 try
481 {
482 if ( !m_xConfigProvider.is() )
484 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
485 uno::UNO_QUERY );
486
487 if ( !m_xConfigProvider.is() )
488 return false;
489
490 OUString aOldParentPath;
491 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
492 if ( nPos != -1 )
493 {
494 // Skip "/Children" segment of the path, too.
495 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
496
497 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
498
499 aOldParentPath += m_aPath.subView( 0, nPos );
500 bOldRoot = false;
501 }
502
503 OUString aNewParentPath;
504 nPos = aNewPath.lastIndexOf( '/' );
505 if ( nPos != -1 )
506 {
507 // Skip "/Children" segment of the path, too.
508 nPos = aNewPath.lastIndexOf( '/', nPos - 1 );
509
510 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
511
512 aNewParentPath += aNewPath.subView( 0, nPos );
513 bNewRoot = false;
514 }
515
516 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
517 {
518 {CFGPROPERTY_NODEPATH, uno::Any(aOldParentPath)}
519 }));
520
521 xOldParentBatch.set(
522 m_xConfigProvider->createInstanceWithArguments(
524 aArguments ),
525 uno::UNO_QUERY );
526
527 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
528
529 if ( !xOldParentBatch.is() )
530 return false;
531
532 if ( aOldParentPath == aNewParentPath )
533 {
534 bDifferentParents = false;
535 xNewParentBatch = xOldParentBatch;
536 }
537 else
538 {
539 bDifferentParents = true;
540
541 uno::Sequence<uno::Any> aArguments2(comphelper::InitAnyPropertySequence(
542 {
543 {CFGPROPERTY_NODEPATH, uno::Any(aNewParentPath)}
544 }));
545
546 xNewParentBatch.set(
547 m_xConfigProvider->createInstanceWithArguments(
549 aArguments2 ),
550 uno::UNO_QUERY );
551
552 OSL_ENSURE(
553 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
554
555 if ( !xNewParentBatch.is() )
556 return false;
557 }
558 }
559 catch ( uno::RuntimeException const & )
560 {
561 throw;
562 }
563 catch ( uno::Exception const & )
564 {
565 // createInstance, createInstanceWithArguments
566
567 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
568 return false;
569 }
570
571
572 // (1) Get entry...
573
574
575 uno::Any aEntry;
576 uno::Reference< container::XNameAccess > xOldParentNameAccess;
577 uno::Reference< container::XNameContainer > xOldNameContainer;
578
579 try
580 {
581 xOldParentNameAccess.set( xOldParentBatch, uno::UNO_QUERY );
582
583 OSL_ENSURE( xOldParentNameAccess.is(),
584 "HierarchyEntry::move - No name access!" );
585
586 if ( !xOldParentNameAccess.is() )
587 return false;
588
589 if ( bOldRoot )
590 {
591 xOldNameContainer.set( xOldParentNameAccess, uno::UNO_QUERY );
592 }
593 else
594 {
595 xOldParentNameAccess->getByName("Children") >>= xOldNameContainer;
596 }
597
598 aEntry = xOldNameContainer->getByName( m_aName );
599 }
600 catch ( container::NoSuchElementException const & )
601 {
602 // getByName
603
604 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
605 return false;
606 }
607 catch ( lang::WrappedTargetException const & )
608 {
609 // getByName
610
611 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
612 return false;
613 }
614
615
616 // (2) Remove entry... Note: Insert BEFORE remove does not work!
617
618
619 try
620 {
621 xOldNameContainer->removeByName( m_aName );
622 xOldParentBatch->commitChanges();
623 }
624 catch ( container::NoSuchElementException const & )
625 {
626 // getByName, removeByName
627
628 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
629 return false;
630 }
631
632
633 // (3) Insert entry at new parent...
634
635
636 try
637 {
638 uno::Reference< container::XNameReplace > xNewNameReplace;
639 aEntry >>= xNewNameReplace;
640
641 OSL_ENSURE( xNewNameReplace.is(),
642 "HierarchyEntry::move - No name replace!" );
643
644 if ( !xNewNameReplace.is() )
645 return false;
646
647 uno::Reference< container::XNameAccess > xNewParentNameAccess;
648 if ( bDifferentParents )
649 xNewParentNameAccess.set( xNewParentBatch, uno::UNO_QUERY );
650 else
651 xNewParentNameAccess = xOldParentNameAccess;
652
653 OSL_ENSURE( xNewParentNameAccess.is(),
654 "HierarchyEntry::move - No name access!" );
655
656 if ( !xNewParentNameAccess.is() )
657 return false;
658
659 uno::Reference< container::XNameContainer > xNewNameContainer;
660 if ( bDifferentParents )
661 {
662 if ( bNewRoot )
663 {
664 xNewNameContainer.set( xNewParentNameAccess, uno::UNO_QUERY );
665 }
666 else
667 {
668 xNewParentNameAccess->getByName("Children") >>= xNewNameContainer;
669 }
670 }
671 else
672 xNewNameContainer = xOldNameContainer;
673
674 if ( !xNewNameContainer.is() )
675 return false;
676
677 xNewNameReplace->replaceByName(
678 "Title",
679 uno::Any( rData.getTitle() ) );
680
681 // TargetURL property may contain a reference to the Office
682 // installation directory. To ensure a reloctable office
683 // installation, the path to the office installation
684 // directory must never be stored directly. Use a placeholder
685 // instead.
686 OUString aValue( rData.getTargetURL() );
687 if ( m_xOfficeInstDirs.is() && !aValue.isEmpty() )
688 aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue );
689 xNewNameReplace->replaceByName(
690 "TargetURL",
691 uno::Any( aValue ) );
692 sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
693 xNewNameReplace->replaceByName(
694 "Type",
695 uno::Any( nType ) );
696
697 xNewNameContainer->insertByName( aNewKey, aEntry );
698 xNewParentBatch->commitChanges();
699 }
700 catch ( container::NoSuchElementException const & )
701 {
702 // replaceByName, insertByName, getByName
703
704 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
705 return false;
706 }
707 catch ( lang::IllegalArgumentException const & )
708 {
709 // replaceByName, insertByName
710
711 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
712 return false;
713 }
714 catch ( container::ElementExistException const & )
715 {
716 // insertByName
717
718 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
719 return false;
720 }
721 catch ( lang::WrappedTargetException const & )
722 {
723 // replaceByName, insertByName, getByName
724
725 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
726 return false;
727 }
728
729 return true;
730}
731
732
734{
735 try
736 {
737 std::unique_lock aGuard( m_aMutex );
738
739 if ( !m_xConfigProvider.is() )
741 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
742 uno::UNO_QUERY );
743
744 if ( m_xConfigProvider.is() )
745 {
746 // Create parent's key. It must exist!
747
748 OUString aParentPath;
749 bool bRoot = true;
750
751 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
752 if ( nPos != -1 )
753 {
754 // Skip "/Children" segment of the path, too.
755 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
756
757 OSL_ENSURE( nPos != -1,
758 "HierarchyEntry::remove - Wrong path!" );
759
760 aParentPath += m_aPath.subView( 0, nPos );
761 bRoot = false;
762 }
763
764 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
765 {
766 {CFGPROPERTY_NODEPATH, uno::Any(aParentPath)}
767 }));
768
769 uno::Reference< util::XChangesBatch > xBatch(
770 m_xConfigProvider->createInstanceWithArguments(
772 aArguments ),
773 uno::UNO_QUERY );
774
775 OSL_ENSURE( xBatch.is(),
776 "HierarchyEntry::remove - No batch!" );
777
778 uno::Reference< container::XNameAccess > xParentNameAccess(
779 xBatch, uno::UNO_QUERY );
780
781 OSL_ENSURE( xParentNameAccess.is(),
782 "HierarchyEntry::remove - No name access!" );
783
784 if ( xBatch.is() && xParentNameAccess.is() )
785 {
786 uno::Reference< container::XNameContainer > xContainer;
787
788 if ( bRoot )
789 {
790 // Special handling for children of root,
791 // which is not an entry. It's only a set
792 // of entries.
793 xContainer.set( xParentNameAccess, uno::UNO_QUERY );
794 }
795 else
796 {
797 // Append new entry to parents child list,
798 // which is a set of entries.
799 xParentNameAccess->getByName("Children") >>= xContainer;
800 }
801
802 OSL_ENSURE( xContainer.is(),
803 "HierarchyEntry::remove - No container!" );
804
805 if ( xContainer.is() )
806 {
807 xContainer->removeByName( m_aName );
808 xBatch->commitChanges();
809 return true;
810 }
811 }
812 }
813 }
814 catch ( uno::RuntimeException const & )
815 {
816 throw;
817 }
818 catch ( container::NoSuchElementException const & )
819 {
820 // getByName, removeByName
821
822 OSL_FAIL(
823 "HierarchyEntry::remove - caught NoSuchElementException!" );
824 }
825 catch ( lang::WrappedTargetException const & )
826 {
827 // getByName, commitChanges
828
829 OSL_FAIL(
830 "HierarchyEntry::remove - caught WrappedTargetException!" );
831 }
832 catch ( uno::Exception const & )
833 {
834 // createInstance, createInstanceWithArguments
835
836 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
837 }
838
839 return false;
840}
841
842
844{
845 if ( it.pos == -1 )
846 {
847 // Init...
848
849 try
850 {
851 uno::Reference< container::XHierarchicalNameAccess >
852 xRootHierNameAccess = getRootReadAccess();
853
854 if ( xRootHierNameAccess.is() )
855 {
856 uno::Reference< container::XNameAccess > xNameAccess;
857
858 if ( !m_aPath.isEmpty() )
859 {
860 OUString aPath = m_aPath + "/Children";
861
862 xRootHierNameAccess->getByHierarchicalName( aPath )
863 >>= xNameAccess;
864 }
865 else
866 xNameAccess.set( xRootHierNameAccess, uno::UNO_QUERY );
867
868 OSL_ENSURE( xNameAccess.is(),
869 "HierarchyEntry::first - No name access!" );
870
871 if ( xNameAccess.is() )
872 it.names = xNameAccess->getElementNames();
873
874 uno::Reference< container::XHierarchicalNameAccess >
875 xHierNameAccess( xNameAccess, uno::UNO_QUERY );
876
877 OSL_ENSURE( xHierNameAccess.is(),
878 "HierarchyEntry::first - No hier. name access!" );
879
880 it.dir = xHierNameAccess;
881
883 }
884 }
885 catch ( uno::RuntimeException const & )
886 {
887 throw;
888 }
889 catch ( container::NoSuchElementException const& )
890 {
891 // getByHierarchicalName
892
893 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
894 }
895 catch ( uno::Exception const & )
896 {
897 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
898 }
899 }
900
901 if ( !it.names.hasElements() )
902 return false;
903
904 it.pos = 0;
905 return true;
906}
907
908
910{
911 if ( it.pos == -1 )
912 return first( it );
913
914 ++it.pos;
915
916 return ( it.pos < it.names.getLength() );
917}
918
919
921 const HierarchyUri& rURI )
922{
923 // Transform path...
924 // folder/subfolder/subsubfolder
925 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
926
927 const OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash.
928 sal_Int32 nLen = aPath.getLength();
929
930 if ( nLen )
931 {
932 OUStringBuffer aNewPath( "['" );
933
934 sal_Int32 nStart = 0;
935 sal_Int32 nEnd = aPath.indexOf( '/' );
936
937 do
938 {
939 if ( nEnd == -1 )
940 nEnd = nLen;
941
942 OUString aToken = aPath.copy( nStart, nEnd - nStart );
943 makeXMLName( aToken, aNewPath );
944
945 if ( nEnd != nLen )
946 {
947 aNewPath.append( "']/Children/['" );
948 nStart = nEnd + 1;
949 nEnd = aPath.indexOf( '/', nStart );
950 }
951 else
952 aNewPath.append( "']" );
953 }
954 while ( nEnd != nLen );
955
956 return aNewPath.makeStringAndClear();
957 }
958
959 return aPath;
960}
961
962
963uno::Reference< container::XHierarchicalNameAccess >
965{
966 if ( !m_xRootReadAccess.is() )
967 {
968 std::unique_lock aGuard( m_aMutex );
969 if ( !m_xRootReadAccess.is() )
970 {
972 {
973 OSL_FAIL( "HierarchyEntry::getRootReadAccess - "
974 "Unable to read any config data! -> #82494#" );
975 return uno::Reference< container::XHierarchicalNameAccess >();
976 }
977
978 try
979 {
980 if ( !m_xConfigProvider.is() )
982 m_xContext->getServiceManager()->createInstanceWithContext(m_aServiceSpecifier, m_xContext),
983 uno::UNO_QUERY );
984
985 if ( m_xConfigProvider.is() )
986 {
987 // Create Root object.
988
989 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
990 {
991 {CFGPROPERTY_NODEPATH, uno::Any(OUString())} // root path
992 }));
993
995
997 m_xConfigProvider->createInstanceWithArguments(
999 aArguments ),
1000 uno::UNO_QUERY );
1001 }
1002 }
1003 catch ( uno::RuntimeException const & )
1004 {
1005 throw;
1006 }
1007 catch ( uno::Exception const & )
1008 {
1009 // createInstance, createInstanceWithArguments
1010
1011 TOOLS_WARN_EXCEPTION("ucb.ucp", "");
1012 }
1013 }
1014 }
1015 return m_xRootReadAccess;
1016}
1017
1018
1019// HierarchyEntry::iterator Implementation.
1020
1021
1023{
1024 if ( ( pos != -1 )
1025 && ( dir.is() )
1026 && ( pos < names.getLength() ) )
1027 {
1028 try
1029 {
1030 OUStringBuffer aKey( "['" );
1031 makeXMLName( names.getConstArray()[ pos ], aKey );
1032 aKey.append( "']" );
1033
1034 OUString aTitle = aKey.makeStringAndClear();
1035 OUString aTargetURL = aTitle;
1036 OUString aType = aTitle;
1037
1038 aTitle += "/Title";
1039 aTargetURL += "/TargetURL";
1040 aType += "/Type";
1041
1042 OUString aValue;
1043 dir->getByHierarchicalName( aTitle ) >>= aValue;
1044 entry.setTitle( aValue );
1045
1046 dir->getByHierarchicalName( aTargetURL ) >>= aValue;
1047
1048 // TargetURL property may contain a reference to the Office
1049 // installation directory. To ensure a reloctable office
1050 // installation, the path to the office installation directory must
1051 // never be stored directly. A placeholder is used instead. Replace
1052 // it by actual installation directory.
1053 if ( officeDirs.is() && !aValue.isEmpty() )
1054 aValue = officeDirs->makeAbsoluteURL( aValue );
1055 entry.setTargetURL( aValue );
1056
1057 if ( dir->hasByHierarchicalName( aType ) )
1058 {
1059 // Might not be present since it was introduced long
1060 // after Title and TargetURL (#82433#)... So not getting
1061 // it is not an error.
1062
1063 // Get Type value.
1064 sal_Int32 nType = 0;
1065 if ( dir->getByHierarchicalName( aType ) >>= nType )
1066 {
1067 if ( nType == 0 )
1068 {
1070 }
1071 else if ( nType == 1 )
1072 {
1074 }
1075 else
1076 {
1077 OSL_FAIL( "HierarchyEntry::getData - "
1078 "Unknown Type value!" );
1079 }
1080 }
1081 }
1082
1083 entry.setName(
1084 names.getConstArray()[ pos ] );
1085 }
1086 catch ( container::NoSuchElementException const & )
1087 {
1089 }
1090 }
1091
1092 return entry;
1093}
1094
1095} // namespace hierarchy_ucp
1096
1097/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
css::uno::Reference< css::lang::XMultiServiceFactory > getConfigProvider(const OUString &rServiceSpecifier)
css::uno::Reference< css::container::XHierarchicalNameAccess > getRootConfigReadNameAccess(const OUString &rServiceSpecifier)
void setName(const OUString &rName)
void setTargetURL(const OUString &rURL)
const OUString & getTitle() const
void setTitle(const OUString &rTitle)
void setType(const Type &rType)
const OUString & getTargetURL() const
css::uno::Sequence< OUString > names
css::uno::Reference< css::container::XHierarchicalNameAccess > dir
const HierarchyEntryData & operator*()
css::uno::Reference< css::util::XOfficeInstallationDirectories > officeDirs
css::uno::Reference< css::container::XHierarchicalNameAccess > m_xRootReadAccess
css::uno::Reference< css::uno::XComponentContext > m_xContext
bool move(const OUString &rNewURL, const HierarchyEntryData &rData)
HierarchyEntry(css::uno::Reference< css::uno::XComponentContext > xContext, HierarchyContentProvider *pProvider, const OUString &rURL)
css::uno::Reference< css::lang::XMultiServiceFactory > m_xConfigProvider
css::uno::Reference< css::container::XHierarchicalNameAccess > getRootReadAccess()
bool setData(const HierarchyEntryData &rData)
bool getData(HierarchyEntryData &rData)
static OUString createPathFromHierarchyURL(const HierarchyUri &rURI)
css::uno::Reference< css::util::XOfficeInstallationDirectories > m_xOfficeInstDirs
const OUString & getService() const
const OUString & getPath() const
int nCount
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
#define HIERARCHY_URL_SCHEME_LENGTH
Sequence< PropertyValue > aArguments
sal_Int64 n
sal_uInt16 nPos
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
static void makeXMLName(std::u16string_view rIn, OUStringBuffer &rBuffer)
constexpr OUStringLiteral READWRITE_SERVICE_NAME
constexpr OUStringLiteral CFGPROPERTY_NODEPATH
constexpr OUStringLiteral READ_SERVICE_NAME
QPRO_FUNC_TYPE nType
uno::Reference< util::XOfficeInstallationDirectories > m_xOfficeInstDirs
sal_uInt16 sal_Unicode
OUString aTargetURL