Bump version to 24.04.3.4
[LibreOffice.git] / ucb / source / core / ucbstore.cxx
blobc57af43642da6f3bb680128881086b4428ec26da
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 <optional>
28 #include <unordered_map>
29 #include <sal/log.hxx>
30 #include <comphelper/diagnose_ex.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/ref.hxx>
33 #include <comphelper/interfacecontainer2.hxx>
34 #include <comphelper/propertysequence.hxx>
35 #include <com/sun/star/beans/IllegalTypeException.hpp>
36 #include <com/sun/star/beans/NotRemoveableException.hpp>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/beans/PropertyExistException.hpp>
39 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
40 #include <com/sun/star/configuration/theDefaultProvider.hpp>
41 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
42 #include <com/sun/star/container/XNameContainer.hpp>
43 #include <com/sun/star/container/XNameReplace.hpp>
44 #include <com/sun/star/util/XChangesBatch.hpp>
45 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
46 #include <cppuhelper/supportsservice.hxx>
47 #include <cppuhelper/implbase.hxx>
48 #include <cppuhelper/weak.hxx>
49 #include <utility>
50 #include "ucbstore.hxx"
52 using namespace com::sun::star::beans;
53 using namespace com::sun::star::configuration;
54 using namespace com::sun::star::container;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::ucb;
57 using namespace com::sun::star::uno;
58 using namespace com::sun::star::util;
59 using namespace comphelper;
60 using namespace cppu;
62 static OUString makeHierarchalNameSegment( std::u16string_view rIn )
64 OUStringBuffer aBuffer( "['" );
66 size_t nCount = rIn.size();
67 for ( size_t n = 0; n < nCount; ++n )
69 const sal_Unicode c = rIn[ n ];
70 switch ( c )
72 case '&':
73 aBuffer.append( "&amp;" );
74 break;
76 case '"':
77 aBuffer.append( "&quot;" );
78 break;
80 case '\'':
81 aBuffer.append( "&apos;" );
82 break;
84 case '<':
85 aBuffer.append( "&lt;" );
86 break;
88 case '>':
89 aBuffer.append( "&gt;" );
90 break;
92 default:
93 aBuffer.append( c );
94 break;
98 aBuffer.append( "']" );
99 return aBuffer.makeStringAndClear();
102 constexpr OUString STORE_CONTENTPROPERTIES_KEY = u"/org.openoffice.ucb.Store/ContentProperties"_ustr;
104 // describe path of cfg entry
105 constexpr OUString CFGPROPERTY_NODEPATH = u"nodepath"_ustr;
107 class PropertySetInfo_Impl : public cppu::WeakImplHelper < XPropertySetInfo >
109 std::optional<Sequence< Property >>
110 m_xProps;
111 PersistentPropertySet* m_pOwner;
113 public:
114 explicit PropertySetInfo_Impl(PersistentPropertySet* pOwner);
116 // XPropertySetInfo
117 virtual Sequence< Property > SAL_CALL getProperties() override;
118 virtual Property SAL_CALL getPropertyByName( const OUString& aName ) override;
119 virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override;
121 // Non-interface methods.
122 void reset() { m_xProps.reset(); }
126 // UcbStore Implementation.
129 UcbStore::UcbStore( const Reference< XComponentContext >& xContext )
130 : m_xContext( xContext )
135 // virtual
136 UcbStore::~UcbStore()
140 OUString SAL_CALL UcbStore::getImplementationName()
142 return "com.sun.star.comp.ucb.UcbStore";
144 sal_Bool SAL_CALL UcbStore::supportsService( const OUString& ServiceName )
146 return cppu::supportsService( this, ServiceName );
148 css::uno::Sequence< OUString > SAL_CALL UcbStore::getSupportedServiceNames()
150 return { "com.sun.star.ucb.Store" };
153 // Service factory implementation.
155 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
156 ucb_UcbStore_get_implementation(
157 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
159 return cppu::acquire(new UcbStore(context));
163 // XPropertySetRegistryFactory methods.
166 // virtual
167 Reference< XPropertySetRegistry > SAL_CALL
168 UcbStore::createPropertySetRegistry( const OUString& )
170 // The URL parameter is ignored by this interface implementation. It always
171 // uses the configuration server as storage medium.
173 if ( !m_xTheRegistry.is() )
175 std::unique_lock aGuard( m_aMutex );
176 if ( !m_xTheRegistry.is() )
177 m_xTheRegistry = new PropertySetRegistry( m_xContext, m_aInitArgs );
180 return m_xTheRegistry;
184 // XInitialization methods.
187 // virtual
188 void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments )
190 std::unique_lock aGuard( m_aMutex );
191 m_aInitArgs = aArguments;
196 // PropertySetRegistry Implementation.
199 PropertySetRegistry::PropertySetRegistry(
200 const Reference< XComponentContext >& xContext,
201 const Sequence< Any > &rInitArgs )
202 : m_xContext( xContext )
203 , m_aInitArgs(rInitArgs)
204 , m_bTriedToGetRootReadAccess(false)
205 , m_bTriedToGetRootWriteAccess(false)
210 // virtual
211 PropertySetRegistry::~PropertySetRegistry()
216 // XServiceInfo methods.
219 OUString SAL_CALL PropertySetRegistry::getImplementationName()
221 return "com.sun.star.comp.ucb.PropertySetRegistry";
224 sal_Bool SAL_CALL PropertySetRegistry::supportsService( const OUString& ServiceName )
226 return cppu::supportsService( this, ServiceName );
229 css::uno::Sequence< OUString > SAL_CALL PropertySetRegistry::getSupportedServiceNames()
231 return { "com.sun.star.ucb.PropertySetRegistry" };
235 // XPropertySetRegistry methods.
238 // virtual
239 Reference< XPersistentPropertySet > SAL_CALL
240 PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create )
242 if ( key.isEmpty() )
243 return Reference< XPersistentPropertySet >();
245 std::unique_lock aGuard( m_aMutex );
247 PropertySetMap_Impl& rSets = m_aPropSets;
249 PropertySetMap_Impl::const_iterator it = rSets.find( key );
250 if ( it != rSets.end() )
251 // Already instantiated.
252 return Reference< XPersistentPropertySet >( (*it).second );
254 // Create new instance.
255 Reference< XNameAccess > xRootNameAccess(
256 getRootConfigReadAccessImpl(aGuard), UNO_QUERY );
257 if ( !xRootNameAccess.is() )
259 SAL_WARN( "ucb", "no root access" );
260 return Reference< XPersistentPropertySet >();
263 // Propertyset in registry?
264 if ( xRootNameAccess->hasByName( key ) )
266 // Yep!
267 return Reference< XPersistentPropertySet >(
268 new PersistentPropertySet(
269 aGuard, *this, key ) );
271 else if ( create )
273 // No. Create entry for propertyset.
275 Reference< XSingleServiceFactory > xFac(
276 getConfigWriteAccessImpl( aGuard, OUString() ), UNO_QUERY );
277 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
278 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
280 OSL_ENSURE( xFac.is(),
281 "PropertySetRegistry::openPropertySet - "
282 "No factory!" );
284 OSL_ENSURE( xBatch.is(),
285 "PropertySetRegistry::openPropertySet - "
286 "No batch!" );
288 OSL_ENSURE( xContainer.is(),
289 "PropertySetRegistry::openPropertySet - "
290 "No container!" );
292 if ( xFac.is() && xBatch.is() && xContainer.is() )
296 // Create new "Properties" config item.
297 Reference< XNameReplace > xNameReplace(
298 xFac->createInstance(), UNO_QUERY );
300 if ( xNameReplace.is() )
302 // Fill new item...
304 // Insert new item.
305 xContainer->insertByName(
306 key, Any( xNameReplace ) );
307 // Commit changes.
308 xBatch->commitChanges();
310 return Reference< XPersistentPropertySet >(
311 new PersistentPropertySet(
312 aGuard, *this, key ) );
315 catch (const IllegalArgumentException&)
317 // insertByName
319 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
320 "caught IllegalArgumentException!" );
322 catch (const ElementExistException&)
324 // insertByName
326 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
327 "caught ElementExistException!" );
329 catch (const WrappedTargetException&)
331 // insertByName, commitChanges
333 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
334 "caught WrappedTargetException!" );
336 catch (const RuntimeException&)
338 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
339 "caught RuntimeException!" );
341 catch (const Exception&)
343 // createInstance
345 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
346 "caught Exception!" );
350 else
352 // No entry. Fail, but no error.
353 return Reference< XPersistentPropertySet >();
356 SAL_WARN( "ucb", "no root access" );
358 return Reference< XPersistentPropertySet >();
362 // virtual
363 void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key )
365 if ( key.isEmpty() )
366 return;
368 std::unique_lock aGuard( m_aMutex );
370 Reference< XNameAccess > xRootNameAccess(
371 getRootConfigReadAccessImpl(aGuard), UNO_QUERY );
372 if ( xRootNameAccess.is() )
374 // Propertyset in registry?
375 if ( !xRootNameAccess->hasByName( key ) )
376 return;
377 Reference< XChangesBatch > xBatch(
378 getConfigWriteAccessImpl( aGuard, OUString() ), UNO_QUERY );
379 Reference< XNameContainer > xContainer( xBatch, UNO_QUERY );
381 if ( xBatch.is() && xContainer.is() )
385 // Remove item.
386 xContainer->removeByName( key );
387 // Commit changes.
388 xBatch->commitChanges();
390 // Success.
391 return;
393 catch (const NoSuchElementException&)
395 // removeByName
397 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
398 "caught NoSuchElementException!" );
399 return;
401 catch (const WrappedTargetException&)
403 // commitChanges
405 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
406 "caught WrappedTargetException!" );
407 return;
411 return;
414 SAL_WARN( "ucb", "no root access" );
418 // XElementAccess methods.
421 // virtual
422 css::uno::Type SAL_CALL PropertySetRegistry::getElementType()
424 return cppu::UnoType<XPersistentPropertySet>::get();
428 // virtual
429 sal_Bool SAL_CALL PropertySetRegistry::hasElements()
431 Reference< XElementAccess > xElemAccess(
432 getRootConfigReadAccess(), UNO_QUERY );
433 if ( xElemAccess.is() )
434 return xElemAccess->hasElements();
436 return false;
440 // XNameAccess methods.
443 // virtual
444 Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName )
446 Reference< XNameAccess > xNameAccess(
447 getRootConfigReadAccess(), UNO_QUERY );
448 if ( xNameAccess.is() )
453 return xNameAccess->getByName( aName );
455 catch (const NoSuchElementException&)
457 // getByName
459 catch (const WrappedTargetException&)
461 // getByName
465 return Any();
469 // virtual
470 Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames()
472 Reference< XNameAccess > xNameAccess(
473 getRootConfigReadAccess(), UNO_QUERY );
474 if ( xNameAccess.is() )
476 return xNameAccess->getElementNames();
478 return Sequence< OUString >( 0 );
482 // virtual
483 sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName )
485 Reference< XNameAccess > xNameAccess(
486 getRootConfigReadAccess(), UNO_QUERY );
487 if ( xNameAccess.is() )
489 return xNameAccess->hasByName( aName );
492 return false;
496 void PropertySetRegistry::add(
497 std::unique_lock<std::mutex>& /*rCreatorGuard*/,
498 PersistentPropertySet* pSet )
500 OUString key( pSet->getKey() );
502 if ( !key.isEmpty() )
504 m_aPropSets[ key ] = pSet;
509 void PropertySetRegistry::remove( PersistentPropertySet* pSet )
511 OUString key( pSet->getKey() );
513 if ( key.isEmpty() )
514 return;
516 std::unique_lock aGuard( m_aMutex );
518 PropertySetMap_Impl& rSets = m_aPropSets;
520 PropertySetMap_Impl::iterator it = rSets.find( key );
521 if ( it != rSets.end() )
523 // Found.
524 rSets.erase( it );
529 void PropertySetRegistry::renamePropertySet( const OUString& rOldKey,
530 const OUString& rNewKey )
532 if ( rOldKey == rNewKey )
533 return;
535 Reference< XNameAccess > xRootNameAccess(
536 getConfigWriteAccess( OUString() ), UNO_QUERY );
537 if ( xRootNameAccess.is() )
539 // Old key present?
540 if ( xRootNameAccess->hasByName( rOldKey ) )
542 // New key not present?
543 if ( xRootNameAccess->hasByName( rNewKey ) )
545 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
546 "New key exists!" );
547 return;
549 Reference< XSingleServiceFactory > xFac(
550 xRootNameAccess, UNO_QUERY );
551 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
552 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
554 OSL_ENSURE( xFac.is(),
555 "PropertySetRegistry::renamePropertySet - "
556 "No factory!" );
558 OSL_ENSURE( xBatch.is(),
559 "PropertySetRegistry::renamePropertySet - "
560 "No batch!" );
562 OSL_ENSURE( xContainer.is(),
563 "PropertySetRegistry::renamePropertySet - "
564 "No container!" );
566 if ( xFac.is() && xBatch.is() && xContainer.is() )
569 // Create new "Properties" config item.
574 Reference< XNameReplace > xNameReplace(
575 xFac->createInstance(), UNO_QUERY );
577 if ( xNameReplace.is() )
579 // Insert new item.
580 xContainer->insertByName(
581 rNewKey, Any( xNameReplace ) );
582 // Commit changes.
583 xBatch->commitChanges();
586 catch (const IllegalArgumentException&)
588 // insertByName
590 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
591 "caught IllegalArgumentException!" );
592 return;
594 catch (const ElementExistException&)
596 // insertByName
598 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
599 "caught ElementExistException!" );
600 return;
602 catch (const WrappedTargetException&)
604 // insertByName, commitChanges
606 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
607 "caught WrappedTargetException!" );
608 return;
610 catch (const RuntimeException&)
612 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
613 "caught RuntimeException!" );
614 return;
616 catch (const Exception&)
618 // createInstance
620 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
621 "caught Exception!" );
622 return;
626 // Copy data...
629 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
630 xRootNameAccess, UNO_QUERY );
631 if ( !xRootHierNameAccess.is() )
633 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
634 "No hierarchical name access!" );
635 return;
640 OUString aOldValuesKey
641 = makeHierarchalNameSegment( rOldKey ) + "/Values";
643 Reference< XNameAccess > xOldNameAccess;
644 xRootHierNameAccess->getByHierarchicalName(
645 aOldValuesKey )
646 >>= xOldNameAccess;
647 if ( !xOldNameAccess.is() )
649 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
650 "No old name access!" );
651 return;
654 // Obtain property names.
655 const Sequence< OUString > aElems
656 = xOldNameAccess->getElementNames();
657 if ( aElems.hasElements() )
659 OUString aNewValuesKey
660 = makeHierarchalNameSegment( rNewKey ) + "/Values";
662 Reference< XSingleServiceFactory > xNewFac;
663 xRootHierNameAccess->getByHierarchicalName(
664 aNewValuesKey )
665 >>= xNewFac;
666 if ( !xNewFac.is() )
668 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
669 "No new factory!" );
670 return;
673 Reference< XNameContainer > xNewContainer(
674 xNewFac, UNO_QUERY );
675 if ( !xNewContainer.is() )
677 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
678 "No new container!" );
679 return;
682 aOldValuesKey += "/";
684 for ( const OUString& rPropName : aElems )
686 // Create new item.
687 Reference< XNameReplace > xNewPropNameReplace(
688 xNewFac->createInstance(), UNO_QUERY );
690 if ( !xNewPropNameReplace.is() )
692 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
693 "No new prop name replace!" );
694 return;
697 // Fill new item...
699 // Set Values
700 OUString aKey = aOldValuesKey + makeHierarchalNameSegment( rPropName );
702 // ... handle
703 OUString aNewKey1 = aKey + "/Handle";
704 Any aAny =
705 xRootHierNameAccess->getByHierarchicalName(
706 aNewKey1 );
707 xNewPropNameReplace->replaceByName( "Handle", aAny );
709 // ... value
710 aNewKey1 = aKey + "/Value";
711 aAny =
712 xRootHierNameAccess->getByHierarchicalName(
713 aNewKey1 );
714 xNewPropNameReplace->replaceByName( "Value", aAny );
716 // ... state
717 aNewKey1 = aKey + "/State";
718 aAny =
719 xRootHierNameAccess->getByHierarchicalName(
720 aNewKey1 );
721 xNewPropNameReplace->replaceByName( "State", aAny );
723 // ... attributes
724 aNewKey1 = aKey + "/Attributes";
725 aAny =
726 xRootHierNameAccess->getByHierarchicalName(
727 aNewKey1 );
728 xNewPropNameReplace->replaceByName( "Attributes", aAny );
730 // Insert new item.
731 xNewContainer->insertByName(
732 rPropName, Any( xNewPropNameReplace ) );
734 // Commit changes.
735 xBatch->commitChanges();
739 catch (const IllegalArgumentException&)
741 // insertByName, replaceByName
743 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
744 "caught IllegalArgumentException!" );
745 return;
747 catch (const ElementExistException&)
749 // insertByName
751 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
752 "caught ElementExistException!" );
753 return;
755 catch (const WrappedTargetException&)
757 // insertByName, replaceByName, commitChanges
759 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
760 "caught WrappedTargetException!" );
761 return;
763 catch (const NoSuchElementException&)
765 // getByHierarchicalName, replaceByName
767 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
768 "caught NoSuchElementException!" );
769 return;
771 catch (const RuntimeException&)
773 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
774 "caught RuntimeException!" );
775 return;
777 catch (const Exception&)
779 // createInstance
781 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
782 "caught Exception!" );
783 return;
787 // Remove old entry...
792 // Remove item.
793 xContainer->removeByName( rOldKey );
794 // Commit changes.
795 xBatch->commitChanges();
797 // Success.
798 return;
800 catch (const NoSuchElementException&)
802 // removeByName
804 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
805 "caught NoSuchElementException!" );
806 return;
808 catch (const WrappedTargetException&)
810 // commitChanges
812 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
813 "caught WrappedTargetException!" );
814 return;
820 OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" );
824 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider(std::unique_lock<std::mutex>& /*rGuard*/)
826 if ( !m_xConfigProvider.is() )
828 const Sequence< Any >& rInitArgs = m_aInitArgs;
830 if ( rInitArgs.hasElements() )
832 // Extract config provider from service init args.
833 rInitArgs[ 0 ] >>= m_xConfigProvider;
835 OSL_ENSURE( m_xConfigProvider.is(),
836 "PropertySetRegistry::getConfigProvider - "
837 "No config provider!" );
839 else
843 m_xConfigProvider = theDefaultProvider::get( m_xContext );
845 catch (const Exception&)
847 TOOLS_WARN_EXCEPTION( "ucb", "");
852 return m_xConfigProvider;
856 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
858 std::unique_lock aGuard( m_aMutex );
859 return getRootConfigReadAccessImpl(aGuard);
862 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccessImpl(std::unique_lock<std::mutex>& rGuard)
866 if ( !m_xRootReadAccess.is() )
868 if ( m_bTriedToGetRootReadAccess )
870 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - "
871 "Unable to read any config data! -> #82494#" );
872 return Reference< XInterface >();
875 getConfigProvider(rGuard);
877 if ( m_xConfigProvider.is() )
879 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
881 {CFGPROPERTY_NODEPATH, Any(STORE_CONTENTPROPERTIES_KEY)}
882 }));
884 m_bTriedToGetRootReadAccess = true;
886 m_xRootReadAccess =
887 m_xConfigProvider->createInstanceWithArguments(
888 "com.sun.star.configuration.ConfigurationAccess",
889 aArguments );
891 if ( m_xRootReadAccess.is() )
892 return m_xRootReadAccess;
895 else
896 return m_xRootReadAccess;
898 catch (const RuntimeException&)
900 throw;
902 catch (const Exception&)
904 // createInstance, createInstanceWithArguments
906 TOOLS_WARN_EXCEPTION("ucb", "");
907 return Reference< XInterface >();
910 SAL_WARN( "ucb", "Error!" );
911 return Reference< XInterface >();
915 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
916 const OUString& rPath )
918 std::unique_lock aGuard( m_aMutex );
919 return getConfigWriteAccessImpl(aGuard, rPath);
922 Reference< XInterface > PropertySetRegistry::getConfigWriteAccessImpl(std::unique_lock<std::mutex>& rGuard,
923 const OUString& rPath )
927 if ( !m_xRootWriteAccess.is() )
929 if ( m_bTriedToGetRootWriteAccess )
931 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
932 "Unable to write any config data! -> #82494#" );
933 return Reference< XInterface >();
936 getConfigProvider(rGuard);
938 if ( m_xConfigProvider.is() )
940 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
942 {CFGPROPERTY_NODEPATH, Any(STORE_CONTENTPROPERTIES_KEY)}
943 }));
945 m_bTriedToGetRootWriteAccess = true;
947 m_xRootWriteAccess =
948 m_xConfigProvider->createInstanceWithArguments(
949 "com.sun.star.configuration.ConfigurationUpdateAccess",
950 aArguments );
952 OSL_ENSURE( m_xRootWriteAccess.is(),
953 "PropertySetRegistry::getConfigWriteAccess - "
954 "No config update access!" );
958 if ( m_xRootWriteAccess.is() )
960 if ( !rPath.isEmpty() )
962 Reference< XHierarchicalNameAccess > xNA(
963 m_xRootWriteAccess, UNO_QUERY );
964 if ( xNA.is() )
966 Reference< XInterface > xInterface;
967 xNA->getByHierarchicalName( rPath ) >>= xInterface;
969 if ( xInterface.is() )
970 return xInterface;
973 else
974 return m_xRootWriteAccess;
977 catch (const RuntimeException&)
979 throw;
981 catch (const NoSuchElementException&)
983 // getByHierarchicalName
985 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
986 "caught NoSuchElementException!" );
987 return Reference< XInterface >();
989 catch (const Exception&)
991 // createInstance, createInstanceWithArguments
993 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
994 "caught Exception!" );
995 return Reference< XInterface >();
998 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" );
999 return Reference< XInterface >();
1003 // PersistentPropertySet Implementation.
1006 PersistentPropertySet::PersistentPropertySet(
1007 std::unique_lock<std::mutex>& rCreatorGuard,
1008 PropertySetRegistry& rCreator,
1009 OUString aKey )
1010 : m_pCreator( &rCreator ), m_aKey(std::move( aKey ))
1012 // register at creator.
1013 rCreator.add( rCreatorGuard, this );
1017 // virtual
1018 PersistentPropertySet::~PersistentPropertySet()
1020 // deregister at creator.
1021 m_pCreator->remove( this );
1024 // XServiceInfo methods.
1026 OUString SAL_CALL PersistentPropertySet::getImplementationName()
1028 return "com.sun.star.comp.ucb.PersistentPropertySet";
1031 sal_Bool SAL_CALL PersistentPropertySet::supportsService( const OUString& ServiceName )
1033 return cppu::supportsService( this, ServiceName );
1036 css::uno::Sequence< OUString > SAL_CALL PersistentPropertySet::getSupportedServiceNames()
1038 return { "com.sun.star.ucb.PersistentPropertySet" };
1042 // XComponent methods.
1045 // virtual
1046 void SAL_CALL PersistentPropertySet::dispose()
1048 std::unique_lock l(m_aMutex);
1049 if ( m_aDisposeEventListeners.getLength(l) )
1051 EventObject aEvt;
1052 aEvt.Source = static_cast< XComponent * >( this );
1053 m_aDisposeEventListeners.disposeAndClear( l, aEvt );
1056 if ( m_aPropSetChangeListeners.getLength(l) )
1058 EventObject aEvt;
1059 aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this );
1060 m_aPropSetChangeListeners.disposeAndClear( l, aEvt );
1063 if ( m_aPropertyChangeListeners.hasContainedTypes(l) )
1065 EventObject aEvt;
1066 aEvt.Source = static_cast< XPropertySet * >( this );
1067 m_aPropertyChangeListeners.disposeAndClear( l, aEvt );
1072 // virtual
1073 void SAL_CALL PersistentPropertySet::addEventListener(
1074 const Reference< XEventListener >& Listener )
1076 std::unique_lock l(m_aMutex);
1078 m_aDisposeEventListeners.addInterface( l, Listener );
1082 // virtual
1083 void SAL_CALL PersistentPropertySet::removeEventListener(
1084 const Reference< XEventListener >& Listener )
1086 std::unique_lock l(m_aMutex);
1087 m_aDisposeEventListeners.removeInterface( l, Listener );
1089 // Note: Don't want to delete empty container here -> performance.
1093 // XPropertySet methods.
1096 // virtual
1097 Reference< XPropertySetInfo > SAL_CALL PersistentPropertySet::getPropertySetInfo()
1099 std::unique_lock l(m_aMutex);
1101 if ( !m_pInfo.is() )
1103 m_pInfo = new PropertySetInfo_Impl( this );
1105 return m_pInfo;
1109 // virtual
1110 void SAL_CALL PersistentPropertySet::setPropertyValue( const OUString& aPropertyName,
1111 const Any& aValue )
1113 std::unique_lock aCGuard(m_aMutex);
1115 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1116 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1117 if ( xRootHierNameAccess.is() )
1119 OUString aFullPropName( getFullKeyImpl(aCGuard) + "/" +
1120 makeHierarchalNameSegment( aPropertyName ) );
1122 // Does property exist?
1123 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1125 Reference< XNameReplace > xNameReplace(
1126 m_pCreator->getConfigWriteAccess(
1127 aFullPropName ), UNO_QUERY );
1128 Reference< XChangesBatch > xBatch(
1129 m_pCreator->getConfigWriteAccess(
1130 OUString() ), UNO_QUERY );
1132 if ( xNameReplace.is() && xBatch.is() )
1136 // Obtain old value
1137 OUString aValueName = aFullPropName + "/Value";
1138 Any aOldValue
1139 = xRootHierNameAccess->getByHierarchicalName(
1140 aValueName );
1141 // Check value type.
1142 if ( aOldValue.getValueType() != aValue.getValueType() )
1144 throw IllegalArgumentException();
1147 // Write value
1148 xNameReplace->replaceByName( "Value", aValue );
1150 // Write state ( Now it is a directly set value )
1151 xNameReplace->replaceByName(
1152 "State",
1153 Any(
1154 sal_Int32(
1155 PropertyState_DIRECT_VALUE ) ) );
1157 // Commit changes.
1158 xBatch->commitChanges();
1160 PropertyChangeEvent aEvt;
1161 if ( m_aPropertyChangeListeners.hasContainedTypes(aCGuard) )
1163 // Obtain handle
1164 aValueName = aFullPropName + "/Handle";
1165 sal_Int32 nHandle = -1;
1166 xRootHierNameAccess->getByHierarchicalName( aValueName )
1167 >>= nHandle;
1169 aEvt.Source = getXWeak();
1170 aEvt.PropertyName = aPropertyName;
1171 aEvt.PropertyHandle = nHandle;
1172 aEvt.Further = false;
1173 aEvt.OldValue = aOldValue;
1174 aEvt.NewValue = aValue;
1176 notifyPropertyChangeEvent( aCGuard, aEvt );
1178 return;
1180 catch (const IllegalArgumentException&)
1182 // replaceByName
1184 catch (const NoSuchElementException&)
1186 // getByHierarchicalName, replaceByName
1188 catch (const WrappedTargetException&)
1190 // replaceByName, commitChanges
1196 throw UnknownPropertyException(aPropertyName);
1200 // virtual
1201 Any SAL_CALL PersistentPropertySet::getPropertyValue(
1202 const OUString& PropertyName )
1204 std::unique_lock aGuard(m_aMutex);
1206 Reference< XHierarchicalNameAccess > xNameAccess(
1207 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1208 if ( xNameAccess.is() )
1210 OUString aFullPropName( getFullKeyImpl(aGuard) + "/" +
1211 makeHierarchalNameSegment( PropertyName ) + "/Value" );
1214 return xNameAccess->getByHierarchicalName( aFullPropName );
1216 catch (const NoSuchElementException&)
1218 throw UnknownPropertyException(aFullPropName);
1222 throw UnknownPropertyException(PropertyName);
1226 // virtual
1227 void SAL_CALL PersistentPropertySet::addPropertyChangeListener(
1228 const OUString& aPropertyName,
1229 const Reference< XPropertyChangeListener >& xListener )
1231 // load();
1233 std::unique_lock aGuard(m_aMutex);
1235 m_aPropertyChangeListeners.addInterface(aGuard, aPropertyName, xListener );
1239 // virtual
1240 void SAL_CALL PersistentPropertySet::removePropertyChangeListener(
1241 const OUString& aPropertyName,
1242 const Reference< XPropertyChangeListener >& aListener )
1244 // load();
1246 std::unique_lock aGuard(m_aMutex);
1248 m_aPropertyChangeListeners.removeInterface(aGuard,
1249 aPropertyName, aListener );
1251 // Note: Don't want to delete empty container here -> performance.
1255 // virtual
1256 void SAL_CALL PersistentPropertySet::addVetoableChangeListener(
1257 const OUString&,
1258 const Reference< XVetoableChangeListener >& )
1260 // load();
1261 // OSL_FAIL( // "PersistentPropertySet::addVetoableChangeListener - N.Y.I." );
1265 // virtual
1266 void SAL_CALL PersistentPropertySet::removeVetoableChangeListener(
1267 const OUString&,
1268 const Reference< XVetoableChangeListener >& )
1270 // load();
1271 // OSL_FAIL( // "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." );
1275 // XPersistentPropertySet methods.
1278 // virtual
1279 Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry()
1281 return m_pCreator;
1285 // virtual
1286 OUString SAL_CALL PersistentPropertySet::getKey()
1288 return m_aKey;
1292 // XNamed methods.
1295 // virtual
1296 OUString SAL_CALL PersistentPropertySet::getName()
1298 // same as getKey()
1299 return m_aKey;
1303 // virtual
1304 void SAL_CALL PersistentPropertySet::setName( const OUString& aName )
1306 if ( aName != m_aKey )
1307 m_pCreator->renamePropertySet( m_aKey, aName );
1311 // XPropertyContainer methods.
1314 // virtual
1315 void SAL_CALL PersistentPropertySet::addProperty(
1316 const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue )
1318 if ( Name.isEmpty() )
1319 throw IllegalArgumentException();
1321 // @@@ What other types can't be written to config server?
1323 // Check type class ( Not all types can be written to storage )
1324 TypeClass eTypeClass = DefaultValue.getValueTypeClass();
1325 if ( eTypeClass == TypeClass_INTERFACE )
1326 throw IllegalTypeException();
1328 std::unique_lock aGuard(m_aMutex);
1330 // Property already in set?
1332 OUString aFullValuesName;
1334 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1335 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1336 if ( xRootHierNameAccess.is() )
1338 aFullValuesName = getFullKeyImpl(aGuard);
1339 OUString aFullPropName = aFullValuesName + "/" +
1340 makeHierarchalNameSegment( Name );
1342 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1344 // Already in set.
1345 throw PropertyExistException();
1349 // Property is always removable.
1350 Attributes |= PropertyAttribute::REMOVABLE;
1352 // Add property.
1354 Reference< XSingleServiceFactory > xFac(
1355 m_pCreator->getConfigWriteAccess( aFullValuesName ),
1356 UNO_QUERY );
1357 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
1358 Reference< XChangesBatch > xBatch(
1359 m_pCreator->getConfigWriteAccess( OUString() ),
1360 UNO_QUERY );
1362 OSL_ENSURE( xFac.is(),
1363 "PersistentPropertySet::addProperty - No factory!" );
1365 OSL_ENSURE( xBatch.is(),
1366 "PersistentPropertySet::addProperty - No batch!" );
1368 OSL_ENSURE( xContainer.is(),
1369 "PersistentPropertySet::addProperty - No container!" );
1371 if ( xFac.is() && xBatch.is() && xContainer.is() )
1375 // Create new "PropertyValue" config item.
1376 Reference< XNameReplace > xNameReplace(
1377 xFac->createInstance(), UNO_QUERY );
1379 if ( xNameReplace.is() )
1381 // Fill new item...
1383 // Set handle
1384 xNameReplace->replaceByName(
1385 "Handle",
1386 Any( sal_Int32( -1 ) ) );
1388 // Set default value
1389 xNameReplace->replaceByName(
1390 "Value",
1391 DefaultValue );
1393 // Set state ( always "default" )
1394 xNameReplace->replaceByName(
1395 "State",
1396 Any(
1397 sal_Int32(
1398 PropertyState_DEFAULT_VALUE ) ) );
1400 // Set attributes
1401 xNameReplace->replaceByName(
1402 "Attributes",
1403 Any( sal_Int32( Attributes ) ) );
1405 // Insert new item.
1406 xContainer->insertByName( Name, Any( xNameReplace ) );
1408 // Commit changes.
1409 xBatch->commitChanges();
1411 // Property set info is invalid.
1412 if ( m_pInfo.is() )
1413 m_pInfo->reset();
1415 // Notify propertyset info change listeners.
1416 if ( m_aPropSetChangeListeners.getLength(aGuard) )
1418 PropertySetInfoChangeEvent evt(
1419 getXWeak(),
1420 Name,
1422 PropertySetInfoChange::PROPERTY_INSERTED );
1423 notifyPropertySetInfoChange(aGuard, evt);
1426 // Success.
1427 return;
1430 catch (const IllegalArgumentException&)
1432 // insertByName
1434 OSL_FAIL( "PersistentPropertySet::addProperty - "
1435 "caught IllegalArgumentException!" );
1436 return;
1438 catch (const ElementExistException&)
1440 // insertByName
1442 OSL_FAIL( "PersistentPropertySet::addProperty - "
1443 "caught ElementExistException!" );
1444 return;
1446 catch (const WrappedTargetException&)
1448 // replaceByName, insertByName, commitChanges
1450 OSL_FAIL( "PersistentPropertySet::addProperty - "
1451 "caught WrappedTargetException!" );
1452 return;
1454 catch (const RuntimeException&)
1456 throw;
1458 catch (const Exception&)
1460 // createInstance
1462 OSL_FAIL( "PersistentPropertySet::addProperty - "
1463 "caught Exception!" );
1464 return;
1468 OSL_FAIL( "PersistentPropertySet::addProperty - Error!" );
1472 // virtual
1473 void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name )
1475 std::unique_lock aGuard(m_aMutex);
1477 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1478 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1479 if ( xRootHierNameAccess.is() )
1481 OUString aFullValuesName = getFullKeyImpl(aGuard);
1482 OUString aFullPropName = aFullValuesName + "/" +
1483 makeHierarchalNameSegment( Name );
1485 // Property in set?
1486 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1487 throw UnknownPropertyException(aFullPropName);
1489 // Property removable?
1492 OUString aFullAttrName = aFullPropName + "/Attributes";
1494 sal_Int32 nAttribs = 0;
1495 if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1496 >>= nAttribs )
1498 if ( !( nAttribs & PropertyAttribute::REMOVABLE ) )
1500 // Not removable!
1501 throw NotRemoveableException();
1504 else
1506 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1507 "No attributes!" );
1508 return;
1511 catch (const NoSuchElementException&)
1513 // getByHierarchicalName
1515 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1516 "caught NoSuchElementException!" );
1519 // Remove property...
1521 Reference< XNameContainer > xContainer(
1522 m_pCreator->getConfigWriteAccess( aFullValuesName ),
1523 UNO_QUERY );
1524 Reference< XChangesBatch > xBatch(
1525 m_pCreator->getConfigWriteAccess( OUString() ),
1526 UNO_QUERY );
1528 OSL_ENSURE( xBatch.is(),
1529 "PersistentPropertySet::removeProperty - No batch!" );
1531 OSL_ENSURE( xContainer.is(),
1532 "PersistentPropertySet::removeProperty - No container!" );
1534 if ( xBatch.is() && xContainer.is() )
1538 sal_Int32 nHandle = -1;
1540 if ( m_aPropSetChangeListeners.getLength(aGuard) )
1542 // Obtain property handle ( needed for propertysetinfo
1543 // change event )...
1547 OUString aFullHandleName = aFullPropName + "/Handle";
1549 if ( ! ( xRootHierNameAccess->getByHierarchicalName(
1550 aFullHandleName ) >>= nHandle ) )
1551 nHandle = -1;
1554 catch (const NoSuchElementException&)
1556 // getByHierarchicalName
1558 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1559 "caught NoSuchElementException!" );
1560 nHandle = -1;
1564 xContainer->removeByName( Name );
1565 xBatch->commitChanges();
1567 // Property set info is invalid.
1568 if ( m_pInfo.is() )
1569 m_pInfo->reset();
1571 // Notify propertyset info change listeners.
1572 if ( m_aPropSetChangeListeners.getLength(aGuard) )
1574 PropertySetInfoChangeEvent evt(
1575 getXWeak(),
1576 Name,
1577 nHandle,
1578 PropertySetInfoChange::PROPERTY_REMOVED );
1579 notifyPropertySetInfoChange( aGuard, evt );
1582 // Success.
1583 return;
1585 catch (const NoSuchElementException&)
1587 // removeByName
1589 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1590 "caught NoSuchElementException!" );
1591 return;
1593 catch (const WrappedTargetException&)
1595 // commitChanges
1597 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1598 "caught WrappedTargetException!" );
1599 return;
1604 OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" );
1608 // XPropertySetInfoChangeNotifier methods.
1611 // virtual
1612 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
1613 const Reference< XPropertySetInfoChangeListener >& Listener )
1615 std::unique_lock aGuard(m_aMutex);
1617 m_aPropSetChangeListeners.addInterface( aGuard, Listener );
1621 // virtual
1622 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
1623 const Reference< XPropertySetInfoChangeListener >& Listener )
1625 std::unique_lock aGuard(m_aMutex);
1626 m_aPropSetChangeListeners.removeInterface( aGuard, Listener );
1630 // XPropertyAccess methods.
1633 // virtual
1634 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
1636 std::unique_lock aGuard(m_aMutex);
1638 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1639 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1640 if ( xRootHierNameAccess.is() )
1644 Reference< XNameAccess > xNameAccess;
1645 xRootHierNameAccess->getByHierarchicalName(getFullKeyImpl(aGuard))
1646 >>= xNameAccess;
1647 if ( xNameAccess.is() )
1649 // Obtain property names.
1651 Sequence< OUString > aElems = xNameAccess->getElementNames();
1653 sal_Int32 nCount = aElems.getLength();
1654 if ( nCount )
1656 Reference< XHierarchicalNameAccess > xHierNameAccess(
1657 xNameAccess, UNO_QUERY );
1659 OSL_ENSURE( xHierNameAccess.is(),
1660 "PersistentPropertySet::getPropertyValues - "
1661 "No hierarchical name access!" );
1663 if ( xHierNameAccess.is() )
1665 Sequence< PropertyValue > aValues( nCount );
1666 auto pValues = aValues.getArray();
1668 static constexpr OUStringLiteral aHandleName(u"/Handle");
1669 static constexpr OUStringLiteral aValueName(u"/Value");
1670 static constexpr OUStringLiteral aStateName(u"/State");
1672 for ( sal_Int32 n = 0; n < nCount; ++n )
1674 PropertyValue& rValue = pValues[ n ];
1675 OUString rName = aElems[ n ];
1676 OUString aXMLName
1677 = makeHierarchalNameSegment( rName );
1679 // Set property name.
1681 rValue.Name = rName;
1685 // Obtain and set property handle
1686 OUString aHierName = aXMLName + aHandleName;
1687 Any aKeyValue
1688 = xHierNameAccess->getByHierarchicalName(
1689 aHierName );
1691 if ( !( aKeyValue >>= rValue.Handle ) )
1692 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1693 "Error getting property handle!" );
1695 catch (const NoSuchElementException&)
1697 // getByHierarchicalName
1699 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1700 "NoSuchElementException!" );
1705 // Obtain and set property value
1706 OUString aHierName = aXMLName + aValueName;
1707 rValue.Value
1708 = xHierNameAccess->getByHierarchicalName(
1709 aHierName );
1711 // Note: The value may be void if addProperty
1712 // was called with a default value
1713 // of type void.
1715 catch (const NoSuchElementException&)
1717 // getByHierarchicalName
1719 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1720 "NoSuchElementException!" );
1725 // Obtain and set property state
1726 OUString aHierName = aXMLName +aStateName;
1727 Any aKeyValue
1728 = xHierNameAccess->getByHierarchicalName(
1729 aHierName );
1731 sal_Int32 nState = 0;
1732 if ( !( aKeyValue >>= nState ) )
1733 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1734 "Error getting property state!" );
1735 else
1736 rValue.State = PropertyState( nState );
1738 catch (const NoSuchElementException&)
1740 // getByHierarchicalName
1742 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1743 "NoSuchElementException!" );
1747 return aValues;
1752 catch (const NoSuchElementException&)
1754 // getByHierarchicalName
1758 return Sequence< PropertyValue >( 0 );
1762 // virtual
1763 void SAL_CALL PersistentPropertySet::setPropertyValues(
1764 const Sequence< PropertyValue >& aProps )
1766 if ( !aProps.hasElements() )
1767 return;
1769 std::unique_lock aCGuard(m_aMutex);
1771 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1772 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1773 if ( xRootHierNameAccess.is() )
1775 std::vector< PropertyChangeEvent > aEvents;
1777 OUString aFullPropNamePrefix( getFullKeyImpl(aCGuard) + "/" );
1779 // Iterate over given property value sequence.
1780 for ( const PropertyValue& rNewValue : aProps )
1782 const OUString& rName = rNewValue.Name;
1784 OUString aFullPropName = aFullPropNamePrefix +
1785 makeHierarchalNameSegment( rName );
1787 // Does property exist?
1788 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1790 Reference< XNameReplace > xNameReplace(
1791 m_pCreator->getConfigWriteAccess(
1792 aFullPropName ), UNO_QUERY );
1793 Reference< XChangesBatch > xBatch(
1794 m_pCreator->getConfigWriteAccess(
1795 OUString() ), UNO_QUERY );
1797 if ( xNameReplace.is() && xBatch.is() )
1801 // Write handle
1802 xNameReplace->replaceByName(
1803 "Handle",
1804 Any( rNewValue.Handle ) );
1806 // Save old value
1807 OUString aValueName = aFullPropName +"/Value";
1808 Any aOldValue
1809 = xRootHierNameAccess->getByHierarchicalName(
1810 aValueName );
1811 // Write value
1812 xNameReplace->replaceByName(
1813 "Value",
1814 rNewValue.Value );
1816 // Write state ( Now it is a directly set value )
1817 xNameReplace->replaceByName(
1818 "State",
1819 Any(
1820 sal_Int32(
1821 PropertyState_DIRECT_VALUE ) ) );
1823 // Commit changes.
1824 xBatch->commitChanges();
1826 if ( m_aPropertyChangeListeners.hasContainedTypes(aCGuard) )
1828 PropertyChangeEvent aEvt;
1829 aEvt.Source = getXWeak();
1830 aEvt.PropertyName = rNewValue.Name;
1831 aEvt.PropertyHandle = rNewValue.Handle;
1832 aEvt.Further = false;
1833 aEvt.OldValue = std::move(aOldValue);
1834 aEvt.NewValue = rNewValue.Value;
1836 aEvents.push_back( aEvt );
1839 catch (const IllegalArgumentException&)
1841 // replaceByName
1843 catch (const NoSuchElementException&)
1845 // getByHierarchicalName, replaceByName
1847 catch (const WrappedTargetException&)
1849 // replaceByName, commitChanges
1855 if ( m_aPropertyChangeListeners.hasContainedTypes(aCGuard) )
1857 // Notify property changes.
1858 for (auto const& event : aEvents)
1860 notifyPropertyChangeEvent( aCGuard, event );
1864 return;
1867 OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" );
1871 // Non-interface methods
1874 void PersistentPropertySet::notifyPropertyChangeEvent(
1875 std::unique_lock<std::mutex>& rGuard,
1876 const PropertyChangeEvent& rEvent ) const
1878 // Get "normal" listeners for the property.
1879 OInterfaceContainerHelper4<XPropertyChangeListener>* pContainer =
1880 m_aPropertyChangeListeners.getContainer( rGuard, rEvent.PropertyName );
1881 if ( pContainer && pContainer->getLength(rGuard) )
1883 pContainer->notifyEach( rGuard, &XPropertyChangeListener::propertyChange, rEvent );
1886 // Get "normal" listeners for all properties.
1887 OInterfaceContainerHelper4<XPropertyChangeListener>* pNoNameContainer =
1888 m_aPropertyChangeListeners.getContainer( rGuard, OUString() );
1889 if ( pNoNameContainer && pNoNameContainer->getLength(rGuard) )
1891 pNoNameContainer->notifyEach( rGuard, &XPropertyChangeListener::propertyChange, rEvent );
1896 void PersistentPropertySet::notifyPropertySetInfoChange(
1897 std::unique_lock<std::mutex>& rGuard,
1898 const PropertySetInfoChangeEvent& evt ) const
1900 // Notify event listeners.
1901 m_aPropSetChangeListeners.notifyEach( rGuard, &XPropertySetInfoChangeListener::propertySetInfoChange, evt );
1905 OUString PersistentPropertySet::getFullKey()
1907 std::unique_lock aGuard(m_aMutex);
1908 return getFullKeyImpl(aGuard);
1911 const OUString& PersistentPropertySet::getFullKeyImpl(std::unique_lock<std::mutex>& )
1913 if ( m_aFullKey.isEmpty() )
1915 m_aFullKey = makeHierarchalNameSegment( m_aKey );
1916 m_aFullKey += "/Values";
1919 return m_aFullKey;
1923 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
1925 return *m_pCreator;
1929 // PropertySetInfo_Impl Implementation.
1932 PropertySetInfo_Impl::PropertySetInfo_Impl(
1933 PersistentPropertySet* pOwner )
1934 : m_pOwner( pOwner )
1939 // XPropertySetInfo methods.
1942 // virtual
1943 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
1945 if ( !m_xProps )
1947 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1948 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
1949 UNO_QUERY );
1950 if ( xRootHierNameAccess.is() )
1954 Reference< XNameAccess > xNameAccess;
1955 xRootHierNameAccess->getByHierarchicalName(
1956 m_pOwner->getFullKey() )
1957 >>= xNameAccess;
1958 if ( xNameAccess.is() )
1960 // Obtain property names.
1962 Sequence< OUString > aElems
1963 = xNameAccess->getElementNames();
1965 sal_uInt32 nCount = aElems.getLength();
1966 Sequence< Property > aPropSeq( nCount );
1968 if ( nCount )
1970 Reference< XHierarchicalNameAccess > xHierNameAccess(
1971 xNameAccess, UNO_QUERY );
1973 OSL_ENSURE( xHierNameAccess.is(),
1974 "PropertySetInfo_Impl::getProperties - "
1975 "No hierarchical name access!" );
1977 if ( xHierNameAccess.is() )
1979 static constexpr OUStringLiteral aHandleName(u"/Handle");
1980 static constexpr OUStringLiteral aValueName(u"/Value");
1981 static constexpr OUStringLiteral aAttrName(u"/Attributes");
1983 Property* pProps = aPropSeq.getArray();
1985 for ( sal_uInt32 n = 0; n < nCount; ++n )
1987 Property& rProp = pProps[ n ];
1988 OUString rName = aElems[ n ];
1989 OUString aXMLName
1990 = makeHierarchalNameSegment( rName );
1992 // Set property name.
1994 rProp.Name = rName;
1998 // Obtain and set property handle
1999 OUString aHierName = aXMLName + aHandleName;
2000 Any aKeyValue
2001 = xHierNameAccess->getByHierarchicalName(
2002 aHierName );
2004 if ( !( aKeyValue >>= rProp.Handle ) )
2005 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2006 "Error getting property handle!" );
2008 catch (const NoSuchElementException&)
2010 // getByHierarchicalName
2012 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2013 "NoSuchElementException!" );
2018 // Obtain and set property type
2019 OUString aHierName = aXMLName + aValueName;
2020 Any aKeyValue
2021 = xHierNameAccess->getByHierarchicalName(
2022 aHierName );
2024 // Note: The type may be void if addProperty
2025 // was called with a default value
2026 // of type void.
2028 rProp.Type = aKeyValue.getValueType();
2030 catch (const NoSuchElementException&)
2032 // getByHierarchicalName
2034 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2035 "NoSuchElementException!" );
2040 // Obtain and set property attributes
2041 OUString aHierName = aXMLName + aAttrName;
2042 Any aKeyValue
2043 = xHierNameAccess->getByHierarchicalName(
2044 aHierName );
2046 sal_Int32 nAttribs = 0;
2047 if ( aKeyValue >>= nAttribs )
2048 rProp.Attributes
2049 = sal_Int16( nAttribs );
2050 else
2051 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2052 "Error getting property attributes!" );
2054 catch (const NoSuchElementException&)
2056 // getByHierarchicalName
2058 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2059 "NoSuchElementException!" );
2065 // Success.
2066 m_xProps = std::move(aPropSeq);
2067 return *m_xProps;
2070 catch (const NoSuchElementException&)
2072 // getByHierarchicalName
2076 OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" );
2077 m_xProps.emplace();
2080 return *m_xProps;
2084 // virtual
2085 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2086 const OUString& aName )
2088 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2089 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2090 UNO_QUERY );
2091 if ( xRootHierNameAccess.is() )
2093 OUString aFullPropName( m_pOwner->getFullKey() + "/" +
2094 makeHierarchalNameSegment( aName ) );
2096 // Does property exist?
2097 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2098 throw UnknownPropertyException(aFullPropName);
2102 Property aProp;
2104 // Obtain handle.
2105 OUString aKey = aFullPropName + "/Handle";
2107 if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2108 >>= aProp.Handle ) )
2110 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2111 "No handle!" );
2112 return Property();
2115 // Obtain Value and extract type.
2116 aKey = aFullPropName + "/Value";
2118 Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2119 if ( !aValue.hasValue() )
2121 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2122 "No Value!" );
2123 return Property();
2126 aProp.Type = aValue.getValueType();
2128 // Obtain Attributes.
2129 aKey = aFullPropName + "/Attributes";
2131 sal_Int32 nAttribs = 0;
2132 if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2133 >>= nAttribs )
2134 aProp.Attributes = sal_Int16( nAttribs );
2135 else
2137 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2138 "No attributes!" );
2139 return Property();
2142 // set name.
2143 aProp.Name = aName;
2145 // Success.
2146 return aProp;
2148 catch (const NoSuchElementException&)
2150 // getByHierarchicalName
2152 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2153 "caught NoSuchElementException!" );
2158 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" );
2159 return Property();
2163 // virtual
2164 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2165 const OUString& Name )
2167 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2168 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2169 UNO_QUERY );
2170 if ( xRootHierNameAccess.is() )
2172 OUString aFullPropName( m_pOwner->getFullKey() + "/" +
2173 makeHierarchalNameSegment( Name ) );
2175 return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2178 return false;
2181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */