xref: /trunk/main/ucb/source/core/ucbstore.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_ucb.hxx"
30 
31 /**************************************************************************
32                                 TODO
33  **************************************************************************
34 
35   *************************************************************************/
36 
37 #include <list>
38 #include <hash_map>
39 #include <osl/diagnose.h>
40 #include <rtl/ustrbuf.hxx>
41 #include <cppuhelper/interfacecontainer.hxx>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
44 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
45 #include <com/sun/star/container/XNameContainer.hpp>
46 #include <com/sun/star/container/XNameReplace.hpp>
47 #include <com/sun/star/util/XChangesBatch.hpp>
48 #include "ucbstore.hxx"
49 
50 using namespace com::sun::star::beans;
51 using namespace com::sun::star::container;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::ucb;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::util;
56 using namespace cppu;
57 using namespace rtl;
58 
59 //=========================================================================
60 rtl::OUString makeHierarchalNameSegment( const rtl::OUString & rIn  )
61 {
62     rtl::OUStringBuffer aBuffer;
63     aBuffer.appendAscii( "['" );
64 
65     sal_Int32 nCount = rIn.getLength();
66     for ( sal_Int32 n = 0; n < nCount; ++n )
67     {
68         const sal_Unicode c = rIn.getStr()[ n ];
69         switch ( c )
70         {
71             case '&':
72                 aBuffer.appendAscii( "&amp;" );
73                 break;
74 
75             case '"':
76                 aBuffer.appendAscii( "&quot;" );
77                 break;
78 
79             case '\'':
80                 aBuffer.appendAscii( "&apos;" );
81                 break;
82 
83             case '<':
84                 aBuffer.appendAscii( "&lt;" );
85                 break;
86 
87             case '>':
88                 aBuffer.appendAscii( "&gt;" );
89                 break;
90 
91             default:
92                 aBuffer.append( c );
93                 break;
94         }
95     }
96 
97     aBuffer.appendAscii( "']" );
98     return rtl::OUString( aBuffer.makeStringAndClear() );
99 }
100 
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 // true->async. update; false->sync. update
108 #define CFGPROPERTY_LAZYWRITE       "lazywrite"
109 
110 //=========================================================================
111 
112 struct equalString_Impl
113 {
114   bool operator()( const OUString& s1, const OUString& s2 ) const
115   {
116         return !!( s1 == s2 );
117   }
118 };
119 
120 struct hashString_Impl
121 {
122     size_t operator()( const OUString & rName ) const
123     {
124         return rName.hashCode();
125     }
126 };
127 
128 //=========================================================================
129 //
130 // PropertySetMap_Impl.
131 //
132 //=========================================================================
133 
134 typedef std::hash_map
135 <
136     OUString,
137     PersistentPropertySet*,
138     hashString_Impl,
139     equalString_Impl
140 >
141 PropertySetMap_Impl;
142 
143 //=========================================================================
144 //
145 // class PropertySetInfo_Impl
146 //
147 //=========================================================================
148 
149 class PropertySetInfo_Impl :
150         public OWeakObject, public XTypeProvider, public XPropertySetInfo
151 {
152     Reference< XMultiServiceFactory > m_xSMgr;
153     Sequence< Property >*             m_pProps;
154     PersistentPropertySet*            m_pOwner;
155 
156 public:
157     PropertySetInfo_Impl( const Reference< XMultiServiceFactory >& rxSMgr,
158                           PersistentPropertySet* pOwner );
159     virtual ~PropertySetInfo_Impl();
160 
161     // XInterface
162     XINTERFACE_DECL()
163 
164     // XTypeProvider
165     XTYPEPROVIDER_DECL()
166 
167     // XPropertySetInfo
168     virtual Sequence< Property > SAL_CALL getProperties()
169         throw( RuntimeException );
170     virtual Property SAL_CALL getPropertyByName( const OUString& aName )
171         throw( UnknownPropertyException, RuntimeException );
172     virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name )
173         throw( RuntimeException );
174 
175     // Non-interface methods.
176     void reset() { delete m_pProps; m_pProps = 0; }
177 };
178 
179 //=========================================================================
180 //
181 // UcbStore_Impl.
182 //
183 //=========================================================================
184 
185 struct UcbStore_Impl
186 {
187     osl::Mutex                        m_aMutex;
188     Sequence< Any >                   m_aInitArgs;
189     Reference< XPropertySetRegistry > m_xTheRegistry;
190 };
191 
192 //=========================================================================
193 //=========================================================================
194 //=========================================================================
195 //
196 // UcbStore Implementation.
197 //
198 //=========================================================================
199 //=========================================================================
200 //=========================================================================
201 
202 UcbStore::UcbStore( const Reference< XMultiServiceFactory >& rXSMgr )
203 : m_xSMgr( rXSMgr ),
204   m_pImpl( new UcbStore_Impl() )
205 {
206 }
207 
208 //=========================================================================
209 // virtual
210 UcbStore::~UcbStore()
211 {
212     delete m_pImpl;
213 }
214 
215 //=========================================================================
216 //
217 // XInterface methods.
218 //
219 //=========================================================================
220 
221 XINTERFACE_IMPL_4( UcbStore,
222                    XTypeProvider,
223                    XServiceInfo,
224                    XPropertySetRegistryFactory,
225                    XInitialization );
226 
227 //=========================================================================
228 //
229 // XTypeProvider methods.
230 //
231 //=========================================================================
232 
233 XTYPEPROVIDER_IMPL_4( UcbStore,
234                       XTypeProvider,
235                       XServiceInfo,
236                       XPropertySetRegistryFactory,
237                       XInitialization );
238 
239 //=========================================================================
240 //
241 // XServiceInfo methods.
242 //
243 //=========================================================================
244 
245 XSERVICEINFO_IMPL_1( UcbStore,
246                      OUString::createFromAscii(
247                         "com.sun.star.comp.ucb.UcbStore" ),
248                      OUString::createFromAscii(
249                         STORE_SERVICE_NAME ) );
250 
251 //=========================================================================
252 //
253 // Service factory implementation.
254 //
255 //=========================================================================
256 
257 ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbStore );
258 
259 //=========================================================================
260 //
261 // XPropertySetRegistryFactory methods.
262 //
263 //=========================================================================
264 
265 // virtual
266 Reference< XPropertySetRegistry > SAL_CALL
267 UcbStore::createPropertySetRegistry( const OUString& )
268     throw( RuntimeException )
269 {
270     // The URL parameter is ignored by this interface implementation. It always
271     // uses the configuration server as storage medium.
272 
273     if ( !m_pImpl->m_xTheRegistry.is() )
274     {
275         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
276         if ( !m_pImpl->m_xTheRegistry.is() )
277             m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xSMgr, getInitArgs() );
278     }
279 
280     return m_pImpl->m_xTheRegistry;
281 }
282 
283 //=========================================================================
284 //
285 // XInitialization methods.
286 //
287 //=========================================================================
288 
289 // virtual
290 void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments )
291     throw( Exception, RuntimeException )
292 {
293     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
294     m_pImpl->m_aInitArgs = aArguments;
295 }
296 
297 //=========================================================================
298 const Sequence< Any >& UcbStore::getInitArgs() const
299 {
300     return m_pImpl->m_aInitArgs;
301 }
302 
303 //=========================================================================
304 //
305 // PropertySetRegistry_Impl.
306 //
307 //=========================================================================
308 
309 struct PropertySetRegistry_Impl
310 {
311     const Sequence< Any >             m_aInitArgs;
312     PropertySetMap_Impl               m_aPropSets;
313     Reference< XMultiServiceFactory > m_xConfigProvider;
314     Reference< XInterface >           m_xRootReadAccess;
315     Reference< XInterface >           m_xRootWriteAccess;
316     osl::Mutex                        m_aMutex;
317     sal_Bool                          m_bTriedToGetRootReadAccess;  // #82494#
318     sal_Bool                          m_bTriedToGetRootWriteAccess; // #82494#
319 
320     PropertySetRegistry_Impl( const Sequence< Any > &rInitArgs )
321     : m_aInitArgs( rInitArgs ),
322       m_bTriedToGetRootReadAccess( sal_False ),
323       m_bTriedToGetRootWriteAccess( sal_False )
324     {
325     }
326 };
327 
328 //=========================================================================
329 //=========================================================================
330 //=========================================================================
331 //
332 // PropertySetRegistry Implementation.
333 //
334 //=========================================================================
335 //=========================================================================
336 //=========================================================================
337 
338 PropertySetRegistry::PropertySetRegistry(
339                         const Reference< XMultiServiceFactory >& rXSMgr,
340                         const Sequence< Any > &rInitArgs )
341 : m_xSMgr( rXSMgr ),
342   m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) )
343 {
344 }
345 
346 //=========================================================================
347 // virtual
348 PropertySetRegistry::~PropertySetRegistry()
349 {
350     delete m_pImpl;
351 }
352 
353 //=========================================================================
354 //
355 // XInterface methods.
356 //
357 //=========================================================================
358 
359 XINTERFACE_IMPL_5( PropertySetRegistry,
360                    XTypeProvider,
361                    XServiceInfo,
362                    XPropertySetRegistry,
363                    XElementAccess, /* base of XNameAccess */
364                    XNameAccess );
365 
366 //=========================================================================
367 //
368 // XTypeProvider methods.
369 //
370 //=========================================================================
371 
372 XTYPEPROVIDER_IMPL_4( PropertySetRegistry,
373                       XTypeProvider,
374                       XServiceInfo,
375                       XPropertySetRegistry,
376                       XNameAccess );
377 
378 //=========================================================================
379 //
380 // XServiceInfo methods.
381 //
382 //=========================================================================
383 
384 XSERVICEINFO_NOFACTORY_IMPL_1( PropertySetRegistry,
385                                OUString::createFromAscii(
386                                 "com.sun.star.comp.ucb.PropertySetRegistry" ),
387                                OUString::createFromAscii(
388                                 PROPSET_REG_SERVICE_NAME ) );
389 
390 //=========================================================================
391 //
392 // XPropertySetRegistry methods.
393 //
394 //=========================================================================
395 
396 // virtual
397 Reference< XPersistentPropertySet > SAL_CALL
398 PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create )
399     throw( RuntimeException )
400 {
401     if ( key.getLength() )
402     {
403         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
404 
405         PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
406 
407         PropertySetMap_Impl::const_iterator it = rSets.find( key );
408         if ( it != rSets.end() )
409         {
410             // Already instanciated.
411             return Reference< XPersistentPropertySet >( (*it).second );
412         }
413         else
414         {
415             // Create new instance.
416             Reference< XNameAccess > xRootNameAccess(
417                                     getRootConfigReadAccess(), UNO_QUERY );
418             if ( xRootNameAccess.is() )
419             {
420                 // Propertyset in registry?
421                 if ( xRootNameAccess->hasByName( key ) )
422                 {
423                     // Yep!
424                     return Reference< XPersistentPropertySet >(
425                                             new PersistentPropertySet(
426                                                     m_xSMgr, *this, key ) );
427                 }
428                 else if ( create )
429                 {
430                     // No. Create entry for propertyset.
431 
432                     Reference< XSingleServiceFactory > xFac(
433                             getConfigWriteAccess( OUString() ), UNO_QUERY );
434                     Reference< XChangesBatch >  xBatch( xFac, UNO_QUERY );
435                     Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
436 
437                     OSL_ENSURE( xFac.is(),
438                                 "PropertySetRegistry::openPropertySet - "
439                                 "No factory!" );
440 
441                     OSL_ENSURE( xBatch.is(),
442                                 "PropertySetRegistry::openPropertySet - "
443                                 "No batch!" );
444 
445                     OSL_ENSURE( xContainer.is(),
446                                 "PropertySetRegistry::openPropertySet - "
447                                 "No conteiner!" );
448 
449                     if ( xFac.is() && xBatch.is() && xContainer.is() )
450                     {
451                         try
452                         {
453                             // Create new "Properties" config item.
454                             Reference< XNameReplace > xNameReplace(
455                                         xFac->createInstance(), UNO_QUERY );
456 
457                             if ( xNameReplace.is() )
458                             {
459                                 // Fill new item...
460 
461 //                              // Set Values
462 //                              xNameReplace->replaceByName(
463 //                                      OUString::createFromAscii( "Values" ),
464 //                                      makeAny( ... ) );
465 
466                                 // Insert new item.
467                                 xContainer->insertByName(
468                                         key, makeAny( xNameReplace ) );
469                                 // Commit changes.
470                                 xBatch->commitChanges();
471 
472                                 return Reference< XPersistentPropertySet >(
473                                             new PersistentPropertySet(
474                                                     m_xSMgr, *this, key ) );
475                             }
476                         }
477                         catch ( IllegalArgumentException& )
478                         {
479                             // insertByName
480 
481                             OSL_ENSURE( sal_False,
482                                         "PropertySetRegistry::openPropertySet - "
483                                         "caught IllegalArgumentException!" );
484                         }
485                         catch ( ElementExistException& )
486                         {
487                             // insertByName
488 
489                             OSL_ENSURE( sal_False,
490                                         "PropertySetRegistry::openPropertySet - "
491                                         "caught ElementExistException!" );
492                         }
493                         catch ( WrappedTargetException& )
494                         {
495                             // insertByName, commitChanges
496 
497                             OSL_ENSURE( sal_False,
498                                         "PropertySetRegistry::openPropertySet - "
499                                         "caught WrappedTargetException!" );
500                         }
501                         catch ( RuntimeException& )
502                         {
503                             OSL_ENSURE( sal_False,
504                                         "PropertySetRegistry::openPropertySet - "
505                                         "caught RuntimeException!" );
506                         }
507                         catch ( Exception& )
508                         {
509                             // createInstance
510 
511                             OSL_ENSURE( sal_False,
512                                         "PropertySetRegistry::openPropertySet - "
513                                         "caught Exception!" );
514                         }
515                     }
516                 }
517                 else
518                 {
519                     // No entry. Fail, but no error.
520                     return Reference< XPersistentPropertySet >();
521                 }
522             }
523 
524             OSL_ENSURE( sal_False,
525                         "PropertySetRegistry::openPropertySet - Error!" );
526         }
527     }
528 
529     return Reference< XPersistentPropertySet >();
530 }
531 
532 //=========================================================================
533 // virtual
534 void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key )
535     throw( RuntimeException )
536 {
537     if ( !key.getLength() )
538         return;
539 
540     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
541 
542     Reference< XNameAccess > xRootNameAccess(
543                                     getRootConfigReadAccess(), UNO_QUERY );
544     if ( xRootNameAccess.is() )
545     {
546         // Propertyset in registry?
547         if ( !xRootNameAccess->hasByName( key ) )
548             return;
549         Reference< XChangesBatch > xBatch(
550                             getConfigWriteAccess( OUString() ), UNO_QUERY );
551         Reference< XNameContainer > xContainer( xBatch, UNO_QUERY );
552 
553         OSL_ENSURE( xBatch.is(),
554                     "PropertySetRegistry::removePropertySet - "
555                     "No batch!" );
556 
557         OSL_ENSURE( xContainer.is(),
558                     "PropertySetRegistry::removePropertySet - "
559                     "No conteiner!" );
560 
561         if ( xBatch.is() && xContainer.is() )
562         {
563             try
564             {
565                 // Remove item.
566                 xContainer->removeByName( key );
567                 // Commit changes.
568                 xBatch->commitChanges();
569 
570                 // Success.
571                 return;
572             }
573             catch ( NoSuchElementException& )
574             {
575                 // removeByName
576 
577                 OSL_ENSURE( sal_False,
578                             "PropertySetRegistry::removePropertySet - "
579                             "caught NoSuchElementException!" );
580                 return;
581             }
582             catch ( WrappedTargetException& )
583             {
584                 // commitChanges
585 
586                 OSL_ENSURE( sal_False,
587                             "PropertySetRegistry::removePropertySet - "
588                             "caught WrappedTargetException!" );
589                 return;
590             }
591         }
592 
593         return;
594     }
595 
596     OSL_ENSURE( sal_False, "PropertySetRegistry::removePropertySet - Error!" );
597 }
598 
599 //=========================================================================
600 //
601 // XElementAccess methods.
602 //
603 //=========================================================================
604 
605 // virtual
606 com::sun::star::uno::Type SAL_CALL PropertySetRegistry::getElementType()
607     throw( RuntimeException )
608 {
609     return getCppuType( ( Reference< XPersistentPropertySet > * ) 0 );
610 }
611 
612 //=========================================================================
613 // virtual
614 sal_Bool SAL_CALL PropertySetRegistry::hasElements()
615     throw( RuntimeException )
616 {
617     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
618 
619     Reference< XElementAccess > xElemAccess(
620                                     getRootConfigReadAccess(), UNO_QUERY );
621     if ( xElemAccess.is() )
622         return xElemAccess->hasElements();
623 
624     return sal_False;
625 }
626 
627 //=========================================================================
628 //
629 // XNameAccess methods.
630 //
631 //=========================================================================
632 
633 // virtual
634 Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName )
635     throw( NoSuchElementException, WrappedTargetException, RuntimeException )
636 {
637     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
638 
639     Reference< XNameAccess > xNameAccess(
640                                     getRootConfigReadAccess(), UNO_QUERY );
641     if ( xNameAccess.is() )
642     {
643 
644         try
645         {
646             return xNameAccess->getByName( aName );
647         }
648         catch ( NoSuchElementException& )
649         {
650             // getByName
651         }
652         catch ( WrappedTargetException& )
653         {
654             // getByName
655         }
656     }
657 
658     return Any();
659 }
660 
661 //=========================================================================
662 // virtual
663 Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames()
664     throw( RuntimeException )
665 {
666     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
667 
668     Reference< XNameAccess > xNameAccess(
669                                     getRootConfigReadAccess(), UNO_QUERY );
670     if ( xNameAccess.is() )
671     {
672         return xNameAccess->getElementNames();
673     }
674     return Sequence< OUString >( 0 );
675 }
676 
677 //=========================================================================
678 // virtual
679 sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName )
680     throw( RuntimeException )
681 {
682     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
683 
684     Reference< XNameAccess > xNameAccess(
685                                     getRootConfigReadAccess(), UNO_QUERY );
686     if ( xNameAccess.is() )
687     {
688         return xNameAccess->hasByName( aName );
689     }
690 
691     return sal_False;
692 }
693 
694 //=========================================================================
695 void PropertySetRegistry::add( PersistentPropertySet* pSet )
696 {
697     OUString key( pSet->getKey() );
698 
699     if ( key.getLength() )
700     {
701         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
702         m_pImpl->m_aPropSets[ key ] = pSet;
703     }
704 }
705 
706 //=========================================================================
707 void PropertySetRegistry::remove( PersistentPropertySet* pSet )
708 {
709     OUString key( pSet->getKey() );
710 
711     if ( key.getLength() )
712     {
713         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
714 
715         PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
716 
717         PropertySetMap_Impl::iterator it = rSets.find( key );
718         if ( it != rSets.end() )
719         {
720             // Found.
721             rSets.erase( it );
722         }
723     }
724 }
725 
726 //=========================================================================
727 void PropertySetRegistry::renamePropertySet( const OUString& rOldKey,
728                                              const OUString& rNewKey )
729 {
730     if ( rOldKey == rNewKey )
731         return;
732 
733     Reference< XNameAccess > xRootNameAccess(
734                             getConfigWriteAccess( OUString() ), UNO_QUERY );
735     if ( xRootNameAccess.is() )
736     {
737         // Old key present?
738         if ( xRootNameAccess->hasByName( rOldKey ) )
739         {
740             // New key not present?
741             if ( xRootNameAccess->hasByName( rNewKey ) )
742             {
743                 OSL_ENSURE( sal_False,
744                             "PropertySetRegistry::renamePropertySet - "
745                             "New key exists!" );
746                 return;
747             }
748             Reference< XSingleServiceFactory > xFac(
749                                                 xRootNameAccess, UNO_QUERY );
750             Reference< XChangesBatch >  xBatch( xFac, UNO_QUERY );
751             Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
752 
753             OSL_ENSURE( xFac.is(),
754                         "PropertySetRegistry::renamePropertySet - "
755                         "No factory!" );
756 
757             OSL_ENSURE( xBatch.is(),
758                         "PropertySetRegistry::renamePropertySet - "
759                         "No batch!" );
760 
761             OSL_ENSURE( xContainer.is(),
762                         "PropertySetRegistry::renamePropertySet - "
763                         "No container!" );
764 
765             if ( xFac.is() && xBatch.is() && xContainer.is() )
766             {
767                 //////////////////////////////////////////////////////
768                 // Create new "Properties" config item.
769                 //////////////////////////////////////////////////////
770 
771                 try
772                 {
773                     Reference< XNameReplace > xNameReplace(
774                                     xFac->createInstance(), UNO_QUERY );
775 
776                     if ( xNameReplace.is() )
777                     {
778                         // Insert new item.
779                         xContainer->insertByName(
780                                     rNewKey, makeAny( xNameReplace ) );
781                         // Commit changes.
782                         xBatch->commitChanges();
783                     }
784                 }
785                 catch ( IllegalArgumentException& )
786                 {
787                     // insertByName
788 
789                     OSL_ENSURE( sal_False,
790                                 "PropertySetRegistry::renamePropertySet - "
791                                 "caught IllegalArgumentException!" );
792                     return;
793                 }
794                 catch ( ElementExistException& )
795                 {
796                     // insertByName
797 
798                     OSL_ENSURE( sal_False,
799                                 "PropertySetRegistry::renamePropertySet - "
800                                 "caught ElementExistException!" );
801                     return;
802                 }
803                 catch ( WrappedTargetException& )
804                 {
805                     // insertByName, commitChanges
806 
807                     OSL_ENSURE( sal_False,
808                                 "PropertySetRegistry::renamePropertySet - "
809                                 "caught WrappedTargetException!" );
810                     return;
811                 }
812                 catch ( RuntimeException& )
813                 {
814                     OSL_ENSURE( sal_False,
815                                 "PropertySetRegistry::renamePropertySet - "
816                                 "caught RuntimeException!" );
817                     return;
818                 }
819                 catch ( Exception& )
820                 {
821                     // createInstance
822 
823                     OSL_ENSURE( sal_False,
824                                 "PropertySetRegistry::renamePropertySet - "
825                                 "caught Exception!" );
826                     return;
827                 }
828 
829                 //////////////////////////////////////////////////////
830                 // Copy data...
831                 //////////////////////////////////////////////////////
832 
833                 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
834                                                 xRootNameAccess, UNO_QUERY );
835                 if ( !xRootHierNameAccess.is() )
836                 {
837                     OSL_ENSURE( sal_False,
838                                 "PropertySetRegistry::renamePropertySet - "
839                                 "No hierarchical name access!" );
840                     return;
841                 }
842 
843                 try
844                 {
845                     rtl::OUString aOldValuesKey
846                         = makeHierarchalNameSegment( rOldKey );
847                     aOldValuesKey += OUString::createFromAscii( "/Values" );
848 
849                     Reference< XNameAccess > xOldNameAccess;
850                     xRootHierNameAccess->getByHierarchicalName(
851                                                         aOldValuesKey )
852                         >>= xOldNameAccess;
853                     if ( !xOldNameAccess.is() )
854                     {
855                         OSL_ENSURE( sal_False,
856                             "PersistentPropertySet::renamePropertySet - "
857                             "No old name access!" );
858                         return;
859                     }
860 
861                     // Obtain property names.
862                     Sequence< OUString > aElems
863                                     = xOldNameAccess->getElementNames();
864                     sal_Int32 nCount = aElems.getLength();
865                     if ( nCount )
866                     {
867                         rtl::OUString aNewValuesKey
868                             = makeHierarchalNameSegment( rNewKey );
869                         aNewValuesKey += OUString::createFromAscii( "/Values" );
870 
871                         Reference< XSingleServiceFactory > xNewFac;
872                         xRootHierNameAccess->getByHierarchicalName(
873                                                         aNewValuesKey )
874                             >>= xNewFac;
875                         if ( !xNewFac.is() )
876                         {
877                             OSL_ENSURE( sal_False,
878                                 "PersistentPropertySet::renamePropertySet - "
879                                 "No new factory!" );
880                             return;
881                         }
882 
883                         Reference< XNameContainer > xNewContainer(
884                                                     xNewFac, UNO_QUERY );
885                         if ( !xNewContainer.is() )
886                         {
887                             OSL_ENSURE( sal_False,
888                                 "PersistentPropertySet::renamePropertySet - "
889                                 "No new container!" );
890                             return;
891                         }
892 
893                         aOldValuesKey += OUString::createFromAscii( "/" );
894 
895                         OUString aHandleKey
896                             = OUString::createFromAscii( "/Handle" );
897                         OUString aValueKey
898                             = OUString::createFromAscii( "/Value" );
899                         OUString aStateKey
900                             = OUString::createFromAscii( "/State" );
901                         OUString aAttrKey
902                             = OUString::createFromAscii( "/Attributes" );
903 
904                         for ( sal_Int32 n = 0; n < nCount; ++n )
905                         {
906                             const OUString& rPropName = aElems[ n ];
907 
908                             // Create new item.
909                             Reference< XNameReplace > xNewPropNameReplace(
910                                 xNewFac->createInstance(), UNO_QUERY );
911 
912                             if ( !xNewPropNameReplace.is() )
913                             {
914                                 OSL_ENSURE( sal_False,
915                                     "PersistentPropertySet::renamePropertySet - "
916                                     "No new prop name replace!" );
917                                 return;
918                             }
919 
920                             // Fill new item...
921 
922                             // Set Values
923                             OUString aKey = aOldValuesKey;
924                             aKey += makeHierarchalNameSegment( rPropName );
925 
926                             // ... handle
927                             OUString aNewKey1 = aKey;
928                             aNewKey1 += aHandleKey;
929                             Any aAny =
930                                 xRootHierNameAccess->getByHierarchicalName(
931                                     aNewKey1 );
932                             xNewPropNameReplace->replaceByName(
933                                 OUString::createFromAscii( "Handle" ),
934                                 aAny );
935 
936                             // ... value
937                             aNewKey1 = aKey;
938                             aNewKey1 += aValueKey;
939                             aAny =
940                                 xRootHierNameAccess->getByHierarchicalName(
941                                     aNewKey1 );
942                             xNewPropNameReplace->replaceByName(
943                                 OUString::createFromAscii( "Value" ),
944                                 aAny );
945 
946                             // ... state
947                             aNewKey1 = aKey;
948                             aNewKey1 += aStateKey;
949                             aAny =
950                                 xRootHierNameAccess->getByHierarchicalName(
951                                     aNewKey1 );
952                             xNewPropNameReplace->replaceByName(
953                                 OUString::createFromAscii( "State" ),
954                                 aAny );
955 
956                             // ... attributes
957                             aNewKey1 = aKey;
958                             aNewKey1 += aAttrKey;
959                             aAny =
960                                 xRootHierNameAccess->getByHierarchicalName(
961                                     aNewKey1 );
962                             xNewPropNameReplace->replaceByName(
963                                 OUString::createFromAscii( "Attributes" ),
964                                 aAny );
965 
966                             // Insert new item.
967                             xNewContainer->insertByName(
968                                 rPropName, makeAny( xNewPropNameReplace ) );
969 
970                             // Commit changes.
971                             xBatch->commitChanges();
972                         }
973                     }
974                 }
975                 catch ( IllegalArgumentException& )
976                 {
977                     // insertByName, replaceByName
978 
979                     OSL_ENSURE( sal_False,
980                                 "PropertySetRegistry::renamePropertySet - "
981                                 "caught IllegalArgumentException!" );
982                     return;
983                 }
984                 catch ( ElementExistException& )
985                 {
986                     // insertByName
987 
988                     OSL_ENSURE( sal_False,
989                                 "PropertySetRegistry::renamePropertySet - "
990                                 "caught ElementExistException!" );
991                     return;
992                 }
993                 catch ( WrappedTargetException& )
994                 {
995                     // insertByName, replaceByName, commitChanges
996 
997                     OSL_ENSURE( sal_False,
998                                 "PropertySetRegistry::renamePropertySet - "
999                                 "caught WrappedTargetException!" );
1000                     return;
1001                 }
1002                 catch ( NoSuchElementException& )
1003                 {
1004                     // getByHierarchicalName, replaceByName
1005 
1006                     OSL_ENSURE( sal_False,
1007                                 "PropertySetRegistry::renamePropertySet - "
1008                                 "caught NoSuchElementException!" );
1009                     return;
1010                 }
1011                 catch ( RuntimeException& )
1012                 {
1013                     OSL_ENSURE( sal_False,
1014                                 "PropertySetRegistry::renamePropertySet - "
1015                                 "caught RuntimeException!" );
1016                     return;
1017                 }
1018                 catch ( Exception& )
1019                 {
1020                     // createInstance
1021 
1022                     OSL_ENSURE( sal_False,
1023                                 "PropertySetRegistry::renamePropertySet - "
1024                                 "caught Exception!" );
1025                     return;
1026                 }
1027 
1028                 //////////////////////////////////////////////////////
1029                 // Remove old entry...
1030                 //////////////////////////////////////////////////////
1031 
1032                 try
1033                 {
1034                     // Remove item.
1035                     xContainer->removeByName( rOldKey );
1036                     // Commit changes.
1037                     xBatch->commitChanges();
1038 
1039                     // Success.
1040                     return;
1041                 }
1042                 catch ( NoSuchElementException& )
1043                 {
1044                     // removeByName
1045 
1046                     OSL_ENSURE( sal_False,
1047                                 "PropertySetRegistry::renamePropertySet - "
1048                                 "caught NoSuchElementException!" );
1049                     return;
1050                 }
1051                 catch ( WrappedTargetException& )
1052                 {
1053                     // commitChanges
1054 
1055                     OSL_ENSURE( sal_False,
1056                                 "PropertySetRegistry::renamePropertySet - "
1057                                 "caught WrappedTargetException!" );
1058                     return;
1059                 }
1060             }
1061         }
1062     }
1063 
1064     OSL_ENSURE( sal_False, "PropertySetRegistry::renamePropertySet - Error!" );
1065 }
1066 
1067 //=========================================================================
1068 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider()
1069 {
1070     if ( !m_pImpl->m_xConfigProvider.is() )
1071     {
1072         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1073         if ( !m_pImpl->m_xConfigProvider.is() )
1074         {
1075             const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs;
1076 
1077             if ( rInitArgs.getLength() > 0 )
1078             {
1079                 // Extract config provider from service init args.
1080                 rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider;
1081 
1082                 OSL_ENSURE( m_pImpl->m_xConfigProvider.is(),
1083                             "PropertySetRegistry::getConfigProvider - "
1084                             "No config provider!" );
1085             }
1086             else
1087             {
1088                 try
1089                 {
1090                     m_pImpl->m_xConfigProvider
1091                         = Reference< XMultiServiceFactory >(
1092                             m_xSMgr->createInstance(
1093                                 OUString::createFromAscii(
1094                                     "com.sun.star.configuration."
1095                                     "ConfigurationProvider" ) ),
1096                             UNO_QUERY );
1097 
1098                     OSL_ENSURE( m_pImpl->m_xConfigProvider.is(),
1099                                 "PropertySetRegistry::getConfigProvider - "
1100                                 "No config provider!" );
1101 
1102                 }
1103                 catch ( Exception& )
1104                 {
1105                     OSL_ENSURE( sal_False,
1106                                 "PropertySetRegistry::getConfigProvider - "
1107                                 "caught exception!" );
1108                 }
1109             }
1110         }
1111     }
1112 
1113     return m_pImpl->m_xConfigProvider;
1114 }
1115 
1116 //=========================================================================
1117 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
1118 {
1119     try
1120     {
1121         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1122 
1123         if ( !m_pImpl->m_xRootReadAccess.is() )
1124         {
1125             if ( m_pImpl->m_bTriedToGetRootReadAccess ) // #82494#
1126             {
1127                 OSL_ENSURE( sal_False,
1128                             "PropertySetRegistry::getRootConfigReadAccess - "
1129                             "Unable to read any config data! -> #82494#" );
1130                 return Reference< XInterface >();
1131             }
1132 
1133             getConfigProvider();
1134 
1135             if ( m_pImpl->m_xConfigProvider.is() )
1136             {
1137                 Sequence< Any > aArguments( 1 );
1138                 PropertyValue aProperty;
1139                 aProperty.Name
1140                     = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
1141                                             CFGPROPERTY_NODEPATH ) );
1142                 aProperty.Value
1143                     <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
1144                                             STORE_CONTENTPROPERTIES_KEY ) );
1145                 aArguments[ 0 ] <<= aProperty;
1146 
1147                 m_pImpl->m_bTriedToGetRootReadAccess = sal_True;
1148 
1149                 m_pImpl->m_xRootReadAccess =
1150                     m_pImpl->m_xConfigProvider->createInstanceWithArguments(
1151                         OUString::createFromAscii(
1152                             "com.sun.star.configuration.ConfigurationAccess" ),
1153                         aArguments );
1154 
1155                 if ( m_pImpl->m_xRootReadAccess.is() )
1156                     return m_pImpl->m_xRootReadAccess;
1157             }
1158         }
1159         else
1160             return m_pImpl->m_xRootReadAccess;
1161     }
1162     catch ( RuntimeException& )
1163     {
1164         throw;
1165     }
1166     catch ( Exception& )
1167     {
1168         // createInstance, createInstanceWithArguments
1169 
1170         OSL_ENSURE( sal_False,
1171             "PropertySetRegistry::getRootConfigReadAccess - caught Exception!" );
1172         return Reference< XInterface >();
1173     }
1174 
1175     OSL_ENSURE( sal_False,
1176                 "PropertySetRegistry::getRootConfigReadAccess - Error!" );
1177     return Reference< XInterface >();
1178 }
1179 
1180 //=========================================================================
1181 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
1182                                                     const OUString& rPath )
1183 {
1184     try
1185     {
1186         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1187 
1188         if ( !m_pImpl->m_xRootWriteAccess.is() )
1189         {
1190             if ( m_pImpl->m_bTriedToGetRootWriteAccess ) // #82494#
1191             {
1192                 OSL_ENSURE( sal_False,
1193                             "PropertySetRegistry::getConfigWriteAccess - "
1194                             "Unable to write any config data! -> #82494#" );
1195                 return Reference< XInterface >();
1196             }
1197 
1198             getConfigProvider();
1199 
1200             if ( m_pImpl->m_xConfigProvider.is() )
1201             {
1202                 Sequence< Any > aArguments( 2 );
1203                 PropertyValue   aProperty;
1204 
1205                 aProperty.Name
1206                     = OUString( RTL_CONSTASCII_USTRINGPARAM(
1207                                             CFGPROPERTY_NODEPATH ) );
1208                 aProperty.Value
1209                     <<= OUString( RTL_CONSTASCII_USTRINGPARAM(
1210                                             STORE_CONTENTPROPERTIES_KEY ) );
1211                 aArguments[ 0 ] <<= aProperty;
1212 
1213                 aProperty.Name
1214                     = OUString( RTL_CONSTASCII_USTRINGPARAM(
1215                                             CFGPROPERTY_LAZYWRITE ) );
1216                 aProperty.Value <<= sal_True;
1217                 aArguments[ 1 ] <<= aProperty;
1218 
1219                 m_pImpl->m_bTriedToGetRootWriteAccess = sal_True;
1220 
1221                 m_pImpl->m_xRootWriteAccess =
1222                     m_pImpl->m_xConfigProvider->createInstanceWithArguments(
1223                         OUString::createFromAscii(
1224                             "com.sun.star.configuration.ConfigurationUpdateAccess" ),
1225                         aArguments );
1226 
1227                 OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(),
1228                             "PropertySetRegistry::getConfigWriteAccess - "
1229                             "No config update access!" );
1230             }
1231         }
1232 
1233         if ( m_pImpl->m_xRootWriteAccess.is() )
1234         {
1235             if ( rPath.getLength() )
1236             {
1237                 Reference< XHierarchicalNameAccess > xNA(
1238                                 m_pImpl->m_xRootWriteAccess, UNO_QUERY );
1239                 if ( xNA.is() )
1240                 {
1241                     Reference< XInterface > xInterface;
1242                     xNA->getByHierarchicalName( rPath ) >>= xInterface;
1243 
1244                     if ( xInterface.is() )
1245                         return xInterface;
1246                 }
1247             }
1248             else
1249                 return m_pImpl->m_xRootWriteAccess;
1250         }
1251     }
1252     catch ( RuntimeException& )
1253     {
1254         throw;
1255     }
1256     catch ( NoSuchElementException& )
1257     {
1258         // getByHierarchicalName
1259 
1260         OSL_ENSURE( sal_False,
1261             "PropertySetRegistry::getConfigWriteAccess - "
1262             "caught NoSuchElementException!" );
1263         return Reference< XInterface >();
1264     }
1265     catch ( Exception& )
1266     {
1267         // createInstance, createInstanceWithArguments
1268 
1269         OSL_ENSURE( sal_False,
1270                     "PropertySetRegistry::getConfigWriteAccess - "
1271                     "caught Exception!" );
1272         return Reference< XInterface >();
1273     }
1274 
1275     OSL_ENSURE( sal_False,
1276                 "PropertySetRegistry::getConfigWriteAccess - Error!" );
1277     return Reference< XInterface >();
1278 }
1279 
1280 //=========================================================================
1281 //
1282 // PropertyListeners_Impl.
1283 //
1284 //=========================================================================
1285 
1286 typedef OMultiTypeInterfaceContainerHelperVar
1287 <
1288     OUString,
1289     hashString_Impl,
1290     equalString_Impl
1291 > PropertyListeners_Impl;
1292 
1293 //=========================================================================
1294 //
1295 // PersistentPropertySet_Impl.
1296 //
1297 //=========================================================================
1298 
1299 struct PersistentPropertySet_Impl
1300 {
1301     PropertySetRegistry*        m_pCreator;
1302     PropertySetInfo_Impl*       m_pInfo;
1303     OUString                    m_aKey;
1304     OUString                    m_aFullKey;
1305     osl::Mutex                  m_aMutex;
1306     OInterfaceContainerHelper*  m_pDisposeEventListeners;
1307     OInterfaceContainerHelper*  m_pPropSetChangeListeners;
1308     PropertyListeners_Impl*     m_pPropertyChangeListeners;
1309 
1310     PersistentPropertySet_Impl( PropertySetRegistry& rCreator,
1311                                 const OUString& rKey )
1312     : m_pCreator( &rCreator ), m_pInfo( NULL ), m_aKey( rKey ),
1313       m_pDisposeEventListeners( NULL ), m_pPropSetChangeListeners( NULL ),
1314       m_pPropertyChangeListeners( NULL )
1315     {
1316         m_pCreator->acquire();
1317     }
1318 
1319     ~PersistentPropertySet_Impl()
1320     {
1321         m_pCreator->release();
1322 
1323         if ( m_pInfo )
1324             m_pInfo->release();
1325 
1326         delete m_pDisposeEventListeners;
1327         delete m_pPropSetChangeListeners;
1328         delete m_pPropertyChangeListeners;
1329     }
1330 };
1331 
1332 //=========================================================================
1333 //=========================================================================
1334 //=========================================================================
1335 //
1336 // PersistentPropertySet Implementation.
1337 //
1338 //=========================================================================
1339 //=========================================================================
1340 //=========================================================================
1341 
1342 PersistentPropertySet::PersistentPropertySet(
1343                         const Reference< XMultiServiceFactory >& rXSMgr,
1344                         PropertySetRegistry& rCreator,
1345                         const OUString& rKey )
1346 : m_xSMgr( rXSMgr ),
1347   m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) )
1348 {
1349     // register at creator.
1350     rCreator.add( this );
1351 }
1352 
1353 //=========================================================================
1354 // virtual
1355 PersistentPropertySet::~PersistentPropertySet()
1356 {
1357     // deregister at creator.
1358     m_pImpl->m_pCreator->remove( this );
1359 
1360     delete m_pImpl;
1361 }
1362 
1363 //=========================================================================
1364 //
1365 // XInterface methods.
1366 //
1367 //=========================================================================
1368 
1369 XINTERFACE_IMPL_9( PersistentPropertySet,
1370                    XTypeProvider,
1371                    XServiceInfo,
1372                    XComponent,
1373                    XPropertySet, /* base of XPersistentPropertySet */
1374                    XNamed,
1375                    XPersistentPropertySet,
1376                    XPropertyContainer,
1377                    XPropertySetInfoChangeNotifier,
1378                    XPropertyAccess );
1379 
1380 //=========================================================================
1381 //
1382 // XTypeProvider methods.
1383 //
1384 //=========================================================================
1385 
1386 XTYPEPROVIDER_IMPL_8( PersistentPropertySet,
1387                       XTypeProvider,
1388                       XServiceInfo,
1389                       XComponent,
1390                       XPersistentPropertySet,
1391                       XNamed,
1392                       XPropertyContainer,
1393                       XPropertySetInfoChangeNotifier,
1394                       XPropertyAccess );
1395 
1396 //=========================================================================
1397 //
1398 // XServiceInfo methods.
1399 //
1400 //=========================================================================
1401 
1402 XSERVICEINFO_NOFACTORY_IMPL_1( PersistentPropertySet,
1403                                OUString::createFromAscii(
1404                                 "com.sun.star.comp.ucb.PersistentPropertySet" ),
1405                                OUString::createFromAscii(
1406                                 PERS_PROPSET_SERVICE_NAME ) );
1407 
1408 //=========================================================================
1409 //
1410 // XComponent methods.
1411 //
1412 //=========================================================================
1413 
1414 // virtual
1415 void SAL_CALL PersistentPropertySet::dispose()
1416     throw( RuntimeException )
1417 {
1418     if ( m_pImpl->m_pDisposeEventListeners &&
1419          m_pImpl->m_pDisposeEventListeners->getLength() )
1420     {
1421         EventObject aEvt;
1422         aEvt.Source = static_cast< XComponent * >( this  );
1423         m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
1424     }
1425 
1426     if ( m_pImpl->m_pPropSetChangeListeners &&
1427          m_pImpl->m_pPropSetChangeListeners->getLength() )
1428     {
1429         EventObject aEvt;
1430         aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this  );
1431         m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
1432     }
1433 
1434     if ( m_pImpl->m_pPropertyChangeListeners )
1435     {
1436         EventObject aEvt;
1437         aEvt.Source = static_cast< XPropertySet * >( this  );
1438         m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
1439     }
1440 }
1441 
1442 //=========================================================================
1443 // virtual
1444 void SAL_CALL PersistentPropertySet::addEventListener(
1445                             const Reference< XEventListener >& Listener )
1446     throw( RuntimeException )
1447 {
1448     if ( !m_pImpl->m_pDisposeEventListeners )
1449         m_pImpl->m_pDisposeEventListeners =
1450                     new OInterfaceContainerHelper( m_pImpl->m_aMutex );
1451 
1452     m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
1453 }
1454 
1455 //=========================================================================
1456 // virtual
1457 void SAL_CALL PersistentPropertySet::removeEventListener(
1458                             const Reference< XEventListener >& Listener )
1459     throw( RuntimeException )
1460 {
1461     if ( m_pImpl->m_pDisposeEventListeners )
1462         m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
1463 
1464     // Note: Don't want to delete empty container here -> performance.
1465 }
1466 
1467 //=========================================================================
1468 //
1469 // XPropertySet methods.
1470 //
1471 //=========================================================================
1472 
1473 // virtual
1474 Reference< XPropertySetInfo > SAL_CALL
1475                                 PersistentPropertySet::getPropertySetInfo()
1476     throw( RuntimeException )
1477 {
1478     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1479 
1480     PropertySetInfo_Impl*& rpInfo = m_pImpl->m_pInfo;
1481     if ( !rpInfo )
1482     {
1483         rpInfo = new PropertySetInfo_Impl( m_xSMgr, this );
1484         rpInfo->acquire();
1485     }
1486     return Reference< XPropertySetInfo >( rpInfo );
1487 }
1488 
1489 //=========================================================================
1490 // virtual
1491 void SAL_CALL PersistentPropertySet::setPropertyValue(
1492                         const OUString& aPropertyName, const Any& aValue )
1493     throw( UnknownPropertyException,
1494            PropertyVetoException,
1495            IllegalArgumentException,
1496            WrappedTargetException,
1497            RuntimeException )
1498 {
1499     if ( !aPropertyName.getLength() )
1500         throw UnknownPropertyException();
1501 
1502     osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1503 
1504     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1505                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1506     if ( xRootHierNameAccess.is() )
1507     {
1508         OUString aFullPropName( getFullKey() );
1509         aFullPropName += OUString::createFromAscii( "/" );
1510         aFullPropName += makeHierarchalNameSegment( aPropertyName );
1511 
1512         // Does property exist?
1513         if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1514         {
1515             Reference< XNameReplace > xNameReplace(
1516                     m_pImpl->m_pCreator->getConfigWriteAccess(
1517                                             aFullPropName ), UNO_QUERY );
1518             Reference< XChangesBatch > xBatch(
1519                     m_pImpl->m_pCreator->getConfigWriteAccess(
1520                                             OUString() ), UNO_QUERY );
1521 
1522             if ( xNameReplace.is() && xBatch.is() )
1523             {
1524                 try
1525                 {
1526                     // Obtain old value
1527                     OUString aValueName = aFullPropName;
1528                     aValueName += OUString::createFromAscii( "/Value" );
1529                     Any aOldValue
1530                         = xRootHierNameAccess->getByHierarchicalName(
1531                                                                 aValueName );
1532                     // Check value type.
1533                     if ( aOldValue.getValueType() != aValue.getValueType() )
1534                     {
1535                         aCGuard.clear();
1536                         throw IllegalArgumentException();
1537                     }
1538 
1539                     // Write value
1540                     xNameReplace->replaceByName(
1541                                     OUString::createFromAscii( "Value" ),
1542                                     aValue );
1543 
1544                     // Write state ( Now it is a directly set value )
1545                     xNameReplace->replaceByName(
1546                                     OUString::createFromAscii( "State" ),
1547                                     makeAny(
1548                                         sal_Int32(
1549                                             PropertyState_DIRECT_VALUE ) ) );
1550 
1551                     // Commit changes.
1552                     xBatch->commitChanges();
1553 
1554                     PropertyChangeEvent aEvt;
1555                     if ( m_pImpl->m_pPropertyChangeListeners )
1556                     {
1557                         // Obtain handle
1558                         aValueName = aFullPropName;
1559                         aValueName += OUString::createFromAscii( "/Handle" );
1560                         sal_Int32 nHandle = -1;
1561                         xRootHierNameAccess->getByHierarchicalName( aValueName )
1562                             >>= nHandle;
1563 
1564                         aEvt.Source         = (OWeakObject*)this;
1565                         aEvt.PropertyName   = aPropertyName;
1566                         aEvt.PropertyHandle = nHandle;
1567                         aEvt.Further        = sal_False;
1568                         aEvt.OldValue       = aOldValue;
1569                         aEvt.NewValue       = aValue;
1570 
1571                         // Callback follows!
1572                         aCGuard.clear();
1573 
1574                         notifyPropertyChangeEvent( aEvt );
1575                     }
1576                     return;
1577                 }
1578                 catch ( IllegalArgumentException& )
1579                 {
1580                     // replaceByName
1581                 }
1582                 catch ( NoSuchElementException& )
1583                 {
1584                     // getByHierarchicalName, replaceByName
1585                 }
1586                 catch ( WrappedTargetException& )
1587                 {
1588                     // replaceByName, commitChanges
1589                 }
1590             }
1591         }
1592     }
1593 
1594     throw UnknownPropertyException();
1595 }
1596 
1597 //=========================================================================
1598 // virtual
1599 Any SAL_CALL PersistentPropertySet::getPropertyValue(
1600                                             const OUString& PropertyName )
1601     throw( UnknownPropertyException,
1602            WrappedTargetException,
1603            RuntimeException )
1604 {
1605     if ( !PropertyName.getLength() )
1606         throw UnknownPropertyException();
1607 
1608     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1609 
1610     Reference< XHierarchicalNameAccess > xNameAccess(
1611                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1612     if ( xNameAccess.is() )
1613     {
1614         OUString aFullPropName( getFullKey() );
1615         aFullPropName += OUString::createFromAscii( "/" );
1616         aFullPropName += makeHierarchalNameSegment( PropertyName );
1617         aFullPropName += OUString::createFromAscii( "/Value" );
1618         try
1619         {
1620             return xNameAccess->getByHierarchicalName( aFullPropName );
1621         }
1622         catch ( NoSuchElementException& )
1623         {
1624             throw UnknownPropertyException();
1625         }
1626     }
1627 
1628     throw UnknownPropertyException();
1629 }
1630 
1631 //=========================================================================
1632 // virtual
1633 void SAL_CALL PersistentPropertySet::addPropertyChangeListener(
1634                     const OUString& aPropertyName,
1635                     const Reference< XPropertyChangeListener >& xListener )
1636     throw( UnknownPropertyException,
1637            WrappedTargetException,
1638            RuntimeException )
1639 {
1640 //  load();
1641 
1642     if ( !m_pImpl->m_pPropertyChangeListeners )
1643         m_pImpl->m_pPropertyChangeListeners =
1644                     new PropertyListeners_Impl( m_pImpl->m_aMutex );
1645 
1646     m_pImpl->m_pPropertyChangeListeners->addInterface(
1647                                                 aPropertyName, xListener );
1648 }
1649 
1650 //=========================================================================
1651 // virtual
1652 void SAL_CALL PersistentPropertySet::removePropertyChangeListener(
1653                     const OUString& aPropertyName,
1654                     const Reference< XPropertyChangeListener >& aListener )
1655     throw( UnknownPropertyException,
1656            WrappedTargetException,
1657            RuntimeException )
1658 {
1659 //  load();
1660 
1661     if ( m_pImpl->m_pPropertyChangeListeners )
1662         m_pImpl->m_pPropertyChangeListeners->removeInterface(
1663                                                 aPropertyName, aListener );
1664 
1665     // Note: Don't want to delete empty container here -> performance.
1666 }
1667 
1668 //=========================================================================
1669 // virtual
1670 void SAL_CALL PersistentPropertySet::addVetoableChangeListener(
1671                     const OUString&,
1672                     const Reference< XVetoableChangeListener >& )
1673     throw( UnknownPropertyException,
1674            WrappedTargetException,
1675            RuntimeException )
1676 {
1677 //  load();
1678 //  OSL_ENSURE( sal_False,
1679 //              "PersistentPropertySet::addVetoableChangeListener - N.Y.I." );
1680 }
1681 
1682 //=========================================================================
1683 // virtual
1684 void SAL_CALL PersistentPropertySet::removeVetoableChangeListener(
1685                     const OUString&,
1686                     const Reference< XVetoableChangeListener >& )
1687     throw( UnknownPropertyException,
1688            WrappedTargetException,
1689            RuntimeException )
1690 {
1691 //  load();
1692 //  OSL_ENSURE( sal_False,
1693 //              "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." );
1694 }
1695 
1696 //=========================================================================
1697 //
1698 // XPersistentPropertySet methods.
1699 //
1700 //=========================================================================
1701 
1702 // virtual
1703 Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry()
1704     throw( RuntimeException )
1705 {
1706     return Reference< XPropertySetRegistry >( m_pImpl->m_pCreator );
1707 }
1708 
1709 //=========================================================================
1710 // virtual
1711 OUString SAL_CALL PersistentPropertySet::getKey()
1712     throw( RuntimeException )
1713 {
1714     return m_pImpl->m_aKey;
1715 }
1716 
1717 //=========================================================================
1718 //
1719 // XNamed methods.
1720 //
1721 //=========================================================================
1722 
1723 // virtual
1724 rtl::OUString SAL_CALL PersistentPropertySet::getName()
1725     throw( RuntimeException )
1726 {
1727     // same as getKey()
1728     return m_pImpl->m_aKey;
1729 }
1730 
1731 //=========================================================================
1732 // virtual
1733 void SAL_CALL PersistentPropertySet::setName( const OUString& aName )
1734     throw( RuntimeException )
1735 {
1736     if ( aName != m_pImpl->m_aKey )
1737         m_pImpl->m_pCreator->renamePropertySet( m_pImpl->m_aKey, aName );
1738 }
1739 
1740 //=========================================================================
1741 //
1742 // XPropertyContainer methods.
1743 //
1744 //=========================================================================
1745 
1746 // virtual
1747 void SAL_CALL PersistentPropertySet::addProperty(
1748         const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue )
1749     throw( PropertyExistException,
1750            IllegalTypeException,
1751            IllegalArgumentException,
1752            RuntimeException )
1753 {
1754     if ( !Name.getLength() )
1755         throw IllegalArgumentException();
1756 
1757     // @@@ What other types can't be written to config server?
1758 
1759     // Check type class ( Not all types can be written to storage )
1760     TypeClass eTypeClass = DefaultValue.getValueTypeClass();
1761     if ( eTypeClass == TypeClass_INTERFACE )
1762         throw IllegalTypeException();
1763 
1764     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1765 
1766     // Property already in set?
1767 
1768     OUString aFullValuesName;
1769 
1770     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1771                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1772     if ( xRootHierNameAccess.is() )
1773     {
1774         aFullValuesName = getFullKey();
1775         OUString aFullPropName = aFullValuesName;
1776         aFullPropName += OUString::createFromAscii( "/" );
1777         aFullPropName += makeHierarchalNameSegment( Name );
1778 
1779         if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1780         {
1781             // Already in set.
1782             throw PropertyExistException();
1783         }
1784     }
1785 
1786     // Property is always removeable.
1787     Attributes |= PropertyAttribute::REMOVEABLE;
1788 
1789     // Add property.
1790 
1791     Reference< XSingleServiceFactory > xFac(
1792                 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1793                 UNO_QUERY );
1794     Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
1795     Reference< XChangesBatch >  xBatch(
1796                 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1797                 UNO_QUERY );
1798 
1799     OSL_ENSURE( xFac.is(),
1800                 "PersistentPropertySet::addProperty - No factory!" );
1801 
1802     OSL_ENSURE( xBatch.is(),
1803                 "PersistentPropertySet::addProperty - No batch!" );
1804 
1805     OSL_ENSURE( xContainer.is(),
1806                 "PersistentPropertySet::addProperty - No container!" );
1807 
1808     if ( xFac.is() && xBatch.is() && xContainer.is() )
1809     {
1810         try
1811         {
1812             // Create new "PropertyValue" config item.
1813             Reference< XNameReplace > xNameReplace(
1814                                         xFac->createInstance(), UNO_QUERY );
1815 
1816             if ( xNameReplace.is() )
1817             {
1818                 // Fill new item...
1819 
1820                 // Set handle
1821                 xNameReplace->replaceByName(
1822                                     OUString::createFromAscii( "Handle" ),
1823                                     makeAny( sal_Int32( -1 ) ) );
1824 
1825                 // Set default value
1826                 xNameReplace->replaceByName(
1827                                     OUString::createFromAscii( "Value" ),
1828                                     DefaultValue );
1829 
1830                 // Set state ( always "default" )
1831                 xNameReplace->replaceByName(
1832                                     OUString::createFromAscii( "State" ),
1833                                     makeAny(
1834                                         sal_Int32(
1835                                             PropertyState_DEFAULT_VALUE ) ) );
1836 
1837                 // Set attributes
1838                 xNameReplace->replaceByName(
1839                                     OUString::createFromAscii( "Attributes" ),
1840                                     makeAny( sal_Int32( Attributes ) ) );
1841 
1842                 // Insert new item.
1843                 xContainer->insertByName( Name, makeAny( xNameReplace ) );
1844 
1845                 // Commit changes.
1846                 xBatch->commitChanges();
1847 
1848                 // Property set info is invalid.
1849                 if ( m_pImpl->m_pInfo )
1850                     m_pImpl->m_pInfo->reset();
1851 
1852                 // Notify propertyset info change listeners.
1853                 if ( m_pImpl->m_pPropSetChangeListeners &&
1854                     m_pImpl->m_pPropSetChangeListeners->getLength() )
1855                 {
1856                     PropertySetInfoChangeEvent evt(
1857                                     static_cast< OWeakObject * >( this ),
1858                                     Name,
1859                                     -1,
1860                                     PropertySetInfoChange::PROPERTY_INSERTED );
1861                     notifyPropertySetInfoChange( evt );
1862                 }
1863 
1864                 // Success.
1865                 return;
1866             }
1867         }
1868         catch ( IllegalArgumentException& )
1869         {
1870             // insertByName
1871 
1872             OSL_ENSURE( sal_False,
1873                         "PersistentPropertySet::addProperty - "
1874                         "caught IllegalArgumentException!" );
1875             return;
1876         }
1877         catch ( ElementExistException& )
1878         {
1879             // insertByName
1880 
1881             OSL_ENSURE( sal_False,
1882                         "PersistentPropertySet::addProperty - "
1883                         "caught ElementExistException!" );
1884             return;
1885         }
1886         catch ( WrappedTargetException& )
1887         {
1888             // replaceByName, insertByName, commitChanges
1889 
1890             OSL_ENSURE( sal_False,
1891                         "PersistentPropertySet::addProperty - "
1892                         "caught WrappedTargetException!" );
1893             return;
1894         }
1895         catch ( RuntimeException& )
1896         {
1897             throw;
1898         }
1899         catch ( Exception& )
1900         {
1901             // createInstance
1902 
1903             OSL_ENSURE( sal_False,
1904                         "PersistentPropertySet::addProperty - "
1905                         "caught Exception!" );
1906             return;
1907         }
1908     }
1909 
1910     OSL_ENSURE( sal_False,
1911                 "PersistentPropertySet::addProperty - Error!" );
1912 }
1913 
1914 //=========================================================================
1915 // virtual
1916 void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name )
1917     throw( UnknownPropertyException,
1918            NotRemoveableException,
1919            RuntimeException )
1920 {
1921     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1922 
1923     OUString aFullValuesName;
1924     OUString aFullPropName;
1925 
1926     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1927                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1928     if ( xRootHierNameAccess.is() )
1929     {
1930         aFullValuesName = getFullKey();
1931         aFullPropName   = aFullValuesName;
1932         aFullPropName   += OUString::createFromAscii( "/" );
1933         aFullPropName   += makeHierarchalNameSegment( Name );
1934 
1935         // Property in set?
1936         if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1937             throw UnknownPropertyException();
1938 
1939         // Property removeable?
1940         try
1941         {
1942             OUString aFullAttrName = aFullPropName;
1943             aFullAttrName += OUString::createFromAscii( "/Attributes" );
1944 
1945             sal_Int32 nAttribs = 0;
1946             if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1947                     >>= nAttribs )
1948             {
1949                 if ( !( nAttribs & PropertyAttribute::REMOVEABLE ) )
1950                 {
1951                     // Not removeable!
1952                     throw NotRemoveableException();
1953                 }
1954             }
1955             else
1956             {
1957                 OSL_ENSURE( sal_False,
1958                             "PersistentPropertySet::removeProperty - "
1959                             "No attributes!" );
1960                 return;
1961             }
1962         }
1963         catch ( NoSuchElementException& )
1964         {
1965             // getByHierarchicalName
1966 
1967             OSL_ENSURE( sal_False,
1968                         "PersistentPropertySet::removeProperty - "
1969                         "caught NoSuchElementException!" );
1970         }
1971 
1972         // Remove property...
1973 
1974         Reference< XNameContainer > xContainer(
1975                 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1976                 UNO_QUERY );
1977         Reference< XChangesBatch > xBatch(
1978                 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1979                 UNO_QUERY );
1980 
1981         OSL_ENSURE( xBatch.is(),
1982                     "PersistentPropertySet::removeProperty - No batch!" );
1983 
1984         OSL_ENSURE( xContainer.is(),
1985                     "PersistentPropertySet::removeProperty - No container!" );
1986 
1987         if ( xBatch.is() && xContainer.is() )
1988         {
1989             try
1990             {
1991                 sal_Int32 nHandle = -1;
1992 
1993                 if ( m_pImpl->m_pPropSetChangeListeners &&
1994                      m_pImpl->m_pPropSetChangeListeners->getLength() )
1995                 {
1996                     // Obtain property handle ( needed for propertysetinfo
1997                     // change event )...
1998 
1999                     try
2000                     {
2001                         OUString aFullHandleName = aFullPropName;
2002                         aFullHandleName
2003                                 += OUString::createFromAscii( "/Handle" );
2004 
2005                         if ( ! ( xRootHierNameAccess->getByHierarchicalName(
2006                                         aFullHandleName ) >>= nHandle ) )
2007                             nHandle = -1;
2008 
2009                     }
2010                     catch ( NoSuchElementException& )
2011                     {
2012                         // getByHierarchicalName
2013 
2014                         OSL_ENSURE( sal_False,
2015                                     "PersistentPropertySet::removeProperty - "
2016                                     "caught NoSuchElementException!" );
2017                         nHandle = -1;
2018                     }
2019                 }
2020 
2021                 xContainer->removeByName( Name );
2022                 xBatch->commitChanges();
2023 
2024                 // Property set info is invalid.
2025                 if ( m_pImpl->m_pInfo )
2026                     m_pImpl->m_pInfo->reset();
2027 
2028                 // Notify propertyset info change listeners.
2029                 if ( m_pImpl->m_pPropSetChangeListeners &&
2030                     m_pImpl->m_pPropSetChangeListeners->getLength() )
2031                 {
2032                     PropertySetInfoChangeEvent evt(
2033                                     static_cast< OWeakObject * >( this ),
2034                                     Name,
2035                                     nHandle,
2036                                     PropertySetInfoChange::PROPERTY_REMOVED );
2037                     notifyPropertySetInfoChange( evt );
2038                 }
2039 
2040                 // Success.
2041                 return;
2042             }
2043             catch ( NoSuchElementException& )
2044             {
2045                 // removeByName
2046 
2047                 OSL_ENSURE( sal_False,
2048                             "PersistentPropertySet::removeProperty - "
2049                             "caught NoSuchElementException!" );
2050                 return;
2051             }
2052             catch ( WrappedTargetException& )
2053             {
2054                 // commitChanges
2055 
2056                 OSL_ENSURE( sal_False,
2057                             "PersistentPropertySet::removeProperty - "
2058                             "caught WrappedTargetException!" );
2059                 return;
2060             }
2061         }
2062     }
2063 
2064     OSL_ENSURE( sal_False,
2065                 "PersistentPropertySet::removeProperty - Error!" );
2066 }
2067 
2068 //=========================================================================
2069 //
2070 // XPropertySetInfoChangeNotifier methods.
2071 //
2072 //=========================================================================
2073 
2074 // virtual
2075 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
2076                 const Reference< XPropertySetInfoChangeListener >& Listener )
2077     throw( RuntimeException )
2078 {
2079     if ( !m_pImpl->m_pPropSetChangeListeners )
2080         m_pImpl->m_pPropSetChangeListeners =
2081                     new OInterfaceContainerHelper( m_pImpl->m_aMutex );
2082 
2083     m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
2084 }
2085 
2086 //=========================================================================
2087 // virtual
2088 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
2089                 const Reference< XPropertySetInfoChangeListener >& Listener )
2090     throw( RuntimeException )
2091 {
2092     if ( m_pImpl->m_pPropSetChangeListeners )
2093         m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
2094 }
2095 
2096 //=========================================================================
2097 //
2098 // XPropertyAccess methods.
2099 //
2100 //=========================================================================
2101 
2102 // virtual
2103 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
2104     throw( RuntimeException )
2105 {
2106     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
2107 
2108     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2109                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
2110     if ( xRootHierNameAccess.is() )
2111     {
2112         try
2113         {
2114             Reference< XNameAccess > xNameAccess;
2115             xRootHierNameAccess->getByHierarchicalName(getFullKey())
2116                 >>= xNameAccess;
2117             if ( xNameAccess.is() )
2118             {
2119                 // Obtain property names.
2120 
2121                 Sequence< OUString > aElems = xNameAccess->getElementNames();
2122 
2123                 sal_Int32 nCount = aElems.getLength();
2124                 if ( nCount )
2125                 {
2126                     Reference< XHierarchicalNameAccess > xHierNameAccess(
2127                                                     xNameAccess, UNO_QUERY );
2128 
2129                     OSL_ENSURE( xHierNameAccess.is(),
2130                                 "PersistentPropertySet::getPropertyValues - "
2131                                 "No hierarchical name access!" );
2132 
2133                     if ( xHierNameAccess.is() )
2134                     {
2135                         Sequence< PropertyValue > aValues( nCount );
2136 
2137                         const OUString aHandleName
2138                                     = OUString::createFromAscii( "/Handle" );
2139                         const OUString aValueName
2140                                     = OUString::createFromAscii( "/Value" );
2141                         const OUString aStateName
2142                                     = OUString::createFromAscii( "/State" );
2143 
2144                         for ( sal_Int32 n = 0; n < nCount; ++n )
2145                         {
2146                             PropertyValue& rValue = aValues[ n ];
2147                             OUString rName    = aElems[ n ];
2148                             OUString aXMLName
2149                                         = makeHierarchalNameSegment( rName );
2150 
2151                             // Set property name.
2152 
2153                             rValue.Name = rName;
2154 
2155                             try
2156                             {
2157                                 // Obtain and set property handle
2158                                 OUString aHierName = aXMLName;
2159                                 aHierName += aHandleName;
2160                                 Any aKeyValue
2161                                     = xHierNameAccess->getByHierarchicalName(
2162                                         aHierName );
2163 
2164                                 if ( !( aKeyValue >>= rValue.Handle ) )
2165                                     OSL_ENSURE( sal_False,
2166                                       "PersistentPropertySet::getPropertyValues - "
2167                                       "Error getting property handle!" );
2168                             }
2169                             catch ( NoSuchElementException& )
2170                             {
2171                                 // getByHierarchicalName
2172 
2173                                 OSL_ENSURE( sal_False,
2174                                   "PersistentPropertySet::getPropertyValues - "
2175                                   "NoSuchElementException!" );
2176                             }
2177 
2178                             try
2179                             {
2180                                 // Obtain and set property value
2181                                 OUString aHierName = aXMLName;
2182                                 aHierName += aValueName;
2183                                 rValue.Value
2184                                     = xHierNameAccess->getByHierarchicalName(
2185                                         aHierName );
2186 
2187                                 // Note: The value may be void if addProperty
2188                                 //       was called with a default value
2189                                 //       of type void.
2190                             }
2191                             catch ( NoSuchElementException& )
2192                             {
2193                                 // getByHierarchicalName
2194 
2195                                 OSL_ENSURE( sal_False,
2196                                   "PersistentPropertySet::getPropertyValues - "
2197                                   "NoSuchElementException!" );
2198                             }
2199 
2200                             try
2201                             {
2202                                 // Obtain and set property state
2203                                 OUString aHierName = aXMLName;
2204                                 aHierName += aStateName;
2205                                 Any aKeyValue
2206                                     = xHierNameAccess->getByHierarchicalName(
2207                                         aHierName );
2208 
2209                                 sal_Int32 nState = 0;
2210                                 if ( !( aKeyValue >>= nState ) )
2211                                     OSL_ENSURE( sal_False,
2212                                       "PersistentPropertySet::getPropertyValues - "
2213                                       "Error getting property state!" );
2214                                 else
2215                                     rValue.State = PropertyState( nState );
2216                             }
2217                             catch ( NoSuchElementException& )
2218                             {
2219                                 // getByHierarchicalName
2220 
2221                                 OSL_ENSURE( sal_False,
2222                                   "PersistentPropertySet::getPropertyValues - "
2223                                   "NoSuchElementException!" );
2224                             }
2225                         }
2226 
2227                         return aValues;
2228                     }
2229                 }
2230             }
2231         }
2232         catch ( NoSuchElementException& )
2233         {
2234             // getByHierarchicalName
2235         }
2236     }
2237 
2238     return Sequence< PropertyValue >( 0 );
2239 }
2240 
2241 //=========================================================================
2242 // virtual
2243 void SAL_CALL PersistentPropertySet::setPropertyValues(
2244                                 const Sequence< PropertyValue >& aProps )
2245     throw( UnknownPropertyException,
2246            PropertyVetoException,
2247            IllegalArgumentException,
2248            WrappedTargetException,
2249            RuntimeException )
2250 {
2251     sal_Int32 nCount = aProps.getLength();
2252     if ( !nCount )
2253         return;
2254 
2255     osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
2256 
2257     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2258                 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
2259     if ( xRootHierNameAccess.is() )
2260     {
2261         const PropertyValue* pNewValues = aProps.getConstArray();
2262 
2263         typedef std::list< PropertyChangeEvent > Events;
2264         Events aEvents;
2265 
2266         OUString aFullPropNamePrefix( getFullKey() );
2267         aFullPropNamePrefix += OUString::createFromAscii( "/" );
2268 
2269         // Iterate over given property value sequence.
2270         for ( sal_Int32 n = 0; n < nCount; ++n )
2271         {
2272             const PropertyValue& rNewValue = pNewValues[ n ];
2273             const OUString& rName = rNewValue.Name;
2274 
2275             OUString aFullPropName = aFullPropNamePrefix;
2276             aFullPropName += makeHierarchalNameSegment( rName );
2277 
2278             // Does property exist?
2279             if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2280             {
2281                 Reference< XNameReplace > xNameReplace(
2282                     m_pImpl->m_pCreator->getConfigWriteAccess(
2283                                             aFullPropName ), UNO_QUERY );
2284                 Reference< XChangesBatch > xBatch(
2285                     m_pImpl->m_pCreator->getConfigWriteAccess(
2286                                             OUString() ), UNO_QUERY );
2287 
2288                 if ( xNameReplace.is() && xBatch.is() )
2289                 {
2290                     try
2291                     {
2292                         // Write handle
2293                         xNameReplace->replaceByName(
2294                                     OUString::createFromAscii( "Handle" ),
2295                                     makeAny( rNewValue.Handle ) );
2296 
2297                         // Save old value
2298                         OUString aValueName = aFullPropName;
2299                         aValueName += OUString::createFromAscii( "/Value" );
2300                         Any aOldValue
2301                             = xRootHierNameAccess->getByHierarchicalName(
2302                                                                 aValueName );
2303                         // Write value
2304                         xNameReplace->replaceByName(
2305                                     OUString::createFromAscii( "Value" ),
2306                                     rNewValue.Value );
2307 
2308                         // Write state ( Now it is a directly set value )
2309                         xNameReplace->replaceByName(
2310                                     OUString::createFromAscii( "State" ),
2311                                     makeAny(
2312                                         sal_Int32(
2313                                             PropertyState_DIRECT_VALUE ) ) );
2314 
2315                         // Commit changes.
2316                         xBatch->commitChanges();
2317 
2318                         if ( m_pImpl->m_pPropertyChangeListeners )
2319                         {
2320                             PropertyChangeEvent aEvt;
2321                             aEvt.Source         = (OWeakObject*)this;
2322                             aEvt.PropertyName   = rNewValue.Name;
2323                             aEvt.PropertyHandle = rNewValue.Handle;
2324                             aEvt.Further        = sal_False;
2325                             aEvt.OldValue       = aOldValue;
2326                             aEvt.NewValue       = rNewValue.Value;
2327 
2328                             aEvents.push_back( aEvt );
2329                         }
2330                     }
2331                     catch ( IllegalArgumentException& )
2332                     {
2333                         // replaceByName
2334                     }
2335                     catch ( NoSuchElementException& )
2336                     {
2337                         // getByHierarchicalName, replaceByName
2338                     }
2339                     catch ( WrappedTargetException& )
2340                     {
2341                         // replaceByName, commitChanges
2342                     }
2343                 }
2344             }
2345         }
2346 
2347         // Callback follows!
2348         aCGuard.clear();
2349 
2350         if ( m_pImpl->m_pPropertyChangeListeners )
2351         {
2352             // Notify property changes.
2353             Events::const_iterator it  = aEvents.begin();
2354             Events::const_iterator end = aEvents.end();
2355 
2356             while ( it != end )
2357             {
2358                 notifyPropertyChangeEvent( (*it) );
2359                 it++;
2360             }
2361         }
2362 
2363         return;
2364     }
2365 
2366     OSL_ENSURE( sal_False,
2367                 "PersistentPropertySet::setPropertyValues - Nothing set!" );
2368 }
2369 
2370 //=========================================================================
2371 //
2372 // Non-interface methods
2373 //
2374 //=========================================================================
2375 
2376 void PersistentPropertySet::notifyPropertyChangeEvent(
2377                                     const PropertyChangeEvent& rEvent ) const
2378 {
2379     // Get "normal" listeners for the property.
2380     OInterfaceContainerHelper* pContainer =
2381             m_pImpl->m_pPropertyChangeListeners->getContainer(
2382                                                     rEvent.PropertyName );
2383     if ( pContainer && pContainer->getLength() )
2384     {
2385         OInterfaceIteratorHelper aIter( *pContainer );
2386         while ( aIter.hasMoreElements() )
2387         {
2388             // Propagate event.
2389             Reference< XPropertyChangeListener > xListener(
2390                                                     aIter.next(), UNO_QUERY );
2391             if ( xListener.is() )
2392                 xListener->propertyChange( rEvent );
2393         }
2394     }
2395 
2396     // Get "normal" listeners for all properties.
2397     OInterfaceContainerHelper* pNoNameContainer =
2398             m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() );
2399     if ( pNoNameContainer && pNoNameContainer->getLength() )
2400     {
2401         OInterfaceIteratorHelper aIter( *pNoNameContainer );
2402         while ( aIter.hasMoreElements() )
2403         {
2404             // Propagate event.
2405             Reference< XPropertyChangeListener > xListener(
2406                                                     aIter.next(), UNO_QUERY );
2407             if ( xListener.is() )
2408                 xListener->propertyChange( rEvent );
2409         }
2410     }
2411 }
2412 
2413 //=========================================================================
2414 void PersistentPropertySet::notifyPropertySetInfoChange(
2415                                 const PropertySetInfoChangeEvent& evt ) const
2416 {
2417     if ( !m_pImpl->m_pPropSetChangeListeners )
2418         return;
2419 
2420     // Notify event listeners.
2421     OInterfaceIteratorHelper aIter( *( m_pImpl->m_pPropSetChangeListeners ) );
2422     while ( aIter.hasMoreElements() )
2423     {
2424         // Propagate event.
2425         Reference< XPropertySetInfoChangeListener >
2426                             xListener( aIter.next(), UNO_QUERY );
2427         if ( xListener.is() )
2428             xListener->propertySetInfoChange( evt );
2429     }
2430 }
2431 
2432 //=========================================================================
2433 const OUString& PersistentPropertySet::getFullKey()
2434 {
2435     if ( !m_pImpl->m_aFullKey.getLength() )
2436     {
2437         osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
2438         if ( !m_pImpl->m_aFullKey.getLength() )
2439         {
2440             m_pImpl->m_aFullKey
2441                 = makeHierarchalNameSegment( m_pImpl->m_aKey );
2442             m_pImpl->m_aFullKey
2443                 += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/Values" ) );
2444         }
2445     }
2446 
2447     return m_pImpl->m_aFullKey;
2448 }
2449 
2450 //=========================================================================
2451 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
2452 {
2453     return *m_pImpl->m_pCreator;
2454 }
2455 
2456 //=========================================================================
2457 //=========================================================================
2458 //
2459 // PropertySetInfo_Impl Implementation.
2460 //
2461 //=========================================================================
2462 //=========================================================================
2463 
2464 PropertySetInfo_Impl::PropertySetInfo_Impl(
2465                         const Reference< XMultiServiceFactory >& rxSMgr,
2466                         PersistentPropertySet* pOwner )
2467 : m_xSMgr( rxSMgr ),
2468   m_pProps( NULL ),
2469   m_pOwner( pOwner )
2470 {
2471 }
2472 
2473 //=========================================================================
2474 // virtual
2475 PropertySetInfo_Impl::~PropertySetInfo_Impl()
2476 {
2477     delete m_pProps;
2478 
2479     // !!! Do not delete m_pOwner !!!
2480 }
2481 
2482 //=========================================================================
2483 //
2484 // XInterface methods.
2485 //
2486 //=========================================================================
2487 
2488 XINTERFACE_IMPL_2( PropertySetInfo_Impl,
2489                    XTypeProvider,
2490                    XPropertySetInfo );
2491 
2492 //=========================================================================
2493 //
2494 // XTypeProvider methods.
2495 //
2496 //=========================================================================
2497 
2498 XTYPEPROVIDER_IMPL_2( PropertySetInfo_Impl,
2499                       XTypeProvider,
2500                       XPropertySetInfo );
2501 
2502 //=========================================================================
2503 //
2504 // XPropertySetInfo methods.
2505 //
2506 //=========================================================================
2507 
2508 // virtual
2509 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
2510     throw( RuntimeException )
2511 {
2512     if ( !m_pProps )
2513     {
2514         Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2515             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2516             UNO_QUERY );
2517         if ( xRootHierNameAccess.is() )
2518         {
2519             try
2520             {
2521                 Reference< XNameAccess > xNameAccess;
2522                 xRootHierNameAccess->getByHierarchicalName(
2523                             m_pOwner->getFullKey() )
2524                     >>= xNameAccess;
2525                 if ( xNameAccess.is() )
2526                 {
2527                     // Obtain property names.
2528 
2529                     Sequence< OUString > aElems
2530                                             = xNameAccess->getElementNames();
2531 
2532                     sal_uInt32 nCount = aElems.getLength();
2533                     Sequence< Property >* pPropSeq
2534                                         = new Sequence< Property >( nCount );
2535 
2536                     if ( nCount )
2537                     {
2538                         Reference< XHierarchicalNameAccess > xHierNameAccess(
2539                                                     xNameAccess, UNO_QUERY );
2540 
2541                         OSL_ENSURE( xHierNameAccess.is(),
2542                                     "PropertySetInfo_Impl::getProperties - "
2543                                     "No hierarchical name access!" );
2544 
2545                         if ( xHierNameAccess.is() )
2546                         {
2547                             const OUString aHandleName
2548                                 = OUString::createFromAscii( "/Handle" );
2549                             const OUString aValueName
2550                                 = OUString::createFromAscii( "/Value" );
2551                             const OUString aAttrName
2552                                 = OUString::createFromAscii( "/Attributes" );
2553 
2554                             Property* pProps = pPropSeq->getArray();
2555 
2556                             for ( sal_uInt32 n = 0; n < nCount; ++n )
2557                             {
2558                                 Property& rProp = pProps[ n ];
2559                                 OUString  rName = aElems[ n ];
2560                                 OUString aXMLName
2561                                     = makeHierarchalNameSegment( rName );
2562 
2563                                 // Set property name.
2564 
2565                                 rProp.Name = rName;
2566 
2567                                 try
2568                                 {
2569                                     // Obtain and set property handle
2570                                     rtl::OUString aHierName = aXMLName;
2571                                     aHierName += aHandleName;
2572                                     Any aKeyValue
2573                                         = xHierNameAccess->getByHierarchicalName(
2574                                             aHierName );
2575 
2576                                     if ( !( aKeyValue >>= rProp.Handle ) )
2577                                         OSL_ENSURE( sal_False,
2578                                         "PropertySetInfo_Impl::getProperties - "
2579                                         "Error getting property handle!" );
2580                                 }
2581                                 catch ( NoSuchElementException& )
2582                                 {
2583                                     // getByHierarchicalName
2584 
2585                                     OSL_ENSURE( sal_False,
2586                                     "PropertySetInfo_Impl::getProperties - "
2587                                     "NoSuchElementException!" );
2588                                 }
2589 
2590                                 try
2591                                 {
2592                                     // Obtain and set property type
2593                                     rtl::OUString aHierName = aXMLName;
2594                                     aHierName += aValueName;
2595                                     Any aKeyValue
2596                                         = xHierNameAccess->getByHierarchicalName(
2597                                             aHierName );
2598 
2599                                     // Note: The type may be void if addProperty
2600                                     //       was called with a default value
2601                                     //       of type void.
2602 
2603                                     rProp.Type = aKeyValue.getValueType();
2604                                 }
2605                                 catch ( NoSuchElementException& )
2606                                 {
2607                                     // getByHierarchicalName
2608 
2609                                     OSL_ENSURE( sal_False,
2610                                     "PropertySetInfo_Impl::getProperties - "
2611                                     "NoSuchElementException!" );
2612                                 }
2613 
2614                                 try
2615                                 {
2616                                     // Obtain and set property attributes
2617                                     rtl::OUString aHierName = aXMLName;
2618                                     aHierName += aAttrName;
2619                                     Any aKeyValue
2620                                         = xHierNameAccess->getByHierarchicalName(
2621                                             aHierName );
2622 
2623                                     sal_Int32 nAttribs = 0;
2624                                     if ( aKeyValue >>= nAttribs )
2625                                         rProp.Attributes
2626                                             = sal_Int16( nAttribs );
2627                                     else
2628                                         OSL_ENSURE( sal_False,
2629                                         "PropertySetInfo_Impl::getProperties - "
2630                                         "Error getting property attributes!" );
2631                                 }
2632                                 catch ( NoSuchElementException& )
2633                                 {
2634                                     // getByHierarchicalName
2635 
2636                                     OSL_ENSURE( sal_False,
2637                                     "PropertySetInfo_Impl::getProperties - "
2638                                     "NoSuchElementException!" );
2639                                 }
2640                             }
2641                         }
2642                     }
2643 
2644                     // Success.
2645                     m_pProps = pPropSeq;
2646                     return *m_pProps;
2647                 }
2648             }
2649             catch ( NoSuchElementException& )
2650             {
2651                 // getByHierarchicalName
2652             }
2653         }
2654 
2655         OSL_ENSURE( sal_False, "PropertySetInfo_Impl::getProperties - Error!" );
2656         m_pProps = new Sequence< Property >( 0 );
2657     }
2658 
2659     return *m_pProps;
2660 }
2661 
2662 //=========================================================================
2663 // virtual
2664 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2665                                                     const OUString& aName )
2666     throw( UnknownPropertyException, RuntimeException )
2667 {
2668     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2669             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2670             UNO_QUERY );
2671     if ( xRootHierNameAccess.is() )
2672     {
2673         OUString aFullPropName( m_pOwner->getFullKey() );
2674         aFullPropName += OUString::createFromAscii( "/" );
2675         aFullPropName += makeHierarchalNameSegment( aName );
2676 
2677         // Does property exist?
2678         if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2679             throw UnknownPropertyException();
2680 
2681         try
2682         {
2683             Property aProp;
2684 
2685             // Obtain handle.
2686             OUString aKey = aFullPropName;
2687             aKey += OUString::createFromAscii( "/Handle" );
2688 
2689             if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2690                     >>= aProp.Handle ) )
2691             {
2692                 OSL_ENSURE( sal_False,
2693                             "PropertySetInfo_Impl::getPropertyByName - "
2694                             "No handle!" );
2695                 return Property();
2696             }
2697 
2698             // Obtain Value and extract type.
2699             aKey = aFullPropName;
2700             aKey += OUString::createFromAscii( "/Value" );
2701 
2702             Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2703             if ( !aValue.hasValue() )
2704             {
2705                 OSL_ENSURE( sal_False,
2706                             "PropertySetInfo_Impl::getPropertyByName - "
2707                             "No Value!" );
2708                 return Property();
2709             }
2710 
2711             aProp.Type = aValue.getValueType();
2712 
2713             // Obtain Attributes.
2714             aKey = aFullPropName;
2715             aKey += OUString::createFromAscii( "/Attributes" );
2716 
2717             sal_Int32 nAttribs = 0;
2718             if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2719                     >>= nAttribs )
2720                 aProp.Attributes = sal_Int16( nAttribs );
2721             else
2722             {
2723                 OSL_ENSURE( sal_False,
2724                             "PropertySetInfo_Impl::getPropertyByName - "
2725                             "No attributes!" );
2726                 return Property();
2727             }
2728 
2729             // set name.
2730             aProp.Name = aName;
2731 
2732             // Success.
2733             return aProp;
2734         }
2735         catch ( NoSuchElementException& )
2736         {
2737             // getByHierarchicalName
2738 
2739             OSL_ENSURE( sal_False,
2740                         "PropertySetInfo_Impl::getPropertyByName - "
2741                         "caught NoSuchElementException!" );
2742         }
2743 
2744     }
2745 
2746     OSL_ENSURE( sal_False, "PropertySetInfo_Impl::getPropertyByName - Error!" );
2747     return Property();
2748 }
2749 
2750 //=========================================================================
2751 // virtual
2752 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2753                                                     const OUString& Name )
2754     throw( RuntimeException )
2755 {
2756     Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2757             m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2758             UNO_QUERY );
2759     if ( xRootHierNameAccess.is() )
2760     {
2761         OUString aFullPropName( m_pOwner->getFullKey() );
2762         aFullPropName += OUString::createFromAscii( "/" );
2763         aFullPropName += makeHierarchalNameSegment( Name );
2764 
2765         return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2766     }
2767 
2768     return sal_False;
2769 }
2770 
2771