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