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