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 <osl/diagnose.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 <ucbhelper/getcomponentcontext.hxx>
49 #include <ucbhelper/macros.hxx>
50 #include <tools/diagnose_ex.h>
51 #include "ucbstore.hxx"
52 
53 using namespace com::sun::star::beans;
54 using namespace com::sun::star::configuration;
55 using namespace com::sun::star::container;
56 using namespace com::sun::star::lang;
57 using namespace com::sun::star::ucb;
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star::util;
60 using namespace comphelper;
61 using namespace cppu;
62 
63 
makeHierarchalNameSegment(const OUString & rIn)64 static OUString makeHierarchalNameSegment( const OUString & rIn  )
65 {
66     OUStringBuffer aBuffer;
67     aBuffer.append( "['" );
68 
69     sal_Int32 nCount = rIn.getLength();
70     for ( sal_Int32 n = 0; n < nCount; ++n )
71     {
72         const sal_Unicode c = rIn[ n ];
73         switch ( c )
74         {
75             case '&':
76                 aBuffer.append( "&amp;" );
77                 break;
78 
79             case '"':
80                 aBuffer.append( "&quot;" );
81                 break;
82 
83             case '\'':
84                 aBuffer.append( "&apos;" );
85                 break;
86 
87             case '<':
88                 aBuffer.append( "&lt;" );
89                 break;
90 
91             case '>':
92                 aBuffer.append( "&gt;" );
93                 break;
94 
95             default:
96                 aBuffer.append( c );
97                 break;
98         }
99     }
100 
101     aBuffer.append( "']" );
102     return aBuffer.makeStringAndClear();
103 }
104 
105 #define STORE_CONTENTPROPERTIES_KEY "/org.openoffice.ucb.Store/ContentProperties"
106 
107 // describe path of cfg entry
108 #define CFGPROPERTY_NODEPATH        "nodepath"
109 
110 // PropertySetMap_Impl.
111 typedef std::unordered_map< OUString, PersistentPropertySet*> PropertySetMap_Impl;
112 
113 // class PropertySetInfo_Impl
114 class PropertySetInfo_Impl : public cppu::WeakImplHelper < XPropertySetInfo >
115 {
116     std::unique_ptr<Sequence< Property >>
117                                       m_pProps;
118     PersistentPropertySet*            m_pOwner;
119 
120 public:
121     explicit PropertySetInfo_Impl(PersistentPropertySet* pOwner);
122 
123     // XPropertySetInfo
124     virtual Sequence< Property > SAL_CALL getProperties() override;
125     virtual Property SAL_CALL getPropertyByName( const OUString& aName ) override;
126     virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override;
127 
128     // Non-interface methods.
reset()129     void reset() { m_pProps.reset(); }
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 : m_xContext( xContext ),
149   m_pImpl( new UcbStore_Impl )
150 {
151 }
152 
153 
154 // virtual
~UcbStore()155 UcbStore::~UcbStore()
156 {
157 }
158 
159 XSERVICEINFO_COMMOM_IMPL( UcbStore,
160                           "com.sun.star.comp.ucb.UcbStore" )
161 /// @throws css::uno::Exception
162 static css::uno::Reference< css::uno::XInterface >
UcbStore_CreateInstance(const css::uno::Reference<css::lang::XMultiServiceFactory> & rSMgr)163 UcbStore_CreateInstance( const css::uno::Reference< css::lang::XMultiServiceFactory> & rSMgr )
164 {
165     return static_cast<css::lang::XServiceInfo*>(
166         new UcbStore(ucbhelper::getComponentContext(rSMgr)));
167 }
168 
169 css::uno::Sequence< OUString >
getSupportedServiceNames_Static()170 UcbStore::getSupportedServiceNames_Static()
171 {
172     css::uno::Sequence< OUString > aSNS { STORE_SERVICE_NAME };
173     return aSNS;
174 }
175 
176 // Service factory implementation.
177 
178 
179 ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbStore );
180 
181 
182 // XPropertySetRegistryFactory methods.
183 
184 
185 // virtual
186 Reference< XPropertySetRegistry > SAL_CALL
createPropertySetRegistry(const OUString &)187 UcbStore::createPropertySetRegistry( const OUString& )
188 {
189     // The URL parameter is ignored by this interface implementation. It always
190     // uses the configuration server as storage medium.
191 
192     if ( !m_pImpl->m_xTheRegistry.is() )
193     {
194         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
195         if ( !m_pImpl->m_xTheRegistry.is() )
196             m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xContext, m_pImpl->m_aInitArgs );
197     }
198 
199     return m_pImpl->m_xTheRegistry;
200 }
201 
202 
203 // XInitialization methods.
204 
205 
206 // virtual
initialize(const Sequence<Any> & aArguments)207 void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments )
208 {
209     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
210     m_pImpl->m_aInitArgs = aArguments;
211 }
212 
213 
214 
215 // PropertySetRegistry_Impl.
216 
217 
218 struct PropertySetRegistry_Impl
219 {
220     const Sequence< Any >             m_aInitArgs;
221     PropertySetMap_Impl               m_aPropSets;
222     Reference< XMultiServiceFactory > m_xConfigProvider;
223     Reference< XInterface >           m_xRootReadAccess;
224     Reference< XInterface >           m_xRootWriteAccess;
225     osl::Mutex                        m_aMutex;
226     bool                              m_bTriedToGetRootReadAccess;
227     bool                              m_bTriedToGetRootWriteAccess;
228 
PropertySetRegistry_ImplPropertySetRegistry_Impl229     explicit PropertySetRegistry_Impl(const Sequence<Any> &rInitArgs)
230         : m_aInitArgs(rInitArgs)
231         , m_bTriedToGetRootReadAccess(false)
232         , m_bTriedToGetRootWriteAccess(false)
233     {
234     }
235 };
236 
237 // PropertySetRegistry Implementation.
238 
239 
PropertySetRegistry(const Reference<XComponentContext> & xContext,const Sequence<Any> & rInitArgs)240 PropertySetRegistry::PropertySetRegistry(
241                         const Reference< XComponentContext >& xContext,
242                         const Sequence< Any > &rInitArgs )
243 : m_xContext( xContext ),
244   m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) )
245 {
246 }
247 
248 
249 // virtual
~PropertySetRegistry()250 PropertySetRegistry::~PropertySetRegistry()
251 {
252 }
253 
254 
255 // XServiceInfo methods.
256 
257 
getImplementationName()258 OUString SAL_CALL PropertySetRegistry::getImplementationName()
259 {
260     return "com.sun.star.comp.ucb.PropertySetRegistry";
261 }
262 
supportsService(const OUString & ServiceName)263 sal_Bool SAL_CALL PropertySetRegistry::supportsService( const OUString& ServiceName )
264 {
265     return cppu::supportsService( this, ServiceName );
266 }
267 
getSupportedServiceNames()268 css::uno::Sequence< OUString > SAL_CALL PropertySetRegistry::getSupportedServiceNames()
269 {
270     return { PROPSET_REG_SERVICE_NAME };
271 }
272 
273 
274 // XPropertySetRegistry methods.
275 
276 
277 // virtual
278 Reference< XPersistentPropertySet > SAL_CALL
openPropertySet(const OUString & key,sal_Bool create)279 PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create )
280 {
281     if ( !key.isEmpty() )
282     {
283         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
284 
285         PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
286 
287         PropertySetMap_Impl::const_iterator it = rSets.find( key );
288         if ( it != rSets.end() )
289         {
290             // Already instantiated.
291             return Reference< XPersistentPropertySet >( (*it).second );
292         }
293         else
294         {
295             // Create new instance.
296             Reference< XNameAccess > xRootNameAccess(
297                                     getRootConfigReadAccess(), UNO_QUERY );
298             if ( xRootNameAccess.is() )
299             {
300                 // Propertyset in registry?
301                 if ( xRootNameAccess->hasByName( key ) )
302                 {
303                     // Yep!
304                     return Reference< XPersistentPropertySet >(
305                                             new PersistentPropertySet(
306                                                     *this, key ) );
307                 }
308                 else if ( create )
309                 {
310                     // No. Create entry for propertyset.
311 
312                     Reference< XSingleServiceFactory > xFac(
313                             getConfigWriteAccess( OUString() ), UNO_QUERY );
314                     Reference< XChangesBatch >  xBatch( xFac, UNO_QUERY );
315                     Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
316 
317                     OSL_ENSURE( xFac.is(),
318                                 "PropertySetRegistry::openPropertySet - "
319                                 "No factory!" );
320 
321                     OSL_ENSURE( xBatch.is(),
322                                 "PropertySetRegistry::openPropertySet - "
323                                 "No batch!" );
324 
325                     OSL_ENSURE( xContainer.is(),
326                                 "PropertySetRegistry::openPropertySet - "
327                                 "No container!" );
328 
329                     if ( xFac.is() && xBatch.is() && xContainer.is() )
330                     {
331                         try
332                         {
333                             // Create new "Properties" config item.
334                             Reference< XNameReplace > xNameReplace(
335                                         xFac->createInstance(), UNO_QUERY );
336 
337                             if ( xNameReplace.is() )
338                             {
339                                 // Fill new item...
340 
341                                 // Insert new item.
342                                 xContainer->insertByName(
343                                         key, makeAny( xNameReplace ) );
344                                 // Commit changes.
345                                 xBatch->commitChanges();
346 
347                                 return Reference< XPersistentPropertySet >(
348                                             new PersistentPropertySet(
349                                                     *this, key ) );
350                             }
351                         }
352                         catch (const IllegalArgumentException&)
353                         {
354                             // insertByName
355 
356                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
357                                         "caught IllegalArgumentException!" );
358                         }
359                         catch (const ElementExistException&)
360                         {
361                             // insertByName
362 
363                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
364                                         "caught ElementExistException!" );
365                         }
366                         catch (const WrappedTargetException&)
367                         {
368                             // insertByName, commitChanges
369 
370                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
371                                         "caught WrappedTargetException!" );
372                         }
373                         catch (const RuntimeException&)
374                         {
375                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
376                                         "caught RuntimeException!" );
377                         }
378                         catch (const Exception&)
379                         {
380                             // createInstance
381 
382                             OSL_FAIL( "PropertySetRegistry::openPropertySet - "
383                                         "caught Exception!" );
384                         }
385                     }
386                 }
387                 else
388                 {
389                     // No entry. Fail, but no error.
390                     return Reference< XPersistentPropertySet >();
391                 }
392             }
393 
394             SAL_WARN( "ucb", "no root access" );
395         }
396     }
397 
398     return Reference< XPersistentPropertySet >();
399 }
400 
401 
402 // virtual
removePropertySet(const OUString & key)403 void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key )
404 {
405     if ( key.isEmpty() )
406         return;
407 
408     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
409 
410     Reference< XNameAccess > xRootNameAccess(
411                                     getRootConfigReadAccess(), UNO_QUERY );
412     if ( xRootNameAccess.is() )
413     {
414         // Propertyset in registry?
415         if ( !xRootNameAccess->hasByName( key ) )
416             return;
417         Reference< XChangesBatch > xBatch(
418                             getConfigWriteAccess( OUString() ), UNO_QUERY );
419         Reference< XNameContainer > xContainer( xBatch, UNO_QUERY );
420 
421         if ( xBatch.is() && xContainer.is() )
422         {
423             try
424             {
425                 // Remove item.
426                 xContainer->removeByName( key );
427                 // Commit changes.
428                 xBatch->commitChanges();
429 
430                 // Success.
431                 return;
432             }
433             catch (const NoSuchElementException&)
434             {
435                 // removeByName
436 
437                 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
438                             "caught NoSuchElementException!" );
439                 return;
440             }
441             catch (const WrappedTargetException&)
442             {
443                 // commitChanges
444 
445                 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
446                             "caught WrappedTargetException!" );
447                 return;
448             }
449         }
450 
451         return;
452     }
453 
454     SAL_WARN( "ucb", "no root access" );
455 }
456 
457 
458 // XElementAccess methods.
459 
460 
461 // virtual
getElementType()462 css::uno::Type SAL_CALL PropertySetRegistry::getElementType()
463 {
464     return cppu::UnoType<XPersistentPropertySet>::get();
465 }
466 
467 
468 // virtual
hasElements()469 sal_Bool SAL_CALL PropertySetRegistry::hasElements()
470 {
471     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
472 
473     Reference< XElementAccess > xElemAccess(
474                                     getRootConfigReadAccess(), UNO_QUERY );
475     if ( xElemAccess.is() )
476         return xElemAccess->hasElements();
477 
478     return false;
479 }
480 
481 
482 // XNameAccess methods.
483 
484 
485 // virtual
getByName(const OUString & aName)486 Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName )
487 {
488     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
489 
490     Reference< XNameAccess > xNameAccess(
491                                     getRootConfigReadAccess(), UNO_QUERY );
492     if ( xNameAccess.is() )
493     {
494 
495         try
496         {
497             return xNameAccess->getByName( aName );
498         }
499         catch (const NoSuchElementException&)
500         {
501             // getByName
502         }
503         catch (const WrappedTargetException&)
504         {
505             // getByName
506         }
507     }
508 
509     return Any();
510 }
511 
512 
513 // virtual
getElementNames()514 Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames()
515 {
516     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
517 
518     Reference< XNameAccess > xNameAccess(
519                                     getRootConfigReadAccess(), UNO_QUERY );
520     if ( xNameAccess.is() )
521     {
522         return xNameAccess->getElementNames();
523     }
524     return Sequence< OUString >( 0 );
525 }
526 
527 
528 // virtual
hasByName(const OUString & aName)529 sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName )
530 {
531     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
532 
533     Reference< XNameAccess > xNameAccess(
534                                     getRootConfigReadAccess(), UNO_QUERY );
535     if ( xNameAccess.is() )
536     {
537         return xNameAccess->hasByName( aName );
538     }
539 
540     return false;
541 }
542 
543 
add(PersistentPropertySet * pSet)544 void PropertySetRegistry::add( PersistentPropertySet* pSet )
545 {
546     OUString key( pSet->getKey() );
547 
548     if ( !key.isEmpty() )
549     {
550         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
551         m_pImpl->m_aPropSets[ key ] = pSet;
552     }
553 }
554 
555 
remove(PersistentPropertySet * pSet)556 void PropertySetRegistry::remove( PersistentPropertySet* pSet )
557 {
558     OUString key( pSet->getKey() );
559 
560     if ( !key.isEmpty() )
561     {
562         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
563 
564         PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
565 
566         PropertySetMap_Impl::iterator it = rSets.find( key );
567         if ( it != rSets.end() )
568         {
569             // Found.
570             rSets.erase( it );
571         }
572     }
573 }
574 
575 
renamePropertySet(const OUString & rOldKey,const OUString & rNewKey)576 void PropertySetRegistry::renamePropertySet( const OUString& rOldKey,
577                                              const OUString& rNewKey )
578 {
579     if ( rOldKey == rNewKey )
580         return;
581 
582     Reference< XNameAccess > xRootNameAccess(
583                             getConfigWriteAccess( OUString() ), UNO_QUERY );
584     if ( xRootNameAccess.is() )
585     {
586         // Old key present?
587         if ( xRootNameAccess->hasByName( rOldKey ) )
588         {
589             // New key not present?
590             if ( xRootNameAccess->hasByName( rNewKey ) )
591             {
592                 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
593                             "New key exists!" );
594                 return;
595             }
596             Reference< XSingleServiceFactory > xFac(
597                                                 xRootNameAccess, UNO_QUERY );
598             Reference< XChangesBatch >  xBatch( xFac, UNO_QUERY );
599             Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
600 
601             OSL_ENSURE( xFac.is(),
602                         "PropertySetRegistry::renamePropertySet - "
603                         "No factory!" );
604 
605             OSL_ENSURE( xBatch.is(),
606                         "PropertySetRegistry::renamePropertySet - "
607                         "No batch!" );
608 
609             OSL_ENSURE( xContainer.is(),
610                         "PropertySetRegistry::renamePropertySet - "
611                         "No container!" );
612 
613             if ( xFac.is() && xBatch.is() && xContainer.is() )
614             {
615 
616                 // Create new "Properties" config item.
617 
618 
619                 try
620                 {
621                     Reference< XNameReplace > xNameReplace(
622                                     xFac->createInstance(), UNO_QUERY );
623 
624                     if ( xNameReplace.is() )
625                     {
626                         // Insert new item.
627                         xContainer->insertByName(
628                                     rNewKey, makeAny( xNameReplace ) );
629                         // Commit changes.
630                         xBatch->commitChanges();
631                     }
632                 }
633                 catch (const IllegalArgumentException&)
634                 {
635                     // insertByName
636 
637                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
638                                 "caught IllegalArgumentException!" );
639                     return;
640                 }
641                 catch (const ElementExistException&)
642                 {
643                     // insertByName
644 
645                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
646                                 "caught ElementExistException!" );
647                     return;
648                 }
649                 catch (const WrappedTargetException&)
650                 {
651                     // insertByName, commitChanges
652 
653                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
654                                 "caught WrappedTargetException!" );
655                     return;
656                 }
657                 catch (const RuntimeException&)
658                 {
659                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
660                                 "caught RuntimeException!" );
661                     return;
662                 }
663                 catch (const Exception&)
664                 {
665                     // createInstance
666 
667                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
668                                 "caught Exception!" );
669                     return;
670                 }
671 
672 
673                 // Copy data...
674 
675 
676                 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
677                                                 xRootNameAccess, UNO_QUERY );
678                 if ( !xRootHierNameAccess.is() )
679                 {
680                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
681                                 "No hierarchical name access!" );
682                     return;
683                 }
684 
685                 try
686                 {
687                     OUString aOldValuesKey
688                         = makeHierarchalNameSegment( rOldKey ) + "/Values";
689 
690                     Reference< XNameAccess > xOldNameAccess;
691                     xRootHierNameAccess->getByHierarchicalName(
692                                                         aOldValuesKey )
693                         >>= xOldNameAccess;
694                     if ( !xOldNameAccess.is() )
695                     {
696                         OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
697                             "No old name access!" );
698                         return;
699                     }
700 
701                     // Obtain property names.
702                     const Sequence< OUString > aElems
703                                     = xOldNameAccess->getElementNames();
704                     if ( aElems.hasElements() )
705                     {
706                         OUString aNewValuesKey
707                             = makeHierarchalNameSegment( rNewKey ) + "/Values";
708 
709                         Reference< XSingleServiceFactory > xNewFac;
710                         xRootHierNameAccess->getByHierarchicalName(
711                                                         aNewValuesKey )
712                             >>= xNewFac;
713                         if ( !xNewFac.is() )
714                         {
715                             OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
716                                 "No new factory!" );
717                             return;
718                         }
719 
720                         Reference< XNameContainer > xNewContainer(
721                                                     xNewFac, UNO_QUERY );
722                         if ( !xNewContainer.is() )
723                         {
724                             OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
725                                 "No new container!" );
726                             return;
727                         }
728 
729                         aOldValuesKey += "/";
730 
731                         OUString const aHandleKey("/Handle");
732                         OUString const aValueKey("/Value");
733                         OUString const aStateKey("/State");
734                         OUString const aAttrKey("/Attributes");
735 
736                         for ( const OUString& rPropName : aElems )
737                         {
738                             // Create new item.
739                             Reference< XNameReplace > xNewPropNameReplace(
740                                 xNewFac->createInstance(), UNO_QUERY );
741 
742                             if ( !xNewPropNameReplace.is() )
743                             {
744                                 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
745                                     "No new prop name replace!" );
746                                 return;
747                             }
748 
749                             // Fill new item...
750 
751                             // Set Values
752                             OUString aKey = aOldValuesKey;
753                             aKey += makeHierarchalNameSegment( rPropName );
754 
755                             // ... handle
756                             OUString aNewKey1 = aKey + aHandleKey;
757                             Any aAny =
758                                 xRootHierNameAccess->getByHierarchicalName(
759                                     aNewKey1 );
760                             xNewPropNameReplace->replaceByName( "Handle", aAny );
761 
762                             // ... value
763                             aNewKey1 = aKey + aValueKey;
764                             aAny =
765                                 xRootHierNameAccess->getByHierarchicalName(
766                                     aNewKey1 );
767                             xNewPropNameReplace->replaceByName( "Value", aAny );
768 
769                             // ... state
770                             aNewKey1 = aKey + aStateKey;
771                             aAny =
772                                 xRootHierNameAccess->getByHierarchicalName(
773                                     aNewKey1 );
774                             xNewPropNameReplace->replaceByName( "State", aAny );
775 
776                             // ... attributes
777                             aNewKey1 = aKey + aAttrKey;
778                             aAny =
779                                 xRootHierNameAccess->getByHierarchicalName(
780                                     aNewKey1 );
781                             xNewPropNameReplace->replaceByName( "Attributes", aAny );
782 
783                             // Insert new item.
784                             xNewContainer->insertByName(
785                                 rPropName, makeAny( xNewPropNameReplace ) );
786 
787                             // Commit changes.
788                             xBatch->commitChanges();
789                         }
790                     }
791                 }
792                 catch (const IllegalArgumentException&)
793                 {
794                     // insertByName, replaceByName
795 
796                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
797                                 "caught IllegalArgumentException!" );
798                     return;
799                 }
800                 catch (const ElementExistException&)
801                 {
802                     // insertByName
803 
804                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
805                                 "caught ElementExistException!" );
806                     return;
807                 }
808                 catch (const WrappedTargetException&)
809                 {
810                     // insertByName, replaceByName, commitChanges
811 
812                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
813                                 "caught WrappedTargetException!" );
814                     return;
815                 }
816                 catch (const NoSuchElementException&)
817                 {
818                     // getByHierarchicalName, replaceByName
819 
820                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
821                                 "caught NoSuchElementException!" );
822                     return;
823                 }
824                 catch (const RuntimeException&)
825                 {
826                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
827                                 "caught RuntimeException!" );
828                     return;
829                 }
830                 catch (const Exception&)
831                 {
832                     // createInstance
833 
834                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
835                                 "caught Exception!" );
836                     return;
837                 }
838 
839 
840                 // Remove old entry...
841 
842 
843                 try
844                 {
845                     // Remove item.
846                     xContainer->removeByName( rOldKey );
847                     // Commit changes.
848                     xBatch->commitChanges();
849 
850                     // Success.
851                     return;
852                 }
853                 catch (const NoSuchElementException&)
854                 {
855                     // removeByName
856 
857                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
858                                 "caught NoSuchElementException!" );
859                     return;
860                 }
861                 catch (const WrappedTargetException&)
862                 {
863                     // commitChanges
864 
865                     OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
866                                 "caught WrappedTargetException!" );
867                     return;
868                 }
869             }
870         }
871     }
872 
873     OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" );
874 }
875 
876 
getConfigProvider()877 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider()
878 {
879     if ( !m_pImpl->m_xConfigProvider.is() )
880     {
881         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
882         if ( !m_pImpl->m_xConfigProvider.is() )
883         {
884             const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs;
885 
886             if ( rInitArgs.hasElements() )
887             {
888                 // Extract config provider from service init args.
889                 rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider;
890 
891                 OSL_ENSURE( m_pImpl->m_xConfigProvider.is(),
892                             "PropertySetRegistry::getConfigProvider - "
893                             "No config provider!" );
894             }
895             else
896             {
897                 try
898                 {
899                     m_pImpl->m_xConfigProvider = theDefaultProvider::get( m_xContext );
900                 }
901                 catch (const Exception&)
902                 {
903                     TOOLS_WARN_EXCEPTION( "ucb", "");
904                 }
905             }
906         }
907     }
908 
909     return m_pImpl->m_xConfigProvider;
910 }
911 
912 
getRootConfigReadAccess()913 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
914 {
915     try
916     {
917         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
918 
919         if ( !m_pImpl->m_xRootReadAccess.is() )
920         {
921             if ( m_pImpl->m_bTriedToGetRootReadAccess )
922             {
923                 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - "
924                             "Unable to read any config data! -> #82494#" );
925                 return Reference< XInterface >();
926             }
927 
928             getConfigProvider();
929 
930             if ( m_pImpl->m_xConfigProvider.is() )
931             {
932                 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
933                 {
934                     {CFGPROPERTY_NODEPATH,  Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
935                 }));
936 
937                 m_pImpl->m_bTriedToGetRootReadAccess = true;
938 
939                 m_pImpl->m_xRootReadAccess =
940                     m_pImpl->m_xConfigProvider->createInstanceWithArguments(
941                         "com.sun.star.configuration.ConfigurationAccess",
942                         aArguments );
943 
944                 if ( m_pImpl->m_xRootReadAccess.is() )
945                     return m_pImpl->m_xRootReadAccess;
946             }
947         }
948         else
949             return m_pImpl->m_xRootReadAccess;
950     }
951     catch (const RuntimeException&)
952     {
953         throw;
954     }
955     catch (const Exception&)
956     {
957         // createInstance, createInstanceWithArguments
958 
959         OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - caught Exception!" );
960         return Reference< XInterface >();
961     }
962 
963     SAL_WARN( "ucb", "Error!" );
964     return Reference< XInterface >();
965 }
966 
967 
getConfigWriteAccess(const OUString & rPath)968 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
969                                                     const OUString& rPath )
970 {
971     try
972     {
973         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
974 
975         if ( !m_pImpl->m_xRootWriteAccess.is() )
976         {
977             if ( m_pImpl->m_bTriedToGetRootWriteAccess )
978             {
979                 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
980                             "Unable to write any config data! -> #82494#" );
981                 return Reference< XInterface >();
982             }
983 
984             getConfigProvider();
985 
986             if ( m_pImpl->m_xConfigProvider.is() )
987             {
988                 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
989                 {
990                     {CFGPROPERTY_NODEPATH,  Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
991                 }));
992 
993                 m_pImpl->m_bTriedToGetRootWriteAccess = true;
994 
995                 m_pImpl->m_xRootWriteAccess =
996                     m_pImpl->m_xConfigProvider->createInstanceWithArguments(
997                         "com.sun.star.configuration.ConfigurationUpdateAccess",
998                         aArguments );
999 
1000                 OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(),
1001                             "PropertySetRegistry::getConfigWriteAccess - "
1002                             "No config update access!" );
1003             }
1004         }
1005 
1006         if ( m_pImpl->m_xRootWriteAccess.is() )
1007         {
1008             if ( !rPath.isEmpty() )
1009             {
1010                 Reference< XHierarchicalNameAccess > xNA(
1011                                 m_pImpl->m_xRootWriteAccess, UNO_QUERY );
1012                 if ( xNA.is() )
1013                 {
1014                     Reference< XInterface > xInterface;
1015                     xNA->getByHierarchicalName( rPath ) >>= xInterface;
1016 
1017                     if ( xInterface.is() )
1018                         return xInterface;
1019                 }
1020             }
1021             else
1022                 return m_pImpl->m_xRootWriteAccess;
1023         }
1024     }
1025     catch (const RuntimeException&)
1026     {
1027         throw;
1028     }
1029     catch (const NoSuchElementException&)
1030     {
1031         // getByHierarchicalName
1032 
1033         OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1034             "caught NoSuchElementException!" );
1035         return Reference< XInterface >();
1036     }
1037     catch (const Exception&)
1038     {
1039         // createInstance, createInstanceWithArguments
1040 
1041         OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1042                     "caught Exception!" );
1043         return Reference< XInterface >();
1044     }
1045 
1046     OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" );
1047     return Reference< XInterface >();
1048 }
1049 
1050 typedef OMultiTypeInterfaceContainerHelperVar<OUString> PropertyListeners_Impl;
1051 
1052 struct PersistentPropertySet_Impl
1053 {
1054     rtl::Reference<PropertySetRegistry>  m_pCreator;
1055     rtl::Reference<PropertySetInfo_Impl> m_pInfo;
1056     OUString const              m_aKey;
1057     OUString                    m_aFullKey;
1058     osl::Mutex                  m_aMutex;
1059     std::unique_ptr<OInterfaceContainerHelper2>  m_pDisposeEventListeners;
1060     std::unique_ptr<OInterfaceContainerHelper2>  m_pPropSetChangeListeners;
1061     std::unique_ptr<PropertyListeners_Impl>      m_pPropertyChangeListeners;
1062 
PersistentPropertySet_ImplPersistentPropertySet_Impl1063     PersistentPropertySet_Impl( PropertySetRegistry& rCreator,
1064                                 const OUString& rKey )
1065     : m_pCreator( &rCreator ), m_aKey( rKey )
1066     {
1067     }
1068 };
1069 
1070 
1071 // PersistentPropertySet Implementation.
1072 
1073 
PersistentPropertySet(PropertySetRegistry & rCreator,const OUString & rKey)1074 PersistentPropertySet::PersistentPropertySet(
1075                         PropertySetRegistry& rCreator,
1076                         const OUString& rKey )
1077 : m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) )
1078 {
1079     // register at creator.
1080     rCreator.add( this );
1081 }
1082 
1083 
1084 // virtual
~PersistentPropertySet()1085 PersistentPropertySet::~PersistentPropertySet()
1086 {
1087     // deregister at creator.
1088     m_pImpl->m_pCreator->remove( this );
1089 }
1090 
1091 // XServiceInfo methods.
1092 
getImplementationName()1093 OUString SAL_CALL PersistentPropertySet::getImplementationName()
1094 {
1095     return "com.sun.star.comp.ucb.PersistentPropertySet";
1096 }
1097 
supportsService(const OUString & ServiceName)1098 sal_Bool SAL_CALL PersistentPropertySet::supportsService( const OUString& ServiceName )
1099 {
1100     return cppu::supportsService( this, ServiceName );
1101 }
1102 
1103 css::uno::Sequence< OUString > SAL_CALL
getSupportedServiceNames()1104 PersistentPropertySet::getSupportedServiceNames()
1105 {
1106     return { PERS_PROPSET_SERVICE_NAME };
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 Reference< XPropertySetInfo >( m_pImpl->m_pInfo.get() );
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 Reference< XPropertySetRegistry >( m_pImpl->m_pCreator.get() );
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     OUString aFullValuesName;
1556     OUString aFullPropName;
1557 
1558     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1559                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1560     if ( xRootHierNameAccess.is() )
1561     {
1562         aFullValuesName = getFullKey();
1563         aFullPropName   = aFullValuesName + "/";
1564         aFullPropName   += makeHierarchalNameSegment( Name );
1565 
1566         // Property in set?
1567         if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1568             throw UnknownPropertyException(aFullPropName);
1569 
1570         // Property removable?
1571         try
1572         {
1573             OUString aFullAttrName = aFullPropName + "/Attributes";
1574 
1575             sal_Int32 nAttribs = 0;
1576             if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1577                     >>= nAttribs )
1578             {
1579                 if ( !( nAttribs & PropertyAttribute::REMOVABLE ) )
1580                 {
1581                     // Not removable!
1582                     throw NotRemoveableException();
1583                 }
1584             }
1585             else
1586             {
1587                 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1588                             "No attributes!" );
1589                 return;
1590             }
1591         }
1592         catch (const NoSuchElementException&)
1593         {
1594             // getByHierarchicalName
1595 
1596             OSL_FAIL( "PersistentPropertySet::removeProperty - "
1597                         "caught NoSuchElementException!" );
1598         }
1599 
1600         // Remove property...
1601 
1602         Reference< XNameContainer > xContainer(
1603                 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1604                 UNO_QUERY );
1605         Reference< XChangesBatch > xBatch(
1606                 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1607                 UNO_QUERY );
1608 
1609         OSL_ENSURE( xBatch.is(),
1610                     "PersistentPropertySet::removeProperty - No batch!" );
1611 
1612         OSL_ENSURE( xContainer.is(),
1613                     "PersistentPropertySet::removeProperty - No container!" );
1614 
1615         if ( xBatch.is() && xContainer.is() )
1616         {
1617             try
1618             {
1619                 sal_Int32 nHandle = -1;
1620 
1621                 if ( m_pImpl->m_pPropSetChangeListeners &&
1622                        m_pImpl->m_pPropSetChangeListeners->getLength() )
1623                 {
1624                     // Obtain property handle ( needed for propertysetinfo
1625                     // change event )...
1626 
1627                     try
1628                     {
1629                         OUString aFullHandleName = aFullPropName + "/Handle";
1630 
1631                         if ( ! ( xRootHierNameAccess->getByHierarchicalName(
1632                                         aFullHandleName ) >>= nHandle ) )
1633                             nHandle = -1;
1634 
1635                     }
1636                     catch (const NoSuchElementException&)
1637                     {
1638                         // getByHierarchicalName
1639 
1640                         OSL_FAIL( "PersistentPropertySet::removeProperty - "
1641                                     "caught NoSuchElementException!" );
1642                         nHandle = -1;
1643                     }
1644                 }
1645 
1646                 xContainer->removeByName( Name );
1647                 xBatch->commitChanges();
1648 
1649                 // Property set info is invalid.
1650                 if ( m_pImpl->m_pInfo.is() )
1651                     m_pImpl->m_pInfo->reset();
1652 
1653                 // Notify propertyset info change listeners.
1654                 if ( m_pImpl->m_pPropSetChangeListeners &&
1655                       m_pImpl->m_pPropSetChangeListeners->getLength() )
1656                 {
1657                     PropertySetInfoChangeEvent evt(
1658                                     static_cast< OWeakObject * >( this ),
1659                                     Name,
1660                                     nHandle,
1661                                     PropertySetInfoChange::PROPERTY_REMOVED );
1662                     notifyPropertySetInfoChange( evt );
1663                 }
1664 
1665                 // Success.
1666                 return;
1667             }
1668             catch (const NoSuchElementException&)
1669             {
1670                 // removeByName
1671 
1672                 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1673                             "caught NoSuchElementException!" );
1674                 return;
1675             }
1676             catch (const WrappedTargetException&)
1677             {
1678                 // commitChanges
1679 
1680                 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1681                             "caught WrappedTargetException!" );
1682                 return;
1683             }
1684         }
1685     }
1686 
1687     OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" );
1688 }
1689 
1690 
1691 // XPropertySetInfoChangeNotifier methods.
1692 
1693 
1694 // virtual
addPropertySetInfoChangeListener(const Reference<XPropertySetInfoChangeListener> & Listener)1695 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
1696                 const Reference< XPropertySetInfoChangeListener >& Listener )
1697 {
1698     if ( !m_pImpl->m_pPropSetChangeListeners )
1699         m_pImpl->m_pPropSetChangeListeners.reset(
1700                     new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) );
1701 
1702     m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
1703 }
1704 
1705 
1706 // virtual
removePropertySetInfoChangeListener(const Reference<XPropertySetInfoChangeListener> & Listener)1707 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
1708                 const Reference< XPropertySetInfoChangeListener >& Listener )
1709 {
1710     if ( m_pImpl->m_pPropSetChangeListeners )
1711         m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
1712 }
1713 
1714 
1715 // XPropertyAccess methods.
1716 
1717 
1718 // virtual
getPropertyValues()1719 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
1720 {
1721     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1722 
1723     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1724                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1725     if ( xRootHierNameAccess.is() )
1726     {
1727         try
1728         {
1729             Reference< XNameAccess > xNameAccess;
1730             xRootHierNameAccess->getByHierarchicalName(getFullKey())
1731                 >>= xNameAccess;
1732             if ( xNameAccess.is() )
1733             {
1734                 // Obtain property names.
1735 
1736                 Sequence< OUString > aElems = xNameAccess->getElementNames();
1737 
1738                 sal_Int32 nCount = aElems.getLength();
1739                 if ( nCount )
1740                 {
1741                     Reference< XHierarchicalNameAccess > xHierNameAccess(
1742                                                     xNameAccess, UNO_QUERY );
1743 
1744                     OSL_ENSURE( xHierNameAccess.is(),
1745                                 "PersistentPropertySet::getPropertyValues - "
1746                                 "No hierarchical name access!" );
1747 
1748                     if ( xHierNameAccess.is() )
1749                     {
1750                         Sequence< PropertyValue > aValues( nCount );
1751 
1752                         const OUString aHandleName("/Handle");
1753                         const OUString aValueName("/Value");
1754                         const OUString aStateName("/State");
1755 
1756                         for ( sal_Int32 n = 0; n < nCount; ++n )
1757                         {
1758                             PropertyValue& rValue = aValues[ n ];
1759                             OUString rName    = aElems[ n ];
1760                             OUString aXMLName
1761                                         = makeHierarchalNameSegment( rName );
1762 
1763                             // Set property name.
1764 
1765                             rValue.Name = rName;
1766 
1767                             try
1768                             {
1769                                 // Obtain and set property handle
1770                                 OUString aHierName = aXMLName + aHandleName;
1771                                 Any aKeyValue
1772                                     = xHierNameAccess->getByHierarchicalName(
1773                                         aHierName );
1774 
1775                                 if ( !( aKeyValue >>= rValue.Handle ) )
1776                                     OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1777                                       "Error getting property handle!" );
1778                             }
1779                             catch (const NoSuchElementException&)
1780                             {
1781                                 // getByHierarchicalName
1782 
1783                                 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1784                                   "NoSuchElementException!" );
1785                             }
1786 
1787                             try
1788                             {
1789                                 // Obtain and set property value
1790                                 OUString aHierName = aXMLName + aValueName;
1791                                 rValue.Value
1792                                     = xHierNameAccess->getByHierarchicalName(
1793                                         aHierName );
1794 
1795                                 // Note: The value may be void if addProperty
1796                                 //       was called with a default value
1797                                 //       of type void.
1798                             }
1799                             catch (const NoSuchElementException&)
1800                             {
1801                                 // getByHierarchicalName
1802 
1803                                 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1804                                   "NoSuchElementException!" );
1805                             }
1806 
1807                             try
1808                             {
1809                                 // Obtain and set property state
1810                                 OUString aHierName = aXMLName +aStateName;
1811                                 Any aKeyValue
1812                                     = xHierNameAccess->getByHierarchicalName(
1813                                         aHierName );
1814 
1815                                 sal_Int32 nState = 0;
1816                                 if ( !( aKeyValue >>= nState ) )
1817                                     OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1818                                       "Error getting property state!" );
1819                                 else
1820                                     rValue.State = PropertyState( nState );
1821                             }
1822                             catch (const NoSuchElementException&)
1823                             {
1824                                 // getByHierarchicalName
1825 
1826                                 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1827                                   "NoSuchElementException!" );
1828                             }
1829                         }
1830 
1831                         return aValues;
1832                     }
1833                 }
1834             }
1835         }
1836         catch (const NoSuchElementException&)
1837         {
1838             // getByHierarchicalName
1839         }
1840     }
1841 
1842     return Sequence< PropertyValue >( 0 );
1843 }
1844 
1845 
1846 // virtual
setPropertyValues(const Sequence<PropertyValue> & aProps)1847 void SAL_CALL PersistentPropertySet::setPropertyValues(
1848                                  const Sequence< PropertyValue >& aProps )
1849 {
1850     if ( !aProps.hasElements() )
1851         return;
1852 
1853     osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1854 
1855     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1856                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1857     if ( xRootHierNameAccess.is() )
1858     {
1859         std::vector< PropertyChangeEvent > aEvents;
1860 
1861         OUString aFullPropNamePrefix( getFullKey() + "/" );
1862 
1863         // Iterate over given property value sequence.
1864         for ( const PropertyValue& rNewValue : aProps )
1865         {
1866             const OUString& rName = rNewValue.Name;
1867 
1868             OUString aFullPropName = aFullPropNamePrefix;
1869             aFullPropName += makeHierarchalNameSegment( rName );
1870 
1871             // Does property exist?
1872             if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1873             {
1874                 Reference< XNameReplace > xNameReplace(
1875                     m_pImpl->m_pCreator->getConfigWriteAccess(
1876                                             aFullPropName ), UNO_QUERY );
1877                 Reference< XChangesBatch > xBatch(
1878                     m_pImpl->m_pCreator->getConfigWriteAccess(
1879                                             OUString() ), UNO_QUERY );
1880 
1881                 if ( xNameReplace.is() && xBatch.is() )
1882                 {
1883                     try
1884                     {
1885                         // Write handle
1886                         xNameReplace->replaceByName(
1887                                     "Handle",
1888                                     makeAny( rNewValue.Handle ) );
1889 
1890                         // Save old value
1891                         OUString aValueName = aFullPropName +"/Value";
1892                         Any aOldValue
1893                             = xRootHierNameAccess->getByHierarchicalName(
1894                                                                 aValueName );
1895                         // Write value
1896                         xNameReplace->replaceByName(
1897                                     "Value",
1898                                     rNewValue.Value );
1899 
1900                         // Write state ( Now it is a directly set value )
1901                         xNameReplace->replaceByName(
1902                                     "State",
1903                                     makeAny(
1904                                         sal_Int32(
1905                                             PropertyState_DIRECT_VALUE ) ) );
1906 
1907                         // Commit changes.
1908                         xBatch->commitChanges();
1909 
1910                         if ( m_pImpl->m_pPropertyChangeListeners )
1911                         {
1912                             PropertyChangeEvent aEvt;
1913                             aEvt.Source         = static_cast<OWeakObject*>(this);
1914                             aEvt.PropertyName   = rNewValue.Name;
1915                             aEvt.PropertyHandle = rNewValue.Handle;
1916                             aEvt.Further        = false;
1917                             aEvt.OldValue       = aOldValue;
1918                             aEvt.NewValue       = rNewValue.Value;
1919 
1920                             aEvents.push_back( aEvt );
1921                         }
1922                     }
1923                     catch (const IllegalArgumentException&)
1924                     {
1925                         // replaceByName
1926                     }
1927                     catch (const NoSuchElementException&)
1928                     {
1929                         // getByHierarchicalName, replaceByName
1930                     }
1931                     catch (const WrappedTargetException&)
1932                     {
1933                         // replaceByName, commitChanges
1934                     }
1935                 }
1936             }
1937         }
1938 
1939         // Callback follows!
1940         aCGuard.clear();
1941 
1942         if ( m_pImpl->m_pPropertyChangeListeners )
1943         {
1944             // Notify property changes.
1945             for (auto const& event : aEvents)
1946             {
1947                 notifyPropertyChangeEvent( event );
1948             }
1949         }
1950 
1951         return;
1952     }
1953 
1954     OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" );
1955 }
1956 
1957 
1958 // Non-interface methods
1959 
1960 
notifyPropertyChangeEvent(const PropertyChangeEvent & rEvent) const1961 void PersistentPropertySet::notifyPropertyChangeEvent(
1962                                     const PropertyChangeEvent& rEvent ) const
1963 {
1964     // Get "normal" listeners for the property.
1965     OInterfaceContainerHelper* pContainer =
1966             m_pImpl->m_pPropertyChangeListeners->getContainer(
1967                                                     rEvent.PropertyName );
1968     if ( pContainer && pContainer->getLength() )
1969     {
1970         OInterfaceIteratorHelper aIter( *pContainer );
1971         while ( aIter.hasMoreElements() )
1972         {
1973             // Propagate event.
1974             Reference< XPropertyChangeListener > xListener(
1975                                                     aIter.next(), UNO_QUERY );
1976             if ( xListener.is() )
1977                 xListener->propertyChange( rEvent );
1978         }
1979     }
1980 
1981     // Get "normal" listeners for all properties.
1982     OInterfaceContainerHelper* pNoNameContainer =
1983             m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() );
1984     if ( pNoNameContainer && pNoNameContainer->getLength() )
1985     {
1986         OInterfaceIteratorHelper aIter( *pNoNameContainer );
1987         while ( aIter.hasMoreElements() )
1988         {
1989             // Propagate event.
1990             Reference< XPropertyChangeListener > xListener(
1991                                                     aIter.next(), UNO_QUERY );
1992             if ( xListener.is() )
1993                 xListener->propertyChange( rEvent );
1994         }
1995     }
1996 }
1997 
1998 
notifyPropertySetInfoChange(const PropertySetInfoChangeEvent & evt) const1999 void PersistentPropertySet::notifyPropertySetInfoChange(
2000                                 const PropertySetInfoChangeEvent& evt ) const
2001 {
2002     if ( !m_pImpl->m_pPropSetChangeListeners )
2003         return;
2004 
2005     // Notify event listeners.
2006     OInterfaceIteratorHelper2 aIter( *( m_pImpl->m_pPropSetChangeListeners ) );
2007     while ( aIter.hasMoreElements() )
2008     {
2009         // Propagate event.
2010         Reference< XPropertySetInfoChangeListener >
2011                             xListener( aIter.next(), UNO_QUERY );
2012         if ( xListener.is() )
2013             xListener->propertySetInfoChange( evt );
2014     }
2015 }
2016 
2017 
getFullKey()2018 const OUString& PersistentPropertySet::getFullKey()
2019 {
2020     if ( m_pImpl->m_aFullKey.isEmpty() )
2021     {
2022         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
2023         if ( m_pImpl->m_aFullKey.isEmpty() )
2024         {
2025             m_pImpl->m_aFullKey
2026                 = makeHierarchalNameSegment( m_pImpl->m_aKey );
2027             m_pImpl->m_aFullKey
2028                 += "/Values";
2029         }
2030     }
2031 
2032     return m_pImpl->m_aFullKey;
2033 }
2034 
2035 
getPropertySetRegistry()2036 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
2037 {
2038     return *m_pImpl->m_pCreator;
2039 }
2040 
2041 
2042 // PropertySetInfo_Impl Implementation.
2043 
2044 
PropertySetInfo_Impl(PersistentPropertySet * pOwner)2045 PropertySetInfo_Impl::PropertySetInfo_Impl(
2046                         PersistentPropertySet* pOwner )
2047 : m_pOwner( pOwner )
2048 {
2049 }
2050 
2051 
2052 // XPropertySetInfo methods.
2053 
2054 
2055 // virtual
getProperties()2056 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
2057 {
2058     if ( !m_pProps )
2059     {
2060         Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2061             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2062             UNO_QUERY );
2063         if ( xRootHierNameAccess.is() )
2064         {
2065             try
2066             {
2067                 Reference< XNameAccess > xNameAccess;
2068                 xRootHierNameAccess->getByHierarchicalName(
2069                             m_pOwner->getFullKey() )
2070                     >>= xNameAccess;
2071                 if ( xNameAccess.is() )
2072                 {
2073                     // Obtain property names.
2074 
2075                     Sequence< OUString > aElems
2076                                             = xNameAccess->getElementNames();
2077 
2078                     sal_uInt32 nCount = aElems.getLength();
2079                     Sequence< Property >* pPropSeq
2080                                         = new Sequence< Property >( nCount );
2081 
2082                     if ( nCount )
2083                     {
2084                         Reference< XHierarchicalNameAccess > xHierNameAccess(
2085                                                     xNameAccess, UNO_QUERY );
2086 
2087                         OSL_ENSURE( xHierNameAccess.is(),
2088                                     "PropertySetInfo_Impl::getProperties - "
2089                                     "No hierarchical name access!" );
2090 
2091                         if ( xHierNameAccess.is() )
2092                         {
2093                             const OUString aHandleName("/Handle");
2094                             const OUString aValueName("/Value");
2095                             const OUString aAttrName("/Attributes");
2096 
2097                             Property* pProps = pPropSeq->getArray();
2098 
2099                             for ( sal_uInt32 n = 0; n < nCount; ++n )
2100                             {
2101                                 Property& rProp = pProps[ n ];
2102                                 OUString  rName = aElems[ n ];
2103                                 OUString aXMLName
2104                                     = makeHierarchalNameSegment( rName );
2105 
2106                                 // Set property name.
2107 
2108                                 rProp.Name = rName;
2109 
2110                                 try
2111                                 {
2112                                     // Obtain and set property handle
2113                                     OUString aHierName = aXMLName + aHandleName;
2114                                     Any aKeyValue
2115                                         = xHierNameAccess->getByHierarchicalName(
2116                                             aHierName );
2117 
2118                                     if ( !( aKeyValue >>= rProp.Handle ) )
2119                                         OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2120                                           "Error getting property handle!" );
2121                                 }
2122                                 catch (const NoSuchElementException&)
2123                                 {
2124                                     // getByHierarchicalName
2125 
2126                                     OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2127                                       "NoSuchElementException!" );
2128                                 }
2129 
2130                                 try
2131                                 {
2132                                     // Obtain and set property type
2133                                     OUString aHierName = aXMLName + aValueName;
2134                                     Any aKeyValue
2135                                         = xHierNameAccess->getByHierarchicalName(
2136                                             aHierName );
2137 
2138                                     // Note: The type may be void if addProperty
2139                                     //       was called with a default value
2140                                     //       of type void.
2141 
2142                                     rProp.Type = aKeyValue.getValueType();
2143                                 }
2144                                 catch (const NoSuchElementException&)
2145                                 {
2146                                     // getByHierarchicalName
2147 
2148                                     OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2149                                       "NoSuchElementException!" );
2150                                 }
2151 
2152                                 try
2153                                 {
2154                                     // Obtain and set property attributes
2155                                     OUString aHierName = aXMLName + aAttrName;
2156                                     Any aKeyValue
2157                                         = xHierNameAccess->getByHierarchicalName(
2158                                             aHierName );
2159 
2160                                     sal_Int32 nAttribs = 0;
2161                                     if ( aKeyValue >>= nAttribs )
2162                                         rProp.Attributes
2163                                             = sal_Int16( nAttribs );
2164                                     else
2165                                         OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2166                                           "Error getting property attributes!" );
2167                                 }
2168                                 catch (const NoSuchElementException&)
2169                                 {
2170                                     // getByHierarchicalName
2171 
2172                                     OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2173                                       "NoSuchElementException!" );
2174                                 }
2175                             }
2176                         }
2177                     }
2178 
2179                     // Success.
2180                     m_pProps.reset( pPropSeq );
2181                     return *m_pProps;
2182                 }
2183             }
2184             catch (const NoSuchElementException&)
2185             {
2186                 // getByHierarchicalName
2187             }
2188         }
2189 
2190         OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" );
2191         m_pProps.reset( new Sequence< Property >( 0 ) );
2192     }
2193 
2194     return *m_pProps;
2195 }
2196 
2197 
2198 // virtual
getPropertyByName(const OUString & aName)2199 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2200                                                     const OUString& aName )
2201 {
2202     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2203             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2204             UNO_QUERY );
2205     if ( xRootHierNameAccess.is() )
2206     {
2207         OUString aFullPropName( m_pOwner->getFullKey() + "/" );
2208         aFullPropName += makeHierarchalNameSegment( aName );
2209 
2210         // Does property exist?
2211         if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2212             throw UnknownPropertyException(aFullPropName);
2213 
2214         try
2215         {
2216             Property aProp;
2217 
2218             // Obtain handle.
2219             OUString aKey = aFullPropName + "/Handle";
2220 
2221             if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2222                     >>= aProp.Handle ) )
2223             {
2224                 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2225                             "No handle!" );
2226                 return Property();
2227             }
2228 
2229             // Obtain Value and extract type.
2230             aKey = aFullPropName + "/Value";
2231 
2232             Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2233             if ( !aValue.hasValue() )
2234             {
2235                 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2236                             "No Value!" );
2237                 return Property();
2238             }
2239 
2240             aProp.Type = aValue.getValueType();
2241 
2242             // Obtain Attributes.
2243             aKey = aFullPropName + "/Attributes";
2244 
2245             sal_Int32 nAttribs = 0;
2246             if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2247                     >>= nAttribs )
2248                 aProp.Attributes = sal_Int16( nAttribs );
2249             else
2250             {
2251                 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2252                             "No attributes!" );
2253                 return Property();
2254             }
2255 
2256             // set name.
2257             aProp.Name = aName;
2258 
2259             // Success.
2260             return aProp;
2261         }
2262         catch (const NoSuchElementException&)
2263         {
2264             // getByHierarchicalName
2265 
2266             OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2267                         "caught NoSuchElementException!" );
2268         }
2269 
2270     }
2271 
2272     OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" );
2273     return Property();
2274 }
2275 
2276 
2277 // virtual
hasPropertyByName(const OUString & Name)2278 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2279                                                     const OUString& Name )
2280 {
2281     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2282             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2283             UNO_QUERY );
2284     if ( xRootHierNameAccess.is() )
2285     {
2286         OUString aFullPropName( m_pOwner->getFullKey() + "/" );
2287         aFullPropName += makeHierarchalNameSegment( Name );
2288 
2289         return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2290     }
2291 
2292     return false;
2293 }
2294 
2295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2296