Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / ucb / source / core / ucbstore.cxx
blobea5e23d38f9b20bdad6b5566129ee428fc749283
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 <memory>
28 #include <unordered_map>
29 #include <sal/log.hxx>
30 #include <osl/diagnose.h>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/ref.hxx>
33 #include <cppuhelper/interfacecontainer.hxx>
34 #include <comphelper/interfacecontainer2.hxx>
35 #include <comphelper/propertysequence.hxx>
36 #include <com/sun/star/beans/IllegalTypeException.hpp>
37 #include <com/sun/star/beans/NotRemoveableException.hpp>
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #include <com/sun/star/beans/PropertyExistException.hpp>
40 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
41 #include <com/sun/star/configuration/theDefaultProvider.hpp>
42 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
43 #include <com/sun/star/container/XNameContainer.hpp>
44 #include <com/sun/star/container/XNameReplace.hpp>
45 #include <com/sun/star/util/XChangesBatch.hpp>
46 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
47 #include <cppuhelper/implbase.hxx>
48 #include <ucbhelper/getcomponentcontext.hxx>
49 #include <ucbhelper/macros.hxx>
50 #include <tools/diagnose_ex.h>
51 #include "ucbstore.hxx"
53 using namespace com::sun::star::beans;
54 using namespace com::sun::star::configuration;
55 using namespace com::sun::star::container;
56 using namespace com::sun::star::lang;
57 using namespace com::sun::star::ucb;
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star::util;
60 using namespace comphelper;
61 using namespace cppu;
64 static OUString makeHierarchalNameSegment( const OUString & rIn )
66 OUStringBuffer aBuffer;
67 aBuffer.append( "['" );
69 sal_Int32 nCount = rIn.getLength();
70 for ( sal_Int32 n = 0; n < nCount; ++n )
72 const sal_Unicode c = rIn[ n ];
73 switch ( c )
75 case '&':
76 aBuffer.append( "&amp;" );
77 break;
79 case '"':
80 aBuffer.append( "&quot;" );
81 break;
83 case '\'':
84 aBuffer.append( "&apos;" );
85 break;
87 case '<':
88 aBuffer.append( "&lt;" );
89 break;
91 case '>':
92 aBuffer.append( "&gt;" );
93 break;
95 default:
96 aBuffer.append( c );
97 break;
101 aBuffer.append( "']" );
102 return aBuffer.makeStringAndClear();
105 #define STORE_CONTENTPROPERTIES_KEY "/org.openoffice.ucb.Store/ContentProperties"
107 // describe path of cfg entry
108 #define CFGPROPERTY_NODEPATH "nodepath"
110 // PropertySetMap_Impl.
111 typedef std::unordered_map< OUString, PersistentPropertySet*> PropertySetMap_Impl;
113 // class PropertySetInfo_Impl
114 class PropertySetInfo_Impl : public cppu::WeakImplHelper < XPropertySetInfo >
116 std::unique_ptr<Sequence< Property >>
117 m_pProps;
118 PersistentPropertySet* m_pOwner;
120 public:
121 explicit PropertySetInfo_Impl(PersistentPropertySet* pOwner);
123 // XPropertySetInfo
124 virtual Sequence< Property > SAL_CALL getProperties() override;
125 virtual Property SAL_CALL getPropertyByName( const OUString& aName ) override;
126 virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override;
128 // Non-interface methods.
129 void reset() { m_pProps.reset(); }
133 // UcbStore_Impl.
136 struct UcbStore_Impl
138 osl::Mutex m_aMutex;
139 Sequence< Any > m_aInitArgs;
140 Reference< XPropertySetRegistry > m_xTheRegistry;
144 // UcbStore Implementation.
147 UcbStore::UcbStore( const Reference< XComponentContext >& xContext )
148 : m_xContext( xContext ),
149 m_pImpl( new UcbStore_Impl )
154 // virtual
155 UcbStore::~UcbStore()
159 XSERVICEINFO_COMMOM_IMPL( UcbStore,
160 "com.sun.star.comp.ucb.UcbStore" )
161 /// @throws css::uno::Exception
162 static css::uno::Reference< css::uno::XInterface >
163 UcbStore_CreateInstance( const css::uno::Reference< css::lang::XMultiServiceFactory> & rSMgr )
165 return static_cast<css::lang::XServiceInfo*>(
166 new UcbStore(ucbhelper::getComponentContext(rSMgr)));
169 css::uno::Sequence< OUString >
170 UcbStore::getSupportedServiceNames_Static()
172 css::uno::Sequence< OUString > aSNS { STORE_SERVICE_NAME };
173 return aSNS;
176 // Service factory implementation.
179 ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbStore );
182 // XPropertySetRegistryFactory methods.
185 // virtual
186 Reference< XPropertySetRegistry > SAL_CALL
187 UcbStore::createPropertySetRegistry( const OUString& )
189 // The URL parameter is ignored by this interface implementation. It always
190 // uses the configuration server as storage medium.
192 if ( !m_pImpl->m_xTheRegistry.is() )
194 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
195 if ( !m_pImpl->m_xTheRegistry.is() )
196 m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xContext, m_pImpl->m_aInitArgs );
199 return m_pImpl->m_xTheRegistry;
203 // XInitialization methods.
206 // virtual
207 void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments )
209 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
210 m_pImpl->m_aInitArgs = aArguments;
215 // PropertySetRegistry_Impl.
218 struct PropertySetRegistry_Impl
220 const Sequence< Any > m_aInitArgs;
221 PropertySetMap_Impl m_aPropSets;
222 Reference< XMultiServiceFactory > m_xConfigProvider;
223 Reference< XInterface > m_xRootReadAccess;
224 Reference< XInterface > m_xRootWriteAccess;
225 osl::Mutex m_aMutex;
226 bool m_bTriedToGetRootReadAccess;
227 bool m_bTriedToGetRootWriteAccess;
229 explicit PropertySetRegistry_Impl(const Sequence<Any> &rInitArgs)
230 : m_aInitArgs(rInitArgs)
231 , m_bTriedToGetRootReadAccess(false)
232 , m_bTriedToGetRootWriteAccess(false)
237 // PropertySetRegistry Implementation.
240 PropertySetRegistry::PropertySetRegistry(
241 const Reference< XComponentContext >& xContext,
242 const Sequence< Any > &rInitArgs )
243 : m_xContext( xContext ),
244 m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) )
249 // virtual
250 PropertySetRegistry::~PropertySetRegistry()
255 // XServiceInfo methods.
258 OUString SAL_CALL PropertySetRegistry::getImplementationName()
260 return "com.sun.star.comp.ucb.PropertySetRegistry";
263 sal_Bool SAL_CALL PropertySetRegistry::supportsService( const OUString& ServiceName )
265 return cppu::supportsService( this, ServiceName );
268 css::uno::Sequence< OUString > SAL_CALL PropertySetRegistry::getSupportedServiceNames()
270 return { PROPSET_REG_SERVICE_NAME };
274 // XPropertySetRegistry methods.
277 // virtual
278 Reference< XPersistentPropertySet > SAL_CALL
279 PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create )
281 if ( !key.isEmpty() )
283 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
285 PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
287 PropertySetMap_Impl::const_iterator it = rSets.find( key );
288 if ( it != rSets.end() )
290 // Already instantiated.
291 return Reference< XPersistentPropertySet >( (*it).second );
293 else
295 // Create new instance.
296 Reference< XNameAccess > xRootNameAccess(
297 getRootConfigReadAccess(), UNO_QUERY );
298 if ( xRootNameAccess.is() )
300 // Propertyset in registry?
301 if ( xRootNameAccess->hasByName( key ) )
303 // Yep!
304 return Reference< XPersistentPropertySet >(
305 new PersistentPropertySet(
306 *this, key ) );
308 else if ( create )
310 // No. Create entry for propertyset.
312 Reference< XSingleServiceFactory > xFac(
313 getConfigWriteAccess( OUString() ), UNO_QUERY );
314 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
315 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
317 OSL_ENSURE( xFac.is(),
318 "PropertySetRegistry::openPropertySet - "
319 "No factory!" );
321 OSL_ENSURE( xBatch.is(),
322 "PropertySetRegistry::openPropertySet - "
323 "No batch!" );
325 OSL_ENSURE( xContainer.is(),
326 "PropertySetRegistry::openPropertySet - "
327 "No container!" );
329 if ( xFac.is() && xBatch.is() && xContainer.is() )
333 // Create new "Properties" config item.
334 Reference< XNameReplace > xNameReplace(
335 xFac->createInstance(), UNO_QUERY );
337 if ( xNameReplace.is() )
339 // Fill new item...
341 // Insert new item.
342 xContainer->insertByName(
343 key, makeAny( xNameReplace ) );
344 // Commit changes.
345 xBatch->commitChanges();
347 return Reference< XPersistentPropertySet >(
348 new PersistentPropertySet(
349 *this, key ) );
352 catch (const IllegalArgumentException&)
354 // insertByName
356 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
357 "caught IllegalArgumentException!" );
359 catch (const ElementExistException&)
361 // insertByName
363 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
364 "caught ElementExistException!" );
366 catch (const WrappedTargetException&)
368 // insertByName, commitChanges
370 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
371 "caught WrappedTargetException!" );
373 catch (const RuntimeException&)
375 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
376 "caught RuntimeException!" );
378 catch (const Exception&)
380 // createInstance
382 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
383 "caught Exception!" );
387 else
389 // No entry. Fail, but no error.
390 return Reference< XPersistentPropertySet >();
394 SAL_WARN( "ucb", "no root access" );
398 return Reference< XPersistentPropertySet >();
402 // virtual
403 void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key )
405 if ( key.isEmpty() )
406 return;
408 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
410 Reference< XNameAccess > xRootNameAccess(
411 getRootConfigReadAccess(), UNO_QUERY );
412 if ( xRootNameAccess.is() )
414 // Propertyset in registry?
415 if ( !xRootNameAccess->hasByName( key ) )
416 return;
417 Reference< XChangesBatch > xBatch(
418 getConfigWriteAccess( OUString() ), UNO_QUERY );
419 Reference< XNameContainer > xContainer( xBatch, UNO_QUERY );
421 if ( xBatch.is() && xContainer.is() )
425 // Remove item.
426 xContainer->removeByName( key );
427 // Commit changes.
428 xBatch->commitChanges();
430 // Success.
431 return;
433 catch (const NoSuchElementException&)
435 // removeByName
437 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
438 "caught NoSuchElementException!" );
439 return;
441 catch (const WrappedTargetException&)
443 // commitChanges
445 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
446 "caught WrappedTargetException!" );
447 return;
451 return;
454 SAL_WARN( "ucb", "no root access" );
458 // XElementAccess methods.
461 // virtual
462 css::uno::Type SAL_CALL PropertySetRegistry::getElementType()
464 return cppu::UnoType<XPersistentPropertySet>::get();
468 // virtual
469 sal_Bool SAL_CALL PropertySetRegistry::hasElements()
471 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
473 Reference< XElementAccess > xElemAccess(
474 getRootConfigReadAccess(), UNO_QUERY );
475 if ( xElemAccess.is() )
476 return xElemAccess->hasElements();
478 return false;
482 // XNameAccess methods.
485 // virtual
486 Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName )
488 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
490 Reference< XNameAccess > xNameAccess(
491 getRootConfigReadAccess(), UNO_QUERY );
492 if ( xNameAccess.is() )
497 return xNameAccess->getByName( aName );
499 catch (const NoSuchElementException&)
501 // getByName
503 catch (const WrappedTargetException&)
505 // getByName
509 return Any();
513 // virtual
514 Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames()
516 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
518 Reference< XNameAccess > xNameAccess(
519 getRootConfigReadAccess(), UNO_QUERY );
520 if ( xNameAccess.is() )
522 return xNameAccess->getElementNames();
524 return Sequence< OUString >( 0 );
528 // virtual
529 sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName )
531 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
533 Reference< XNameAccess > xNameAccess(
534 getRootConfigReadAccess(), UNO_QUERY );
535 if ( xNameAccess.is() )
537 return xNameAccess->hasByName( aName );
540 return false;
544 void PropertySetRegistry::add( PersistentPropertySet* pSet )
546 OUString key( pSet->getKey() );
548 if ( !key.isEmpty() )
550 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
551 m_pImpl->m_aPropSets[ key ] = pSet;
556 void PropertySetRegistry::remove( PersistentPropertySet* pSet )
558 OUString key( pSet->getKey() );
560 if ( !key.isEmpty() )
562 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
564 PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
566 PropertySetMap_Impl::iterator it = rSets.find( key );
567 if ( it != rSets.end() )
569 // Found.
570 rSets.erase( it );
576 void PropertySetRegistry::renamePropertySet( const OUString& rOldKey,
577 const OUString& rNewKey )
579 if ( rOldKey == rNewKey )
580 return;
582 Reference< XNameAccess > xRootNameAccess(
583 getConfigWriteAccess( OUString() ), UNO_QUERY );
584 if ( xRootNameAccess.is() )
586 // Old key present?
587 if ( xRootNameAccess->hasByName( rOldKey ) )
589 // New key not present?
590 if ( xRootNameAccess->hasByName( rNewKey ) )
592 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
593 "New key exists!" );
594 return;
596 Reference< XSingleServiceFactory > xFac(
597 xRootNameAccess, UNO_QUERY );
598 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
599 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
601 OSL_ENSURE( xFac.is(),
602 "PropertySetRegistry::renamePropertySet - "
603 "No factory!" );
605 OSL_ENSURE( xBatch.is(),
606 "PropertySetRegistry::renamePropertySet - "
607 "No batch!" );
609 OSL_ENSURE( xContainer.is(),
610 "PropertySetRegistry::renamePropertySet - "
611 "No container!" );
613 if ( xFac.is() && xBatch.is() && xContainer.is() )
616 // Create new "Properties" config item.
621 Reference< XNameReplace > xNameReplace(
622 xFac->createInstance(), UNO_QUERY );
624 if ( xNameReplace.is() )
626 // Insert new item.
627 xContainer->insertByName(
628 rNewKey, makeAny( xNameReplace ) );
629 // Commit changes.
630 xBatch->commitChanges();
633 catch (const IllegalArgumentException&)
635 // insertByName
637 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
638 "caught IllegalArgumentException!" );
639 return;
641 catch (const ElementExistException&)
643 // insertByName
645 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
646 "caught ElementExistException!" );
647 return;
649 catch (const WrappedTargetException&)
651 // insertByName, commitChanges
653 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
654 "caught WrappedTargetException!" );
655 return;
657 catch (const RuntimeException&)
659 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
660 "caught RuntimeException!" );
661 return;
663 catch (const Exception&)
665 // createInstance
667 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
668 "caught Exception!" );
669 return;
673 // Copy data...
676 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
677 xRootNameAccess, UNO_QUERY );
678 if ( !xRootHierNameAccess.is() )
680 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
681 "No hierarchical name access!" );
682 return;
687 OUString aOldValuesKey
688 = makeHierarchalNameSegment( rOldKey ) + "/Values";
690 Reference< XNameAccess > xOldNameAccess;
691 xRootHierNameAccess->getByHierarchicalName(
692 aOldValuesKey )
693 >>= xOldNameAccess;
694 if ( !xOldNameAccess.is() )
696 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
697 "No old name access!" );
698 return;
701 // Obtain property names.
702 const Sequence< OUString > aElems
703 = xOldNameAccess->getElementNames();
704 if ( aElems.hasElements() )
706 OUString aNewValuesKey
707 = makeHierarchalNameSegment( rNewKey ) + "/Values";
709 Reference< XSingleServiceFactory > xNewFac;
710 xRootHierNameAccess->getByHierarchicalName(
711 aNewValuesKey )
712 >>= xNewFac;
713 if ( !xNewFac.is() )
715 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
716 "No new factory!" );
717 return;
720 Reference< XNameContainer > xNewContainer(
721 xNewFac, UNO_QUERY );
722 if ( !xNewContainer.is() )
724 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
725 "No new container!" );
726 return;
729 aOldValuesKey += "/";
731 OUString const aHandleKey("/Handle");
732 OUString const aValueKey("/Value");
733 OUString const aStateKey("/State");
734 OUString const aAttrKey("/Attributes");
736 for ( const OUString& rPropName : aElems )
738 // Create new item.
739 Reference< XNameReplace > xNewPropNameReplace(
740 xNewFac->createInstance(), UNO_QUERY );
742 if ( !xNewPropNameReplace.is() )
744 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
745 "No new prop name replace!" );
746 return;
749 // Fill new item...
751 // Set Values
752 OUString aKey = aOldValuesKey;
753 aKey += makeHierarchalNameSegment( rPropName );
755 // ... handle
756 OUString aNewKey1 = aKey + aHandleKey;
757 Any aAny =
758 xRootHierNameAccess->getByHierarchicalName(
759 aNewKey1 );
760 xNewPropNameReplace->replaceByName( "Handle", aAny );
762 // ... value
763 aNewKey1 = aKey + aValueKey;
764 aAny =
765 xRootHierNameAccess->getByHierarchicalName(
766 aNewKey1 );
767 xNewPropNameReplace->replaceByName( "Value", aAny );
769 // ... state
770 aNewKey1 = aKey + aStateKey;
771 aAny =
772 xRootHierNameAccess->getByHierarchicalName(
773 aNewKey1 );
774 xNewPropNameReplace->replaceByName( "State", aAny );
776 // ... attributes
777 aNewKey1 = aKey + aAttrKey;
778 aAny =
779 xRootHierNameAccess->getByHierarchicalName(
780 aNewKey1 );
781 xNewPropNameReplace->replaceByName( "Attributes", aAny );
783 // Insert new item.
784 xNewContainer->insertByName(
785 rPropName, makeAny( xNewPropNameReplace ) );
787 // Commit changes.
788 xBatch->commitChanges();
792 catch (const IllegalArgumentException&)
794 // insertByName, replaceByName
796 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
797 "caught IllegalArgumentException!" );
798 return;
800 catch (const ElementExistException&)
802 // insertByName
804 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
805 "caught ElementExistException!" );
806 return;
808 catch (const WrappedTargetException&)
810 // insertByName, replaceByName, commitChanges
812 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
813 "caught WrappedTargetException!" );
814 return;
816 catch (const NoSuchElementException&)
818 // getByHierarchicalName, replaceByName
820 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
821 "caught NoSuchElementException!" );
822 return;
824 catch (const RuntimeException&)
826 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
827 "caught RuntimeException!" );
828 return;
830 catch (const Exception&)
832 // createInstance
834 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
835 "caught Exception!" );
836 return;
840 // Remove old entry...
845 // Remove item.
846 xContainer->removeByName( rOldKey );
847 // Commit changes.
848 xBatch->commitChanges();
850 // Success.
851 return;
853 catch (const NoSuchElementException&)
855 // removeByName
857 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
858 "caught NoSuchElementException!" );
859 return;
861 catch (const WrappedTargetException&)
863 // commitChanges
865 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
866 "caught WrappedTargetException!" );
867 return;
873 OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" );
877 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider()
879 if ( !m_pImpl->m_xConfigProvider.is() )
881 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
882 if ( !m_pImpl->m_xConfigProvider.is() )
884 const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs;
886 if ( rInitArgs.hasElements() )
888 // Extract config provider from service init args.
889 rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider;
891 OSL_ENSURE( m_pImpl->m_xConfigProvider.is(),
892 "PropertySetRegistry::getConfigProvider - "
893 "No config provider!" );
895 else
899 m_pImpl->m_xConfigProvider = theDefaultProvider::get( m_xContext );
901 catch (const Exception&)
903 TOOLS_WARN_EXCEPTION( "ucb", "");
909 return m_pImpl->m_xConfigProvider;
913 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
917 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
919 if ( !m_pImpl->m_xRootReadAccess.is() )
921 if ( m_pImpl->m_bTriedToGetRootReadAccess )
923 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - "
924 "Unable to read any config data! -> #82494#" );
925 return Reference< XInterface >();
928 getConfigProvider();
930 if ( m_pImpl->m_xConfigProvider.is() )
932 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
934 {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
935 }));
937 m_pImpl->m_bTriedToGetRootReadAccess = true;
939 m_pImpl->m_xRootReadAccess =
940 m_pImpl->m_xConfigProvider->createInstanceWithArguments(
941 "com.sun.star.configuration.ConfigurationAccess",
942 aArguments );
944 if ( m_pImpl->m_xRootReadAccess.is() )
945 return m_pImpl->m_xRootReadAccess;
948 else
949 return m_pImpl->m_xRootReadAccess;
951 catch (const RuntimeException&)
953 throw;
955 catch (const Exception&)
957 // createInstance, createInstanceWithArguments
959 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - caught Exception!" );
960 return Reference< XInterface >();
963 SAL_WARN( "ucb", "Error!" );
964 return Reference< XInterface >();
968 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
969 const OUString& rPath )
973 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
975 if ( !m_pImpl->m_xRootWriteAccess.is() )
977 if ( m_pImpl->m_bTriedToGetRootWriteAccess )
979 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
980 "Unable to write any config data! -> #82494#" );
981 return Reference< XInterface >();
984 getConfigProvider();
986 if ( m_pImpl->m_xConfigProvider.is() )
988 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
990 {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
991 }));
993 m_pImpl->m_bTriedToGetRootWriteAccess = true;
995 m_pImpl->m_xRootWriteAccess =
996 m_pImpl->m_xConfigProvider->createInstanceWithArguments(
997 "com.sun.star.configuration.ConfigurationUpdateAccess",
998 aArguments );
1000 OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(),
1001 "PropertySetRegistry::getConfigWriteAccess - "
1002 "No config update access!" );
1006 if ( m_pImpl->m_xRootWriteAccess.is() )
1008 if ( !rPath.isEmpty() )
1010 Reference< XHierarchicalNameAccess > xNA(
1011 m_pImpl->m_xRootWriteAccess, UNO_QUERY );
1012 if ( xNA.is() )
1014 Reference< XInterface > xInterface;
1015 xNA->getByHierarchicalName( rPath ) >>= xInterface;
1017 if ( xInterface.is() )
1018 return xInterface;
1021 else
1022 return m_pImpl->m_xRootWriteAccess;
1025 catch (const RuntimeException&)
1027 throw;
1029 catch (const NoSuchElementException&)
1031 // getByHierarchicalName
1033 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1034 "caught NoSuchElementException!" );
1035 return Reference< XInterface >();
1037 catch (const Exception&)
1039 // createInstance, createInstanceWithArguments
1041 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1042 "caught Exception!" );
1043 return Reference< XInterface >();
1046 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" );
1047 return Reference< XInterface >();
1050 typedef OMultiTypeInterfaceContainerHelperVar<OUString> PropertyListeners_Impl;
1052 struct PersistentPropertySet_Impl
1054 rtl::Reference<PropertySetRegistry> m_pCreator;
1055 rtl::Reference<PropertySetInfo_Impl> m_pInfo;
1056 OUString const m_aKey;
1057 OUString m_aFullKey;
1058 osl::Mutex m_aMutex;
1059 std::unique_ptr<OInterfaceContainerHelper2> m_pDisposeEventListeners;
1060 std::unique_ptr<OInterfaceContainerHelper2> m_pPropSetChangeListeners;
1061 std::unique_ptr<PropertyListeners_Impl> m_pPropertyChangeListeners;
1063 PersistentPropertySet_Impl( PropertySetRegistry& rCreator,
1064 const OUString& rKey )
1065 : m_pCreator( &rCreator ), m_aKey( rKey )
1071 // PersistentPropertySet Implementation.
1074 PersistentPropertySet::PersistentPropertySet(
1075 PropertySetRegistry& rCreator,
1076 const OUString& rKey )
1077 : m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) )
1079 // register at creator.
1080 rCreator.add( this );
1084 // virtual
1085 PersistentPropertySet::~PersistentPropertySet()
1087 // deregister at creator.
1088 m_pImpl->m_pCreator->remove( this );
1091 // XServiceInfo methods.
1093 OUString SAL_CALL PersistentPropertySet::getImplementationName()
1095 return "com.sun.star.comp.ucb.PersistentPropertySet";
1098 sal_Bool SAL_CALL PersistentPropertySet::supportsService( const OUString& ServiceName )
1100 return cppu::supportsService( this, ServiceName );
1103 css::uno::Sequence< OUString > SAL_CALL
1104 PersistentPropertySet::getSupportedServiceNames()
1106 return { PERS_PROPSET_SERVICE_NAME };
1110 // XComponent methods.
1113 // virtual
1114 void SAL_CALL PersistentPropertySet::dispose()
1116 if ( m_pImpl->m_pDisposeEventListeners &&
1117 m_pImpl->m_pDisposeEventListeners->getLength() )
1119 EventObject aEvt;
1120 aEvt.Source = static_cast< XComponent * >( this );
1121 m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
1124 if ( m_pImpl->m_pPropSetChangeListeners &&
1125 m_pImpl->m_pPropSetChangeListeners->getLength() )
1127 EventObject aEvt;
1128 aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this );
1129 m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
1132 if ( m_pImpl->m_pPropertyChangeListeners )
1134 EventObject aEvt;
1135 aEvt.Source = static_cast< XPropertySet * >( this );
1136 m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
1141 // virtual
1142 void SAL_CALL PersistentPropertySet::addEventListener(
1143 const Reference< XEventListener >& Listener )
1145 if ( !m_pImpl->m_pDisposeEventListeners )
1146 m_pImpl->m_pDisposeEventListeners.reset(
1147 new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) );
1149 m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
1153 // virtual
1154 void SAL_CALL PersistentPropertySet::removeEventListener(
1155 const Reference< XEventListener >& Listener )
1157 if ( m_pImpl->m_pDisposeEventListeners )
1158 m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
1160 // Note: Don't want to delete empty container here -> performance.
1164 // XPropertySet methods.
1167 // virtual
1168 Reference< XPropertySetInfo > SAL_CALL PersistentPropertySet::getPropertySetInfo()
1170 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1172 if ( !m_pImpl->m_pInfo.is() )
1174 m_pImpl->m_pInfo = new PropertySetInfo_Impl( this );
1176 return Reference< XPropertySetInfo >( m_pImpl->m_pInfo.get() );
1180 // virtual
1181 void SAL_CALL PersistentPropertySet::setPropertyValue( const OUString& aPropertyName,
1182 const Any& aValue )
1184 osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1186 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1187 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1188 if ( xRootHierNameAccess.is() )
1190 OUString aFullPropName( getFullKey() + "/" );
1191 aFullPropName += makeHierarchalNameSegment( aPropertyName );
1193 // Does property exist?
1194 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1196 Reference< XNameReplace > xNameReplace(
1197 m_pImpl->m_pCreator->getConfigWriteAccess(
1198 aFullPropName ), UNO_QUERY );
1199 Reference< XChangesBatch > xBatch(
1200 m_pImpl->m_pCreator->getConfigWriteAccess(
1201 OUString() ), UNO_QUERY );
1203 if ( xNameReplace.is() && xBatch.is() )
1207 // Obtain old value
1208 OUString aValueName = aFullPropName + "/Value";
1209 Any aOldValue
1210 = xRootHierNameAccess->getByHierarchicalName(
1211 aValueName );
1212 // Check value type.
1213 if ( aOldValue.getValueType() != aValue.getValueType() )
1215 aCGuard.clear();
1216 throw IllegalArgumentException();
1219 // Write value
1220 xNameReplace->replaceByName( "Value", aValue );
1222 // Write state ( Now it is a directly set value )
1223 xNameReplace->replaceByName(
1224 "State",
1225 makeAny(
1226 sal_Int32(
1227 PropertyState_DIRECT_VALUE ) ) );
1229 // Commit changes.
1230 xBatch->commitChanges();
1232 PropertyChangeEvent aEvt;
1233 if ( m_pImpl->m_pPropertyChangeListeners )
1235 // Obtain handle
1236 aValueName = aFullPropName + "/Handle";
1237 sal_Int32 nHandle = -1;
1238 xRootHierNameAccess->getByHierarchicalName( aValueName )
1239 >>= nHandle;
1241 aEvt.Source = static_cast<OWeakObject*>(this);
1242 aEvt.PropertyName = aPropertyName;
1243 aEvt.PropertyHandle = nHandle;
1244 aEvt.Further = false;
1245 aEvt.OldValue = aOldValue;
1246 aEvt.NewValue = aValue;
1248 // Callback follows!
1249 aCGuard.clear();
1251 notifyPropertyChangeEvent( aEvt );
1253 return;
1255 catch (const IllegalArgumentException&)
1257 // replaceByName
1259 catch (const NoSuchElementException&)
1261 // getByHierarchicalName, replaceByName
1263 catch (const WrappedTargetException&)
1265 // replaceByName, commitChanges
1271 throw UnknownPropertyException(aPropertyName);
1275 // virtual
1276 Any SAL_CALL PersistentPropertySet::getPropertyValue(
1277 const OUString& PropertyName )
1279 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1281 Reference< XHierarchicalNameAccess > xNameAccess(
1282 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1283 if ( xNameAccess.is() )
1285 OUString aFullPropName( getFullKey() + "/" );
1286 aFullPropName += makeHierarchalNameSegment( PropertyName ) + "/Value";
1289 return xNameAccess->getByHierarchicalName( aFullPropName );
1291 catch (const NoSuchElementException&)
1293 throw UnknownPropertyException(aFullPropName);
1297 throw UnknownPropertyException(PropertyName);
1301 // virtual
1302 void SAL_CALL PersistentPropertySet::addPropertyChangeListener(
1303 const OUString& aPropertyName,
1304 const Reference< XPropertyChangeListener >& xListener )
1306 // load();
1308 if ( !m_pImpl->m_pPropertyChangeListeners )
1309 m_pImpl->m_pPropertyChangeListeners.reset(
1310 new PropertyListeners_Impl( m_pImpl->m_aMutex ) );
1312 m_pImpl->m_pPropertyChangeListeners->addInterface(
1313 aPropertyName, xListener );
1317 // virtual
1318 void SAL_CALL PersistentPropertySet::removePropertyChangeListener(
1319 const OUString& aPropertyName,
1320 const Reference< XPropertyChangeListener >& aListener )
1322 // load();
1324 if ( m_pImpl->m_pPropertyChangeListeners )
1325 m_pImpl->m_pPropertyChangeListeners->removeInterface(
1326 aPropertyName, aListener );
1328 // Note: Don't want to delete empty container here -> performance.
1332 // virtual
1333 void SAL_CALL PersistentPropertySet::addVetoableChangeListener(
1334 const OUString&,
1335 const Reference< XVetoableChangeListener >& )
1337 // load();
1338 // OSL_FAIL( // "PersistentPropertySet::addVetoableChangeListener - N.Y.I." );
1342 // virtual
1343 void SAL_CALL PersistentPropertySet::removeVetoableChangeListener(
1344 const OUString&,
1345 const Reference< XVetoableChangeListener >& )
1347 // load();
1348 // OSL_FAIL( // "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." );
1352 // XPersistentPropertySet methods.
1355 // virtual
1356 Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry()
1358 return Reference< XPropertySetRegistry >( m_pImpl->m_pCreator.get() );
1362 // virtual
1363 OUString SAL_CALL PersistentPropertySet::getKey()
1365 return m_pImpl->m_aKey;
1369 // XNamed methods.
1372 // virtual
1373 OUString SAL_CALL PersistentPropertySet::getName()
1375 // same as getKey()
1376 return m_pImpl->m_aKey;
1380 // virtual
1381 void SAL_CALL PersistentPropertySet::setName( const OUString& aName )
1383 if ( aName != m_pImpl->m_aKey )
1384 m_pImpl->m_pCreator->renamePropertySet( m_pImpl->m_aKey, aName );
1388 // XPropertyContainer methods.
1391 // virtual
1392 void SAL_CALL PersistentPropertySet::addProperty(
1393 const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue )
1395 if ( Name.isEmpty() )
1396 throw IllegalArgumentException();
1398 // @@@ What other types can't be written to config server?
1400 // Check type class ( Not all types can be written to storage )
1401 TypeClass eTypeClass = DefaultValue.getValueTypeClass();
1402 if ( eTypeClass == TypeClass_INTERFACE )
1403 throw IllegalTypeException();
1405 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1407 // Property already in set?
1409 OUString aFullValuesName;
1411 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1412 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1413 if ( xRootHierNameAccess.is() )
1415 aFullValuesName = getFullKey();
1416 OUString aFullPropName = aFullValuesName + "/";
1417 aFullPropName += makeHierarchalNameSegment( Name );
1419 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1421 // Already in set.
1422 throw PropertyExistException();
1426 // Property is always removable.
1427 Attributes |= PropertyAttribute::REMOVABLE;
1429 // Add property.
1431 Reference< XSingleServiceFactory > xFac(
1432 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1433 UNO_QUERY );
1434 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
1435 Reference< XChangesBatch > xBatch(
1436 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1437 UNO_QUERY );
1439 OSL_ENSURE( xFac.is(),
1440 "PersistentPropertySet::addProperty - No factory!" );
1442 OSL_ENSURE( xBatch.is(),
1443 "PersistentPropertySet::addProperty - No batch!" );
1445 OSL_ENSURE( xContainer.is(),
1446 "PersistentPropertySet::addProperty - No container!" );
1448 if ( xFac.is() && xBatch.is() && xContainer.is() )
1452 // Create new "PropertyValue" config item.
1453 Reference< XNameReplace > xNameReplace(
1454 xFac->createInstance(), UNO_QUERY );
1456 if ( xNameReplace.is() )
1458 // Fill new item...
1460 // Set handle
1461 xNameReplace->replaceByName(
1462 "Handle",
1463 makeAny( sal_Int32( -1 ) ) );
1465 // Set default value
1466 xNameReplace->replaceByName(
1467 "Value",
1468 DefaultValue );
1470 // Set state ( always "default" )
1471 xNameReplace->replaceByName(
1472 "State",
1473 makeAny(
1474 sal_Int32(
1475 PropertyState_DEFAULT_VALUE ) ) );
1477 // Set attributes
1478 xNameReplace->replaceByName(
1479 "Attributes",
1480 makeAny( sal_Int32( Attributes ) ) );
1482 // Insert new item.
1483 xContainer->insertByName( Name, makeAny( xNameReplace ) );
1485 // Commit changes.
1486 xBatch->commitChanges();
1488 // Property set info is invalid.
1489 if ( m_pImpl->m_pInfo.is() )
1490 m_pImpl->m_pInfo->reset();
1492 // Notify propertyset info change listeners.
1493 if ( m_pImpl->m_pPropSetChangeListeners &&
1494 m_pImpl->m_pPropSetChangeListeners->getLength() )
1496 PropertySetInfoChangeEvent evt(
1497 static_cast< OWeakObject * >( this ),
1498 Name,
1500 PropertySetInfoChange::PROPERTY_INSERTED );
1501 notifyPropertySetInfoChange( evt );
1504 // Success.
1505 return;
1508 catch (const IllegalArgumentException&)
1510 // insertByName
1512 OSL_FAIL( "PersistentPropertySet::addProperty - "
1513 "caught IllegalArgumentException!" );
1514 return;
1516 catch (const ElementExistException&)
1518 // insertByName
1520 OSL_FAIL( "PersistentPropertySet::addProperty - "
1521 "caught ElementExistException!" );
1522 return;
1524 catch (const WrappedTargetException&)
1526 // replaceByName, insertByName, commitChanges
1528 OSL_FAIL( "PersistentPropertySet::addProperty - "
1529 "caught WrappedTargetException!" );
1530 return;
1532 catch (const RuntimeException&)
1534 throw;
1536 catch (const Exception&)
1538 // createInstance
1540 OSL_FAIL( "PersistentPropertySet::addProperty - "
1541 "caught Exception!" );
1542 return;
1546 OSL_FAIL( "PersistentPropertySet::addProperty - Error!" );
1550 // virtual
1551 void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name )
1553 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1555 OUString aFullValuesName;
1556 OUString aFullPropName;
1558 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1559 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1560 if ( xRootHierNameAccess.is() )
1562 aFullValuesName = getFullKey();
1563 aFullPropName = aFullValuesName + "/";
1564 aFullPropName += makeHierarchalNameSegment( Name );
1566 // Property in set?
1567 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1568 throw UnknownPropertyException(aFullPropName);
1570 // Property removable?
1573 OUString aFullAttrName = aFullPropName + "/Attributes";
1575 sal_Int32 nAttribs = 0;
1576 if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1577 >>= nAttribs )
1579 if ( !( nAttribs & PropertyAttribute::REMOVABLE ) )
1581 // Not removable!
1582 throw NotRemoveableException();
1585 else
1587 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1588 "No attributes!" );
1589 return;
1592 catch (const NoSuchElementException&)
1594 // getByHierarchicalName
1596 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1597 "caught NoSuchElementException!" );
1600 // Remove property...
1602 Reference< XNameContainer > xContainer(
1603 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1604 UNO_QUERY );
1605 Reference< XChangesBatch > xBatch(
1606 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1607 UNO_QUERY );
1609 OSL_ENSURE( xBatch.is(),
1610 "PersistentPropertySet::removeProperty - No batch!" );
1612 OSL_ENSURE( xContainer.is(),
1613 "PersistentPropertySet::removeProperty - No container!" );
1615 if ( xBatch.is() && xContainer.is() )
1619 sal_Int32 nHandle = -1;
1621 if ( m_pImpl->m_pPropSetChangeListeners &&
1622 m_pImpl->m_pPropSetChangeListeners->getLength() )
1624 // Obtain property handle ( needed for propertysetinfo
1625 // change event )...
1629 OUString aFullHandleName = aFullPropName + "/Handle";
1631 if ( ! ( xRootHierNameAccess->getByHierarchicalName(
1632 aFullHandleName ) >>= nHandle ) )
1633 nHandle = -1;
1636 catch (const NoSuchElementException&)
1638 // getByHierarchicalName
1640 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1641 "caught NoSuchElementException!" );
1642 nHandle = -1;
1646 xContainer->removeByName( Name );
1647 xBatch->commitChanges();
1649 // Property set info is invalid.
1650 if ( m_pImpl->m_pInfo.is() )
1651 m_pImpl->m_pInfo->reset();
1653 // Notify propertyset info change listeners.
1654 if ( m_pImpl->m_pPropSetChangeListeners &&
1655 m_pImpl->m_pPropSetChangeListeners->getLength() )
1657 PropertySetInfoChangeEvent evt(
1658 static_cast< OWeakObject * >( this ),
1659 Name,
1660 nHandle,
1661 PropertySetInfoChange::PROPERTY_REMOVED );
1662 notifyPropertySetInfoChange( evt );
1665 // Success.
1666 return;
1668 catch (const NoSuchElementException&)
1670 // removeByName
1672 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1673 "caught NoSuchElementException!" );
1674 return;
1676 catch (const WrappedTargetException&)
1678 // commitChanges
1680 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1681 "caught WrappedTargetException!" );
1682 return;
1687 OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" );
1691 // XPropertySetInfoChangeNotifier methods.
1694 // virtual
1695 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
1696 const Reference< XPropertySetInfoChangeListener >& Listener )
1698 if ( !m_pImpl->m_pPropSetChangeListeners )
1699 m_pImpl->m_pPropSetChangeListeners.reset(
1700 new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) );
1702 m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
1706 // virtual
1707 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
1708 const Reference< XPropertySetInfoChangeListener >& Listener )
1710 if ( m_pImpl->m_pPropSetChangeListeners )
1711 m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
1715 // XPropertyAccess methods.
1718 // virtual
1719 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
1721 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1723 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1724 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1725 if ( xRootHierNameAccess.is() )
1729 Reference< XNameAccess > xNameAccess;
1730 xRootHierNameAccess->getByHierarchicalName(getFullKey())
1731 >>= xNameAccess;
1732 if ( xNameAccess.is() )
1734 // Obtain property names.
1736 Sequence< OUString > aElems = xNameAccess->getElementNames();
1738 sal_Int32 nCount = aElems.getLength();
1739 if ( nCount )
1741 Reference< XHierarchicalNameAccess > xHierNameAccess(
1742 xNameAccess, UNO_QUERY );
1744 OSL_ENSURE( xHierNameAccess.is(),
1745 "PersistentPropertySet::getPropertyValues - "
1746 "No hierarchical name access!" );
1748 if ( xHierNameAccess.is() )
1750 Sequence< PropertyValue > aValues( nCount );
1752 const OUString aHandleName("/Handle");
1753 const OUString aValueName("/Value");
1754 const OUString aStateName("/State");
1756 for ( sal_Int32 n = 0; n < nCount; ++n )
1758 PropertyValue& rValue = aValues[ n ];
1759 OUString rName = aElems[ n ];
1760 OUString aXMLName
1761 = makeHierarchalNameSegment( rName );
1763 // Set property name.
1765 rValue.Name = rName;
1769 // Obtain and set property handle
1770 OUString aHierName = aXMLName + aHandleName;
1771 Any aKeyValue
1772 = xHierNameAccess->getByHierarchicalName(
1773 aHierName );
1775 if ( !( aKeyValue >>= rValue.Handle ) )
1776 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1777 "Error getting property handle!" );
1779 catch (const NoSuchElementException&)
1781 // getByHierarchicalName
1783 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1784 "NoSuchElementException!" );
1789 // Obtain and set property value
1790 OUString aHierName = aXMLName + aValueName;
1791 rValue.Value
1792 = xHierNameAccess->getByHierarchicalName(
1793 aHierName );
1795 // Note: The value may be void if addProperty
1796 // was called with a default value
1797 // of type void.
1799 catch (const NoSuchElementException&)
1801 // getByHierarchicalName
1803 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1804 "NoSuchElementException!" );
1809 // Obtain and set property state
1810 OUString aHierName = aXMLName +aStateName;
1811 Any aKeyValue
1812 = xHierNameAccess->getByHierarchicalName(
1813 aHierName );
1815 sal_Int32 nState = 0;
1816 if ( !( aKeyValue >>= nState ) )
1817 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1818 "Error getting property state!" );
1819 else
1820 rValue.State = PropertyState( nState );
1822 catch (const NoSuchElementException&)
1824 // getByHierarchicalName
1826 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1827 "NoSuchElementException!" );
1831 return aValues;
1836 catch (const NoSuchElementException&)
1838 // getByHierarchicalName
1842 return Sequence< PropertyValue >( 0 );
1846 // virtual
1847 void SAL_CALL PersistentPropertySet::setPropertyValues(
1848 const Sequence< PropertyValue >& aProps )
1850 if ( !aProps.hasElements() )
1851 return;
1853 osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1855 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1856 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1857 if ( xRootHierNameAccess.is() )
1859 std::vector< PropertyChangeEvent > aEvents;
1861 OUString aFullPropNamePrefix( getFullKey() + "/" );
1863 // Iterate over given property value sequence.
1864 for ( const PropertyValue& rNewValue : aProps )
1866 const OUString& rName = rNewValue.Name;
1868 OUString aFullPropName = aFullPropNamePrefix;
1869 aFullPropName += makeHierarchalNameSegment( rName );
1871 // Does property exist?
1872 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1874 Reference< XNameReplace > xNameReplace(
1875 m_pImpl->m_pCreator->getConfigWriteAccess(
1876 aFullPropName ), UNO_QUERY );
1877 Reference< XChangesBatch > xBatch(
1878 m_pImpl->m_pCreator->getConfigWriteAccess(
1879 OUString() ), UNO_QUERY );
1881 if ( xNameReplace.is() && xBatch.is() )
1885 // Write handle
1886 xNameReplace->replaceByName(
1887 "Handle",
1888 makeAny( rNewValue.Handle ) );
1890 // Save old value
1891 OUString aValueName = aFullPropName +"/Value";
1892 Any aOldValue
1893 = xRootHierNameAccess->getByHierarchicalName(
1894 aValueName );
1895 // Write value
1896 xNameReplace->replaceByName(
1897 "Value",
1898 rNewValue.Value );
1900 // Write state ( Now it is a directly set value )
1901 xNameReplace->replaceByName(
1902 "State",
1903 makeAny(
1904 sal_Int32(
1905 PropertyState_DIRECT_VALUE ) ) );
1907 // Commit changes.
1908 xBatch->commitChanges();
1910 if ( m_pImpl->m_pPropertyChangeListeners )
1912 PropertyChangeEvent aEvt;
1913 aEvt.Source = static_cast<OWeakObject*>(this);
1914 aEvt.PropertyName = rNewValue.Name;
1915 aEvt.PropertyHandle = rNewValue.Handle;
1916 aEvt.Further = false;
1917 aEvt.OldValue = aOldValue;
1918 aEvt.NewValue = rNewValue.Value;
1920 aEvents.push_back( aEvt );
1923 catch (const IllegalArgumentException&)
1925 // replaceByName
1927 catch (const NoSuchElementException&)
1929 // getByHierarchicalName, replaceByName
1931 catch (const WrappedTargetException&)
1933 // replaceByName, commitChanges
1939 // Callback follows!
1940 aCGuard.clear();
1942 if ( m_pImpl->m_pPropertyChangeListeners )
1944 // Notify property changes.
1945 for (auto const& event : aEvents)
1947 notifyPropertyChangeEvent( event );
1951 return;
1954 OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" );
1958 // Non-interface methods
1961 void PersistentPropertySet::notifyPropertyChangeEvent(
1962 const PropertyChangeEvent& rEvent ) const
1964 // Get "normal" listeners for the property.
1965 OInterfaceContainerHelper* pContainer =
1966 m_pImpl->m_pPropertyChangeListeners->getContainer(
1967 rEvent.PropertyName );
1968 if ( pContainer && pContainer->getLength() )
1970 OInterfaceIteratorHelper aIter( *pContainer );
1971 while ( aIter.hasMoreElements() )
1973 // Propagate event.
1974 Reference< XPropertyChangeListener > xListener(
1975 aIter.next(), UNO_QUERY );
1976 if ( xListener.is() )
1977 xListener->propertyChange( rEvent );
1981 // Get "normal" listeners for all properties.
1982 OInterfaceContainerHelper* pNoNameContainer =
1983 m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() );
1984 if ( pNoNameContainer && pNoNameContainer->getLength() )
1986 OInterfaceIteratorHelper aIter( *pNoNameContainer );
1987 while ( aIter.hasMoreElements() )
1989 // Propagate event.
1990 Reference< XPropertyChangeListener > xListener(
1991 aIter.next(), UNO_QUERY );
1992 if ( xListener.is() )
1993 xListener->propertyChange( rEvent );
1999 void PersistentPropertySet::notifyPropertySetInfoChange(
2000 const PropertySetInfoChangeEvent& evt ) const
2002 if ( !m_pImpl->m_pPropSetChangeListeners )
2003 return;
2005 // Notify event listeners.
2006 OInterfaceIteratorHelper2 aIter( *( m_pImpl->m_pPropSetChangeListeners ) );
2007 while ( aIter.hasMoreElements() )
2009 // Propagate event.
2010 Reference< XPropertySetInfoChangeListener >
2011 xListener( aIter.next(), UNO_QUERY );
2012 if ( xListener.is() )
2013 xListener->propertySetInfoChange( evt );
2018 const OUString& PersistentPropertySet::getFullKey()
2020 if ( m_pImpl->m_aFullKey.isEmpty() )
2022 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
2023 if ( m_pImpl->m_aFullKey.isEmpty() )
2025 m_pImpl->m_aFullKey
2026 = makeHierarchalNameSegment( m_pImpl->m_aKey );
2027 m_pImpl->m_aFullKey
2028 += "/Values";
2032 return m_pImpl->m_aFullKey;
2036 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
2038 return *m_pImpl->m_pCreator;
2042 // PropertySetInfo_Impl Implementation.
2045 PropertySetInfo_Impl::PropertySetInfo_Impl(
2046 PersistentPropertySet* pOwner )
2047 : m_pOwner( pOwner )
2052 // XPropertySetInfo methods.
2055 // virtual
2056 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
2058 if ( !m_pProps )
2060 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2061 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2062 UNO_QUERY );
2063 if ( xRootHierNameAccess.is() )
2067 Reference< XNameAccess > xNameAccess;
2068 xRootHierNameAccess->getByHierarchicalName(
2069 m_pOwner->getFullKey() )
2070 >>= xNameAccess;
2071 if ( xNameAccess.is() )
2073 // Obtain property names.
2075 Sequence< OUString > aElems
2076 = xNameAccess->getElementNames();
2078 sal_uInt32 nCount = aElems.getLength();
2079 Sequence< Property >* pPropSeq
2080 = new Sequence< Property >( nCount );
2082 if ( nCount )
2084 Reference< XHierarchicalNameAccess > xHierNameAccess(
2085 xNameAccess, UNO_QUERY );
2087 OSL_ENSURE( xHierNameAccess.is(),
2088 "PropertySetInfo_Impl::getProperties - "
2089 "No hierarchical name access!" );
2091 if ( xHierNameAccess.is() )
2093 const OUString aHandleName("/Handle");
2094 const OUString aValueName("/Value");
2095 const OUString aAttrName("/Attributes");
2097 Property* pProps = pPropSeq->getArray();
2099 for ( sal_uInt32 n = 0; n < nCount; ++n )
2101 Property& rProp = pProps[ n ];
2102 OUString rName = aElems[ n ];
2103 OUString aXMLName
2104 = makeHierarchalNameSegment( rName );
2106 // Set property name.
2108 rProp.Name = rName;
2112 // Obtain and set property handle
2113 OUString aHierName = aXMLName + aHandleName;
2114 Any aKeyValue
2115 = xHierNameAccess->getByHierarchicalName(
2116 aHierName );
2118 if ( !( aKeyValue >>= rProp.Handle ) )
2119 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2120 "Error getting property handle!" );
2122 catch (const NoSuchElementException&)
2124 // getByHierarchicalName
2126 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2127 "NoSuchElementException!" );
2132 // Obtain and set property type
2133 OUString aHierName = aXMLName + aValueName;
2134 Any aKeyValue
2135 = xHierNameAccess->getByHierarchicalName(
2136 aHierName );
2138 // Note: The type may be void if addProperty
2139 // was called with a default value
2140 // of type void.
2142 rProp.Type = aKeyValue.getValueType();
2144 catch (const NoSuchElementException&)
2146 // getByHierarchicalName
2148 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2149 "NoSuchElementException!" );
2154 // Obtain and set property attributes
2155 OUString aHierName = aXMLName + aAttrName;
2156 Any aKeyValue
2157 = xHierNameAccess->getByHierarchicalName(
2158 aHierName );
2160 sal_Int32 nAttribs = 0;
2161 if ( aKeyValue >>= nAttribs )
2162 rProp.Attributes
2163 = sal_Int16( nAttribs );
2164 else
2165 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2166 "Error getting property attributes!" );
2168 catch (const NoSuchElementException&)
2170 // getByHierarchicalName
2172 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2173 "NoSuchElementException!" );
2179 // Success.
2180 m_pProps.reset( pPropSeq );
2181 return *m_pProps;
2184 catch (const NoSuchElementException&)
2186 // getByHierarchicalName
2190 OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" );
2191 m_pProps.reset( new Sequence< Property >( 0 ) );
2194 return *m_pProps;
2198 // virtual
2199 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2200 const OUString& aName )
2202 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2203 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2204 UNO_QUERY );
2205 if ( xRootHierNameAccess.is() )
2207 OUString aFullPropName( m_pOwner->getFullKey() + "/" );
2208 aFullPropName += makeHierarchalNameSegment( aName );
2210 // Does property exist?
2211 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2212 throw UnknownPropertyException(aFullPropName);
2216 Property aProp;
2218 // Obtain handle.
2219 OUString aKey = aFullPropName + "/Handle";
2221 if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2222 >>= aProp.Handle ) )
2224 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2225 "No handle!" );
2226 return Property();
2229 // Obtain Value and extract type.
2230 aKey = aFullPropName + "/Value";
2232 Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2233 if ( !aValue.hasValue() )
2235 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2236 "No Value!" );
2237 return Property();
2240 aProp.Type = aValue.getValueType();
2242 // Obtain Attributes.
2243 aKey = aFullPropName + "/Attributes";
2245 sal_Int32 nAttribs = 0;
2246 if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2247 >>= nAttribs )
2248 aProp.Attributes = sal_Int16( nAttribs );
2249 else
2251 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2252 "No attributes!" );
2253 return Property();
2256 // set name.
2257 aProp.Name = aName;
2259 // Success.
2260 return aProp;
2262 catch (const NoSuchElementException&)
2264 // getByHierarchicalName
2266 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2267 "caught NoSuchElementException!" );
2272 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" );
2273 return Property();
2277 // virtual
2278 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2279 const OUString& Name )
2281 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2282 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2283 UNO_QUERY );
2284 if ( xRootHierNameAccess.is() )
2286 OUString aFullPropName( m_pOwner->getFullKey() + "/" );
2287 aFullPropName += makeHierarchalNameSegment( Name );
2289 return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2292 return false;
2295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */