bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / core / ucbstore.cxx
blob98fb48aba888c0d53c652fcb08c166389854da49
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
22 TODO
23 **************************************************************************
25 *************************************************************************/
27 #include <list>
28 #include <unordered_map>
29 #include <osl/diagnose.h>
30 #include <rtl/ustrbuf.hxx>
31 #include <cppuhelper/interfacecontainer.hxx>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
34 #include <com/sun/star/configuration/theDefaultProvider.hpp>
35 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
36 #include <com/sun/star/container/XNameContainer.hpp>
37 #include <com/sun/star/container/XNameReplace.hpp>
38 #include <com/sun/star/util/XChangesBatch.hpp>
39 #include <comphelper/processfactory.hxx>
40 #include <cppuhelper/implbase1.hxx>
41 #include "ucbstore.hxx"
43 using namespace com::sun::star::beans;
44 using namespace com::sun::star::configuration;
45 using namespace com::sun::star::container;
46 using namespace com::sun::star::lang;
47 using namespace com::sun::star::ucb;
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::util;
50 using namespace cppu;
54 OUString makeHierarchalNameSegment( const OUString & rIn )
56 OUStringBuffer aBuffer;
57 aBuffer.appendAscii( "['" );
59 sal_Int32 nCount = rIn.getLength();
60 for ( sal_Int32 n = 0; n < nCount; ++n )
62 const sal_Unicode c = rIn[ n ];
63 switch ( c )
65 case '&':
66 aBuffer.appendAscii( "&amp;" );
67 break;
69 case '"':
70 aBuffer.appendAscii( "&quot;" );
71 break;
73 case '\'':
74 aBuffer.appendAscii( "&apos;" );
75 break;
77 case '<':
78 aBuffer.appendAscii( "&lt;" );
79 break;
81 case '>':
82 aBuffer.appendAscii( "&gt;" );
83 break;
85 default:
86 aBuffer.append( c );
87 break;
91 aBuffer.appendAscii( "']" );
92 return OUString( aBuffer.makeStringAndClear() );
95 #define STORE_CONTENTPROPERTIES_KEY "/org.openoffice.ucb.Store/ContentProperties"
97 // describe path of cfg entry
98 #define CFGPROPERTY_NODEPATH "nodepath"
99 // true->async. update; false->sync. update
100 #define CFGPROPERTY_LAZYWRITE "lazywrite"
102 // PropertySetMap_Impl.
103 typedef std::unordered_map
105 OUString,
106 PersistentPropertySet*,
107 OUStringHash
109 PropertySetMap_Impl;
111 // class PropertySetInfo_Impl
112 class PropertySetInfo_Impl : public cppu::WeakImplHelper1 < XPropertySetInfo >
114 Reference< XComponentContext > m_xContext;
115 Sequence< Property >* m_pProps;
116 PersistentPropertySet* m_pOwner;
118 public:
119 PropertySetInfo_Impl( const Reference< XComponentContext >& xContext,
120 PersistentPropertySet* pOwner );
121 virtual ~PropertySetInfo_Impl();
123 // XPropertySetInfo
124 virtual Sequence< Property > SAL_CALL getProperties()
125 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
126 virtual Property SAL_CALL getPropertyByName( const OUString& aName )
127 throw( UnknownPropertyException, RuntimeException, std::exception ) SAL_OVERRIDE;
128 virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name )
129 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
131 // Non-interface methods.
132 void reset() { delete m_pProps; m_pProps = 0; }
137 // UcbStore_Impl.
141 struct UcbStore_Impl
143 osl::Mutex m_aMutex;
144 Sequence< Any > m_aInitArgs;
145 Reference< XPropertySetRegistry > m_xTheRegistry;
152 // UcbStore Implementation.
158 UcbStore::UcbStore( const Reference< XComponentContext >& xContext )
159 : m_xContext( xContext ),
160 m_pImpl( new UcbStore_Impl() )
165 // virtual
166 UcbStore::~UcbStore()
168 delete m_pImpl;
172 XSERVICEINFO_IMPL_1_CTX( UcbStore,
173 OUString( "com.sun.star.comp.ucb.UcbStore" ),
174 STORE_SERVICE_NAME );
178 // Service factory implementation.
182 ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbStore );
186 // XPropertySetRegistryFactory methods.
190 // virtual
191 Reference< XPropertySetRegistry > SAL_CALL
192 UcbStore::createPropertySetRegistry( const OUString& )
193 throw( RuntimeException, std::exception )
195 // The URL parameter is ignored by this interface implementation. It always
196 // uses the configuration server as storage medium.
198 if ( !m_pImpl->m_xTheRegistry.is() )
200 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
201 if ( !m_pImpl->m_xTheRegistry.is() )
202 m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xContext, getInitArgs() );
205 return m_pImpl->m_xTheRegistry;
210 // XInitialization methods.
214 // virtual
215 void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments )
216 throw( Exception, RuntimeException, std::exception )
218 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
219 m_pImpl->m_aInitArgs = aArguments;
223 const Sequence< Any >& UcbStore::getInitArgs() const
225 return m_pImpl->m_aInitArgs;
230 // PropertySetRegistry_Impl.
234 struct PropertySetRegistry_Impl
236 const Sequence< Any > m_aInitArgs;
237 PropertySetMap_Impl m_aPropSets;
238 Reference< XMultiServiceFactory > m_xConfigProvider;
239 Reference< XInterface > m_xRootReadAccess;
240 Reference< XInterface > m_xRootWriteAccess;
241 osl::Mutex m_aMutex;
242 bool m_bTriedToGetRootReadAccess; // #82494#
243 bool m_bTriedToGetRootWriteAccess; // #82494#
245 PropertySetRegistry_Impl( const Sequence< Any > &rInitArgs )
246 : m_aInitArgs( rInitArgs ),
247 m_bTriedToGetRootReadAccess( false ),
248 m_bTriedToGetRootWriteAccess( false )
257 // PropertySetRegistry Implementation.
263 PropertySetRegistry::PropertySetRegistry(
264 const Reference< XComponentContext >& xContext,
265 const Sequence< Any > &rInitArgs )
266 : m_xContext( xContext ),
267 m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) )
272 // virtual
273 PropertySetRegistry::~PropertySetRegistry()
275 delete m_pImpl;
280 // XServiceInfo methods.
284 XSERVICEINFO_NOFACTORY_IMPL_1( PropertySetRegistry,
285 OUString( "com.sun.star.comp.ucb.PropertySetRegistry" ),
286 PROPSET_REG_SERVICE_NAME );
290 // XPropertySetRegistry methods.
294 // virtual
295 Reference< XPersistentPropertySet > SAL_CALL
296 PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create )
297 throw( RuntimeException, std::exception )
299 if ( !key.isEmpty() )
301 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
303 PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
305 PropertySetMap_Impl::const_iterator it = rSets.find( key );
306 if ( it != rSets.end() )
308 // Already instantiated.
309 return Reference< XPersistentPropertySet >( (*it).second );
311 else
313 // Create new instance.
314 Reference< XNameAccess > xRootNameAccess(
315 getRootConfigReadAccess(), UNO_QUERY );
316 if ( xRootNameAccess.is() )
318 // Propertyset in registry?
319 if ( xRootNameAccess->hasByName( key ) )
321 // Yep!
322 return Reference< XPersistentPropertySet >(
323 new PersistentPropertySet(
324 m_xContext, *this, key ) );
326 else if ( create )
328 // No. Create entry for propertyset.
330 Reference< XSingleServiceFactory > xFac(
331 getConfigWriteAccess( OUString() ), UNO_QUERY );
332 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
333 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
335 OSL_ENSURE( xFac.is(),
336 "PropertySetRegistry::openPropertySet - "
337 "No factory!" );
339 OSL_ENSURE( xBatch.is(),
340 "PropertySetRegistry::openPropertySet - "
341 "No batch!" );
343 OSL_ENSURE( xContainer.is(),
344 "PropertySetRegistry::openPropertySet - "
345 "No container!" );
347 if ( xFac.is() && xBatch.is() && xContainer.is() )
351 // Create new "Properties" config item.
352 Reference< XNameReplace > xNameReplace(
353 xFac->createInstance(), UNO_QUERY );
355 if ( xNameReplace.is() )
357 // Fill new item...
359 // // Set Values
360 // xNameReplace->replaceByName(
361 // OUString("Values"),
362 // makeAny( ... ) );
364 // Insert new item.
365 xContainer->insertByName(
366 key, makeAny( xNameReplace ) );
367 // Commit changes.
368 xBatch->commitChanges();
370 return Reference< XPersistentPropertySet >(
371 new PersistentPropertySet(
372 m_xContext, *this, key ) );
375 catch (const IllegalArgumentException&)
377 // insertByName
379 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
380 "caught IllegalArgumentException!" );
382 catch (const ElementExistException&)
384 // insertByName
386 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
387 "caught ElementExistException!" );
389 catch (const WrappedTargetException&)
391 // insertByName, commitChanges
393 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
394 "caught WrappedTargetException!" );
396 catch (const RuntimeException&)
398 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
399 "caught RuntimeException!" );
401 catch (const Exception&)
403 // createInstance
405 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
406 "caught Exception!" );
410 else
412 // No entry. Fail, but no error.
413 return Reference< XPersistentPropertySet >();
417 OSL_TRACE( "PropertySetRegistry::openPropertySet no root access" );
421 return Reference< XPersistentPropertySet >();
425 // virtual
426 void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key )
427 throw( RuntimeException, std::exception )
429 if ( key.isEmpty() )
430 return;
432 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
434 Reference< XNameAccess > xRootNameAccess(
435 getRootConfigReadAccess(), UNO_QUERY );
436 if ( xRootNameAccess.is() )
438 // Propertyset in registry?
439 if ( !xRootNameAccess->hasByName( key ) )
440 return;
441 Reference< XChangesBatch > xBatch(
442 getConfigWriteAccess( OUString() ), UNO_QUERY );
443 Reference< XNameContainer > xContainer( xBatch, UNO_QUERY );
445 if ( xBatch.is() && xContainer.is() )
449 // Remove item.
450 xContainer->removeByName( key );
451 // Commit changes.
452 xBatch->commitChanges();
454 // Success.
455 return;
457 catch (const NoSuchElementException&)
459 // removeByName
461 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
462 "caught NoSuchElementException!" );
463 return;
465 catch (const WrappedTargetException&)
467 // commitChanges
469 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
470 "caught WrappedTargetException!" );
471 return;
475 return;
478 OSL_TRACE( "PropertySetRegistry::removePropertySet - no root access" );
483 // XElementAccess methods.
487 // virtual
488 com::sun::star::uno::Type SAL_CALL PropertySetRegistry::getElementType()
489 throw( RuntimeException, std::exception )
491 return cppu::UnoType<XPersistentPropertySet>::get();
495 // virtual
496 sal_Bool SAL_CALL PropertySetRegistry::hasElements()
497 throw( RuntimeException, std::exception )
499 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
501 Reference< XElementAccess > xElemAccess(
502 getRootConfigReadAccess(), UNO_QUERY );
503 if ( xElemAccess.is() )
504 return xElemAccess->hasElements();
506 return sal_False;
511 // XNameAccess methods.
515 // virtual
516 Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName )
517 throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
519 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
521 Reference< XNameAccess > xNameAccess(
522 getRootConfigReadAccess(), UNO_QUERY );
523 if ( xNameAccess.is() )
528 return xNameAccess->getByName( aName );
530 catch (const NoSuchElementException&)
532 // getByName
534 catch (const WrappedTargetException&)
536 // getByName
540 return Any();
544 // virtual
545 Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames()
546 throw( RuntimeException, std::exception )
548 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
550 Reference< XNameAccess > xNameAccess(
551 getRootConfigReadAccess(), UNO_QUERY );
552 if ( xNameAccess.is() )
554 return xNameAccess->getElementNames();
556 return Sequence< OUString >( 0 );
560 // virtual
561 sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName )
562 throw( RuntimeException, std::exception )
564 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
566 Reference< XNameAccess > xNameAccess(
567 getRootConfigReadAccess(), UNO_QUERY );
568 if ( xNameAccess.is() )
570 return xNameAccess->hasByName( aName );
573 return sal_False;
577 void PropertySetRegistry::add( PersistentPropertySet* pSet )
579 OUString key( pSet->getKey() );
581 if ( !key.isEmpty() )
583 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
584 m_pImpl->m_aPropSets[ key ] = pSet;
589 void PropertySetRegistry::remove( PersistentPropertySet* pSet )
591 OUString key( pSet->getKey() );
593 if ( !key.isEmpty() )
595 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
597 PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
599 PropertySetMap_Impl::iterator it = rSets.find( key );
600 if ( it != rSets.end() )
602 // Found.
603 rSets.erase( it );
609 void PropertySetRegistry::renamePropertySet( const OUString& rOldKey,
610 const OUString& rNewKey )
612 if ( rOldKey == rNewKey )
613 return;
615 Reference< XNameAccess > xRootNameAccess(
616 getConfigWriteAccess( OUString() ), UNO_QUERY );
617 if ( xRootNameAccess.is() )
619 // Old key present?
620 if ( xRootNameAccess->hasByName( rOldKey ) )
622 // New key not present?
623 if ( xRootNameAccess->hasByName( rNewKey ) )
625 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
626 "New key exists!" );
627 return;
629 Reference< XSingleServiceFactory > xFac(
630 xRootNameAccess, UNO_QUERY );
631 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
632 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
634 OSL_ENSURE( xFac.is(),
635 "PropertySetRegistry::renamePropertySet - "
636 "No factory!" );
638 OSL_ENSURE( xBatch.is(),
639 "PropertySetRegistry::renamePropertySet - "
640 "No batch!" );
642 OSL_ENSURE( xContainer.is(),
643 "PropertySetRegistry::renamePropertySet - "
644 "No container!" );
646 if ( xFac.is() && xBatch.is() && xContainer.is() )
649 // Create new "Properties" config item.
654 Reference< XNameReplace > xNameReplace(
655 xFac->createInstance(), UNO_QUERY );
657 if ( xNameReplace.is() )
659 // Insert new item.
660 xContainer->insertByName(
661 rNewKey, makeAny( xNameReplace ) );
662 // Commit changes.
663 xBatch->commitChanges();
666 catch (const IllegalArgumentException&)
668 // insertByName
670 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
671 "caught IllegalArgumentException!" );
672 return;
674 catch (const ElementExistException&)
676 // insertByName
678 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
679 "caught ElementExistException!" );
680 return;
682 catch (const WrappedTargetException&)
684 // insertByName, commitChanges
686 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
687 "caught WrappedTargetException!" );
688 return;
690 catch (const RuntimeException&)
692 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
693 "caught RuntimeException!" );
694 return;
696 catch (const Exception&)
698 // createInstance
700 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
701 "caught Exception!" );
702 return;
706 // Copy data...
709 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
710 xRootNameAccess, UNO_QUERY );
711 if ( !xRootHierNameAccess.is() )
713 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
714 "No hierarchical name access!" );
715 return;
720 OUString aOldValuesKey
721 = makeHierarchalNameSegment( rOldKey );
722 aOldValuesKey += "/Values";
724 Reference< XNameAccess > xOldNameAccess;
725 xRootHierNameAccess->getByHierarchicalName(
726 aOldValuesKey )
727 >>= xOldNameAccess;
728 if ( !xOldNameAccess.is() )
730 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
731 "No old name access!" );
732 return;
735 // Obtain property names.
736 Sequence< OUString > aElems
737 = xOldNameAccess->getElementNames();
738 sal_Int32 nCount = aElems.getLength();
739 if ( nCount )
741 OUString aNewValuesKey
742 = makeHierarchalNameSegment( rNewKey );
743 aNewValuesKey += "/Values";
745 Reference< XSingleServiceFactory > xNewFac;
746 xRootHierNameAccess->getByHierarchicalName(
747 aNewValuesKey )
748 >>= xNewFac;
749 if ( !xNewFac.is() )
751 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
752 "No new factory!" );
753 return;
756 Reference< XNameContainer > xNewContainer(
757 xNewFac, UNO_QUERY );
758 if ( !xNewContainer.is() )
760 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
761 "No new container!" );
762 return;
765 aOldValuesKey += "/";
767 OUString aHandleKey("/Handle");
768 OUString aValueKey("/Value");
769 OUString aStateKey("/State");
770 OUString aAttrKey("/Attributes");
772 for ( sal_Int32 n = 0; n < nCount; ++n )
774 const OUString& rPropName = aElems[ n ];
776 // Create new item.
777 Reference< XNameReplace > xNewPropNameReplace(
778 xNewFac->createInstance(), UNO_QUERY );
780 if ( !xNewPropNameReplace.is() )
782 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
783 "No new prop name replace!" );
784 return;
787 // Fill new item...
789 // Set Values
790 OUString aKey = aOldValuesKey;
791 aKey += makeHierarchalNameSegment( rPropName );
793 // ... handle
794 OUString aNewKey1 = aKey;
795 aNewKey1 += aHandleKey;
796 Any aAny =
797 xRootHierNameAccess->getByHierarchicalName(
798 aNewKey1 );
799 xNewPropNameReplace->replaceByName(
800 OUString("Handle"),
801 aAny );
803 // ... value
804 aNewKey1 = aKey;
805 aNewKey1 += aValueKey;
806 aAny =
807 xRootHierNameAccess->getByHierarchicalName(
808 aNewKey1 );
809 xNewPropNameReplace->replaceByName(
810 OUString("Value"),
811 aAny );
813 // ... state
814 aNewKey1 = aKey;
815 aNewKey1 += aStateKey;
816 aAny =
817 xRootHierNameAccess->getByHierarchicalName(
818 aNewKey1 );
819 xNewPropNameReplace->replaceByName(
820 OUString("State"),
821 aAny );
823 // ... attributes
824 aNewKey1 = aKey;
825 aNewKey1 += aAttrKey;
826 aAny =
827 xRootHierNameAccess->getByHierarchicalName(
828 aNewKey1 );
829 xNewPropNameReplace->replaceByName(
830 OUString("Attributes"),
831 aAny );
833 // Insert new item.
834 xNewContainer->insertByName(
835 rPropName, makeAny( xNewPropNameReplace ) );
837 // Commit changes.
838 xBatch->commitChanges();
842 catch (const IllegalArgumentException&)
844 // insertByName, replaceByName
846 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
847 "caught IllegalArgumentException!" );
848 return;
850 catch (const ElementExistException&)
852 // insertByName
854 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
855 "caught ElementExistException!" );
856 return;
858 catch (const WrappedTargetException&)
860 // insertByName, replaceByName, commitChanges
862 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
863 "caught WrappedTargetException!" );
864 return;
866 catch (const NoSuchElementException&)
868 // getByHierarchicalName, replaceByName
870 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
871 "caught NoSuchElementException!" );
872 return;
874 catch (const RuntimeException&)
876 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
877 "caught RuntimeException!" );
878 return;
880 catch (const Exception&)
882 // createInstance
884 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
885 "caught Exception!" );
886 return;
890 // Remove old entry...
895 // Remove item.
896 xContainer->removeByName( rOldKey );
897 // Commit changes.
898 xBatch->commitChanges();
900 // Success.
901 return;
903 catch (const NoSuchElementException&)
905 // removeByName
907 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
908 "caught NoSuchElementException!" );
909 return;
911 catch (const WrappedTargetException&)
913 // commitChanges
915 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
916 "caught WrappedTargetException!" );
917 return;
923 OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" );
927 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider()
929 if ( !m_pImpl->m_xConfigProvider.is() )
931 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
932 if ( !m_pImpl->m_xConfigProvider.is() )
934 const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs;
936 if ( rInitArgs.getLength() > 0 )
938 // Extract config provider from service init args.
939 rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider;
941 OSL_ENSURE( m_pImpl->m_xConfigProvider.is(),
942 "PropertySetRegistry::getConfigProvider - "
943 "No config provider!" );
945 else
949 m_pImpl->m_xConfigProvider = theDefaultProvider::get( m_xContext );
951 catch (const Exception&)
953 OSL_TRACE( "PropertySetRegistry::getConfigProvider - "
954 "caught exception!" );
960 return m_pImpl->m_xConfigProvider;
964 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
968 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
970 if ( !m_pImpl->m_xRootReadAccess.is() )
972 if ( m_pImpl->m_bTriedToGetRootReadAccess ) // #82494#
974 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - "
975 "Unable to read any config data! -> #82494#" );
976 return Reference< XInterface >();
979 getConfigProvider();
981 if ( m_pImpl->m_xConfigProvider.is() )
983 Sequence< Any > aArguments( 1 );
984 PropertyValue aProperty;
985 aProperty.Name = CFGPROPERTY_NODEPATH;
986 aProperty.Value
987 <<= OUString( STORE_CONTENTPROPERTIES_KEY );
988 aArguments[ 0 ] <<= aProperty;
990 m_pImpl->m_bTriedToGetRootReadAccess = true;
992 m_pImpl->m_xRootReadAccess =
993 m_pImpl->m_xConfigProvider->createInstanceWithArguments(
994 OUString( "com.sun.star.configuration.ConfigurationAccess" ),
995 aArguments );
997 if ( m_pImpl->m_xRootReadAccess.is() )
998 return m_pImpl->m_xRootReadAccess;
1001 else
1002 return m_pImpl->m_xRootReadAccess;
1004 catch (const RuntimeException&)
1006 throw;
1008 catch (const Exception&)
1010 // createInstance, createInstanceWithArguments
1012 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - caught Exception!" );
1013 return Reference< XInterface >();
1016 OSL_TRACE( "PropertySetRegistry::getRootConfigReadAccess - Error!" );
1017 return Reference< XInterface >();
1021 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
1022 const OUString& rPath )
1026 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1028 if ( !m_pImpl->m_xRootWriteAccess.is() )
1030 if ( m_pImpl->m_bTriedToGetRootWriteAccess ) // #82494#
1032 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1033 "Unable to write any config data! -> #82494#" );
1034 return Reference< XInterface >();
1037 getConfigProvider();
1039 if ( m_pImpl->m_xConfigProvider.is() )
1041 Sequence< Any > aArguments( 2 );
1042 PropertyValue aProperty;
1044 aProperty.Name = CFGPROPERTY_NODEPATH;
1045 aProperty.Value <<= OUString( STORE_CONTENTPROPERTIES_KEY );
1046 aArguments[ 0 ] <<= aProperty;
1048 aProperty.Name = CFGPROPERTY_LAZYWRITE;
1049 aProperty.Value <<= sal_True;
1050 aArguments[ 1 ] <<= aProperty;
1052 m_pImpl->m_bTriedToGetRootWriteAccess = true;
1054 m_pImpl->m_xRootWriteAccess =
1055 m_pImpl->m_xConfigProvider->createInstanceWithArguments(
1056 OUString( "com.sun.star.configuration.ConfigurationUpdateAccess" ),
1057 aArguments );
1059 OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(),
1060 "PropertySetRegistry::getConfigWriteAccess - "
1061 "No config update access!" );
1065 if ( m_pImpl->m_xRootWriteAccess.is() )
1067 if ( !rPath.isEmpty() )
1069 Reference< XHierarchicalNameAccess > xNA(
1070 m_pImpl->m_xRootWriteAccess, UNO_QUERY );
1071 if ( xNA.is() )
1073 Reference< XInterface > xInterface;
1074 xNA->getByHierarchicalName( rPath ) >>= xInterface;
1076 if ( xInterface.is() )
1077 return xInterface;
1080 else
1081 return m_pImpl->m_xRootWriteAccess;
1084 catch (const RuntimeException&)
1086 throw;
1088 catch (const NoSuchElementException&)
1090 // getByHierarchicalName
1092 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1093 "caught NoSuchElementException!" );
1094 return Reference< XInterface >();
1096 catch (const Exception&)
1098 // createInstance, createInstanceWithArguments
1100 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1101 "caught Exception!" );
1102 return Reference< XInterface >();
1105 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" );
1106 return Reference< XInterface >();
1109 typedef OMultiTypeInterfaceContainerHelperVar<OUString> PropertyListeners_Impl;
1111 struct PersistentPropertySet_Impl
1113 PropertySetRegistry* m_pCreator;
1114 PropertySetInfo_Impl* m_pInfo;
1115 OUString m_aKey;
1116 OUString m_aFullKey;
1117 osl::Mutex m_aMutex;
1118 OInterfaceContainerHelper* m_pDisposeEventListeners;
1119 OInterfaceContainerHelper* m_pPropSetChangeListeners;
1120 PropertyListeners_Impl* m_pPropertyChangeListeners;
1122 PersistentPropertySet_Impl( PropertySetRegistry& rCreator,
1123 const OUString& rKey )
1124 : m_pCreator( &rCreator ), m_pInfo( NULL ), m_aKey( rKey ),
1125 m_pDisposeEventListeners( NULL ), m_pPropSetChangeListeners( NULL ),
1126 m_pPropertyChangeListeners( NULL )
1128 m_pCreator->acquire();
1131 ~PersistentPropertySet_Impl()
1133 m_pCreator->release();
1135 if ( m_pInfo )
1136 m_pInfo->release();
1138 delete m_pDisposeEventListeners;
1139 delete m_pPropSetChangeListeners;
1140 delete m_pPropertyChangeListeners;
1148 // PersistentPropertySet Implementation.
1154 PersistentPropertySet::PersistentPropertySet(
1155 const Reference< XComponentContext >& xContext,
1156 PropertySetRegistry& rCreator,
1157 const OUString& rKey )
1158 : m_xContext( xContext ),
1159 m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) )
1161 // register at creator.
1162 rCreator.add( this );
1166 // virtual
1167 PersistentPropertySet::~PersistentPropertySet()
1169 // deregister at creator.
1170 m_pImpl->m_pCreator->remove( this );
1172 delete m_pImpl;
1175 // XServiceInfo methods.
1179 XSERVICEINFO_NOFACTORY_IMPL_1( PersistentPropertySet,
1180 OUString( "com.sun.star.comp.ucb.PersistentPropertySet" ),
1181 PERS_PROPSET_SERVICE_NAME );
1185 // XComponent methods.
1189 // virtual
1190 void SAL_CALL PersistentPropertySet::dispose()
1191 throw( RuntimeException, std::exception )
1193 if ( m_pImpl->m_pDisposeEventListeners &&
1194 m_pImpl->m_pDisposeEventListeners->getLength() )
1196 EventObject aEvt;
1197 aEvt.Source = static_cast< XComponent * >( this );
1198 m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
1201 if ( m_pImpl->m_pPropSetChangeListeners &&
1202 m_pImpl->m_pPropSetChangeListeners->getLength() )
1204 EventObject aEvt;
1205 aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this );
1206 m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
1209 if ( m_pImpl->m_pPropertyChangeListeners )
1211 EventObject aEvt;
1212 aEvt.Source = static_cast< XPropertySet * >( this );
1213 m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
1218 // virtual
1219 void SAL_CALL PersistentPropertySet::addEventListener(
1220 const Reference< XEventListener >& Listener )
1221 throw( RuntimeException, std::exception )
1223 if ( !m_pImpl->m_pDisposeEventListeners )
1224 m_pImpl->m_pDisposeEventListeners =
1225 new OInterfaceContainerHelper( m_pImpl->m_aMutex );
1227 m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
1231 // virtual
1232 void SAL_CALL PersistentPropertySet::removeEventListener(
1233 const Reference< XEventListener >& Listener )
1234 throw( RuntimeException, std::exception )
1236 if ( m_pImpl->m_pDisposeEventListeners )
1237 m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
1239 // Note: Don't want to delete empty container here -> performance.
1244 // XPropertySet methods.
1248 // virtual
1249 Reference< XPropertySetInfo > SAL_CALL PersistentPropertySet::getPropertySetInfo()
1250 throw( RuntimeException, std::exception )
1252 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1254 PropertySetInfo_Impl*& rpInfo = m_pImpl->m_pInfo;
1255 if ( !rpInfo )
1257 rpInfo = new PropertySetInfo_Impl( m_xContext, this );
1258 rpInfo->acquire();
1260 return Reference< XPropertySetInfo >( rpInfo );
1264 // virtual
1265 void SAL_CALL PersistentPropertySet::setPropertyValue( const OUString& aPropertyName,
1266 const Any& aValue )
1267 throw( UnknownPropertyException,
1268 PropertyVetoException,
1269 IllegalArgumentException,
1270 WrappedTargetException,
1271 RuntimeException,
1272 std::exception )
1274 if ( aPropertyName.isEmpty() )
1275 throw UnknownPropertyException();
1277 osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1279 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1280 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1281 if ( xRootHierNameAccess.is() )
1283 OUString aFullPropName( getFullKey() );
1284 aFullPropName += "/";
1285 aFullPropName += makeHierarchalNameSegment( aPropertyName );
1287 // Does property exist?
1288 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1290 Reference< XNameReplace > xNameReplace(
1291 m_pImpl->m_pCreator->getConfigWriteAccess(
1292 aFullPropName ), UNO_QUERY );
1293 Reference< XChangesBatch > xBatch(
1294 m_pImpl->m_pCreator->getConfigWriteAccess(
1295 OUString() ), UNO_QUERY );
1297 if ( xNameReplace.is() && xBatch.is() )
1301 // Obtain old value
1302 OUString aValueName = aFullPropName;
1303 aValueName += "/Value";
1304 Any aOldValue
1305 = xRootHierNameAccess->getByHierarchicalName(
1306 aValueName );
1307 // Check value type.
1308 if ( aOldValue.getValueType() != aValue.getValueType() )
1310 aCGuard.clear();
1311 throw IllegalArgumentException();
1314 // Write value
1315 xNameReplace->replaceByName(
1316 OUString("Value"),
1317 aValue );
1319 // Write state ( Now it is a directly set value )
1320 xNameReplace->replaceByName(
1321 OUString("State"),
1322 makeAny(
1323 sal_Int32(
1324 PropertyState_DIRECT_VALUE ) ) );
1326 // Commit changes.
1327 xBatch->commitChanges();
1329 PropertyChangeEvent aEvt;
1330 if ( m_pImpl->m_pPropertyChangeListeners )
1332 // Obtain handle
1333 aValueName = aFullPropName;
1334 aValueName += "/Handle";
1335 sal_Int32 nHandle = -1;
1336 xRootHierNameAccess->getByHierarchicalName( aValueName )
1337 >>= nHandle;
1339 aEvt.Source = (OWeakObject*)this;
1340 aEvt.PropertyName = aPropertyName;
1341 aEvt.PropertyHandle = nHandle;
1342 aEvt.Further = sal_False;
1343 aEvt.OldValue = aOldValue;
1344 aEvt.NewValue = aValue;
1346 // Callback follows!
1347 aCGuard.clear();
1349 notifyPropertyChangeEvent( aEvt );
1351 return;
1353 catch (const IllegalArgumentException&)
1355 // replaceByName
1357 catch (const NoSuchElementException&)
1359 // getByHierarchicalName, replaceByName
1361 catch (const WrappedTargetException&)
1363 // replaceByName, commitChanges
1369 throw UnknownPropertyException();
1373 // virtual
1374 Any SAL_CALL PersistentPropertySet::getPropertyValue(
1375 const OUString& PropertyName )
1376 throw( UnknownPropertyException,
1377 WrappedTargetException,
1378 RuntimeException, std::exception )
1380 if ( PropertyName.isEmpty() )
1381 throw UnknownPropertyException();
1383 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1385 Reference< XHierarchicalNameAccess > xNameAccess(
1386 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1387 if ( xNameAccess.is() )
1389 OUString aFullPropName( getFullKey() );
1390 aFullPropName += "/";
1391 aFullPropName += makeHierarchalNameSegment( PropertyName );
1392 aFullPropName += "/Value";
1395 return xNameAccess->getByHierarchicalName( aFullPropName );
1397 catch (const NoSuchElementException&)
1399 throw UnknownPropertyException();
1403 throw UnknownPropertyException();
1407 // virtual
1408 void SAL_CALL PersistentPropertySet::addPropertyChangeListener(
1409 const OUString& aPropertyName,
1410 const Reference< XPropertyChangeListener >& xListener )
1411 throw( UnknownPropertyException,
1412 WrappedTargetException,
1413 RuntimeException, std::exception )
1415 // load();
1417 if ( !m_pImpl->m_pPropertyChangeListeners )
1418 m_pImpl->m_pPropertyChangeListeners =
1419 new PropertyListeners_Impl( m_pImpl->m_aMutex );
1421 m_pImpl->m_pPropertyChangeListeners->addInterface(
1422 aPropertyName, xListener );
1426 // virtual
1427 void SAL_CALL PersistentPropertySet::removePropertyChangeListener(
1428 const OUString& aPropertyName,
1429 const Reference< XPropertyChangeListener >& aListener )
1430 throw( UnknownPropertyException,
1431 WrappedTargetException,
1432 RuntimeException, std::exception )
1434 // load();
1436 if ( m_pImpl->m_pPropertyChangeListeners )
1437 m_pImpl->m_pPropertyChangeListeners->removeInterface(
1438 aPropertyName, aListener );
1440 // Note: Don't want to delete empty container here -> performance.
1444 // virtual
1445 void SAL_CALL PersistentPropertySet::addVetoableChangeListener(
1446 const OUString&,
1447 const Reference< XVetoableChangeListener >& )
1448 throw( UnknownPropertyException,
1449 WrappedTargetException,
1450 RuntimeException, std::exception )
1452 // load();
1453 // OSL_FAIL( // "PersistentPropertySet::addVetoableChangeListener - N.Y.I." );
1457 // virtual
1458 void SAL_CALL PersistentPropertySet::removeVetoableChangeListener(
1459 const OUString&,
1460 const Reference< XVetoableChangeListener >& )
1461 throw( UnknownPropertyException,
1462 WrappedTargetException,
1463 RuntimeException, std::exception )
1465 // load();
1466 // OSL_FAIL( // "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." );
1471 // XPersistentPropertySet methods.
1475 // virtual
1476 Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry()
1477 throw( RuntimeException, std::exception )
1479 return Reference< XPropertySetRegistry >( m_pImpl->m_pCreator );
1483 // virtual
1484 OUString SAL_CALL PersistentPropertySet::getKey()
1485 throw( RuntimeException, std::exception )
1487 return m_pImpl->m_aKey;
1492 // XNamed methods.
1496 // virtual
1497 OUString SAL_CALL PersistentPropertySet::getName()
1498 throw( RuntimeException, std::exception )
1500 // same as getKey()
1501 return m_pImpl->m_aKey;
1505 // virtual
1506 void SAL_CALL PersistentPropertySet::setName( const OUString& aName )
1507 throw( RuntimeException, std::exception )
1509 if ( aName != m_pImpl->m_aKey )
1510 m_pImpl->m_pCreator->renamePropertySet( m_pImpl->m_aKey, aName );
1515 // XPropertyContainer methods.
1519 // virtual
1520 void SAL_CALL PersistentPropertySet::addProperty(
1521 const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue )
1522 throw( PropertyExistException,
1523 IllegalTypeException,
1524 IllegalArgumentException,
1525 RuntimeException, std::exception )
1527 if ( Name.isEmpty() )
1528 throw IllegalArgumentException();
1530 // @@@ What other types can't be written to config server?
1532 // Check type class ( Not all types can be written to storage )
1533 TypeClass eTypeClass = DefaultValue.getValueTypeClass();
1534 if ( eTypeClass == TypeClass_INTERFACE )
1535 throw IllegalTypeException();
1537 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1539 // Property already in set?
1541 OUString aFullValuesName;
1543 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1544 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1545 if ( xRootHierNameAccess.is() )
1547 aFullValuesName = getFullKey();
1548 OUString aFullPropName = aFullValuesName;
1549 aFullPropName += "/";
1550 aFullPropName += makeHierarchalNameSegment( Name );
1552 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1554 // Already in set.
1555 throw PropertyExistException();
1559 // Property is always removable.
1560 Attributes |= PropertyAttribute::REMOVABLE;
1562 // Add property.
1564 Reference< XSingleServiceFactory > xFac(
1565 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1566 UNO_QUERY );
1567 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
1568 Reference< XChangesBatch > xBatch(
1569 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1570 UNO_QUERY );
1572 OSL_ENSURE( xFac.is(),
1573 "PersistentPropertySet::addProperty - No factory!" );
1575 OSL_ENSURE( xBatch.is(),
1576 "PersistentPropertySet::addProperty - No batch!" );
1578 OSL_ENSURE( xContainer.is(),
1579 "PersistentPropertySet::addProperty - No container!" );
1581 if ( xFac.is() && xBatch.is() && xContainer.is() )
1585 // Create new "PropertyValue" config item.
1586 Reference< XNameReplace > xNameReplace(
1587 xFac->createInstance(), UNO_QUERY );
1589 if ( xNameReplace.is() )
1591 // Fill new item...
1593 // Set handle
1594 xNameReplace->replaceByName(
1595 OUString("Handle"),
1596 makeAny( sal_Int32( -1 ) ) );
1598 // Set default value
1599 xNameReplace->replaceByName(
1600 OUString("Value"),
1601 DefaultValue );
1603 // Set state ( always "default" )
1604 xNameReplace->replaceByName(
1605 OUString("State"),
1606 makeAny(
1607 sal_Int32(
1608 PropertyState_DEFAULT_VALUE ) ) );
1610 // Set attributes
1611 xNameReplace->replaceByName(
1612 OUString("Attributes"),
1613 makeAny( sal_Int32( Attributes ) ) );
1615 // Insert new item.
1616 xContainer->insertByName( Name, makeAny( xNameReplace ) );
1618 // Commit changes.
1619 xBatch->commitChanges();
1621 // Property set info is invalid.
1622 if ( m_pImpl->m_pInfo )
1623 m_pImpl->m_pInfo->reset();
1625 // Notify propertyset info change listeners.
1626 if ( m_pImpl->m_pPropSetChangeListeners &&
1627 m_pImpl->m_pPropSetChangeListeners->getLength() )
1629 PropertySetInfoChangeEvent evt(
1630 static_cast< OWeakObject * >( this ),
1631 Name,
1633 PropertySetInfoChange::PROPERTY_INSERTED );
1634 notifyPropertySetInfoChange( evt );
1637 // Success.
1638 return;
1641 catch (const IllegalArgumentException&)
1643 // insertByName
1645 OSL_FAIL( "PersistentPropertySet::addProperty - "
1646 "caught IllegalArgumentException!" );
1647 return;
1649 catch (const ElementExistException&)
1651 // insertByName
1653 OSL_FAIL( "PersistentPropertySet::addProperty - "
1654 "caught ElementExistException!" );
1655 return;
1657 catch (const WrappedTargetException&)
1659 // replaceByName, insertByName, commitChanges
1661 OSL_FAIL( "PersistentPropertySet::addProperty - "
1662 "caught WrappedTargetException!" );
1663 return;
1665 catch (const RuntimeException&)
1667 throw;
1669 catch (const Exception&)
1671 // createInstance
1673 OSL_FAIL( "PersistentPropertySet::addProperty - "
1674 "caught Exception!" );
1675 return;
1679 OSL_FAIL( "PersistentPropertySet::addProperty - Error!" );
1683 // virtual
1684 void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name )
1685 throw( UnknownPropertyException,
1686 NotRemoveableException,
1687 RuntimeException, std::exception )
1689 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1691 OUString aFullValuesName;
1692 OUString aFullPropName;
1694 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1695 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1696 if ( xRootHierNameAccess.is() )
1698 aFullValuesName = getFullKey();
1699 aFullPropName = aFullValuesName;
1700 aFullPropName += "/";
1701 aFullPropName += makeHierarchalNameSegment( Name );
1703 // Property in set?
1704 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1705 throw UnknownPropertyException();
1707 // Property removable?
1710 OUString aFullAttrName = aFullPropName;
1711 aFullAttrName += "/Attributes";
1713 sal_Int32 nAttribs = 0;
1714 if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1715 >>= nAttribs )
1717 if ( !( nAttribs & PropertyAttribute::REMOVABLE ) )
1719 // Not removable!
1720 throw NotRemoveableException();
1723 else
1725 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1726 "No attributes!" );
1727 return;
1730 catch (const NoSuchElementException&)
1732 // getByHierarchicalName
1734 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1735 "caught NoSuchElementException!" );
1738 // Remove property...
1740 Reference< XNameContainer > xContainer(
1741 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1742 UNO_QUERY );
1743 Reference< XChangesBatch > xBatch(
1744 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1745 UNO_QUERY );
1747 OSL_ENSURE( xBatch.is(),
1748 "PersistentPropertySet::removeProperty - No batch!" );
1750 OSL_ENSURE( xContainer.is(),
1751 "PersistentPropertySet::removeProperty - No container!" );
1753 if ( xBatch.is() && xContainer.is() )
1757 sal_Int32 nHandle = -1;
1759 if ( m_pImpl->m_pPropSetChangeListeners &&
1760 m_pImpl->m_pPropSetChangeListeners->getLength() )
1762 // Obtain property handle ( needed for propertysetinfo
1763 // change event )...
1767 OUString aFullHandleName = aFullPropName;
1768 aFullHandleName
1769 += "/Handle";
1771 if ( ! ( xRootHierNameAccess->getByHierarchicalName(
1772 aFullHandleName ) >>= nHandle ) )
1773 nHandle = -1;
1776 catch (const NoSuchElementException&)
1778 // getByHierarchicalName
1780 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1781 "caught NoSuchElementException!" );
1782 nHandle = -1;
1786 xContainer->removeByName( Name );
1787 xBatch->commitChanges();
1789 // Property set info is invalid.
1790 if ( m_pImpl->m_pInfo )
1791 m_pImpl->m_pInfo->reset();
1793 // Notify propertyset info change listeners.
1794 if ( m_pImpl->m_pPropSetChangeListeners &&
1795 m_pImpl->m_pPropSetChangeListeners->getLength() )
1797 PropertySetInfoChangeEvent evt(
1798 static_cast< OWeakObject * >( this ),
1799 Name,
1800 nHandle,
1801 PropertySetInfoChange::PROPERTY_REMOVED );
1802 notifyPropertySetInfoChange( evt );
1805 // Success.
1806 return;
1808 catch (const NoSuchElementException&)
1810 // removeByName
1812 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1813 "caught NoSuchElementException!" );
1814 return;
1816 catch (const WrappedTargetException&)
1818 // commitChanges
1820 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1821 "caught WrappedTargetException!" );
1822 return;
1827 OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" );
1832 // XPropertySetInfoChangeNotifier methods.
1836 // virtual
1837 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
1838 const Reference< XPropertySetInfoChangeListener >& Listener )
1839 throw( RuntimeException, std::exception )
1841 if ( !m_pImpl->m_pPropSetChangeListeners )
1842 m_pImpl->m_pPropSetChangeListeners =
1843 new OInterfaceContainerHelper( m_pImpl->m_aMutex );
1845 m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
1849 // virtual
1850 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
1851 const Reference< XPropertySetInfoChangeListener >& Listener )
1852 throw( RuntimeException, std::exception )
1854 if ( m_pImpl->m_pPropSetChangeListeners )
1855 m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
1860 // XPropertyAccess methods.
1864 // virtual
1865 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
1866 throw( RuntimeException, std::exception )
1868 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1870 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1871 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1872 if ( xRootHierNameAccess.is() )
1876 Reference< XNameAccess > xNameAccess;
1877 xRootHierNameAccess->getByHierarchicalName(getFullKey())
1878 >>= xNameAccess;
1879 if ( xNameAccess.is() )
1881 // Obtain property names.
1883 Sequence< OUString > aElems = xNameAccess->getElementNames();
1885 sal_Int32 nCount = aElems.getLength();
1886 if ( nCount )
1888 Reference< XHierarchicalNameAccess > xHierNameAccess(
1889 xNameAccess, UNO_QUERY );
1891 OSL_ENSURE( xHierNameAccess.is(),
1892 "PersistentPropertySet::getPropertyValues - "
1893 "No hierarchical name access!" );
1895 if ( xHierNameAccess.is() )
1897 Sequence< PropertyValue > aValues( nCount );
1899 const OUString aHandleName("/Handle");
1900 const OUString aValueName("/Value");
1901 const OUString aStateName("/State");
1903 for ( sal_Int32 n = 0; n < nCount; ++n )
1905 PropertyValue& rValue = aValues[ n ];
1906 OUString rName = aElems[ n ];
1907 OUString aXMLName
1908 = makeHierarchalNameSegment( rName );
1910 // Set property name.
1912 rValue.Name = rName;
1916 // Obtain and set property handle
1917 OUString aHierName = aXMLName;
1918 aHierName += aHandleName;
1919 Any aKeyValue
1920 = xHierNameAccess->getByHierarchicalName(
1921 aHierName );
1923 if ( !( aKeyValue >>= rValue.Handle ) )
1924 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1925 "Error getting property handle!" );
1927 catch (const NoSuchElementException&)
1929 // getByHierarchicalName
1931 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1932 "NoSuchElementException!" );
1937 // Obtain and set property value
1938 OUString aHierName = aXMLName;
1939 aHierName += aValueName;
1940 rValue.Value
1941 = xHierNameAccess->getByHierarchicalName(
1942 aHierName );
1944 // Note: The value may be void if addProperty
1945 // was called with a default value
1946 // of type void.
1948 catch (const NoSuchElementException&)
1950 // getByHierarchicalName
1952 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1953 "NoSuchElementException!" );
1958 // Obtain and set property state
1959 OUString aHierName = aXMLName;
1960 aHierName += aStateName;
1961 Any aKeyValue
1962 = xHierNameAccess->getByHierarchicalName(
1963 aHierName );
1965 sal_Int32 nState = 0;
1966 if ( !( aKeyValue >>= nState ) )
1967 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1968 "Error getting property state!" );
1969 else
1970 rValue.State = PropertyState( nState );
1972 catch (const NoSuchElementException&)
1974 // getByHierarchicalName
1976 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1977 "NoSuchElementException!" );
1981 return aValues;
1986 catch (const NoSuchElementException&)
1988 // getByHierarchicalName
1992 return Sequence< PropertyValue >( 0 );
1996 // virtual
1997 void SAL_CALL PersistentPropertySet::setPropertyValues(
1998 const Sequence< PropertyValue >& aProps )
1999 throw( UnknownPropertyException,
2000 PropertyVetoException,
2001 IllegalArgumentException,
2002 WrappedTargetException,
2003 RuntimeException, std::exception )
2005 sal_Int32 nCount = aProps.getLength();
2006 if ( !nCount )
2007 return;
2009 osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
2011 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2012 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
2013 if ( xRootHierNameAccess.is() )
2015 const PropertyValue* pNewValues = aProps.getConstArray();
2017 typedef std::list< PropertyChangeEvent > Events;
2018 Events aEvents;
2020 OUString aFullPropNamePrefix( getFullKey() );
2021 aFullPropNamePrefix += "/";
2023 // Iterate over given property value sequence.
2024 for ( sal_Int32 n = 0; n < nCount; ++n )
2026 const PropertyValue& rNewValue = pNewValues[ n ];
2027 const OUString& rName = rNewValue.Name;
2029 OUString aFullPropName = aFullPropNamePrefix;
2030 aFullPropName += makeHierarchalNameSegment( rName );
2032 // Does property exist?
2033 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2035 Reference< XNameReplace > xNameReplace(
2036 m_pImpl->m_pCreator->getConfigWriteAccess(
2037 aFullPropName ), UNO_QUERY );
2038 Reference< XChangesBatch > xBatch(
2039 m_pImpl->m_pCreator->getConfigWriteAccess(
2040 OUString() ), UNO_QUERY );
2042 if ( xNameReplace.is() && xBatch.is() )
2046 // Write handle
2047 xNameReplace->replaceByName(
2048 OUString("Handle"),
2049 makeAny( rNewValue.Handle ) );
2051 // Save old value
2052 OUString aValueName = aFullPropName;
2053 aValueName += "/Value";
2054 Any aOldValue
2055 = xRootHierNameAccess->getByHierarchicalName(
2056 aValueName );
2057 // Write value
2058 xNameReplace->replaceByName(
2059 OUString("Value"),
2060 rNewValue.Value );
2062 // Write state ( Now it is a directly set value )
2063 xNameReplace->replaceByName(
2064 OUString("State"),
2065 makeAny(
2066 sal_Int32(
2067 PropertyState_DIRECT_VALUE ) ) );
2069 // Commit changes.
2070 xBatch->commitChanges();
2072 if ( m_pImpl->m_pPropertyChangeListeners )
2074 PropertyChangeEvent aEvt;
2075 aEvt.Source = (OWeakObject*)this;
2076 aEvt.PropertyName = rNewValue.Name;
2077 aEvt.PropertyHandle = rNewValue.Handle;
2078 aEvt.Further = sal_False;
2079 aEvt.OldValue = aOldValue;
2080 aEvt.NewValue = rNewValue.Value;
2082 aEvents.push_back( aEvt );
2085 catch (const IllegalArgumentException&)
2087 // replaceByName
2089 catch (const NoSuchElementException&)
2091 // getByHierarchicalName, replaceByName
2093 catch (const WrappedTargetException&)
2095 // replaceByName, commitChanges
2101 // Callback follows!
2102 aCGuard.clear();
2104 if ( m_pImpl->m_pPropertyChangeListeners )
2106 // Notify property changes.
2107 Events::const_iterator it = aEvents.begin();
2108 Events::const_iterator end = aEvents.end();
2110 while ( it != end )
2112 notifyPropertyChangeEvent( (*it) );
2113 ++it;
2117 return;
2120 OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" );
2125 // Non-interface methods
2129 void PersistentPropertySet::notifyPropertyChangeEvent(
2130 const PropertyChangeEvent& rEvent ) const
2132 // Get "normal" listeners for the property.
2133 OInterfaceContainerHelper* pContainer =
2134 m_pImpl->m_pPropertyChangeListeners->getContainer(
2135 rEvent.PropertyName );
2136 if ( pContainer && pContainer->getLength() )
2138 OInterfaceIteratorHelper aIter( *pContainer );
2139 while ( aIter.hasMoreElements() )
2141 // Propagate event.
2142 Reference< XPropertyChangeListener > xListener(
2143 aIter.next(), UNO_QUERY );
2144 if ( xListener.is() )
2145 xListener->propertyChange( rEvent );
2149 // Get "normal" listeners for all properties.
2150 OInterfaceContainerHelper* pNoNameContainer =
2151 m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() );
2152 if ( pNoNameContainer && pNoNameContainer->getLength() )
2154 OInterfaceIteratorHelper aIter( *pNoNameContainer );
2155 while ( aIter.hasMoreElements() )
2157 // Propagate event.
2158 Reference< XPropertyChangeListener > xListener(
2159 aIter.next(), UNO_QUERY );
2160 if ( xListener.is() )
2161 xListener->propertyChange( rEvent );
2167 void PersistentPropertySet::notifyPropertySetInfoChange(
2168 const PropertySetInfoChangeEvent& evt ) const
2170 if ( !m_pImpl->m_pPropSetChangeListeners )
2171 return;
2173 // Notify event listeners.
2174 OInterfaceIteratorHelper aIter( *( m_pImpl->m_pPropSetChangeListeners ) );
2175 while ( aIter.hasMoreElements() )
2177 // Propagate event.
2178 Reference< XPropertySetInfoChangeListener >
2179 xListener( aIter.next(), UNO_QUERY );
2180 if ( xListener.is() )
2181 xListener->propertySetInfoChange( evt );
2186 const OUString& PersistentPropertySet::getFullKey()
2188 if ( m_pImpl->m_aFullKey.isEmpty() )
2190 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
2191 if ( m_pImpl->m_aFullKey.isEmpty() )
2193 m_pImpl->m_aFullKey
2194 = makeHierarchalNameSegment( m_pImpl->m_aKey );
2195 m_pImpl->m_aFullKey
2196 += "/Values";
2200 return m_pImpl->m_aFullKey;
2204 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
2206 return *m_pImpl->m_pCreator;
2212 // PropertySetInfo_Impl Implementation.
2217 PropertySetInfo_Impl::PropertySetInfo_Impl(
2218 const Reference< XComponentContext >& xContext,
2219 PersistentPropertySet* pOwner )
2220 : m_xContext( xContext ),
2221 m_pProps( NULL ),
2222 m_pOwner( pOwner )
2227 // virtual
2228 PropertySetInfo_Impl::~PropertySetInfo_Impl()
2230 delete m_pProps;
2232 // !!! Do not delete m_pOwner !!!
2235 // XPropertySetInfo methods.
2239 // virtual
2240 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
2241 throw( RuntimeException, std::exception )
2243 if ( !m_pProps )
2245 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2246 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2247 UNO_QUERY );
2248 if ( xRootHierNameAccess.is() )
2252 Reference< XNameAccess > xNameAccess;
2253 xRootHierNameAccess->getByHierarchicalName(
2254 m_pOwner->getFullKey() )
2255 >>= xNameAccess;
2256 if ( xNameAccess.is() )
2258 // Obtain property names.
2260 Sequence< OUString > aElems
2261 = xNameAccess->getElementNames();
2263 sal_uInt32 nCount = aElems.getLength();
2264 Sequence< Property >* pPropSeq
2265 = new Sequence< Property >( nCount );
2267 if ( nCount )
2269 Reference< XHierarchicalNameAccess > xHierNameAccess(
2270 xNameAccess, UNO_QUERY );
2272 OSL_ENSURE( xHierNameAccess.is(),
2273 "PropertySetInfo_Impl::getProperties - "
2274 "No hierarchical name access!" );
2276 if ( xHierNameAccess.is() )
2278 const OUString aHandleName("/Handle");
2279 const OUString aValueName("/Value");
2280 const OUString aAttrName("/Attributes");
2282 Property* pProps = pPropSeq->getArray();
2284 for ( sal_uInt32 n = 0; n < nCount; ++n )
2286 Property& rProp = pProps[ n ];
2287 OUString rName = aElems[ n ];
2288 OUString aXMLName
2289 = makeHierarchalNameSegment( rName );
2291 // Set property name.
2293 rProp.Name = rName;
2297 // Obtain and set property handle
2298 OUString aHierName = aXMLName;
2299 aHierName += aHandleName;
2300 Any aKeyValue
2301 = xHierNameAccess->getByHierarchicalName(
2302 aHierName );
2304 if ( !( aKeyValue >>= rProp.Handle ) )
2305 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2306 "Error getting property handle!" );
2308 catch (const NoSuchElementException&)
2310 // getByHierarchicalName
2312 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2313 "NoSuchElementException!" );
2318 // Obtain and set property type
2319 OUString aHierName = aXMLName;
2320 aHierName += aValueName;
2321 Any aKeyValue
2322 = xHierNameAccess->getByHierarchicalName(
2323 aHierName );
2325 // Note: The type may be void if addProperty
2326 // was called with a default value
2327 // of type void.
2329 rProp.Type = aKeyValue.getValueType();
2331 catch (const NoSuchElementException&)
2333 // getByHierarchicalName
2335 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2336 "NoSuchElementException!" );
2341 // Obtain and set property attributes
2342 OUString aHierName = aXMLName;
2343 aHierName += aAttrName;
2344 Any aKeyValue
2345 = xHierNameAccess->getByHierarchicalName(
2346 aHierName );
2348 sal_Int32 nAttribs = 0;
2349 if ( aKeyValue >>= nAttribs )
2350 rProp.Attributes
2351 = sal_Int16( nAttribs );
2352 else
2353 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2354 "Error getting property attributes!" );
2356 catch (const NoSuchElementException&)
2358 // getByHierarchicalName
2360 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2361 "NoSuchElementException!" );
2367 // Success.
2368 m_pProps = pPropSeq;
2369 return *m_pProps;
2372 catch (const NoSuchElementException&)
2374 // getByHierarchicalName
2378 OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" );
2379 m_pProps = new Sequence< Property >( 0 );
2382 return *m_pProps;
2386 // virtual
2387 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2388 const OUString& aName )
2389 throw( UnknownPropertyException, RuntimeException, std::exception )
2391 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2392 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2393 UNO_QUERY );
2394 if ( xRootHierNameAccess.is() )
2396 OUString aFullPropName( m_pOwner->getFullKey() );
2397 aFullPropName += "/";
2398 aFullPropName += makeHierarchalNameSegment( aName );
2400 // Does property exist?
2401 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2402 throw UnknownPropertyException();
2406 Property aProp;
2408 // Obtain handle.
2409 OUString aKey = aFullPropName;
2410 aKey += "/Handle";
2412 if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2413 >>= aProp.Handle ) )
2415 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2416 "No handle!" );
2417 return Property();
2420 // Obtain Value and extract type.
2421 aKey = aFullPropName;
2422 aKey += "/Value";
2424 Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2425 if ( !aValue.hasValue() )
2427 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2428 "No Value!" );
2429 return Property();
2432 aProp.Type = aValue.getValueType();
2434 // Obtain Attributes.
2435 aKey = aFullPropName;
2436 aKey += "/Attributes";
2438 sal_Int32 nAttribs = 0;
2439 if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2440 >>= nAttribs )
2441 aProp.Attributes = sal_Int16( nAttribs );
2442 else
2444 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2445 "No attributes!" );
2446 return Property();
2449 // set name.
2450 aProp.Name = aName;
2452 // Success.
2453 return aProp;
2455 catch (const NoSuchElementException&)
2457 // getByHierarchicalName
2459 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2460 "caught NoSuchElementException!" );
2465 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" );
2466 return Property();
2470 // virtual
2471 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2472 const OUString& Name )
2473 throw( RuntimeException, std::exception )
2475 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2476 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2477 UNO_QUERY );
2478 if ( xRootHierNameAccess.is() )
2480 OUString aFullPropName( m_pOwner->getFullKey() );
2481 aFullPropName += "/";
2482 aFullPropName += makeHierarchalNameSegment( Name );
2484 return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2487 return sal_False;
2490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */