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