1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_hier.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 - HierarchyEntry::move
32 --> Rewrite to use XNamed ( once this is supported by config db api ).
33
34 *************************************************************************/
35 #include "hierarchydata.hxx"
36
37 #include <vector>
38 #include <osl/diagnose.h>
39 #include <rtl/ustrbuf.hxx>
40 #include <com/sun/star/beans/PropertyValue.hpp>
41 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
42 #include <com/sun/star/container/XNameContainer.hpp>
43 #include <com/sun/star/container/XNameReplace.hpp>
44 #include <com/sun/star/util/XChangesBatch.hpp>
45 #ifndef _COM_SUN_STAR_UTIL_XOFFICEINSTALLTIONDIRECTORIES_HPP_
46 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp>
47 #endif
48 #include "hierarchyprovider.hxx"
49 #include "hierarchyuri.hxx"
50
51 using namespace com::sun::star;
52
53 namespace hierarchy_ucp
54 {
55
56 //=========================================================================
57 struct HierarchyEntry::iterator_Impl
58 {
59 HierarchyEntryData entry;
60 uno::Reference< container::XHierarchicalNameAccess > dir;
61 uno::Reference< util::XOfficeInstallationDirectories > officeDirs;
62 uno::Sequence< rtl::OUString> names;
63 sal_Int32 pos;
iterator_Implhierarchy_ucp::HierarchyEntry::iterator_Impl64 iterator_Impl()
65 : officeDirs( 0 ), pos( -1 /* before first */ ) {};
66 };
67
68 //=========================================================================
makeXMLName(const rtl::OUString & rIn,rtl::OUStringBuffer & rBuffer)69 void makeXMLName( const rtl::OUString & rIn, rtl::OUStringBuffer & rBuffer )
70 {
71 sal_Int32 nCount = rIn.getLength();
72 for ( sal_Int32 n = 0; n < nCount; ++n )
73 {
74 const sal_Unicode c = rIn.getStr()[ n ];
75 switch ( c )
76 {
77 case '&':
78 rBuffer.appendAscii( "&" );
79 break;
80
81 case '"':
82 rBuffer.appendAscii( """ );
83 break;
84
85 case '\'':
86 rBuffer.appendAscii( "'" );
87 break;
88
89 case '<':
90 rBuffer.appendAscii( "<" );
91 break;
92
93 case '>':
94 rBuffer.appendAscii( ">" );
95 break;
96
97 default:
98 rBuffer.append( c );
99 break;
100 }
101 }
102 }
103
104 //=========================================================================
105 //=========================================================================
106 //
107 // HierarchyEntry Implementation.
108 //
109 //=========================================================================
110 //=========================================================================
111
112 #define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess"
113 #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
114
115 // describe path of cfg entry
116 #define CFGPROPERTY_NODEPATH "nodepath"
117
118 //=========================================================================
HierarchyEntry(const uno::Reference<lang::XMultiServiceFactory> & rSMgr,HierarchyContentProvider * pProvider,const rtl::OUString & rURL)119 HierarchyEntry::HierarchyEntry(
120 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
121 HierarchyContentProvider* pProvider,
122 const rtl::OUString& rURL )
123 : m_xSMgr( rSMgr ),
124 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ),
125 m_bTriedToGetRootReadAccess( sal_False )
126 {
127 HierarchyUri aUri( rURL );
128 m_aServiceSpecifier = aUri.getService();
129
130 if ( pProvider )
131 {
132 m_xConfigProvider
133 = pProvider->getConfigProvider( m_aServiceSpecifier );
134 m_xRootReadAccess
135 = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier );
136 }
137
138 // Note: do not init m_aPath in init list. createPathFromHierarchyURL
139 // needs m_xSMgr and m_aMutex.
140 m_aPath = createPathFromHierarchyURL( aUri );
141
142 // Extract language independent name from URL.
143 sal_Int32 nPos = rURL.lastIndexOf( '/' );
144 if ( nPos > HIERARCHY_URL_SCHEME_LENGTH )
145 m_aName = rURL.copy( nPos + 1 );
146 else
147 OSL_ENSURE( sal_False, "HierarchyEntry - Invalid URL!" );
148 }
149
150 //=========================================================================
hasData()151 sal_Bool HierarchyEntry::hasData()
152 {
153 osl::Guard< osl::Mutex > aGuard( m_aMutex );
154 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
155 = getRootReadAccess();
156
157 OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" );
158
159 if ( xRootReadAccess.is() )
160 return xRootReadAccess->hasByHierarchicalName( m_aPath );
161
162 return sal_False;
163 }
164
165 //=========================================================================
getData(HierarchyEntryData & rData)166 sal_Bool HierarchyEntry::getData( HierarchyEntryData& rData )
167 {
168 try
169 {
170 osl::Guard< osl::Mutex > aGuard( m_aMutex );
171
172 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess
173 = getRootReadAccess();
174
175 OSL_ENSURE( xRootReadAccess.is(),
176 "HierarchyEntry::getData - No root!" );
177
178 if ( xRootReadAccess.is() )
179 {
180 rtl::OUString aTitlePath = m_aPath;
181 aTitlePath += rtl::OUString::createFromAscii( "/Title" );
182
183 // Note: Avoid NoSuchElementExceptions, because exceptions are
184 // relatively 'expensive'. Checking for availability of
185 // title value is sufficient here, because if it is
186 // there, the other values will be available too.
187 if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) )
188 return sal_False;
189
190 rtl::OUString aValue;
191
192 // Get Title value.
193 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath )
194 >>= aValue ) )
195 {
196 OSL_ENSURE( sal_False,
197 "HierarchyEntry::getData - "
198 "Got no Title value!" );
199 return sal_False;
200 }
201
202 rData.setTitle( aValue );
203
204 // Get TargetURL value.
205 rtl::OUString aTargetURLPath = m_aPath;
206 aTargetURLPath += rtl::OUString::createFromAscii( "/TargetURL" );
207 if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath )
208 >>= aValue ) )
209 {
210 OSL_ENSURE( sal_False,
211 "HierarchyEntry::getData - "
212 "Got no TargetURL value!" );
213 return sal_False;
214 }
215
216 // TargetURL property may contain a reference to the Office
217 // installation directory. To ensure a reloctable office
218 // installation, the path to the office installtion directory must
219 // never be stored directly. A placeholder is used instead. Replace
220 // it by actual installation directory.
221 if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) )
222 aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue );
223 rData.setTargetURL( aValue );
224
225 rtl::OUString aTypePath = m_aPath;
226 aTypePath += rtl::OUString::createFromAscii( "/Type" );
227 if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) )
228 {
229 // Might not be present since it was introduced long after
230 // Title and TargetURL (#82433#)... So not getting it is
231 // not an error.
232
233 // Get Type value.
234 sal_Int32 nType = 0;
235 if ( xRootReadAccess->getByHierarchicalName( aTypePath )
236 >>= nType )
237 {
238 if ( nType == 0 )
239 {
240 rData.setType( HierarchyEntryData::LINK );
241 }
242 else if ( nType == 1 )
243 {
244 rData.setType( HierarchyEntryData::FOLDER );
245 }
246 else
247 {
248 OSL_ENSURE( sal_False,
249 "HierarchyEntry::getData - "
250 "Unknown Type value!" );
251 return sal_False;
252 }
253 }
254 }
255
256 rData.setName( m_aName );
257 return sal_True;
258 }
259 }
260 catch ( uno::RuntimeException const & )
261 {
262 throw;
263 }
264 catch ( container::NoSuchElementException const & )
265 {
266 // getByHierarchicalName
267
268 OSL_ENSURE( sal_False,
269 "HierarchyEntry::getData - caught NoSuchElementException!" );
270 }
271 return sal_False;
272 }
273
274 //=========================================================================
setData(const HierarchyEntryData & rData,sal_Bool bCreate)275 sal_Bool HierarchyEntry::setData(
276 const HierarchyEntryData& rData, sal_Bool bCreate )
277 {
278 try
279 {
280 osl::Guard< osl::Mutex > aGuard( m_aMutex );
281
282 if ( !m_xConfigProvider.is() )
283 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
284 m_xSMgr->createInstance( m_aServiceSpecifier ),
285 uno::UNO_QUERY );
286
287 if ( m_xConfigProvider.is() )
288 {
289 // Create parent's key. It must exist!
290
291 rtl::OUString aParentPath;
292 sal_Bool bRoot = sal_True;
293
294 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
295 if ( nPos != -1 )
296 {
297 // Skip "/Children" segment of the path, too.
298 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
299
300 OSL_ENSURE( nPos != -1,
301 "HierarchyEntry::setData - Wrong path!" );
302
303 aParentPath += m_aPath.copy( 0, nPos );
304 bRoot = sal_False;
305 }
306
307 uno::Sequence< uno::Any > aArguments( 1 );
308 beans::PropertyValue aProperty;
309
310 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
311 CFGPROPERTY_NODEPATH ) );
312 aProperty.Value <<= aParentPath;
313 aArguments[ 0 ] <<= aProperty;
314
315 uno::Reference< util::XChangesBatch > xBatch(
316 m_xConfigProvider->createInstanceWithArguments(
317 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
318 READWRITE_SERVICE_NAME ) ),
319 aArguments ),
320 uno::UNO_QUERY );
321
322 OSL_ENSURE( xBatch.is(),
323 "HierarchyEntry::setData - No batch!" );
324
325 uno::Reference< container::XNameAccess > xParentNameAccess(
326 xBatch, uno::UNO_QUERY );
327
328 OSL_ENSURE( xParentNameAccess.is(),
329 "HierarchyEntry::setData - No name access!" );
330
331 if ( xBatch.is() && xParentNameAccess.is() )
332 {
333 // Try to create own key. It must not exist!
334
335 sal_Bool bExists = sal_True;
336 uno::Any aMyKey;
337
338 try
339 {
340 uno::Reference< container::XNameAccess > xNameAccess;
341
342 if ( bRoot )
343 {
344 xNameAccess = xParentNameAccess;
345 }
346 else
347 {
348 xParentNameAccess->getByName(
349 rtl::OUString::createFromAscii( "Children" ) )
350 >>= xNameAccess;
351 }
352
353 if ( xNameAccess->hasByName( m_aName ) )
354 aMyKey = xNameAccess->getByName( m_aName );
355 else
356 bExists = sal_False;
357 }
358 catch ( container::NoSuchElementException const & )
359 {
360 bExists = sal_False;
361 }
362
363 uno::Reference< container::XNameReplace > xNameReplace;
364 uno::Reference< container::XNameContainer > xContainer;
365
366 if ( bExists )
367 {
368 // Key exists. Replace values.
369
370 aMyKey >>= xNameReplace;
371
372 OSL_ENSURE( xNameReplace.is(),
373 "HierarchyEntry::setData - No name replace!" );
374 }
375 else
376 {
377 if ( !bCreate )
378 return sal_True;
379
380 // Key does not exist. Create / fill / insert it.
381
382 uno::Reference< lang::XSingleServiceFactory > xFac;
383
384 if ( bRoot )
385 {
386 // Special handling for children of root,
387 // which is not an entry. It's only a set
388 // of entries.
389 xFac = uno::Reference< lang::XSingleServiceFactory >(
390 xParentNameAccess, uno::UNO_QUERY );
391 }
392 else
393 {
394 // Append new entry to parents child list,
395 // which is a set of entries.
396 xParentNameAccess->getByName(
397 rtl::OUString::createFromAscii(
398 "Children" ) ) >>= xFac;
399 }
400
401 OSL_ENSURE( xFac.is(),
402 "HierarchyEntry::setData - No factory!" );
403
404 if ( xFac.is() )
405 {
406 xNameReplace
407 = uno::Reference< container::XNameReplace >(
408 xFac->createInstance(), uno::UNO_QUERY );
409
410 OSL_ENSURE( xNameReplace.is(),
411 "HierarchyEntry::setData - No name replace!" );
412
413 if ( xNameReplace.is() )
414 {
415 xContainer
416 = uno::Reference< container::XNameContainer >(
417 xFac, uno::UNO_QUERY );
418
419 OSL_ENSURE( xContainer.is(),
420 "HierarchyEntry::setData - No container!" );
421 }
422 }
423 }
424
425 if ( xNameReplace.is() )
426 {
427 // Set Title value.
428 xNameReplace->replaceByName(
429 rtl::OUString::createFromAscii( "Title" ),
430 uno::makeAny( rData.getTitle() ) );
431
432 // Set TargetURL value.
433
434 // TargetURL property may contain a reference to the Office
435 // installation directory. To ensure a reloctable office
436 // installation, the path to the office installtion
437 // directory must never be stored directly. Use a
438 // placeholder instead.
439 rtl::OUString aValue( rData.getTargetURL() );
440 if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) )
441 aValue
442 = m_xOfficeInstDirs->makeRelocatableURL( aValue );
443
444 xNameReplace->replaceByName(
445 rtl::OUString::createFromAscii( "TargetURL" ),
446 uno::makeAny( aValue ) );
447
448 // Set Type value.
449 sal_Int32 nType
450 = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
451 xNameReplace->replaceByName(
452 rtl::OUString::createFromAscii( "Type" ),
453 uno::makeAny( nType ) );
454
455 if ( xContainer.is() )
456 xContainer->insertByName(
457 m_aName, uno::makeAny( xNameReplace ) );
458
459 // Commit changes.
460 xBatch->commitChanges();
461 return sal_True;
462 }
463 }
464 }
465 }
466 catch ( uno::RuntimeException const & )
467 {
468 throw;
469 }
470 catch ( lang::IllegalArgumentException const & )
471 {
472 // replaceByName, insertByName
473
474 OSL_ENSURE(
475 sal_False,
476 "HierarchyEntry::setData - caught IllegalArgumentException!" );
477 }
478 catch ( container::NoSuchElementException const & )
479 {
480 // replaceByName, getByName
481
482 OSL_ENSURE(
483 sal_False,
484 "HierarchyEntry::setData - caught NoSuchElementException!" );
485 }
486 catch ( container::ElementExistException const & )
487 {
488 // insertByName
489
490 OSL_ENSURE(
491 sal_False,
492 "HierarchyEntry::setData - caught ElementExistException!" );
493 }
494 catch ( lang::WrappedTargetException const & )
495 {
496 // replaceByName, insertByName, getByName, commitChanges
497
498 OSL_ENSURE(
499 sal_False,
500 "HierarchyEntry::setData - caught WrappedTargetException!" );
501 }
502 catch ( uno::Exception const & )
503 {
504 // createInstance, createInstanceWithArguments
505
506 OSL_ENSURE(
507 sal_False,
508 "HierarchyEntry::setData - caught Exception!" );
509 }
510
511 return sal_False;
512 }
513
514 //=========================================================================
move(const rtl::OUString & rNewURL,const HierarchyEntryData & rData)515 sal_Bool HierarchyEntry::move(
516 const rtl::OUString& rNewURL, const HierarchyEntryData& rData )
517 {
518 osl::Guard< osl::Mutex > aGuard( m_aMutex );
519
520 rtl::OUString aNewPath = createPathFromHierarchyURL( rNewURL );
521
522 if ( aNewPath == m_aPath )
523 return sal_True;
524
525 #if 0
526 // In the "near future"... ( not yet implemented in config db )
527
528 - get update access for m_aPath
529 - update access -> XNamed
530 - xNamed::setName( newName )
531 - updateaccess commit
532 #else
533
534 sal_Bool bOldRoot = sal_True;
535 uno::Reference< util::XChangesBatch > xOldParentBatch;
536
537 rtl::OUString aNewKey;
538 sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' );
539 if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH )
540 aNewKey = rNewURL.copy( nURLPos + 1 );
541 else
542 {
543 OSL_ENSURE( sal_False, "HierarchyEntry::move - Invalid URL!" );
544 return sal_False;
545 }
546
547 sal_Bool bNewRoot = sal_True;
548 uno::Reference< util::XChangesBatch > xNewParentBatch;
549
550 sal_Bool bDifferentParents = sal_True;
551
552 try
553 {
554 if ( !m_xConfigProvider.is() )
555 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
556 m_xSMgr->createInstance( m_aServiceSpecifier ),
557 uno::UNO_QUERY );
558
559 if ( !m_xConfigProvider.is() )
560 return sal_False;
561
562 rtl::OUString aOldParentPath;
563 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
564 if ( nPos != -1 )
565 {
566 // Skip "/Children" segment of the path, too.
567 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
568
569 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
570
571 aOldParentPath += m_aPath.copy( 0, nPos );
572 bOldRoot = sal_False;
573 }
574
575 rtl::OUString aNewParentPath;
576 nPos = aNewPath.lastIndexOf( '/' );
577 if ( nPos != -1 )
578 {
579 // Skip "/Children" segment of the path, too.
580 nPos = aNewPath.lastIndexOf( '/', nPos - 1 );
581
582 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" );
583
584 aNewParentPath += aNewPath.copy( 0, nPos );
585 bNewRoot = sal_False;
586 }
587
588 uno::Sequence< uno::Any > aArguments( 1 );
589 beans::PropertyValue aProperty;
590
591 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
592 CFGPROPERTY_NODEPATH ) );
593 aProperty.Value <<= aOldParentPath;
594 aArguments[ 0 ] <<= aProperty;
595
596 xOldParentBatch = uno::Reference< util::XChangesBatch >(
597 m_xConfigProvider->createInstanceWithArguments(
598 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
599 READWRITE_SERVICE_NAME ) ),
600 aArguments ),
601 uno::UNO_QUERY );
602
603 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" );
604
605 if ( !xOldParentBatch.is() )
606 return sal_False;
607
608 if ( aOldParentPath == aNewParentPath )
609 {
610 bDifferentParents = sal_False;
611 xNewParentBatch = xOldParentBatch;
612 }
613 else
614 {
615 bDifferentParents = sal_True;
616
617 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
618 CFGPROPERTY_NODEPATH ) );
619 aProperty.Value <<= aNewParentPath;
620 aArguments[ 0 ] <<= aProperty;
621
622 xNewParentBatch = uno::Reference< util::XChangesBatch >(
623 m_xConfigProvider->createInstanceWithArguments(
624 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
625 READWRITE_SERVICE_NAME ) ),
626 aArguments ),
627 uno::UNO_QUERY );
628
629 OSL_ENSURE(
630 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" );
631
632 if ( !xNewParentBatch.is() )
633 return sal_False;
634 }
635 }
636 catch ( uno::RuntimeException const & )
637 {
638 throw;
639 }
640 catch ( uno::Exception const & )
641 {
642 // createInstance, createInstanceWithArguments
643
644 OSL_ENSURE( sal_False, "HierarchyEntry::move - caught Exception!" );
645 return sal_False;
646 }
647
648 //////////////////////////////////////////////////////////////////////
649 // (1) Get entry...
650 //////////////////////////////////////////////////////////////////////
651
652 uno::Any aEntry;
653 uno::Reference< container::XNameAccess > xOldParentNameAccess;
654 uno::Reference< container::XNameContainer > xOldNameContainer;
655
656 try
657 {
658 xOldParentNameAccess
659 = uno::Reference< container::XNameAccess >(
660 xOldParentBatch, uno::UNO_QUERY );
661
662 OSL_ENSURE( xOldParentNameAccess.is(),
663 "HierarchyEntry::move - No name access!" );
664
665 if ( !xOldParentNameAccess.is() )
666 return sal_False;
667
668 if ( bOldRoot )
669 {
670 xOldNameContainer = uno::Reference< container::XNameContainer >(
671 xOldParentNameAccess, uno::UNO_QUERY );
672 }
673 else
674 {
675 xOldParentNameAccess->getByName(
676 rtl::OUString::createFromAscii( "Children" ) )
677 >>= xOldNameContainer;
678 }
679
680 aEntry = xOldNameContainer->getByName( m_aName );
681 }
682 catch ( container::NoSuchElementException const & )
683 {
684 // getByName
685
686 OSL_ENSURE( sal_False,
687 "HierarchyEntry::move - caught NoSuchElementException!" );
688 return sal_False;
689 }
690 catch ( lang::WrappedTargetException const & )
691 {
692 // getByName
693
694 OSL_ENSURE( sal_False,
695 "HierarchyEntry::move - caught WrappedTargetException!" );
696 return sal_False;
697 }
698
699 //////////////////////////////////////////////////////////////////////
700 // (2) Remove entry... Note: Insert BEFORE remove does not work!
701 //////////////////////////////////////////////////////////////////////
702
703 try
704 {
705 xOldNameContainer->removeByName( m_aName );
706 xOldParentBatch->commitChanges();
707 }
708 catch ( container::NoSuchElementException const & )
709 {
710 // getByName, removeByName
711
712 OSL_ENSURE( sal_False,
713 "HierarchyEntry::move - caught NoSuchElementException!" );
714 return sal_False;
715 }
716
717 //////////////////////////////////////////////////////////////////////
718 // (3) Insert entry at new parent...
719 //////////////////////////////////////////////////////////////////////
720
721 try
722 {
723 uno::Reference< container::XNameReplace > xNewNameReplace;
724 aEntry >>= xNewNameReplace;
725
726 OSL_ENSURE( xNewNameReplace.is(),
727 "HierarchyEntry::move - No name replace!" );
728
729 if ( !xNewNameReplace.is() )
730 return sal_False;
731
732 uno::Reference< container::XNameAccess > xNewParentNameAccess;
733 if ( bDifferentParents )
734 xNewParentNameAccess
735 = uno::Reference< container::XNameAccess >(
736 xNewParentBatch, uno::UNO_QUERY );
737 else
738 xNewParentNameAccess = xOldParentNameAccess;
739
740 OSL_ENSURE( xNewParentNameAccess.is(),
741 "HierarchyEntry::move - No name access!" );
742
743 if ( !xNewParentNameAccess.is() )
744 return sal_False;
745
746 uno::Reference< container::XNameContainer > xNewNameContainer;
747 if ( bDifferentParents )
748 {
749 if ( bNewRoot )
750 {
751 xNewNameContainer
752 = uno::Reference< container::XNameContainer >(
753 xNewParentNameAccess, uno::UNO_QUERY );
754 }
755 else
756 {
757 xNewParentNameAccess->getByName(
758 rtl::OUString::createFromAscii( "Children" ) )
759 >>= xNewNameContainer;
760 }
761 }
762 else
763 xNewNameContainer = xOldNameContainer;
764
765 if ( !xNewNameContainer.is() )
766 return sal_False;
767
768 xNewNameReplace->replaceByName(
769 rtl::OUString::createFromAscii( "Title" ),
770 uno::makeAny( rData.getTitle() ) );
771
772 // TargetURL property may contain a reference to the Office
773 // installation directory. To ensure a reloctable office
774 // installation, the path to the office installtion
775 // directory must never be stored directly. Use a placeholder
776 // instead.
777 rtl::OUString aValue( rData.getTargetURL() );
778 if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) )
779 aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue );
780 xNewNameReplace->replaceByName(
781 rtl::OUString::createFromAscii( "TargetURL" ),
782 uno::makeAny( aValue ) );
783 sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1;
784 xNewNameReplace->replaceByName(
785 rtl::OUString::createFromAscii( "Type" ),
786 uno::makeAny( nType ) );
787
788 xNewNameContainer->insertByName( aNewKey, aEntry );
789 xNewParentBatch->commitChanges();
790 }
791 catch ( container::NoSuchElementException const & )
792 {
793 // replaceByName, insertByName, getByName
794
795 OSL_ENSURE( sal_False,
796 "HierarchyEntry::move - caught NoSuchElementException!" );
797 return sal_False;
798 }
799 catch ( lang::IllegalArgumentException const & )
800 {
801 // replaceByName, insertByName
802
803 OSL_ENSURE(
804 sal_False,
805 "HierarchyEntry::move - caught IllegalArgumentException!" );
806 return sal_False;
807 }
808 catch ( container::ElementExistException const & )
809 {
810 // insertByName
811
812 OSL_ENSURE( sal_False,
813 "HierarchyEntry::move - caught ElementExistException!" );
814 return sal_False;
815 }
816 catch ( lang::WrappedTargetException const & )
817 {
818 // replaceByName, insertByName, getByName
819
820 OSL_ENSURE( sal_False,
821 "HierarchyEntry::move - caught WrappedTargetException!" );
822 return sal_False;
823 }
824
825 #if 0
826 //////////////////////////////////////////////////////////////////////
827 // (4) Commit changes...
828 //////////////////////////////////////////////////////////////////////
829
830 try
831 {
832 xNewParentBatch->commitChanges();
833
834 if ( bDifferentParents )
835 xOldParentBatch->commitChanges();
836 }
837 catch ( lang::WrappedTargetException const & )
838 {
839 // commitChanges
840
841 OSL_ENSURE( sal_False,
842 "HierarchyEntry::move - caught WrappedTargetException!" );
843 return sal_False;
844 }
845 #endif
846
847 return sal_True;
848 #endif
849 }
850
851 //=========================================================================
remove()852 sal_Bool HierarchyEntry::remove()
853 {
854 try
855 {
856 osl::Guard< osl::Mutex > aGuard( m_aMutex );
857
858 if ( !m_xConfigProvider.is() )
859 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >(
860 m_xSMgr->createInstance( m_aServiceSpecifier ),
861 uno::UNO_QUERY );
862
863 if ( m_xConfigProvider.is() )
864 {
865 // Create parent's key. It must exist!
866
867 rtl::OUString aParentPath;
868 sal_Bool bRoot = sal_True;
869
870 sal_Int32 nPos = m_aPath.lastIndexOf( '/' );
871 if ( nPos != -1 )
872 {
873 // Skip "/Children" segment of the path, too.
874 nPos = m_aPath.lastIndexOf( '/', nPos - 1 );
875
876 OSL_ENSURE( nPos != -1,
877 "HierarchyEntry::remove - Wrong path!" );
878
879 aParentPath += m_aPath.copy( 0, nPos );
880 bRoot = sal_False;
881 }
882
883 uno::Sequence< uno::Any > aArguments( 1 );
884 beans::PropertyValue aProperty;
885
886 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
887 CFGPROPERTY_NODEPATH ) );
888 aProperty.Value <<= aParentPath;
889 aArguments[ 0 ] <<= aProperty;
890
891 uno::Reference< util::XChangesBatch > xBatch(
892 m_xConfigProvider->createInstanceWithArguments(
893 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
894 READWRITE_SERVICE_NAME ) ),
895 aArguments ),
896 uno::UNO_QUERY );
897
898 OSL_ENSURE( xBatch.is(),
899 "HierarchyEntry::remove - No batch!" );
900
901 uno::Reference< container::XNameAccess > xParentNameAccess(
902 xBatch, uno::UNO_QUERY );
903
904 OSL_ENSURE( xParentNameAccess.is(),
905 "HierarchyEntry::remove - No name access!" );
906
907 if ( xBatch.is() && xParentNameAccess.is() )
908 {
909 uno::Reference< container::XNameContainer > xContainer;
910
911 if ( bRoot )
912 {
913 // Special handling for children of root,
914 // which is not an entry. It's only a set
915 // of entries.
916 xContainer = uno::Reference< container::XNameContainer >(
917 xParentNameAccess, uno::UNO_QUERY );
918 }
919 else
920 {
921 // Append new entry to parents child list,
922 // which is a set of entries.
923 xParentNameAccess->getByName(
924 rtl::OUString::createFromAscii( "Children" ) )
925 >>= xContainer;
926 }
927
928 OSL_ENSURE( xContainer.is(),
929 "HierarchyEntry::remove - No container!" );
930
931 if ( xContainer.is() )
932 {
933 xContainer->removeByName( m_aName );
934 xBatch->commitChanges();
935 return sal_True;
936 }
937 }
938 }
939 }
940 catch ( uno::RuntimeException const & )
941 {
942 throw;
943 }
944 catch ( container::NoSuchElementException const & )
945 {
946 // getByName, removeByName
947
948 OSL_ENSURE(
949 sal_False,
950 "HierarchyEntry::remove - caught NoSuchElementException!" );
951 }
952 catch ( lang::WrappedTargetException const & )
953 {
954 // getByName, commitChanges
955
956 OSL_ENSURE(
957 sal_False,
958 "HierarchyEntry::remove - caught WrappedTargetException!" );
959 }
960 catch ( uno::Exception const & )
961 {
962 // createInstance, createInstanceWithArguments
963
964 OSL_ENSURE( sal_False,
965 "HierarchyEntry::remove - caught Exception!" );
966 }
967
968 return sal_False;
969 }
970
971 //=========================================================================
first(iterator & it)972 sal_Bool HierarchyEntry::first( iterator& it )
973 {
974 osl::Guard< osl::Mutex > aGuard( m_aMutex );
975
976 if ( it.m_pImpl->pos == -1 )
977 {
978 // Init...
979
980 try
981 {
982 uno::Reference< container::XHierarchicalNameAccess >
983 xRootHierNameAccess = getRootReadAccess();
984
985 if ( xRootHierNameAccess.is() )
986 {
987 uno::Reference< container::XNameAccess > xNameAccess;
988
989 if ( m_aPath.getLength() > 0 )
990 {
991 rtl::OUString aPath = m_aPath;
992 aPath += rtl::OUString::createFromAscii( "/Children" );
993
994 xRootHierNameAccess->getByHierarchicalName( aPath )
995 >>= xNameAccess;
996 }
997 else
998 xNameAccess
999 = uno::Reference< container::XNameAccess >(
1000 xRootHierNameAccess, uno::UNO_QUERY );
1001
1002 OSL_ENSURE( xNameAccess.is(),
1003 "HierarchyEntry::first - No name access!" );
1004
1005 if ( xNameAccess.is() )
1006 it.m_pImpl->names = xNameAccess->getElementNames();
1007
1008 uno::Reference< container::XHierarchicalNameAccess >
1009 xHierNameAccess( xNameAccess, uno::UNO_QUERY );
1010
1011 OSL_ENSURE( xHierNameAccess.is(),
1012 "HierarchyEntry::first - No hier. name access!" );
1013
1014 it.m_pImpl->dir = xHierNameAccess;
1015
1016 it.m_pImpl->officeDirs = m_xOfficeInstDirs;
1017 }
1018 }
1019 catch ( uno::RuntimeException const & )
1020 {
1021 throw;
1022 }
1023 catch ( container::NoSuchElementException const& )
1024 {
1025 // getByHierarchicalName
1026
1027 OSL_ENSURE(
1028 sal_False,
1029 "HierarchyEntry::first - caught NoSuchElementException!" );
1030 }
1031 catch ( uno::Exception const & )
1032 {
1033 OSL_ENSURE( sal_False,
1034 "HierarchyEntry::first - caught Exception!" );
1035 }
1036 }
1037
1038 if ( it.m_pImpl->names.getLength() == 0 )
1039 return sal_False;
1040
1041 it.m_pImpl->pos = 0;
1042 return sal_True;
1043 }
1044
1045 //=========================================================================
next(iterator & it)1046 sal_Bool HierarchyEntry::next( iterator& it )
1047 {
1048 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1049
1050 if ( it.m_pImpl->pos == -1 )
1051 return first( it );
1052
1053 ++(it.m_pImpl->pos);
1054
1055 return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() );
1056 }
1057
1058 //=========================================================================
createPathFromHierarchyURL(const HierarchyUri & rURI)1059 rtl::OUString HierarchyEntry::createPathFromHierarchyURL(
1060 const HierarchyUri& rURI )
1061 {
1062 // Transform path....
1063 // folder/subfolder/subsubfolder
1064 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder']
1065
1066 const rtl::OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash.
1067 sal_Int32 nLen = aPath.getLength();
1068
1069 if ( nLen )
1070 {
1071 rtl::OUStringBuffer aNewPath;
1072 aNewPath.appendAscii( "['" );
1073
1074 sal_Int32 nStart = 0;
1075 sal_Int32 nEnd = aPath.indexOf( '/' );
1076
1077 do
1078 {
1079 if ( nEnd == -1 )
1080 nEnd = nLen;
1081
1082 rtl::OUString aToken = aPath.copy( nStart, nEnd - nStart );
1083 makeXMLName( aToken, aNewPath );
1084
1085 if ( nEnd != nLen )
1086 {
1087 aNewPath.appendAscii( "']/Children/['" );
1088 nStart = nEnd + 1;
1089 nEnd = aPath.indexOf( '/', nStart );
1090 }
1091 else
1092 aNewPath.appendAscii( "']" );
1093 }
1094 while ( nEnd != nLen );
1095
1096 return aNewPath.makeStringAndClear();
1097 }
1098
1099 return aPath;
1100 }
1101
1102 //=========================================================================
1103 uno::Reference< container::XHierarchicalNameAccess >
getRootReadAccess()1104 HierarchyEntry::getRootReadAccess()
1105 {
1106 if ( !m_xRootReadAccess.is() )
1107 {
1108 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1109 if ( !m_xRootReadAccess.is() )
1110 {
1111 if ( m_bTriedToGetRootReadAccess ) // #82494#
1112 {
1113 OSL_ENSURE( sal_False,
1114 "HierarchyEntry::getRootReadAccess - "
1115 "Unable to read any config data! -> #82494#" );
1116 return uno::Reference< container::XHierarchicalNameAccess >();
1117 }
1118
1119 try
1120 {
1121 if ( !m_xConfigProvider.is() )
1122 m_xConfigProvider
1123 = uno::Reference< lang::XMultiServiceFactory >(
1124 m_xSMgr->createInstance( m_aServiceSpecifier ),
1125 uno::UNO_QUERY );
1126
1127 if ( m_xConfigProvider.is() )
1128 {
1129 // Create Root object.
1130
1131 uno::Sequence< uno::Any > aArguments( 1 );
1132 beans::PropertyValue aProperty;
1133 aProperty.Name = rtl::OUString(
1134 RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH ) );
1135 aProperty.Value <<= rtl::OUString(); // root path
1136 aArguments[ 0 ] <<= aProperty;
1137
1138 m_bTriedToGetRootReadAccess = sal_True;
1139
1140 m_xRootReadAccess
1141 = uno::Reference< container::XHierarchicalNameAccess >(
1142 m_xConfigProvider->createInstanceWithArguments(
1143 rtl::OUString(
1144 RTL_CONSTASCII_USTRINGPARAM(
1145 READ_SERVICE_NAME ) ),
1146 aArguments ),
1147 uno::UNO_QUERY );
1148 }
1149 }
1150 catch ( uno::RuntimeException const & )
1151 {
1152 throw;
1153 }
1154 catch ( uno::Exception const & )
1155 {
1156 // createInstance, createInstanceWithArguments
1157
1158 OSL_ENSURE( sal_False,
1159 "HierarchyEntry::getRootReadAccess - "
1160 "caught Exception!" );
1161 }
1162 }
1163 }
1164 return m_xRootReadAccess;
1165 }
1166
1167 //=========================================================================
1168 //=========================================================================
1169 //
1170 // HierarchyEntry::iterator Implementation.
1171 //
1172 //=========================================================================
1173 //=========================================================================
1174
iterator()1175 HierarchyEntry::iterator::iterator()
1176 {
1177 m_pImpl = new iterator_Impl;
1178 }
1179
1180 //=========================================================================
~iterator()1181 HierarchyEntry::iterator::~iterator()
1182 {
1183 delete m_pImpl;
1184 }
1185
1186 //=========================================================================
operator *() const1187 const HierarchyEntryData& HierarchyEntry::iterator::operator*() const
1188 {
1189 if ( ( m_pImpl->pos != -1 )
1190 && ( m_pImpl->dir.is() )
1191 && ( m_pImpl->pos < m_pImpl->names.getLength() ) )
1192 {
1193 try
1194 {
1195 rtl::OUStringBuffer aKey;
1196 aKey.appendAscii( "['" );
1197 makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey );
1198 aKey.appendAscii( "']" );
1199
1200 rtl::OUString aTitle = aKey.makeStringAndClear();
1201 rtl::OUString aTargetURL = aTitle;
1202 rtl::OUString aType = aTitle;
1203
1204 aTitle += rtl::OUString::createFromAscii( "/Title" );
1205 aTargetURL += rtl::OUString::createFromAscii( "/TargetURL" );
1206 aType += rtl::OUString::createFromAscii( "/Type" );
1207
1208 rtl::OUString aValue;
1209 m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue;
1210 m_pImpl->entry.setTitle( aValue );
1211
1212 m_pImpl->dir->getByHierarchicalName( aTargetURL ) >>= aValue;
1213
1214 // TargetURL property may contain a reference to the Office
1215 // installation directory. To ensure a reloctable office
1216 // installation, the path to the office installtion directory must
1217 // never be stored directly. A placeholder is used instead. Replace
1218 // it by actual installation directory.
1219 if ( m_pImpl->officeDirs.is() && ( aValue.getLength() > 0 ) )
1220 aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue );
1221 m_pImpl->entry.setTargetURL( aValue );
1222
1223 if ( m_pImpl->dir->hasByHierarchicalName( aType ) )
1224 {
1225 // Might not be present since it was introduced long
1226 // after Title and TargetURL (#82433#)... So not getting
1227 // it is not an error.
1228
1229 // Get Type value.
1230 sal_Int32 nType = 0;
1231 if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType )
1232 {
1233 if ( nType == 0 )
1234 {
1235 m_pImpl->entry.setType( HierarchyEntryData::LINK );
1236 }
1237 else if ( nType == 1 )
1238 {
1239 m_pImpl->entry.setType( HierarchyEntryData::FOLDER );
1240 }
1241 else
1242 {
1243 OSL_ENSURE( sal_False,
1244 "HierarchyEntry::getData - "
1245 "Unknown Type value!" );
1246 }
1247 }
1248 }
1249
1250 m_pImpl->entry.setName(
1251 m_pImpl->names.getConstArray()[ m_pImpl->pos ] );
1252 }
1253 catch ( container::NoSuchElementException const & )
1254 {
1255 m_pImpl->entry = HierarchyEntryData();
1256 }
1257 }
1258
1259 return m_pImpl->entry;
1260 }
1261
1262 } // namespace hierarchy_ucp
1263