Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / core / ucbstore.cxx
blob1aae1235c0f032a5796e08821c40982fc5a5a863
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 OUStringLiteral STORE_CONTENTPROPERTIES_KEY = u"/org.openoffice.ucb.Store/ContentProperties";
104 // describe path of cfg entry
105 constexpr OUStringLiteral CFGPROPERTY_NODEPATH = u"nodepath";
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 OUString const aHandleKey("/Handle");
685 OUString const aValueKey("/Value");
686 OUString const aStateKey("/State");
687 OUString const aAttrKey("/Attributes");
689 for ( const OUString& rPropName : aElems )
691 // Create new item.
692 Reference< XNameReplace > xNewPropNameReplace(
693 xNewFac->createInstance(), UNO_QUERY );
695 if ( !xNewPropNameReplace.is() )
697 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
698 "No new prop name replace!" );
699 return;
702 // Fill new item...
704 // Set Values
705 OUString aKey = aOldValuesKey + makeHierarchalNameSegment( rPropName );
707 // ... handle
708 OUString aNewKey1 = aKey + aHandleKey;
709 Any aAny =
710 xRootHierNameAccess->getByHierarchicalName(
711 aNewKey1 );
712 xNewPropNameReplace->replaceByName( "Handle", aAny );
714 // ... value
715 aNewKey1 = aKey + aValueKey;
716 aAny =
717 xRootHierNameAccess->getByHierarchicalName(
718 aNewKey1 );
719 xNewPropNameReplace->replaceByName( "Value", aAny );
721 // ... state
722 aNewKey1 = aKey + aStateKey;
723 aAny =
724 xRootHierNameAccess->getByHierarchicalName(
725 aNewKey1 );
726 xNewPropNameReplace->replaceByName( "State", aAny );
728 // ... attributes
729 aNewKey1 = aKey + aAttrKey;
730 aAny =
731 xRootHierNameAccess->getByHierarchicalName(
732 aNewKey1 );
733 xNewPropNameReplace->replaceByName( "Attributes", aAny );
735 // Insert new item.
736 xNewContainer->insertByName(
737 rPropName, Any( xNewPropNameReplace ) );
739 // Commit changes.
740 xBatch->commitChanges();
744 catch (const IllegalArgumentException&)
746 // insertByName, replaceByName
748 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
749 "caught IllegalArgumentException!" );
750 return;
752 catch (const ElementExistException&)
754 // insertByName
756 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
757 "caught ElementExistException!" );
758 return;
760 catch (const WrappedTargetException&)
762 // insertByName, replaceByName, commitChanges
764 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
765 "caught WrappedTargetException!" );
766 return;
768 catch (const NoSuchElementException&)
770 // getByHierarchicalName, replaceByName
772 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
773 "caught NoSuchElementException!" );
774 return;
776 catch (const RuntimeException&)
778 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
779 "caught RuntimeException!" );
780 return;
782 catch (const Exception&)
784 // createInstance
786 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
787 "caught Exception!" );
788 return;
792 // Remove old entry...
797 // Remove item.
798 xContainer->removeByName( rOldKey );
799 // Commit changes.
800 xBatch->commitChanges();
802 // Success.
803 return;
805 catch (const NoSuchElementException&)
807 // removeByName
809 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
810 "caught NoSuchElementException!" );
811 return;
813 catch (const WrappedTargetException&)
815 // commitChanges
817 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
818 "caught WrappedTargetException!" );
819 return;
825 OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" );
829 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider(std::unique_lock<std::mutex>& /*rGuard*/)
831 if ( !m_xConfigProvider.is() )
833 const Sequence< Any >& rInitArgs = m_aInitArgs;
835 if ( rInitArgs.hasElements() )
837 // Extract config provider from service init args.
838 rInitArgs[ 0 ] >>= m_xConfigProvider;
840 OSL_ENSURE( m_xConfigProvider.is(),
841 "PropertySetRegistry::getConfigProvider - "
842 "No config provider!" );
844 else
848 m_xConfigProvider = theDefaultProvider::get( m_xContext );
850 catch (const Exception&)
852 TOOLS_WARN_EXCEPTION( "ucb", "");
857 return m_xConfigProvider;
861 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
863 std::unique_lock aGuard( m_aMutex );
864 return getRootConfigReadAccessImpl(aGuard);
867 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccessImpl(std::unique_lock<std::mutex>& rGuard)
871 if ( !m_xRootReadAccess.is() )
873 if ( m_bTriedToGetRootReadAccess )
875 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - "
876 "Unable to read any config data! -> #82494#" );
877 return Reference< XInterface >();
880 getConfigProvider(rGuard);
882 if ( m_xConfigProvider.is() )
884 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
886 {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
887 }));
889 m_bTriedToGetRootReadAccess = true;
891 m_xRootReadAccess =
892 m_xConfigProvider->createInstanceWithArguments(
893 "com.sun.star.configuration.ConfigurationAccess",
894 aArguments );
896 if ( m_xRootReadAccess.is() )
897 return m_xRootReadAccess;
900 else
901 return m_xRootReadAccess;
903 catch (const RuntimeException&)
905 throw;
907 catch (const Exception&)
909 // createInstance, createInstanceWithArguments
911 TOOLS_WARN_EXCEPTION("ucb", "");
912 return Reference< XInterface >();
915 SAL_WARN( "ucb", "Error!" );
916 return Reference< XInterface >();
920 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
921 const OUString& rPath )
923 std::unique_lock aGuard( m_aMutex );
924 return getConfigWriteAccessImpl(aGuard, rPath);
927 Reference< XInterface > PropertySetRegistry::getConfigWriteAccessImpl(std::unique_lock<std::mutex>& rGuard,
928 const OUString& rPath )
932 if ( !m_xRootWriteAccess.is() )
934 if ( m_bTriedToGetRootWriteAccess )
936 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
937 "Unable to write any config data! -> #82494#" );
938 return Reference< XInterface >();
941 getConfigProvider(rGuard);
943 if ( m_xConfigProvider.is() )
945 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
947 {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
948 }));
950 m_bTriedToGetRootWriteAccess = true;
952 m_xRootWriteAccess =
953 m_xConfigProvider->createInstanceWithArguments(
954 "com.sun.star.configuration.ConfigurationUpdateAccess",
955 aArguments );
957 OSL_ENSURE( m_xRootWriteAccess.is(),
958 "PropertySetRegistry::getConfigWriteAccess - "
959 "No config update access!" );
963 if ( m_xRootWriteAccess.is() )
965 if ( !rPath.isEmpty() )
967 Reference< XHierarchicalNameAccess > xNA(
968 m_xRootWriteAccess, UNO_QUERY );
969 if ( xNA.is() )
971 Reference< XInterface > xInterface;
972 xNA->getByHierarchicalName( rPath ) >>= xInterface;
974 if ( xInterface.is() )
975 return xInterface;
978 else
979 return m_xRootWriteAccess;
982 catch (const RuntimeException&)
984 throw;
986 catch (const NoSuchElementException&)
988 // getByHierarchicalName
990 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
991 "caught NoSuchElementException!" );
992 return Reference< XInterface >();
994 catch (const Exception&)
996 // createInstance, createInstanceWithArguments
998 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
999 "caught Exception!" );
1000 return Reference< XInterface >();
1003 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" );
1004 return Reference< XInterface >();
1008 // PersistentPropertySet Implementation.
1011 PersistentPropertySet::PersistentPropertySet(
1012 std::unique_lock<std::mutex>& rCreatorGuard,
1013 PropertySetRegistry& rCreator,
1014 OUString aKey )
1015 : m_pCreator( &rCreator ), m_aKey(std::move( aKey ))
1017 // register at creator.
1018 rCreator.add( rCreatorGuard, this );
1022 // virtual
1023 PersistentPropertySet::~PersistentPropertySet()
1025 // deregister at creator.
1026 m_pCreator->remove( this );
1029 // XServiceInfo methods.
1031 OUString SAL_CALL PersistentPropertySet::getImplementationName()
1033 return "com.sun.star.comp.ucb.PersistentPropertySet";
1036 sal_Bool SAL_CALL PersistentPropertySet::supportsService( const OUString& ServiceName )
1038 return cppu::supportsService( this, ServiceName );
1041 css::uno::Sequence< OUString > SAL_CALL PersistentPropertySet::getSupportedServiceNames()
1043 return { "com.sun.star.ucb.PersistentPropertySet" };
1047 // XComponent methods.
1050 // virtual
1051 void SAL_CALL PersistentPropertySet::dispose()
1053 std::unique_lock l(m_aMutex);
1054 if ( m_aDisposeEventListeners.getLength(l) )
1056 EventObject aEvt;
1057 aEvt.Source = static_cast< XComponent * >( this );
1058 m_aDisposeEventListeners.disposeAndClear( l, aEvt );
1061 if ( m_aPropSetChangeListeners.getLength(l) )
1063 EventObject aEvt;
1064 aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this );
1065 m_aPropSetChangeListeners.disposeAndClear( l, aEvt );
1068 if ( m_aPropertyChangeListeners.hasContainedTypes(l) )
1070 EventObject aEvt;
1071 aEvt.Source = static_cast< XPropertySet * >( this );
1072 m_aPropertyChangeListeners.disposeAndClear( l, aEvt );
1077 // virtual
1078 void SAL_CALL PersistentPropertySet::addEventListener(
1079 const Reference< XEventListener >& Listener )
1081 std::unique_lock l(m_aMutex);
1083 m_aDisposeEventListeners.addInterface( l, Listener );
1087 // virtual
1088 void SAL_CALL PersistentPropertySet::removeEventListener(
1089 const Reference< XEventListener >& Listener )
1091 std::unique_lock l(m_aMutex);
1092 m_aDisposeEventListeners.removeInterface( l, Listener );
1094 // Note: Don't want to delete empty container here -> performance.
1098 // XPropertySet methods.
1101 // virtual
1102 Reference< XPropertySetInfo > SAL_CALL PersistentPropertySet::getPropertySetInfo()
1104 std::unique_lock l(m_aMutex);
1106 if ( !m_pInfo.is() )
1108 m_pInfo = new PropertySetInfo_Impl( this );
1110 return m_pInfo;
1114 // virtual
1115 void SAL_CALL PersistentPropertySet::setPropertyValue( const OUString& aPropertyName,
1116 const Any& aValue )
1118 std::unique_lock aCGuard(m_aMutex);
1120 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1121 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1122 if ( xRootHierNameAccess.is() )
1124 OUString aFullPropName( getFullKeyImpl(aCGuard) + "/" +
1125 makeHierarchalNameSegment( aPropertyName ) );
1127 // Does property exist?
1128 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1130 Reference< XNameReplace > xNameReplace(
1131 m_pCreator->getConfigWriteAccess(
1132 aFullPropName ), UNO_QUERY );
1133 Reference< XChangesBatch > xBatch(
1134 m_pCreator->getConfigWriteAccess(
1135 OUString() ), UNO_QUERY );
1137 if ( xNameReplace.is() && xBatch.is() )
1141 // Obtain old value
1142 OUString aValueName = aFullPropName + "/Value";
1143 Any aOldValue
1144 = xRootHierNameAccess->getByHierarchicalName(
1145 aValueName );
1146 // Check value type.
1147 if ( aOldValue.getValueType() != aValue.getValueType() )
1149 throw IllegalArgumentException();
1152 // Write value
1153 xNameReplace->replaceByName( "Value", aValue );
1155 // Write state ( Now it is a directly set value )
1156 xNameReplace->replaceByName(
1157 "State",
1158 Any(
1159 sal_Int32(
1160 PropertyState_DIRECT_VALUE ) ) );
1162 // Commit changes.
1163 xBatch->commitChanges();
1165 PropertyChangeEvent aEvt;
1166 if ( m_aPropertyChangeListeners.hasContainedTypes(aCGuard) )
1168 // Obtain handle
1169 aValueName = aFullPropName + "/Handle";
1170 sal_Int32 nHandle = -1;
1171 xRootHierNameAccess->getByHierarchicalName( aValueName )
1172 >>= nHandle;
1174 aEvt.Source = static_cast<OWeakObject*>(this);
1175 aEvt.PropertyName = aPropertyName;
1176 aEvt.PropertyHandle = nHandle;
1177 aEvt.Further = false;
1178 aEvt.OldValue = aOldValue;
1179 aEvt.NewValue = aValue;
1181 notifyPropertyChangeEvent( aCGuard, aEvt );
1183 return;
1185 catch (const IllegalArgumentException&)
1187 // replaceByName
1189 catch (const NoSuchElementException&)
1191 // getByHierarchicalName, replaceByName
1193 catch (const WrappedTargetException&)
1195 // replaceByName, commitChanges
1201 throw UnknownPropertyException(aPropertyName);
1205 // virtual
1206 Any SAL_CALL PersistentPropertySet::getPropertyValue(
1207 const OUString& PropertyName )
1209 std::unique_lock aGuard(m_aMutex);
1211 Reference< XHierarchicalNameAccess > xNameAccess(
1212 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1213 if ( xNameAccess.is() )
1215 OUString aFullPropName( getFullKeyImpl(aGuard) + "/" +
1216 makeHierarchalNameSegment( PropertyName ) + "/Value" );
1219 return xNameAccess->getByHierarchicalName( aFullPropName );
1221 catch (const NoSuchElementException&)
1223 throw UnknownPropertyException(aFullPropName);
1227 throw UnknownPropertyException(PropertyName);
1231 // virtual
1232 void SAL_CALL PersistentPropertySet::addPropertyChangeListener(
1233 const OUString& aPropertyName,
1234 const Reference< XPropertyChangeListener >& xListener )
1236 // load();
1238 std::unique_lock aGuard(m_aMutex);
1240 m_aPropertyChangeListeners.addInterface(aGuard, aPropertyName, xListener );
1244 // virtual
1245 void SAL_CALL PersistentPropertySet::removePropertyChangeListener(
1246 const OUString& aPropertyName,
1247 const Reference< XPropertyChangeListener >& aListener )
1249 // load();
1251 std::unique_lock aGuard(m_aMutex);
1253 m_aPropertyChangeListeners.removeInterface(aGuard,
1254 aPropertyName, aListener );
1256 // Note: Don't want to delete empty container here -> performance.
1260 // virtual
1261 void SAL_CALL PersistentPropertySet::addVetoableChangeListener(
1262 const OUString&,
1263 const Reference< XVetoableChangeListener >& )
1265 // load();
1266 // OSL_FAIL( // "PersistentPropertySet::addVetoableChangeListener - N.Y.I." );
1270 // virtual
1271 void SAL_CALL PersistentPropertySet::removeVetoableChangeListener(
1272 const OUString&,
1273 const Reference< XVetoableChangeListener >& )
1275 // load();
1276 // OSL_FAIL( // "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." );
1280 // XPersistentPropertySet methods.
1283 // virtual
1284 Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry()
1286 return m_pCreator;
1290 // virtual
1291 OUString SAL_CALL PersistentPropertySet::getKey()
1293 return m_aKey;
1297 // XNamed methods.
1300 // virtual
1301 OUString SAL_CALL PersistentPropertySet::getName()
1303 // same as getKey()
1304 return m_aKey;
1308 // virtual
1309 void SAL_CALL PersistentPropertySet::setName( const OUString& aName )
1311 if ( aName != m_aKey )
1312 m_pCreator->renamePropertySet( m_aKey, aName );
1316 // XPropertyContainer methods.
1319 // virtual
1320 void SAL_CALL PersistentPropertySet::addProperty(
1321 const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue )
1323 if ( Name.isEmpty() )
1324 throw IllegalArgumentException();
1326 // @@@ What other types can't be written to config server?
1328 // Check type class ( Not all types can be written to storage )
1329 TypeClass eTypeClass = DefaultValue.getValueTypeClass();
1330 if ( eTypeClass == TypeClass_INTERFACE )
1331 throw IllegalTypeException();
1333 std::unique_lock aGuard(m_aMutex);
1335 // Property already in set?
1337 OUString aFullValuesName;
1339 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1340 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1341 if ( xRootHierNameAccess.is() )
1343 aFullValuesName = getFullKeyImpl(aGuard);
1344 OUString aFullPropName = aFullValuesName + "/" +
1345 makeHierarchalNameSegment( Name );
1347 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1349 // Already in set.
1350 throw PropertyExistException();
1354 // Property is always removable.
1355 Attributes |= PropertyAttribute::REMOVABLE;
1357 // Add property.
1359 Reference< XSingleServiceFactory > xFac(
1360 m_pCreator->getConfigWriteAccess( aFullValuesName ),
1361 UNO_QUERY );
1362 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
1363 Reference< XChangesBatch > xBatch(
1364 m_pCreator->getConfigWriteAccess( OUString() ),
1365 UNO_QUERY );
1367 OSL_ENSURE( xFac.is(),
1368 "PersistentPropertySet::addProperty - No factory!" );
1370 OSL_ENSURE( xBatch.is(),
1371 "PersistentPropertySet::addProperty - No batch!" );
1373 OSL_ENSURE( xContainer.is(),
1374 "PersistentPropertySet::addProperty - No container!" );
1376 if ( xFac.is() && xBatch.is() && xContainer.is() )
1380 // Create new "PropertyValue" config item.
1381 Reference< XNameReplace > xNameReplace(
1382 xFac->createInstance(), UNO_QUERY );
1384 if ( xNameReplace.is() )
1386 // Fill new item...
1388 // Set handle
1389 xNameReplace->replaceByName(
1390 "Handle",
1391 Any( sal_Int32( -1 ) ) );
1393 // Set default value
1394 xNameReplace->replaceByName(
1395 "Value",
1396 DefaultValue );
1398 // Set state ( always "default" )
1399 xNameReplace->replaceByName(
1400 "State",
1401 Any(
1402 sal_Int32(
1403 PropertyState_DEFAULT_VALUE ) ) );
1405 // Set attributes
1406 xNameReplace->replaceByName(
1407 "Attributes",
1408 Any( sal_Int32( Attributes ) ) );
1410 // Insert new item.
1411 xContainer->insertByName( Name, Any( xNameReplace ) );
1413 // Commit changes.
1414 xBatch->commitChanges();
1416 // Property set info is invalid.
1417 if ( m_pInfo.is() )
1418 m_pInfo->reset();
1420 // Notify propertyset info change listeners.
1421 if ( m_aPropSetChangeListeners.getLength(aGuard) )
1423 PropertySetInfoChangeEvent evt(
1424 static_cast< OWeakObject * >( this ),
1425 Name,
1427 PropertySetInfoChange::PROPERTY_INSERTED );
1428 notifyPropertySetInfoChange(aGuard, evt);
1431 // Success.
1432 return;
1435 catch (const IllegalArgumentException&)
1437 // insertByName
1439 OSL_FAIL( "PersistentPropertySet::addProperty - "
1440 "caught IllegalArgumentException!" );
1441 return;
1443 catch (const ElementExistException&)
1445 // insertByName
1447 OSL_FAIL( "PersistentPropertySet::addProperty - "
1448 "caught ElementExistException!" );
1449 return;
1451 catch (const WrappedTargetException&)
1453 // replaceByName, insertByName, commitChanges
1455 OSL_FAIL( "PersistentPropertySet::addProperty - "
1456 "caught WrappedTargetException!" );
1457 return;
1459 catch (const RuntimeException&)
1461 throw;
1463 catch (const Exception&)
1465 // createInstance
1467 OSL_FAIL( "PersistentPropertySet::addProperty - "
1468 "caught Exception!" );
1469 return;
1473 OSL_FAIL( "PersistentPropertySet::addProperty - Error!" );
1477 // virtual
1478 void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name )
1480 std::unique_lock aGuard(m_aMutex);
1482 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1483 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1484 if ( xRootHierNameAccess.is() )
1486 OUString aFullValuesName = getFullKeyImpl(aGuard);
1487 OUString aFullPropName = aFullValuesName + "/" +
1488 makeHierarchalNameSegment( Name );
1490 // Property in set?
1491 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1492 throw UnknownPropertyException(aFullPropName);
1494 // Property removable?
1497 OUString aFullAttrName = aFullPropName + "/Attributes";
1499 sal_Int32 nAttribs = 0;
1500 if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1501 >>= nAttribs )
1503 if ( !( nAttribs & PropertyAttribute::REMOVABLE ) )
1505 // Not removable!
1506 throw NotRemoveableException();
1509 else
1511 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1512 "No attributes!" );
1513 return;
1516 catch (const NoSuchElementException&)
1518 // getByHierarchicalName
1520 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1521 "caught NoSuchElementException!" );
1524 // Remove property...
1526 Reference< XNameContainer > xContainer(
1527 m_pCreator->getConfigWriteAccess( aFullValuesName ),
1528 UNO_QUERY );
1529 Reference< XChangesBatch > xBatch(
1530 m_pCreator->getConfigWriteAccess( OUString() ),
1531 UNO_QUERY );
1533 OSL_ENSURE( xBatch.is(),
1534 "PersistentPropertySet::removeProperty - No batch!" );
1536 OSL_ENSURE( xContainer.is(),
1537 "PersistentPropertySet::removeProperty - No container!" );
1539 if ( xBatch.is() && xContainer.is() )
1543 sal_Int32 nHandle = -1;
1545 if ( m_aPropSetChangeListeners.getLength(aGuard) )
1547 // Obtain property handle ( needed for propertysetinfo
1548 // change event )...
1552 OUString aFullHandleName = aFullPropName + "/Handle";
1554 if ( ! ( xRootHierNameAccess->getByHierarchicalName(
1555 aFullHandleName ) >>= nHandle ) )
1556 nHandle = -1;
1559 catch (const NoSuchElementException&)
1561 // getByHierarchicalName
1563 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1564 "caught NoSuchElementException!" );
1565 nHandle = -1;
1569 xContainer->removeByName( Name );
1570 xBatch->commitChanges();
1572 // Property set info is invalid.
1573 if ( m_pInfo.is() )
1574 m_pInfo->reset();
1576 // Notify propertyset info change listeners.
1577 if ( m_aPropSetChangeListeners.getLength(aGuard) )
1579 PropertySetInfoChangeEvent evt(
1580 static_cast< OWeakObject * >( this ),
1581 Name,
1582 nHandle,
1583 PropertySetInfoChange::PROPERTY_REMOVED );
1584 notifyPropertySetInfoChange( aGuard, evt );
1587 // Success.
1588 return;
1590 catch (const NoSuchElementException&)
1592 // removeByName
1594 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1595 "caught NoSuchElementException!" );
1596 return;
1598 catch (const WrappedTargetException&)
1600 // commitChanges
1602 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1603 "caught WrappedTargetException!" );
1604 return;
1609 OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" );
1613 // XPropertySetInfoChangeNotifier methods.
1616 // virtual
1617 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
1618 const Reference< XPropertySetInfoChangeListener >& Listener )
1620 std::unique_lock aGuard(m_aMutex);
1622 m_aPropSetChangeListeners.addInterface( aGuard, Listener );
1626 // virtual
1627 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
1628 const Reference< XPropertySetInfoChangeListener >& Listener )
1630 std::unique_lock aGuard(m_aMutex);
1631 m_aPropSetChangeListeners.removeInterface( aGuard, Listener );
1635 // XPropertyAccess methods.
1638 // virtual
1639 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
1641 std::unique_lock aGuard(m_aMutex);
1643 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1644 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1645 if ( xRootHierNameAccess.is() )
1649 Reference< XNameAccess > xNameAccess;
1650 xRootHierNameAccess->getByHierarchicalName(getFullKeyImpl(aGuard))
1651 >>= xNameAccess;
1652 if ( xNameAccess.is() )
1654 // Obtain property names.
1656 Sequence< OUString > aElems = xNameAccess->getElementNames();
1658 sal_Int32 nCount = aElems.getLength();
1659 if ( nCount )
1661 Reference< XHierarchicalNameAccess > xHierNameAccess(
1662 xNameAccess, UNO_QUERY );
1664 OSL_ENSURE( xHierNameAccess.is(),
1665 "PersistentPropertySet::getPropertyValues - "
1666 "No hierarchical name access!" );
1668 if ( xHierNameAccess.is() )
1670 Sequence< PropertyValue > aValues( nCount );
1671 auto pValues = aValues.getArray();
1673 static const OUStringLiteral aHandleName(u"/Handle");
1674 static const OUStringLiteral aValueName(u"/Value");
1675 static const OUStringLiteral aStateName(u"/State");
1677 for ( sal_Int32 n = 0; n < nCount; ++n )
1679 PropertyValue& rValue = pValues[ n ];
1680 OUString rName = aElems[ n ];
1681 OUString aXMLName
1682 = makeHierarchalNameSegment( rName );
1684 // Set property name.
1686 rValue.Name = rName;
1690 // Obtain and set property handle
1691 OUString aHierName = aXMLName + aHandleName;
1692 Any aKeyValue
1693 = xHierNameAccess->getByHierarchicalName(
1694 aHierName );
1696 if ( !( aKeyValue >>= rValue.Handle ) )
1697 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1698 "Error getting property handle!" );
1700 catch (const NoSuchElementException&)
1702 // getByHierarchicalName
1704 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1705 "NoSuchElementException!" );
1710 // Obtain and set property value
1711 OUString aHierName = aXMLName + aValueName;
1712 rValue.Value
1713 = xHierNameAccess->getByHierarchicalName(
1714 aHierName );
1716 // Note: The value may be void if addProperty
1717 // was called with a default value
1718 // of type void.
1720 catch (const NoSuchElementException&)
1722 // getByHierarchicalName
1724 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1725 "NoSuchElementException!" );
1730 // Obtain and set property state
1731 OUString aHierName = aXMLName +aStateName;
1732 Any aKeyValue
1733 = xHierNameAccess->getByHierarchicalName(
1734 aHierName );
1736 sal_Int32 nState = 0;
1737 if ( !( aKeyValue >>= nState ) )
1738 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1739 "Error getting property state!" );
1740 else
1741 rValue.State = PropertyState( nState );
1743 catch (const NoSuchElementException&)
1745 // getByHierarchicalName
1747 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1748 "NoSuchElementException!" );
1752 return aValues;
1757 catch (const NoSuchElementException&)
1759 // getByHierarchicalName
1763 return Sequence< PropertyValue >( 0 );
1767 // virtual
1768 void SAL_CALL PersistentPropertySet::setPropertyValues(
1769 const Sequence< PropertyValue >& aProps )
1771 if ( !aProps.hasElements() )
1772 return;
1774 std::unique_lock aCGuard(m_aMutex);
1776 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1777 m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1778 if ( xRootHierNameAccess.is() )
1780 std::vector< PropertyChangeEvent > aEvents;
1782 OUString aFullPropNamePrefix( getFullKeyImpl(aCGuard) + "/" );
1784 // Iterate over given property value sequence.
1785 for ( const PropertyValue& rNewValue : aProps )
1787 const OUString& rName = rNewValue.Name;
1789 OUString aFullPropName = aFullPropNamePrefix +
1790 makeHierarchalNameSegment( rName );
1792 // Does property exist?
1793 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1795 Reference< XNameReplace > xNameReplace(
1796 m_pCreator->getConfigWriteAccess(
1797 aFullPropName ), UNO_QUERY );
1798 Reference< XChangesBatch > xBatch(
1799 m_pCreator->getConfigWriteAccess(
1800 OUString() ), UNO_QUERY );
1802 if ( xNameReplace.is() && xBatch.is() )
1806 // Write handle
1807 xNameReplace->replaceByName(
1808 "Handle",
1809 Any( rNewValue.Handle ) );
1811 // Save old value
1812 OUString aValueName = aFullPropName +"/Value";
1813 Any aOldValue
1814 = xRootHierNameAccess->getByHierarchicalName(
1815 aValueName );
1816 // Write value
1817 xNameReplace->replaceByName(
1818 "Value",
1819 rNewValue.Value );
1821 // Write state ( Now it is a directly set value )
1822 xNameReplace->replaceByName(
1823 "State",
1824 Any(
1825 sal_Int32(
1826 PropertyState_DIRECT_VALUE ) ) );
1828 // Commit changes.
1829 xBatch->commitChanges();
1831 if ( m_aPropertyChangeListeners.hasContainedTypes(aCGuard) )
1833 PropertyChangeEvent aEvt;
1834 aEvt.Source = static_cast<OWeakObject*>(this);
1835 aEvt.PropertyName = rNewValue.Name;
1836 aEvt.PropertyHandle = rNewValue.Handle;
1837 aEvt.Further = false;
1838 aEvt.OldValue = aOldValue;
1839 aEvt.NewValue = rNewValue.Value;
1841 aEvents.push_back( aEvt );
1844 catch (const IllegalArgumentException&)
1846 // replaceByName
1848 catch (const NoSuchElementException&)
1850 // getByHierarchicalName, replaceByName
1852 catch (const WrappedTargetException&)
1854 // replaceByName, commitChanges
1860 if ( m_aPropertyChangeListeners.hasContainedTypes(aCGuard) )
1862 // Notify property changes.
1863 for (auto const& event : aEvents)
1865 notifyPropertyChangeEvent( aCGuard, event );
1869 return;
1872 OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" );
1876 // Non-interface methods
1879 void PersistentPropertySet::notifyPropertyChangeEvent(
1880 std::unique_lock<std::mutex>& rGuard,
1881 const PropertyChangeEvent& rEvent ) const
1883 // Get "normal" listeners for the property.
1884 OInterfaceContainerHelper4<XPropertyChangeListener>* pContainer =
1885 m_aPropertyChangeListeners.getContainer( rGuard, rEvent.PropertyName );
1886 if ( pContainer && pContainer->getLength(rGuard) )
1888 pContainer->notifyEach( rGuard, &XPropertyChangeListener::propertyChange, rEvent );
1891 // Get "normal" listeners for all properties.
1892 OInterfaceContainerHelper4<XPropertyChangeListener>* pNoNameContainer =
1893 m_aPropertyChangeListeners.getContainer( rGuard, OUString() );
1894 if ( pNoNameContainer && pNoNameContainer->getLength(rGuard) )
1896 pNoNameContainer->notifyEach( rGuard, &XPropertyChangeListener::propertyChange, rEvent );
1901 void PersistentPropertySet::notifyPropertySetInfoChange(
1902 std::unique_lock<std::mutex>& rGuard,
1903 const PropertySetInfoChangeEvent& evt ) const
1905 // Notify event listeners.
1906 m_aPropSetChangeListeners.notifyEach( rGuard, &XPropertySetInfoChangeListener::propertySetInfoChange, evt );
1910 OUString PersistentPropertySet::getFullKey()
1912 std::unique_lock aGuard(m_aMutex);
1913 return getFullKeyImpl(aGuard);
1916 const OUString& PersistentPropertySet::getFullKeyImpl(std::unique_lock<std::mutex>& )
1918 if ( m_aFullKey.isEmpty() )
1920 m_aFullKey = makeHierarchalNameSegment( m_aKey );
1921 m_aFullKey += "/Values";
1924 return m_aFullKey;
1928 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
1930 return *m_pCreator;
1934 // PropertySetInfo_Impl Implementation.
1937 PropertySetInfo_Impl::PropertySetInfo_Impl(
1938 PersistentPropertySet* pOwner )
1939 : m_pOwner( pOwner )
1944 // XPropertySetInfo methods.
1947 // virtual
1948 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
1950 if ( !m_xProps )
1952 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1953 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
1954 UNO_QUERY );
1955 if ( xRootHierNameAccess.is() )
1959 Reference< XNameAccess > xNameAccess;
1960 xRootHierNameAccess->getByHierarchicalName(
1961 m_pOwner->getFullKey() )
1962 >>= xNameAccess;
1963 if ( xNameAccess.is() )
1965 // Obtain property names.
1967 Sequence< OUString > aElems
1968 = xNameAccess->getElementNames();
1970 sal_uInt32 nCount = aElems.getLength();
1971 Sequence< Property > aPropSeq( nCount );
1973 if ( nCount )
1975 Reference< XHierarchicalNameAccess > xHierNameAccess(
1976 xNameAccess, UNO_QUERY );
1978 OSL_ENSURE( xHierNameAccess.is(),
1979 "PropertySetInfo_Impl::getProperties - "
1980 "No hierarchical name access!" );
1982 if ( xHierNameAccess.is() )
1984 static const OUStringLiteral aHandleName(u"/Handle");
1985 static const OUStringLiteral aValueName(u"/Value");
1986 static const OUStringLiteral aAttrName(u"/Attributes");
1988 Property* pProps = aPropSeq.getArray();
1990 for ( sal_uInt32 n = 0; n < nCount; ++n )
1992 Property& rProp = pProps[ n ];
1993 OUString rName = aElems[ n ];
1994 OUString aXMLName
1995 = makeHierarchalNameSegment( rName );
1997 // Set property name.
1999 rProp.Name = rName;
2003 // Obtain and set property handle
2004 OUString aHierName = aXMLName + aHandleName;
2005 Any aKeyValue
2006 = xHierNameAccess->getByHierarchicalName(
2007 aHierName );
2009 if ( !( aKeyValue >>= rProp.Handle ) )
2010 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2011 "Error getting property handle!" );
2013 catch (const NoSuchElementException&)
2015 // getByHierarchicalName
2017 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2018 "NoSuchElementException!" );
2023 // Obtain and set property type
2024 OUString aHierName = aXMLName + aValueName;
2025 Any aKeyValue
2026 = xHierNameAccess->getByHierarchicalName(
2027 aHierName );
2029 // Note: The type may be void if addProperty
2030 // was called with a default value
2031 // of type void.
2033 rProp.Type = aKeyValue.getValueType();
2035 catch (const NoSuchElementException&)
2037 // getByHierarchicalName
2039 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2040 "NoSuchElementException!" );
2045 // Obtain and set property attributes
2046 OUString aHierName = aXMLName + aAttrName;
2047 Any aKeyValue
2048 = xHierNameAccess->getByHierarchicalName(
2049 aHierName );
2051 sal_Int32 nAttribs = 0;
2052 if ( aKeyValue >>= nAttribs )
2053 rProp.Attributes
2054 = sal_Int16( nAttribs );
2055 else
2056 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2057 "Error getting property attributes!" );
2059 catch (const NoSuchElementException&)
2061 // getByHierarchicalName
2063 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2064 "NoSuchElementException!" );
2070 // Success.
2071 m_xProps = std::move(aPropSeq);
2072 return *m_xProps;
2075 catch (const NoSuchElementException&)
2077 // getByHierarchicalName
2081 OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" );
2082 m_xProps.emplace();
2085 return *m_xProps;
2089 // virtual
2090 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2091 const OUString& aName )
2093 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2094 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2095 UNO_QUERY );
2096 if ( xRootHierNameAccess.is() )
2098 OUString aFullPropName( m_pOwner->getFullKey() + "/" +
2099 makeHierarchalNameSegment( aName ) );
2101 // Does property exist?
2102 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2103 throw UnknownPropertyException(aFullPropName);
2107 Property aProp;
2109 // Obtain handle.
2110 OUString aKey = aFullPropName + "/Handle";
2112 if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2113 >>= aProp.Handle ) )
2115 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2116 "No handle!" );
2117 return Property();
2120 // Obtain Value and extract type.
2121 aKey = aFullPropName + "/Value";
2123 Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2124 if ( !aValue.hasValue() )
2126 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2127 "No Value!" );
2128 return Property();
2131 aProp.Type = aValue.getValueType();
2133 // Obtain Attributes.
2134 aKey = aFullPropName + "/Attributes";
2136 sal_Int32 nAttribs = 0;
2137 if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2138 >>= nAttribs )
2139 aProp.Attributes = sal_Int16( nAttribs );
2140 else
2142 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2143 "No attributes!" );
2144 return Property();
2147 // set name.
2148 aProp.Name = aName;
2150 // Success.
2151 return aProp;
2153 catch (const NoSuchElementException&)
2155 // getByHierarchicalName
2157 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2158 "caught NoSuchElementException!" );
2163 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" );
2164 return Property();
2168 // virtual
2169 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2170 const OUString& Name )
2172 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2173 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2174 UNO_QUERY );
2175 if ( xRootHierNameAccess.is() )
2177 OUString aFullPropName( m_pOwner->getFullKey() + "/" +
2178 makeHierarchalNameSegment( Name ) );
2180 return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2183 return false;
2186 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */