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   *************************************************************************/
26 
27 #include <memory>
28 #include <unordered_map>
29 #include <sal/log.hxx>
30 #include <tools/diagnose_ex.h>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/ref.hxx>
33 #include <cppuhelper/interfacecontainer.hxx>
34 #include <comphelper/interfacecontainer2.hxx>
35 #include <comphelper/propertysequence.hxx>
36 #include <com/sun/star/beans/IllegalTypeException.hpp>
37 #include <com/sun/star/beans/NotRemoveableException.hpp>
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #include <com/sun/star/beans/PropertyExistException.hpp>
40 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
41 #include <com/sun/star/configuration/theDefaultProvider.hpp>
42 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
43 #include <com/sun/star/container/XNameContainer.hpp>
44 #include <com/sun/star/container/XNameReplace.hpp>
45 #include <com/sun/star/util/XChangesBatch.hpp>
46 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
47 #include <cppuhelper/implbase.hxx>
48 #include <cppuhelper/weak.hxx>
49 #include <ucbhelper/macros.hxx>
50 #include "ucbstore.hxx"
51 
52 using namespace com::sun::star::beans;
53 using namespace com::sun::star::configuration;
54 using namespace com::sun::star::container;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::ucb;
57 using namespace com::sun::star::uno;
58 using namespace com::sun::star::util;
59 using namespace comphelper;
60 using namespace cppu;
61 
makeHierarchalNameSegment(const OUString & rIn)62 static OUString makeHierarchalNameSegment( const OUString & rIn  )
63 {
64     OUStringBuffer aBuffer;
65     aBuffer.append( "['" );
66 
67     sal_Int32 nCount = rIn.getLength();
68     for ( sal_Int32 n = 0; n < nCount; ++n )
69     {
70         const sal_Unicode c = rIn[ n ];
71         switch ( c )
72         {
73             case '&':
74                 aBuffer.append( "&amp;" );
75                 break;
76 
77             case '"':
78                 aBuffer.append( "&quot;" );
79                 break;
80 
81             case '\'':
82                 aBuffer.append( "&apos;" );
83                 break;
84 
85             case '<':
86                 aBuffer.append( "&lt;" );
87                 break;
88 
89             case '>':
90                 aBuffer.append( "&gt;" );
91                 break;
92 
93             default:
94                 aBuffer.append( c );
95                 break;
96         }
97     }
98 
99     aBuffer.append( "']" );
100     return aBuffer.makeStringAndClear();
101 }
102 
103 #define STORE_CONTENTPROPERTIES_KEY "/org.openoffice.ucb.Store/ContentProperties"
104 
105 // describe path of cfg entry
106 #define CFGPROPERTY_NODEPATH        "nodepath"
107 
108 // PropertySetMap_Impl.
109 typedef std::unordered_map< OUString, PersistentPropertySet*> PropertySetMap_Impl;
110 
111 namespace {
112 
113 class PropertySetInfo_Impl : public cppu::WeakImplHelper < XPropertySetInfo >
114 {
115     std::unique_ptr<Sequence< Property >>
116                                       m_pProps;
117     PersistentPropertySet*            m_pOwner;
118 
119 public:
120     explicit PropertySetInfo_Impl(PersistentPropertySet* pOwner);
121 
122     // XPropertySetInfo
123     virtual Sequence< Property > SAL_CALL getProperties() override;
124     virtual Property SAL_CALL getPropertyByName( const OUString& aName ) override;
125     virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override;
126 
127     // Non-interface methods.
reset()128     void reset() { m_pProps.reset(); }
129 };
130 
131 }
132 
133 // UcbStore_Impl.
134 
135 
136 struct UcbStore_Impl
137 {
138     osl::Mutex                        m_aMutex;
139     Sequence< Any >                   m_aInitArgs;
140     Reference< XPropertySetRegistry > m_xTheRegistry;
141 };
142 
143 
144 // UcbStore Implementation.
145 
146 
UcbStore(const Reference<XComponentContext> & xContext)147 UcbStore::UcbStore( const Reference< XComponentContext >& xContext )
148 : UcbStore_Base(m_aMutex),
149   m_xContext( xContext ),
150   m_pImpl( new UcbStore_Impl )
151 {
152 }
153 
154 
155 // virtual
~UcbStore()156 UcbStore::~UcbStore()
157 {
158 }
159 
getImplementationName()160 OUString SAL_CALL UcbStore::getImplementationName()
161 {
162     return "com.sun.star.comp.ucb.UcbStore";
163 }
supportsService(const OUString & ServiceName)164 sal_Bool SAL_CALL UcbStore::supportsService( const OUString& ServiceName )
165 {
166     return cppu::supportsService( this, ServiceName );
167 }
getSupportedServiceNames()168 css::uno::Sequence< OUString > SAL_CALL UcbStore::getSupportedServiceNames()
169 {
170     return { "com.sun.star.ucb.Store" };
171 }
172 
173 // Service factory implementation.
174 
175 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
ucb_UcbStore_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)176 ucb_UcbStore_get_implementation(
177     css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
178 {
179     return cppu::acquire(new UcbStore(context));
180 }
181 
182 
183 // XPropertySetRegistryFactory methods.
184 
185 
186 // virtual
187 Reference< XPropertySetRegistry > SAL_CALL
createPropertySetRegistry(const OUString &)188 UcbStore::createPropertySetRegistry( const OUString& )
189 {
190     // The URL parameter is ignored by this interface implementation. It always
191     // uses the configuration server as storage medium.
192 
193     if ( !m_pImpl->m_xTheRegistry.is() )
194     {
195         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
196         if ( !m_pImpl->m_xTheRegistry.is() )
197             m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xContext, m_pImpl->m_aInitArgs );
198     }
199 
200     return m_pImpl->m_xTheRegistry;
201 }
202 
203 
204 // XInitialization methods.
205 
206 
207 // virtual
initialize(const Sequence<Any> & aArguments)208 void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments )
209 {
210     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
211     m_pImpl->m_aInitArgs = aArguments;
212 }
213 
214 
215 
216 // PropertySetRegistry_Impl.
217 
218 
219 struct PropertySetRegistry_Impl
220 {
221     const Sequence< Any >             m_aInitArgs;
222     PropertySetMap_Impl               m_aPropSets;
223     Reference< XMultiServiceFactory > m_xConfigProvider;
224     Reference< XInterface >           m_xRootReadAccess;
225     Reference< XInterface >           m_xRootWriteAccess;
226     osl::Mutex                        m_aMutex;
227     bool                              m_bTriedToGetRootReadAccess;
228     bool                              m_bTriedToGetRootWriteAccess;
229 
PropertySetRegistry_ImplPropertySetRegistry_Impl230     explicit PropertySetRegistry_Impl(const Sequence<Any> &rInitArgs)
231         : m_aInitArgs(rInitArgs)
232         , m_bTriedToGetRootReadAccess(false)
233         , m_bTriedToGetRootWriteAccess(false)
234     {
235     }
236 };
237 
238 // PropertySetRegistry Implementation.
239 
240 
PropertySetRegistry(const Reference<XComponentContext> & xContext,const Sequence<Any> & rInitArgs)241 PropertySetRegistry::PropertySetRegistry(
242                         const Reference< XComponentContext >& xContext,
243                         const Sequence< Any > &rInitArgs )
244 : m_xContext( xContext ),
245   m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) )
246 {
247 }
248 
249 
250 // virtual
~PropertySetRegistry()251 PropertySetRegistry::~PropertySetRegistry()
252 {
253 }
254 
255 
256 // XServiceInfo methods.
257 
258 
getImplementationName()259 OUString SAL_CALL PropertySetRegistry::getImplementationName()
260 {
261     return "com.sun.star.comp.ucb.PropertySetRegistry";
262 }
263 
supportsService(const OUString & ServiceName)264 sal_Bool SAL_CALL PropertySetRegistry::supportsService( const OUString& ServiceName )
265 {
266     return cppu::supportsService( this, ServiceName );
267 }
268 
getSupportedServiceNames()269 css::uno::Sequence< OUString > SAL_CALL PropertySetRegistry::getSupportedServiceNames()
270 {
271     return {  "com.sun.star.ucb.PropertySetRegistry" };
272 }
273 
274 
275 // XPropertySetRegistry methods.
276 
277 
278 // virtual
279 Reference< XPersistentPropertySet > SAL_CALL
openPropertySet(const OUString & key,sal_Bool create)280 PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create )
281 {
282     if ( !key.isEmpty() )
283     {
284         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
285 
286         PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
287 
288         PropertySetMap_Impl::const_iterator it = rSets.find( key );
289         if ( it != rSets.end() )
290         {
291             // Already instantiated.
292             return Reference< XPersistentPropertySet >( (*it).second );
293         }
294         else
295         {
296             // Create new instance.
297             Reference< XNameAccess > xRootNameAccess(
298                                     getRootConfigReadAccess(), UNO_QUERY );
299             if ( xRootNameAccess.is() )
300             {
301                 // Propertyset in registry?
302                 if ( xRootNameAccess->hasByName( key ) )
303                 {
304                     // Yep!
305                     return Reference< XPersistentPropertySet >(
306                                             new PersistentPropertySet(
307                                                     *this, key ) );
308                 }
309                 else if ( create )
310                 {
311                     // No. Create entry for propertyset.
312 
313                     Reference< XSingleServiceFactory > xFac(
314                             getConfigWriteAccess( OUString() ), UNO_QUERY );
315                     Reference< XChangesBatch >  xBatch( xFac, UNO_QUERY );
316                     Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
317 
318                     OSL_ENSURE( xFac.is(),
319                                 "PropertySetRegistry::openPropertySet - "
320                                 "No factory!" );
321 
322                     OSL_ENSURE( xBatch.is(),
323                                 "PropertySetRegistry::openPropertySet - "
324                                 "No batch!" );
325 
326                     OSL_ENSURE( xContainer.is(),
327                                 "PropertySetRegistry::openPropertySet - "
328                                 "No container!" );
329 
330                     if ( xFac.is() && xBatch.is() && xContainer.is() )
331                     {
332                         try
333                         {
334                             // Create new "Properties" config item.
335                             Reference< XNameReplace > xNameReplace(
336                                         xFac->createInstance(), UNO_QUERY );
337 
338                             if ( xNameReplace.is() )
339                             {
340                                 // Fill new item...
341 
342                                 // Insert new item.
343                                 xContainer->insertByName(
344                                         key, makeAny( xNameReplace ) );
345                                 // Commit changes.
346                                 xBatch->commitChanges();
347 
348                                 return Reference< XPersistentPropertySet >(
349                                             new PersistentPropertySet(
350                                                     *this, key ) );
351                             }
352                         }
353                         catch (const IllegalArgumentException&)
354                         {
355                             // insertByName
356 
357                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
358                                         "caught IllegalArgumentException!" );
359                         }
360                         catch (const ElementExistException&)
361                         {
362                             // insertByName
363 
364                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
365                                         "caught ElementExistException!" );
366                         }
367                         catch (const WrappedTargetException&)
368                         {
369                             // insertByName, commitChanges
370 
371                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
372                                         "caught WrappedTargetException!" );
373                         }
374                         catch (const RuntimeException&)
375                         {
376                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
377                                         "caught RuntimeException!" );
378                         }
379                         catch (const Exception&)
380                         {
381                             // createInstance
382 
383                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
384                                         "caught Exception!" );
385                         }
386                     }
387                 }
388                 else
389                 {
390                     // No entry. Fail, but no error.
391                     return Reference< XPersistentPropertySet >();
392                 }
393             }
394 
395             SAL_WARN( "ucb", "no root access" );
396         }
397     }
398 
399     return Reference< XPersistentPropertySet >();
400 }
401 
402 
403 // virtual
removePropertySet(const OUString & key)404 void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key )
405 {
406     if ( key.isEmpty() )
407         return;
408 
409     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
410 
411     Reference< XNameAccess > xRootNameAccess(
412                                     getRootConfigReadAccess(), UNO_QUERY );
413     if ( xRootNameAccess.is() )
414     {
415         // Propertyset in registry?
416         if ( !xRootNameAccess->hasByName( key ) )
417             return;
418         Reference< XChangesBatch > xBatch(
419                             getConfigWriteAccess( OUString() ), UNO_QUERY );
420         Reference< XNameContainer > xContainer( xBatch, UNO_QUERY );
421 
422         if ( xBatch.is() && xContainer.is() )
423         {
424             try
425             {
426                 // Remove item.
427                 xContainer->removeByName( key );
428                 // Commit changes.
429                 xBatch->commitChanges();
430 
431                 // Success.
432                 return;
433             }
434             catch (const NoSuchElementException&)
435             {
436                 // removeByName
437 
438                 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
439                             "caught NoSuchElementException!" );
440                 return;
441             }
442             catch (const WrappedTargetException&)
443             {
444                 // commitChanges
445 
446                 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
447                             "caught WrappedTargetException!" );
448                 return;
449             }
450         }
451 
452         return;
453     }
454 
455     SAL_WARN( "ucb", "no root access" );
456 }
457 
458 
459 // XElementAccess methods.
460 
461 
462 // virtual
getElementType()463 css::uno::Type SAL_CALL PropertySetRegistry::getElementType()
464 {
465     return cppu::UnoType<XPersistentPropertySet>::get();
466 }
467 
468 
469 // virtual
hasElements()470 sal_Bool SAL_CALL PropertySetRegistry::hasElements()
471 {
472     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
473 
474     Reference< XElementAccess > xElemAccess(
475                                     getRootConfigReadAccess(), UNO_QUERY );
476     if ( xElemAccess.is() )
477         return xElemAccess->hasElements();
478 
479     return false;
480 }
481 
482 
483 // XNameAccess methods.
484 
485 
486 // virtual
getByName(const OUString & aName)487 Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName )
488 {
489     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
490 
491     Reference< XNameAccess > xNameAccess(
492                                     getRootConfigReadAccess(), UNO_QUERY );
493     if ( xNameAccess.is() )
494     {
495 
496         try
497         {
498             return xNameAccess->getByName( aName );
499         }
500         catch (const NoSuchElementException&)
501         {
502             // getByName
503         }
504         catch (const WrappedTargetException&)
505         {
506             // getByName
507         }
508     }
509 
510     return Any();
511 }
512 
513 
514 // virtual
getElementNames()515 Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames()
516 {
517     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
518 
519     Reference< XNameAccess > xNameAccess(
520                                     getRootConfigReadAccess(), UNO_QUERY );
521     if ( xNameAccess.is() )
522     {
523         return xNameAccess->getElementNames();
524     }
525     return Sequence< OUString >( 0 );
526 }
527 
528 
529 // virtual
hasByName(const OUString & aName)530 sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName )
531 {
532     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
533 
534     Reference< XNameAccess > xNameAccess(
535                                     getRootConfigReadAccess(), UNO_QUERY );
536     if ( xNameAccess.is() )
537     {
538         return xNameAccess->hasByName( aName );
539     }
540 
541     return false;
542 }
543 
544 
add(PersistentPropertySet * pSet)545 void PropertySetRegistry::add( PersistentPropertySet* pSet )
546 {
547     OUString key( pSet->getKey() );
548 
549     if ( !key.isEmpty() )
550     {
551         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
552         m_pImpl->m_aPropSets[ key ] = pSet;
553     }
554 }
555 
556 
remove(PersistentPropertySet * pSet)557 void PropertySetRegistry::remove( PersistentPropertySet* pSet )
558 {
559     OUString key( pSet->getKey() );
560 
561     if ( key.isEmpty() )
562         return;
563 
564     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
565 
566     PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
567 
568     PropertySetMap_Impl::iterator it = rSets.find( key );
569     if ( it != rSets.end() )
570     {
571         // Found.
572         rSets.erase( it );
573     }
574 }
575 
576 
renamePropertySet(const OUString & rOldKey,const OUString & rNewKey)577 void PropertySetRegistry::renamePropertySet( const OUString& rOldKey,
578                                              const OUString& rNewKey )
579 {
580     if ( rOldKey == rNewKey )
581         return;
582 
583     Reference< XNameAccess > xRootNameAccess(
584                             getConfigWriteAccess( OUString() ), UNO_QUERY );
585     if ( xRootNameAccess.is() )
586     {
587         // Old key present?
588         if ( xRootNameAccess->hasByName( rOldKey ) )
589         {
590             // New key not present?
591             if ( xRootNameAccess->hasByName( rNewKey ) )
592             {
593                 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
594                             "New key exists!" );
595                 return;
596             }
597             Reference< XSingleServiceFactory > xFac(
598                                                 xRootNameAccess, UNO_QUERY );
599             Reference< XChangesBatch >  xBatch( xFac, UNO_QUERY );
600             Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
601 
602             OSL_ENSURE( xFac.is(),
603                         "PropertySetRegistry::renamePropertySet - "
604                         "No factory!" );
605 
606             OSL_ENSURE( xBatch.is(),
607                         "PropertySetRegistry::renamePropertySet - "
608                         "No batch!" );
609 
610             OSL_ENSURE( xContainer.is(),
611                         "PropertySetRegistry::renamePropertySet - "
612                         "No container!" );
613 
614             if ( xFac.is() && xBatch.is() && xContainer.is() )
615             {
616 
617                 // Create new "Properties" config item.
618 
619 
620                 try
621                 {
622                     Reference< XNameReplace > xNameReplace(
623                                     xFac->createInstance(), UNO_QUERY );
624 
625                     if ( xNameReplace.is() )
626                     {
627                         // Insert new item.
628                         xContainer->insertByName(
629                                     rNewKey, makeAny( xNameReplace ) );
630                         // Commit changes.
631                         xBatch->commitChanges();
632                     }
633                 }
634                 catch (const IllegalArgumentException&)
635                 {
636                     // insertByName
637 
638                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
639                                 "caught IllegalArgumentException!" );
640                     return;
641                 }
642                 catch (const ElementExistException&)
643                 {
644                     // insertByName
645 
646                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
647                                 "caught ElementExistException!" );
648                     return;
649                 }
650                 catch (const WrappedTargetException&)
651                 {
652                     // insertByName, commitChanges
653 
654                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
655                                 "caught WrappedTargetException!" );
656                     return;
657                 }
658                 catch (const RuntimeException&)
659                 {
660                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
661                                 "caught RuntimeException!" );
662                     return;
663                 }
664                 catch (const Exception&)
665                 {
666                     // createInstance
667 
668                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
669                                 "caught Exception!" );
670                     return;
671                 }
672 
673 
674                 // Copy data...
675 
676 
677                 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
678                                                 xRootNameAccess, UNO_QUERY );
679                 if ( !xRootHierNameAccess.is() )
680                 {
681                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
682                                 "No hierarchical name access!" );
683                     return;
684                 }
685 
686                 try
687                 {
688                     OUString aOldValuesKey
689                         = makeHierarchalNameSegment( rOldKey ) + "/Values";
690 
691                     Reference< XNameAccess > xOldNameAccess;
692                     xRootHierNameAccess->getByHierarchicalName(
693                                                         aOldValuesKey )
694                         >>= xOldNameAccess;
695                     if ( !xOldNameAccess.is() )
696                     {
697                         OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
698                             "No old name access!" );
699                         return;
700                     }
701 
702                     // Obtain property names.
703                     const Sequence< OUString > aElems
704                                     = xOldNameAccess->getElementNames();
705                     if ( aElems.hasElements() )
706                     {
707                         OUString aNewValuesKey
708                             = makeHierarchalNameSegment( rNewKey ) + "/Values";
709 
710                         Reference< XSingleServiceFactory > xNewFac;
711                         xRootHierNameAccess->getByHierarchicalName(
712                                                         aNewValuesKey )
713                             >>= xNewFac;
714                         if ( !xNewFac.is() )
715                         {
716                             OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
717                                 "No new factory!" );
718                             return;
719                         }
720 
721                         Reference< XNameContainer > xNewContainer(
722                                                     xNewFac, UNO_QUERY );
723                         if ( !xNewContainer.is() )
724                         {
725                             OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
726                                 "No new container!" );
727                             return;
728                         }
729 
730                         aOldValuesKey += "/";
731 
732                         OUString const aHandleKey("/Handle");
733                         OUString const aValueKey("/Value");
734                         OUString const aStateKey("/State");
735                         OUString const aAttrKey("/Attributes");
736 
737                         for ( const OUString& rPropName : aElems )
738                         {
739                             // Create new item.
740                             Reference< XNameReplace > xNewPropNameReplace(
741                                 xNewFac->createInstance(), UNO_QUERY );
742 
743                             if ( !xNewPropNameReplace.is() )
744                             {
745                                 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
746                                     "No new prop name replace!" );
747                                 return;
748                             }
749 
750                             // Fill new item...
751 
752                             // Set Values
753                             OUString aKey = aOldValuesKey;
754                             aKey += makeHierarchalNameSegment( rPropName );
755 
756                             // ... handle
757                             OUString aNewKey1 = aKey + aHandleKey;
758                             Any aAny =
759                                 xRootHierNameAccess->getByHierarchicalName(
760                                     aNewKey1 );
761                             xNewPropNameReplace->replaceByName( "Handle", aAny );
762 
763                             // ... value
764                             aNewKey1 = aKey + aValueKey;
765                             aAny =
766                                 xRootHierNameAccess->getByHierarchicalName(
767                                     aNewKey1 );
768                             xNewPropNameReplace->replaceByName( "Value", aAny );
769 
770                             // ... state
771                             aNewKey1 = aKey + aStateKey;
772                             aAny =
773                                 xRootHierNameAccess->getByHierarchicalName(
774                                     aNewKey1 );
775                             xNewPropNameReplace->replaceByName( "State", aAny );
776 
777                             // ... attributes
778                             aNewKey1 = aKey + aAttrKey;
779                             aAny =
780                                 xRootHierNameAccess->getByHierarchicalName(
781                                     aNewKey1 );
782                             xNewPropNameReplace->replaceByName( "Attributes", aAny );
783 
784                             // Insert new item.
785                             xNewContainer->insertByName(
786                                 rPropName, makeAny( xNewPropNameReplace ) );
787 
788                             // Commit changes.
789                             xBatch->commitChanges();
790                         }
791                     }
792                 }
793                 catch (const IllegalArgumentException&)
794                 {
795                     // insertByName, replaceByName
796 
797                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
798                                 "caught IllegalArgumentException!" );
799                     return;
800                 }
801                 catch (const ElementExistException&)
802                 {
803                     // insertByName
804 
805                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
806                                 "caught ElementExistException!" );
807                     return;
808                 }
809                 catch (const WrappedTargetException&)
810                 {
811                     // insertByName, replaceByName, commitChanges
812 
813                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
814                                 "caught WrappedTargetException!" );
815                     return;
816                 }
817                 catch (const NoSuchElementException&)
818                 {
819                     // getByHierarchicalName, replaceByName
820 
821                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
822                                 "caught NoSuchElementException!" );
823                     return;
824                 }
825                 catch (const RuntimeException&)
826                 {
827                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
828                                 "caught RuntimeException!" );
829                     return;
830                 }
831                 catch (const Exception&)
832                 {
833                     // createInstance
834 
835                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
836                                 "caught Exception!" );
837                     return;
838                 }
839 
840 
841                 // Remove old entry...
842 
843 
844                 try
845                 {
846                     // Remove item.
847                     xContainer->removeByName( rOldKey );
848                     // Commit changes.
849                     xBatch->commitChanges();
850 
851                     // Success.
852                     return;
853                 }
854                 catch (const NoSuchElementException&)
855                 {
856                     // removeByName
857 
858                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
859                                 "caught NoSuchElementException!" );
860                     return;
861                 }
862                 catch (const WrappedTargetException&)
863                 {
864                     // commitChanges
865 
866                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
867                                 "caught WrappedTargetException!" );
868                     return;
869                 }
870             }
871         }
872     }
873 
874     OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" );
875 }
876 
877 
getConfigProvider()878 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider()
879 {
880     if ( !m_pImpl->m_xConfigProvider.is() )
881     {
882         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
883         if ( !m_pImpl->m_xConfigProvider.is() )
884         {
885             const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs;
886 
887             if ( rInitArgs.hasElements() )
888             {
889                 // Extract config provider from service init args.
890                 rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider;
891 
892                 OSL_ENSURE( m_pImpl->m_xConfigProvider.is(),
893                             "PropertySetRegistry::getConfigProvider - "
894                             "No config provider!" );
895             }
896             else
897             {
898                 try
899                 {
900                     m_pImpl->m_xConfigProvider = theDefaultProvider::get( m_xContext );
901                 }
902                 catch (const Exception&)
903                 {
904                     TOOLS_WARN_EXCEPTION( "ucb", "");
905                 }
906             }
907         }
908     }
909 
910     return m_pImpl->m_xConfigProvider;
911 }
912 
913 
getRootConfigReadAccess()914 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
915 {
916     try
917     {
918         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
919 
920         if ( !m_pImpl->m_xRootReadAccess.is() )
921         {
922             if ( m_pImpl->m_bTriedToGetRootReadAccess )
923             {
924                 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - "
925                             "Unable to read any config data! -> #82494#" );
926                 return Reference< XInterface >();
927             }
928 
929             getConfigProvider();
930 
931             if ( m_pImpl->m_xConfigProvider.is() )
932             {
933                 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
934                 {
935                     {CFGPROPERTY_NODEPATH,  Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
936                 }));
937 
938                 m_pImpl->m_bTriedToGetRootReadAccess = true;
939 
940                 m_pImpl->m_xRootReadAccess =
941                     m_pImpl->m_xConfigProvider->createInstanceWithArguments(
942                         "com.sun.star.configuration.ConfigurationAccess",
943                         aArguments );
944 
945                 if ( m_pImpl->m_xRootReadAccess.is() )
946                     return m_pImpl->m_xRootReadAccess;
947             }
948         }
949         else
950             return m_pImpl->m_xRootReadAccess;
951     }
952     catch (const RuntimeException&)
953     {
954         throw;
955     }
956     catch (const Exception&)
957     {
958         // createInstance, createInstanceWithArguments
959 
960         TOOLS_WARN_EXCEPTION("ucb", "");
961         return Reference< XInterface >();
962     }
963 
964     SAL_WARN( "ucb", "Error!" );
965     return Reference< XInterface >();
966 }
967 
968 
getConfigWriteAccess(const OUString & rPath)969 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
970                                                     const OUString& rPath )
971 {
972     try
973     {
974         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
975 
976         if ( !m_pImpl->m_xRootWriteAccess.is() )
977         {
978             if ( m_pImpl->m_bTriedToGetRootWriteAccess )
979             {
980                 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
981                             "Unable to write any config data! -> #82494#" );
982                 return Reference< XInterface >();
983             }
984 
985             getConfigProvider();
986 
987             if ( m_pImpl->m_xConfigProvider.is() )
988             {
989                 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
990                 {
991                     {CFGPROPERTY_NODEPATH,  Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
992                 }));
993 
994                 m_pImpl->m_bTriedToGetRootWriteAccess = true;
995 
996                 m_pImpl->m_xRootWriteAccess =
997                     m_pImpl->m_xConfigProvider->createInstanceWithArguments(
998                         "com.sun.star.configuration.ConfigurationUpdateAccess",
999                         aArguments );
1000 
1001                 OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(),
1002                             "PropertySetRegistry::getConfigWriteAccess - "
1003                             "No config update access!" );
1004             }
1005         }
1006 
1007         if ( m_pImpl->m_xRootWriteAccess.is() )
1008         {
1009             if ( !rPath.isEmpty() )
1010             {
1011                 Reference< XHierarchicalNameAccess > xNA(
1012                                 m_pImpl->m_xRootWriteAccess, UNO_QUERY );
1013                 if ( xNA.is() )
1014                 {
1015                     Reference< XInterface > xInterface;
1016                     xNA->getByHierarchicalName( rPath ) >>= xInterface;
1017 
1018                     if ( xInterface.is() )
1019                         return xInterface;
1020                 }
1021             }
1022             else
1023                 return m_pImpl->m_xRootWriteAccess;
1024         }
1025     }
1026     catch (const RuntimeException&)
1027     {
1028         throw;
1029     }
1030     catch (const NoSuchElementException&)
1031     {
1032         // getByHierarchicalName
1033 
1034         OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1035             "caught NoSuchElementException!" );
1036         return Reference< XInterface >();
1037     }
1038     catch (const Exception&)
1039     {
1040         // createInstance, createInstanceWithArguments
1041 
1042         OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1043                     "caught Exception!" );
1044         return Reference< XInterface >();
1045     }
1046 
1047     OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" );
1048     return Reference< XInterface >();
1049 }
1050 
1051 typedef OMultiTypeInterfaceContainerHelperVar<OUString> PropertyListeners_Impl;
1052 
1053 struct PersistentPropertySet_Impl
1054 {
1055     rtl::Reference<PropertySetRegistry>  m_pCreator;
1056     rtl::Reference<PropertySetInfo_Impl> m_pInfo;
1057     OUString                    m_aKey;
1058     OUString                    m_aFullKey;
1059     osl::Mutex                  m_aMutex;
1060     std::unique_ptr<OInterfaceContainerHelper2>  m_pDisposeEventListeners;
1061     std::unique_ptr<OInterfaceContainerHelper2>  m_pPropSetChangeListeners;
1062     std::unique_ptr<PropertyListeners_Impl>      m_pPropertyChangeListeners;
1063 
PersistentPropertySet_ImplPersistentPropertySet_Impl1064     PersistentPropertySet_Impl( PropertySetRegistry& rCreator,
1065                                 const OUString& rKey )
1066     : m_pCreator( &rCreator ), m_aKey( rKey )
1067     {
1068     }
1069 };
1070 
1071 
1072 // PersistentPropertySet Implementation.
1073 
1074 
PersistentPropertySet(PropertySetRegistry & rCreator,const OUString & rKey)1075 PersistentPropertySet::PersistentPropertySet(
1076                         PropertySetRegistry& rCreator,
1077                         const OUString& rKey )
1078 : m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) )
1079 {
1080     // register at creator.
1081     rCreator.add( this );
1082 }
1083 
1084 
1085 // virtual
~PersistentPropertySet()1086 PersistentPropertySet::~PersistentPropertySet()
1087 {
1088     // deregister at creator.
1089     m_pImpl->m_pCreator->remove( this );
1090 }
1091 
1092 // XServiceInfo methods.
1093 
getImplementationName()1094 OUString SAL_CALL PersistentPropertySet::getImplementationName()
1095 {
1096     return "com.sun.star.comp.ucb.PersistentPropertySet";
1097 }
1098 
supportsService(const OUString & ServiceName)1099 sal_Bool SAL_CALL PersistentPropertySet::supportsService( const OUString& ServiceName )
1100 {
1101     return cppu::supportsService( this, ServiceName );
1102 }
1103 
getSupportedServiceNames()1104 css::uno::Sequence< OUString > SAL_CALL PersistentPropertySet::getSupportedServiceNames()
1105 {
1106     return { "com.sun.star.ucb.PersistentPropertySet" };
1107 }
1108 
1109 
1110 // XComponent methods.
1111 
1112 
1113 // virtual
dispose()1114 void SAL_CALL PersistentPropertySet::dispose()
1115 {
1116     if ( m_pImpl->m_pDisposeEventListeners &&
1117          m_pImpl->m_pDisposeEventListeners->getLength() )
1118     {
1119         EventObject aEvt;
1120         aEvt.Source = static_cast< XComponent * >( this  );
1121         m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
1122     }
1123 
1124     if ( m_pImpl->m_pPropSetChangeListeners &&
1125          m_pImpl->m_pPropSetChangeListeners->getLength() )
1126     {
1127         EventObject aEvt;
1128         aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this  );
1129         m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
1130     }
1131 
1132     if ( m_pImpl->m_pPropertyChangeListeners )
1133     {
1134         EventObject aEvt;
1135         aEvt.Source = static_cast< XPropertySet * >( this  );
1136         m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
1137     }
1138 }
1139 
1140 
1141 // virtual
addEventListener(const Reference<XEventListener> & Listener)1142 void SAL_CALL PersistentPropertySet::addEventListener(
1143                             const Reference< XEventListener >& Listener )
1144 {
1145     if ( !m_pImpl->m_pDisposeEventListeners )
1146         m_pImpl->m_pDisposeEventListeners.reset(
1147                     new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) );
1148 
1149     m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
1150 }
1151 
1152 
1153 // virtual
removeEventListener(const Reference<XEventListener> & Listener)1154 void SAL_CALL PersistentPropertySet::removeEventListener(
1155                             const Reference< XEventListener >& Listener )
1156 {
1157     if ( m_pImpl->m_pDisposeEventListeners )
1158         m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
1159 
1160     // Note: Don't want to delete empty container here -> performance.
1161 }
1162 
1163 
1164 // XPropertySet methods.
1165 
1166 
1167 // virtual
getPropertySetInfo()1168 Reference< XPropertySetInfo > SAL_CALL PersistentPropertySet::getPropertySetInfo()
1169 {
1170     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1171 
1172     if ( !m_pImpl->m_pInfo.is() )
1173     {
1174         m_pImpl->m_pInfo = new PropertySetInfo_Impl( this );
1175     }
1176     return m_pImpl->m_pInfo;
1177 }
1178 
1179 
1180 // virtual
setPropertyValue(const OUString & aPropertyName,const Any & aValue)1181 void SAL_CALL PersistentPropertySet::setPropertyValue( const OUString& aPropertyName,
1182                                                        const Any& aValue )
1183 {
1184     osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1185 
1186     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1187                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1188     if ( xRootHierNameAccess.is() )
1189     {
1190         OUString aFullPropName( getFullKey() + "/" );
1191         aFullPropName += makeHierarchalNameSegment( aPropertyName );
1192 
1193         // Does property exist?
1194         if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1195         {
1196             Reference< XNameReplace > xNameReplace(
1197                     m_pImpl->m_pCreator->getConfigWriteAccess(
1198                                             aFullPropName ), UNO_QUERY );
1199             Reference< XChangesBatch > xBatch(
1200                     m_pImpl->m_pCreator->getConfigWriteAccess(
1201                                             OUString() ), UNO_QUERY );
1202 
1203             if ( xNameReplace.is() && xBatch.is() )
1204             {
1205                 try
1206                 {
1207                     // Obtain old value
1208                     OUString aValueName = aFullPropName + "/Value";
1209                     Any aOldValue
1210                         = xRootHierNameAccess->getByHierarchicalName(
1211                                                                 aValueName );
1212                     // Check value type.
1213                     if ( aOldValue.getValueType() != aValue.getValueType() )
1214                     {
1215                         aCGuard.clear();
1216                         throw IllegalArgumentException();
1217                     }
1218 
1219                     // Write value
1220                     xNameReplace->replaceByName( "Value", aValue );
1221 
1222                     // Write state ( Now it is a directly set value )
1223                     xNameReplace->replaceByName(
1224                                     "State",
1225                                     makeAny(
1226                                         sal_Int32(
1227                                             PropertyState_DIRECT_VALUE ) ) );
1228 
1229                     // Commit changes.
1230                     xBatch->commitChanges();
1231 
1232                     PropertyChangeEvent aEvt;
1233                     if ( m_pImpl->m_pPropertyChangeListeners )
1234                     {
1235                         // Obtain handle
1236                         aValueName = aFullPropName + "/Handle";
1237                         sal_Int32 nHandle = -1;
1238                         xRootHierNameAccess->getByHierarchicalName( aValueName )
1239                             >>= nHandle;
1240 
1241                         aEvt.Source         = static_cast<OWeakObject*>(this);
1242                         aEvt.PropertyName   = aPropertyName;
1243                         aEvt.PropertyHandle = nHandle;
1244                         aEvt.Further        = false;
1245                         aEvt.OldValue       = aOldValue;
1246                         aEvt.NewValue       = aValue;
1247 
1248                         // Callback follows!
1249                         aCGuard.clear();
1250 
1251                         notifyPropertyChangeEvent( aEvt );
1252                     }
1253                     return;
1254                 }
1255                 catch (const IllegalArgumentException&)
1256                 {
1257                     // replaceByName
1258                 }
1259                 catch (const NoSuchElementException&)
1260                 {
1261                     // getByHierarchicalName, replaceByName
1262                 }
1263                 catch (const WrappedTargetException&)
1264                 {
1265                     // replaceByName, commitChanges
1266                 }
1267             }
1268         }
1269     }
1270 
1271     throw UnknownPropertyException(aPropertyName);
1272 }
1273 
1274 
1275 // virtual
getPropertyValue(const OUString & PropertyName)1276 Any SAL_CALL PersistentPropertySet::getPropertyValue(
1277                                             const OUString& PropertyName )
1278 {
1279     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1280 
1281     Reference< XHierarchicalNameAccess > xNameAccess(
1282                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1283     if ( xNameAccess.is() )
1284     {
1285         OUString aFullPropName( getFullKey() + "/" );
1286         aFullPropName += makeHierarchalNameSegment( PropertyName ) + "/Value";
1287         try
1288         {
1289             return xNameAccess->getByHierarchicalName( aFullPropName );
1290         }
1291         catch (const NoSuchElementException&)
1292         {
1293             throw UnknownPropertyException(aFullPropName);
1294         }
1295     }
1296 
1297     throw UnknownPropertyException(PropertyName);
1298 }
1299 
1300 
1301 // virtual
addPropertyChangeListener(const OUString & aPropertyName,const Reference<XPropertyChangeListener> & xListener)1302 void SAL_CALL PersistentPropertySet::addPropertyChangeListener(
1303                     const OUString& aPropertyName,
1304                     const Reference< XPropertyChangeListener >& xListener )
1305 {
1306 //  load();
1307 
1308     if ( !m_pImpl->m_pPropertyChangeListeners )
1309         m_pImpl->m_pPropertyChangeListeners.reset(
1310                     new PropertyListeners_Impl( m_pImpl->m_aMutex ) );
1311 
1312     m_pImpl->m_pPropertyChangeListeners->addInterface(
1313                                                 aPropertyName, xListener );
1314 }
1315 
1316 
1317 // virtual
removePropertyChangeListener(const OUString & aPropertyName,const Reference<XPropertyChangeListener> & aListener)1318 void SAL_CALL PersistentPropertySet::removePropertyChangeListener(
1319                     const OUString& aPropertyName,
1320                     const Reference< XPropertyChangeListener >& aListener )
1321 {
1322 //  load();
1323 
1324     if ( m_pImpl->m_pPropertyChangeListeners )
1325         m_pImpl->m_pPropertyChangeListeners->removeInterface(
1326                                                 aPropertyName, aListener );
1327 
1328     // Note: Don't want to delete empty container here -> performance.
1329 }
1330 
1331 
1332 // virtual
addVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)1333 void SAL_CALL PersistentPropertySet::addVetoableChangeListener(
1334                     const OUString&,
1335                     const Reference< XVetoableChangeListener >& )
1336 {
1337 //  load();
1338 //  OSL_FAIL( //                "PersistentPropertySet::addVetoableChangeListener - N.Y.I." );
1339 }
1340 
1341 
1342 // virtual
removeVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)1343 void SAL_CALL PersistentPropertySet::removeVetoableChangeListener(
1344                     const OUString&,
1345                     const Reference< XVetoableChangeListener >& )
1346 {
1347 //  load();
1348 //  OSL_FAIL( //                "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." );
1349 }
1350 
1351 
1352 // XPersistentPropertySet methods.
1353 
1354 
1355 // virtual
getRegistry()1356 Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry()
1357 {
1358     return m_pImpl->m_pCreator;
1359 }
1360 
1361 
1362 // virtual
getKey()1363 OUString SAL_CALL PersistentPropertySet::getKey()
1364 {
1365     return m_pImpl->m_aKey;
1366 }
1367 
1368 
1369 // XNamed methods.
1370 
1371 
1372 // virtual
getName()1373 OUString SAL_CALL PersistentPropertySet::getName()
1374 {
1375     // same as getKey()
1376     return m_pImpl->m_aKey;
1377 }
1378 
1379 
1380 // virtual
setName(const OUString & aName)1381 void SAL_CALL PersistentPropertySet::setName( const OUString& aName )
1382 {
1383     if ( aName != m_pImpl->m_aKey )
1384         m_pImpl->m_pCreator->renamePropertySet( m_pImpl->m_aKey, aName );
1385 }
1386 
1387 
1388 // XPropertyContainer methods.
1389 
1390 
1391 // virtual
addProperty(const OUString & Name,sal_Int16 Attributes,const Any & DefaultValue)1392 void SAL_CALL PersistentPropertySet::addProperty(
1393         const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue )
1394 {
1395     if ( Name.isEmpty() )
1396         throw IllegalArgumentException();
1397 
1398     // @@@ What other types can't be written to config server?
1399 
1400     // Check type class ( Not all types can be written to storage )
1401     TypeClass eTypeClass = DefaultValue.getValueTypeClass();
1402     if ( eTypeClass == TypeClass_INTERFACE )
1403         throw IllegalTypeException();
1404 
1405     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1406 
1407     // Property already in set?
1408 
1409     OUString aFullValuesName;
1410 
1411     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1412                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1413     if ( xRootHierNameAccess.is() )
1414     {
1415         aFullValuesName = getFullKey();
1416         OUString aFullPropName = aFullValuesName + "/";
1417         aFullPropName += makeHierarchalNameSegment( Name );
1418 
1419         if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1420         {
1421             // Already in set.
1422             throw PropertyExistException();
1423         }
1424     }
1425 
1426     // Property is always removable.
1427     Attributes |= PropertyAttribute::REMOVABLE;
1428 
1429     // Add property.
1430 
1431     Reference< XSingleServiceFactory > xFac(
1432                 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1433                 UNO_QUERY );
1434     Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
1435     Reference< XChangesBatch >  xBatch(
1436                 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1437                 UNO_QUERY );
1438 
1439     OSL_ENSURE( xFac.is(),
1440                 "PersistentPropertySet::addProperty - No factory!" );
1441 
1442     OSL_ENSURE( xBatch.is(),
1443                 "PersistentPropertySet::addProperty - No batch!" );
1444 
1445     OSL_ENSURE( xContainer.is(),
1446                 "PersistentPropertySet::addProperty - No container!" );
1447 
1448     if ( xFac.is() && xBatch.is() && xContainer.is() )
1449     {
1450         try
1451         {
1452             // Create new "PropertyValue" config item.
1453             Reference< XNameReplace > xNameReplace(
1454                                         xFac->createInstance(), UNO_QUERY );
1455 
1456             if ( xNameReplace.is() )
1457             {
1458                 // Fill new item...
1459 
1460                 // Set handle
1461                 xNameReplace->replaceByName(
1462                                     "Handle",
1463                                     makeAny( sal_Int32( -1 ) ) );
1464 
1465                 // Set default value
1466                 xNameReplace->replaceByName(
1467                                     "Value",
1468                                     DefaultValue );
1469 
1470                 // Set state ( always "default" )
1471                 xNameReplace->replaceByName(
1472                                     "State",
1473                                     makeAny(
1474                                         sal_Int32(
1475                                             PropertyState_DEFAULT_VALUE ) ) );
1476 
1477                 // Set attributes
1478                 xNameReplace->replaceByName(
1479                                     "Attributes",
1480                                     makeAny( sal_Int32( Attributes ) ) );
1481 
1482                 // Insert new item.
1483                 xContainer->insertByName( Name, makeAny( xNameReplace ) );
1484 
1485                 // Commit changes.
1486                 xBatch->commitChanges();
1487 
1488                 // Property set info is invalid.
1489                 if ( m_pImpl->m_pInfo.is() )
1490                     m_pImpl->m_pInfo->reset();
1491 
1492                 // Notify propertyset info change listeners.
1493                 if ( m_pImpl->m_pPropSetChangeListeners &&
1494                      m_pImpl->m_pPropSetChangeListeners->getLength() )
1495                 {
1496                     PropertySetInfoChangeEvent evt(
1497                                     static_cast< OWeakObject * >( this ),
1498                                     Name,
1499                                     -1,
1500                                     PropertySetInfoChange::PROPERTY_INSERTED );
1501                     notifyPropertySetInfoChange( evt );
1502                 }
1503 
1504                 // Success.
1505                 return;
1506             }
1507         }
1508         catch (const IllegalArgumentException&)
1509         {
1510             // insertByName
1511 
1512             OSL_FAIL( "PersistentPropertySet::addProperty - "
1513                         "caught IllegalArgumentException!" );
1514             return;
1515         }
1516         catch (const ElementExistException&)
1517         {
1518             // insertByName
1519 
1520             OSL_FAIL( "PersistentPropertySet::addProperty - "
1521                         "caught ElementExistException!" );
1522             return;
1523         }
1524         catch (const WrappedTargetException&)
1525         {
1526             // replaceByName, insertByName, commitChanges
1527 
1528             OSL_FAIL( "PersistentPropertySet::addProperty - "
1529                         "caught WrappedTargetException!" );
1530             return;
1531         }
1532         catch (const RuntimeException&)
1533         {
1534             throw;
1535         }
1536         catch (const Exception&)
1537         {
1538             // createInstance
1539 
1540             OSL_FAIL( "PersistentPropertySet::addProperty - "
1541                         "caught Exception!" );
1542             return;
1543         }
1544     }
1545 
1546     OSL_FAIL( "PersistentPropertySet::addProperty - Error!" );
1547 }
1548 
1549 
1550 // virtual
removeProperty(const OUString & Name)1551 void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name )
1552 {
1553     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1554 
1555     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1556                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1557     if ( xRootHierNameAccess.is() )
1558     {
1559         OUString aFullValuesName = getFullKey();
1560         OUString aFullPropName   = aFullValuesName + "/";
1561         aFullPropName   += makeHierarchalNameSegment( Name );
1562 
1563         // Property in set?
1564         if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1565             throw UnknownPropertyException(aFullPropName);
1566 
1567         // Property removable?
1568         try
1569         {
1570             OUString aFullAttrName = aFullPropName + "/Attributes";
1571 
1572             sal_Int32 nAttribs = 0;
1573             if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1574                     >>= nAttribs )
1575             {
1576                 if ( !( nAttribs & PropertyAttribute::REMOVABLE ) )
1577                 {
1578                     // Not removable!
1579                     throw NotRemoveableException();
1580                 }
1581             }
1582             else
1583             {
1584                 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1585                             "No attributes!" );
1586                 return;
1587             }
1588         }
1589         catch (const NoSuchElementException&)
1590         {
1591             // getByHierarchicalName
1592 
1593             OSL_FAIL( "PersistentPropertySet::removeProperty - "
1594                         "caught NoSuchElementException!" );
1595         }
1596 
1597         // Remove property...
1598 
1599         Reference< XNameContainer > xContainer(
1600                 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1601                 UNO_QUERY );
1602         Reference< XChangesBatch > xBatch(
1603                 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1604                 UNO_QUERY );
1605 
1606         OSL_ENSURE( xBatch.is(),
1607                     "PersistentPropertySet::removeProperty - No batch!" );
1608 
1609         OSL_ENSURE( xContainer.is(),
1610                     "PersistentPropertySet::removeProperty - No container!" );
1611 
1612         if ( xBatch.is() && xContainer.is() )
1613         {
1614             try
1615             {
1616                 sal_Int32 nHandle = -1;
1617 
1618                 if ( m_pImpl->m_pPropSetChangeListeners &&
1619                        m_pImpl->m_pPropSetChangeListeners->getLength() )
1620                 {
1621                     // Obtain property handle ( needed for propertysetinfo
1622                     // change event )...
1623 
1624                     try
1625                     {
1626                         OUString aFullHandleName = aFullPropName + "/Handle";
1627 
1628                         if ( ! ( xRootHierNameAccess->getByHierarchicalName(
1629                                         aFullHandleName ) >>= nHandle ) )
1630                             nHandle = -1;
1631 
1632                     }
1633                     catch (const NoSuchElementException&)
1634                     {
1635                         // getByHierarchicalName
1636 
1637                         OSL_FAIL( "PersistentPropertySet::removeProperty - "
1638                                     "caught NoSuchElementException!" );
1639                         nHandle = -1;
1640                     }
1641                 }
1642 
1643                 xContainer->removeByName( Name );
1644                 xBatch->commitChanges();
1645 
1646                 // Property set info is invalid.
1647                 if ( m_pImpl->m_pInfo.is() )
1648                     m_pImpl->m_pInfo->reset();
1649 
1650                 // Notify propertyset info change listeners.
1651                 if ( m_pImpl->m_pPropSetChangeListeners &&
1652                       m_pImpl->m_pPropSetChangeListeners->getLength() )
1653                 {
1654                     PropertySetInfoChangeEvent evt(
1655                                     static_cast< OWeakObject * >( this ),
1656                                     Name,
1657                                     nHandle,
1658                                     PropertySetInfoChange::PROPERTY_REMOVED );
1659                     notifyPropertySetInfoChange( evt );
1660                 }
1661 
1662                 // Success.
1663                 return;
1664             }
1665             catch (const NoSuchElementException&)
1666             {
1667                 // removeByName
1668 
1669                 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1670                             "caught NoSuchElementException!" );
1671                 return;
1672             }
1673             catch (const WrappedTargetException&)
1674             {
1675                 // commitChanges
1676 
1677                 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1678                             "caught WrappedTargetException!" );
1679                 return;
1680             }
1681         }
1682     }
1683 
1684     OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" );
1685 }
1686 
1687 
1688 // XPropertySetInfoChangeNotifier methods.
1689 
1690 
1691 // virtual
addPropertySetInfoChangeListener(const Reference<XPropertySetInfoChangeListener> & Listener)1692 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
1693                 const Reference< XPropertySetInfoChangeListener >& Listener )
1694 {
1695     if ( !m_pImpl->m_pPropSetChangeListeners )
1696         m_pImpl->m_pPropSetChangeListeners.reset(
1697                     new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) );
1698 
1699     m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
1700 }
1701 
1702 
1703 // virtual
removePropertySetInfoChangeListener(const Reference<XPropertySetInfoChangeListener> & Listener)1704 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
1705                 const Reference< XPropertySetInfoChangeListener >& Listener )
1706 {
1707     if ( m_pImpl->m_pPropSetChangeListeners )
1708         m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
1709 }
1710 
1711 
1712 // XPropertyAccess methods.
1713 
1714 
1715 // virtual
getPropertyValues()1716 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
1717 {
1718     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1719 
1720     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1721                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1722     if ( xRootHierNameAccess.is() )
1723     {
1724         try
1725         {
1726             Reference< XNameAccess > xNameAccess;
1727             xRootHierNameAccess->getByHierarchicalName(getFullKey())
1728                 >>= xNameAccess;
1729             if ( xNameAccess.is() )
1730             {
1731                 // Obtain property names.
1732 
1733                 Sequence< OUString > aElems = xNameAccess->getElementNames();
1734 
1735                 sal_Int32 nCount = aElems.getLength();
1736                 if ( nCount )
1737                 {
1738                     Reference< XHierarchicalNameAccess > xHierNameAccess(
1739                                                     xNameAccess, UNO_QUERY );
1740 
1741                     OSL_ENSURE( xHierNameAccess.is(),
1742                                 "PersistentPropertySet::getPropertyValues - "
1743                                 "No hierarchical name access!" );
1744 
1745                     if ( xHierNameAccess.is() )
1746                     {
1747                         Sequence< PropertyValue > aValues( nCount );
1748 
1749                         static const OUStringLiteral aHandleName(u"/Handle");
1750                         static const OUStringLiteral aValueName(u"/Value");
1751                         static const OUStringLiteral aStateName(u"/State");
1752 
1753                         for ( sal_Int32 n = 0; n < nCount; ++n )
1754                         {
1755                             PropertyValue& rValue = aValues[ n ];
1756                             OUString rName    = aElems[ n ];
1757                             OUString aXMLName
1758                                         = makeHierarchalNameSegment( rName );
1759 
1760                             // Set property name.
1761 
1762                             rValue.Name = rName;
1763 
1764                             try
1765                             {
1766                                 // Obtain and set property handle
1767                                 OUString aHierName = aXMLName + aHandleName;
1768                                 Any aKeyValue
1769                                     = xHierNameAccess->getByHierarchicalName(
1770                                         aHierName );
1771 
1772                                 if ( !( aKeyValue >>= rValue.Handle ) )
1773                                     OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1774                                       "Error getting property handle!" );
1775                             }
1776                             catch (const NoSuchElementException&)
1777                             {
1778                                 // getByHierarchicalName
1779 
1780                                 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1781                                   "NoSuchElementException!" );
1782                             }
1783 
1784                             try
1785                             {
1786                                 // Obtain and set property value
1787                                 OUString aHierName = aXMLName + aValueName;
1788                                 rValue.Value
1789                                     = xHierNameAccess->getByHierarchicalName(
1790                                         aHierName );
1791 
1792                                 // Note: The value may be void if addProperty
1793                                 //       was called with a default value
1794                                 //       of type void.
1795                             }
1796                             catch (const NoSuchElementException&)
1797                             {
1798                                 // getByHierarchicalName
1799 
1800                                 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1801                                   "NoSuchElementException!" );
1802                             }
1803 
1804                             try
1805                             {
1806                                 // Obtain and set property state
1807                                 OUString aHierName = aXMLName +aStateName;
1808                                 Any aKeyValue
1809                                     = xHierNameAccess->getByHierarchicalName(
1810                                         aHierName );
1811 
1812                                 sal_Int32 nState = 0;
1813                                 if ( !( aKeyValue >>= nState ) )
1814                                     OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1815                                       "Error getting property state!" );
1816                                 else
1817                                     rValue.State = PropertyState( nState );
1818                             }
1819                             catch (const NoSuchElementException&)
1820                             {
1821                                 // getByHierarchicalName
1822 
1823                                 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1824                                   "NoSuchElementException!" );
1825                             }
1826                         }
1827 
1828                         return aValues;
1829                     }
1830                 }
1831             }
1832         }
1833         catch (const NoSuchElementException&)
1834         {
1835             // getByHierarchicalName
1836         }
1837     }
1838 
1839     return Sequence< PropertyValue >( 0 );
1840 }
1841 
1842 
1843 // virtual
setPropertyValues(const Sequence<PropertyValue> & aProps)1844 void SAL_CALL PersistentPropertySet::setPropertyValues(
1845                                  const Sequence< PropertyValue >& aProps )
1846 {
1847     if ( !aProps.hasElements() )
1848         return;
1849 
1850     osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1851 
1852     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1853                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1854     if ( xRootHierNameAccess.is() )
1855     {
1856         std::vector< PropertyChangeEvent > aEvents;
1857 
1858         OUString aFullPropNamePrefix( getFullKey() + "/" );
1859 
1860         // Iterate over given property value sequence.
1861         for ( const PropertyValue& rNewValue : aProps )
1862         {
1863             const OUString& rName = rNewValue.Name;
1864 
1865             OUString aFullPropName = aFullPropNamePrefix;
1866             aFullPropName += makeHierarchalNameSegment( rName );
1867 
1868             // Does property exist?
1869             if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1870             {
1871                 Reference< XNameReplace > xNameReplace(
1872                     m_pImpl->m_pCreator->getConfigWriteAccess(
1873                                             aFullPropName ), UNO_QUERY );
1874                 Reference< XChangesBatch > xBatch(
1875                     m_pImpl->m_pCreator->getConfigWriteAccess(
1876                                             OUString() ), UNO_QUERY );
1877 
1878                 if ( xNameReplace.is() && xBatch.is() )
1879                 {
1880                     try
1881                     {
1882                         // Write handle
1883                         xNameReplace->replaceByName(
1884                                     "Handle",
1885                                     makeAny( rNewValue.Handle ) );
1886 
1887                         // Save old value
1888                         OUString aValueName = aFullPropName +"/Value";
1889                         Any aOldValue
1890                             = xRootHierNameAccess->getByHierarchicalName(
1891                                                                 aValueName );
1892                         // Write value
1893                         xNameReplace->replaceByName(
1894                                     "Value",
1895                                     rNewValue.Value );
1896 
1897                         // Write state ( Now it is a directly set value )
1898                         xNameReplace->replaceByName(
1899                                     "State",
1900                                     makeAny(
1901                                         sal_Int32(
1902                                             PropertyState_DIRECT_VALUE ) ) );
1903 
1904                         // Commit changes.
1905                         xBatch->commitChanges();
1906 
1907                         if ( m_pImpl->m_pPropertyChangeListeners )
1908                         {
1909                             PropertyChangeEvent aEvt;
1910                             aEvt.Source         = static_cast<OWeakObject*>(this);
1911                             aEvt.PropertyName   = rNewValue.Name;
1912                             aEvt.PropertyHandle = rNewValue.Handle;
1913                             aEvt.Further        = false;
1914                             aEvt.OldValue       = aOldValue;
1915                             aEvt.NewValue       = rNewValue.Value;
1916 
1917                             aEvents.push_back( aEvt );
1918                         }
1919                     }
1920                     catch (const IllegalArgumentException&)
1921                     {
1922                         // replaceByName
1923                     }
1924                     catch (const NoSuchElementException&)
1925                     {
1926                         // getByHierarchicalName, replaceByName
1927                     }
1928                     catch (const WrappedTargetException&)
1929                     {
1930                         // replaceByName, commitChanges
1931                     }
1932                 }
1933             }
1934         }
1935 
1936         // Callback follows!
1937         aCGuard.clear();
1938 
1939         if ( m_pImpl->m_pPropertyChangeListeners )
1940         {
1941             // Notify property changes.
1942             for (auto const& event : aEvents)
1943             {
1944                 notifyPropertyChangeEvent( event );
1945             }
1946         }
1947 
1948         return;
1949     }
1950 
1951     OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" );
1952 }
1953 
1954 
1955 // Non-interface methods
1956 
1957 
notifyPropertyChangeEvent(const PropertyChangeEvent & rEvent) const1958 void PersistentPropertySet::notifyPropertyChangeEvent(
1959                                     const PropertyChangeEvent& rEvent ) const
1960 {
1961     // Get "normal" listeners for the property.
1962     OInterfaceContainerHelper* pContainer =
1963             m_pImpl->m_pPropertyChangeListeners->getContainer(
1964                                                     rEvent.PropertyName );
1965     if ( pContainer && pContainer->getLength() )
1966     {
1967         OInterfaceIteratorHelper aIter( *pContainer );
1968         while ( aIter.hasMoreElements() )
1969         {
1970             // Propagate event.
1971             Reference< XPropertyChangeListener > xListener(
1972                                                     aIter.next(), UNO_QUERY );
1973             if ( xListener.is() )
1974                 xListener->propertyChange( rEvent );
1975         }
1976     }
1977 
1978     // Get "normal" listeners for all properties.
1979     OInterfaceContainerHelper* pNoNameContainer =
1980             m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() );
1981     if ( pNoNameContainer && pNoNameContainer->getLength() )
1982     {
1983         OInterfaceIteratorHelper aIter( *pNoNameContainer );
1984         while ( aIter.hasMoreElements() )
1985         {
1986             // Propagate event.
1987             Reference< XPropertyChangeListener > xListener(
1988                                                     aIter.next(), UNO_QUERY );
1989             if ( xListener.is() )
1990                 xListener->propertyChange( rEvent );
1991         }
1992     }
1993 }
1994 
1995 
notifyPropertySetInfoChange(const PropertySetInfoChangeEvent & evt) const1996 void PersistentPropertySet::notifyPropertySetInfoChange(
1997                                 const PropertySetInfoChangeEvent& evt ) const
1998 {
1999     if ( !m_pImpl->m_pPropSetChangeListeners )
2000         return;
2001 
2002     // Notify event listeners.
2003     OInterfaceIteratorHelper2 aIter( *( m_pImpl->m_pPropSetChangeListeners ) );
2004     while ( aIter.hasMoreElements() )
2005     {
2006         // Propagate event.
2007         Reference< XPropertySetInfoChangeListener >
2008                             xListener( aIter.next(), UNO_QUERY );
2009         if ( xListener.is() )
2010             xListener->propertySetInfoChange( evt );
2011     }
2012 }
2013 
2014 
getFullKey()2015 const OUString& PersistentPropertySet::getFullKey()
2016 {
2017     if ( m_pImpl->m_aFullKey.isEmpty() )
2018     {
2019         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
2020         if ( m_pImpl->m_aFullKey.isEmpty() )
2021         {
2022             m_pImpl->m_aFullKey
2023                 = makeHierarchalNameSegment( m_pImpl->m_aKey );
2024             m_pImpl->m_aFullKey
2025                 += "/Values";
2026         }
2027     }
2028 
2029     return m_pImpl->m_aFullKey;
2030 }
2031 
2032 
getPropertySetRegistry()2033 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
2034 {
2035     return *m_pImpl->m_pCreator;
2036 }
2037 
2038 
2039 // PropertySetInfo_Impl Implementation.
2040 
2041 
PropertySetInfo_Impl(PersistentPropertySet * pOwner)2042 PropertySetInfo_Impl::PropertySetInfo_Impl(
2043                         PersistentPropertySet* pOwner )
2044 : m_pOwner( pOwner )
2045 {
2046 }
2047 
2048 
2049 // XPropertySetInfo methods.
2050 
2051 
2052 // virtual
getProperties()2053 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
2054 {
2055     if ( !m_pProps )
2056     {
2057         Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2058             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2059             UNO_QUERY );
2060         if ( xRootHierNameAccess.is() )
2061         {
2062             try
2063             {
2064                 Reference< XNameAccess > xNameAccess;
2065                 xRootHierNameAccess->getByHierarchicalName(
2066                             m_pOwner->getFullKey() )
2067                     >>= xNameAccess;
2068                 if ( xNameAccess.is() )
2069                 {
2070                     // Obtain property names.
2071 
2072                     Sequence< OUString > aElems
2073                                             = xNameAccess->getElementNames();
2074 
2075                     sal_uInt32 nCount = aElems.getLength();
2076                     Sequence< Property >* pPropSeq
2077                                         = new Sequence< Property >( nCount );
2078 
2079                     if ( nCount )
2080                     {
2081                         Reference< XHierarchicalNameAccess > xHierNameAccess(
2082                                                     xNameAccess, UNO_QUERY );
2083 
2084                         OSL_ENSURE( xHierNameAccess.is(),
2085                                     "PropertySetInfo_Impl::getProperties - "
2086                                     "No hierarchical name access!" );
2087 
2088                         if ( xHierNameAccess.is() )
2089                         {
2090                             static const OUStringLiteral aHandleName(u"/Handle");
2091                             static const OUStringLiteral aValueName(u"/Value");
2092                             static const OUStringLiteral aAttrName(u"/Attributes");
2093 
2094                             Property* pProps = pPropSeq->getArray();
2095 
2096                             for ( sal_uInt32 n = 0; n < nCount; ++n )
2097                             {
2098                                 Property& rProp = pProps[ n ];
2099                                 OUString  rName = aElems[ n ];
2100                                 OUString aXMLName
2101                                     = makeHierarchalNameSegment( rName );
2102 
2103                                 // Set property name.
2104 
2105                                 rProp.Name = rName;
2106 
2107                                 try
2108                                 {
2109                                     // Obtain and set property handle
2110                                     OUString aHierName = aXMLName + aHandleName;
2111                                     Any aKeyValue
2112                                         = xHierNameAccess->getByHierarchicalName(
2113                                             aHierName );
2114 
2115                                     if ( !( aKeyValue >>= rProp.Handle ) )
2116                                         OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2117                                           "Error getting property handle!" );
2118                                 }
2119                                 catch (const NoSuchElementException&)
2120                                 {
2121                                     // getByHierarchicalName
2122 
2123                                     OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2124                                       "NoSuchElementException!" );
2125                                 }
2126 
2127                                 try
2128                                 {
2129                                     // Obtain and set property type
2130                                     OUString aHierName = aXMLName + aValueName;
2131                                     Any aKeyValue
2132                                         = xHierNameAccess->getByHierarchicalName(
2133                                             aHierName );
2134 
2135                                     // Note: The type may be void if addProperty
2136                                     //       was called with a default value
2137                                     //       of type void.
2138 
2139                                     rProp.Type = aKeyValue.getValueType();
2140                                 }
2141                                 catch (const NoSuchElementException&)
2142                                 {
2143                                     // getByHierarchicalName
2144 
2145                                     OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2146                                       "NoSuchElementException!" );
2147                                 }
2148 
2149                                 try
2150                                 {
2151                                     // Obtain and set property attributes
2152                                     OUString aHierName = aXMLName + aAttrName;
2153                                     Any aKeyValue
2154                                         = xHierNameAccess->getByHierarchicalName(
2155                                             aHierName );
2156 
2157                                     sal_Int32 nAttribs = 0;
2158                                     if ( aKeyValue >>= nAttribs )
2159                                         rProp.Attributes
2160                                             = sal_Int16( nAttribs );
2161                                     else
2162                                         OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2163                                           "Error getting property attributes!" );
2164                                 }
2165                                 catch (const NoSuchElementException&)
2166                                 {
2167                                     // getByHierarchicalName
2168 
2169                                     OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2170                                       "NoSuchElementException!" );
2171                                 }
2172                             }
2173                         }
2174                     }
2175 
2176                     // Success.
2177                     m_pProps.reset( pPropSeq );
2178                     return *m_pProps;
2179                 }
2180             }
2181             catch (const NoSuchElementException&)
2182             {
2183                 // getByHierarchicalName
2184             }
2185         }
2186 
2187         OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" );
2188         m_pProps.reset( new Sequence< Property >( 0 ) );
2189     }
2190 
2191     return *m_pProps;
2192 }
2193 
2194 
2195 // virtual
getPropertyByName(const OUString & aName)2196 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2197                                                     const OUString& aName )
2198 {
2199     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2200             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2201             UNO_QUERY );
2202     if ( xRootHierNameAccess.is() )
2203     {
2204         OUString aFullPropName( m_pOwner->getFullKey() + "/" );
2205         aFullPropName += makeHierarchalNameSegment( aName );
2206 
2207         // Does property exist?
2208         if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2209             throw UnknownPropertyException(aFullPropName);
2210 
2211         try
2212         {
2213             Property aProp;
2214 
2215             // Obtain handle.
2216             OUString aKey = aFullPropName + "/Handle";
2217 
2218             if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2219                     >>= aProp.Handle ) )
2220             {
2221                 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2222                             "No handle!" );
2223                 return Property();
2224             }
2225 
2226             // Obtain Value and extract type.
2227             aKey = aFullPropName + "/Value";
2228 
2229             Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2230             if ( !aValue.hasValue() )
2231             {
2232                 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2233                             "No Value!" );
2234                 return Property();
2235             }
2236 
2237             aProp.Type = aValue.getValueType();
2238 
2239             // Obtain Attributes.
2240             aKey = aFullPropName + "/Attributes";
2241 
2242             sal_Int32 nAttribs = 0;
2243             if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2244                     >>= nAttribs )
2245                 aProp.Attributes = sal_Int16( nAttribs );
2246             else
2247             {
2248                 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2249                             "No attributes!" );
2250                 return Property();
2251             }
2252 
2253             // set name.
2254             aProp.Name = aName;
2255 
2256             // Success.
2257             return aProp;
2258         }
2259         catch (const NoSuchElementException&)
2260         {
2261             // getByHierarchicalName
2262 
2263             OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2264                         "caught NoSuchElementException!" );
2265         }
2266 
2267     }
2268 
2269     OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" );
2270     return Property();
2271 }
2272 
2273 
2274 // virtual
hasPropertyByName(const OUString & Name)2275 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2276                                                     const OUString& Name )
2277 {
2278     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2279             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2280             UNO_QUERY );
2281     if ( xRootHierNameAccess.is() )
2282     {
2283         OUString aFullPropName( m_pOwner->getFullKey() + "/" );
2284         aFullPropName += makeHierarchalNameSegment( Name );
2285 
2286         return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2287     }
2288 
2289     return false;
2290 }
2291 
2292 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2293