lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / ucb / source / core / ucbstore.cxx
blob74b4771b60ee2cc3f7ddfd3fef770b7257c5c239
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 <list>
29 #include <unordered_map>
30 #include <sal/log.hxx>
31 #include <osl/diagnose.h>
32 #include <rtl/ustrbuf.hxx>
33 #include <rtl/ref.hxx>
34 #include <cppuhelper/interfacecontainer.hxx>
35 #include <comphelper/interfacecontainer2.hxx>
36 #include <comphelper/propertysequence.hxx>
37 #include <com/sun/star/beans/IllegalTypeException.hpp>
38 #include <com/sun/star/beans/NotRemoveableException.hpp>
39 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <com/sun/star/beans/PropertyExistException.hpp>
41 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
42 #include <com/sun/star/configuration/theDefaultProvider.hpp>
43 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
44 #include <com/sun/star/container/XNameContainer.hpp>
45 #include <com/sun/star/container/XNameReplace.hpp>
46 #include <com/sun/star/util/XChangesBatch.hpp>
47 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
48 #include <comphelper/processfactory.hxx>
49 #include <cppuhelper/implbase.hxx>
50 #include <ucbhelper/getcomponentcontext.hxx>
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 OUString( "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 css::lang::XServiceInfo* pX =
166 static_cast<css::lang::XServiceInfo*>(new UcbStore( ucbhelper::getComponentContext(rSMgr) ));
167 return css::uno::Reference< css::uno::XInterface >::query( pX );
170 css::uno::Sequence< OUString >
171 UcbStore::getSupportedServiceNames_Static()
173 css::uno::Sequence< OUString > aSNS { STORE_SERVICE_NAME };
174 return aSNS;
177 // Service factory implementation.
180 ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbStore );
183 // XPropertySetRegistryFactory methods.
186 // virtual
187 Reference< XPropertySetRegistry > SAL_CALL
188 UcbStore::createPropertySetRegistry( const OUString& )
190 // The URL parameter is ignored by this interface implementation. It always
191 // uses the configuration server as storage medium.
193 if ( !m_pImpl->m_xTheRegistry.is() )
195 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
196 if ( !m_pImpl->m_xTheRegistry.is() )
197 m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xContext, m_pImpl->m_aInitArgs );
200 return m_pImpl->m_xTheRegistry;
204 // XInitialization methods.
207 // virtual
208 void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments )
210 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
211 m_pImpl->m_aInitArgs = aArguments;
216 // PropertySetRegistry_Impl.
219 struct PropertySetRegistry_Impl
221 const Sequence< Any > m_aInitArgs;
222 PropertySetMap_Impl m_aPropSets;
223 Reference< XMultiServiceFactory > m_xConfigProvider;
224 Reference< XInterface > m_xRootReadAccess;
225 Reference< XInterface > m_xRootWriteAccess;
226 osl::Mutex m_aMutex;
227 bool m_bTriedToGetRootReadAccess;
228 bool m_bTriedToGetRootWriteAccess;
230 explicit PropertySetRegistry_Impl(const Sequence<Any> &rInitArgs)
231 : m_aInitArgs(rInitArgs)
232 , m_bTriedToGetRootReadAccess(false)
233 , m_bTriedToGetRootWriteAccess(false)
238 // PropertySetRegistry Implementation.
241 PropertySetRegistry::PropertySetRegistry(
242 const Reference< XComponentContext >& xContext,
243 const Sequence< Any > &rInitArgs )
244 : m_xContext( xContext ),
245 m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) )
250 // virtual
251 PropertySetRegistry::~PropertySetRegistry()
256 // XServiceInfo methods.
259 OUString SAL_CALL PropertySetRegistry::getImplementationName()
261 return OUString( "com.sun.star.comp.ucb.PropertySetRegistry" );
264 sal_Bool SAL_CALL PropertySetRegistry::supportsService( const OUString& ServiceName )
266 return cppu::supportsService( this, ServiceName );
269 css::uno::Sequence< OUString > SAL_CALL PropertySetRegistry::getSupportedServiceNames()
271 return { PROPSET_REG_SERVICE_NAME };
275 // XPropertySetRegistry methods.
278 // virtual
279 Reference< XPersistentPropertySet > SAL_CALL
280 PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create )
282 if ( !key.isEmpty() )
284 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
286 PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
288 PropertySetMap_Impl::const_iterator it = rSets.find( key );
289 if ( it != rSets.end() )
291 // Already instantiated.
292 return Reference< XPersistentPropertySet >( (*it).second );
294 else
296 // Create new instance.
297 Reference< XNameAccess > xRootNameAccess(
298 getRootConfigReadAccess(), UNO_QUERY );
299 if ( xRootNameAccess.is() )
301 // Propertyset in registry?
302 if ( xRootNameAccess->hasByName( key ) )
304 // Yep!
305 return Reference< XPersistentPropertySet >(
306 new PersistentPropertySet(
307 *this, key ) );
309 else if ( create )
311 // No. Create entry for propertyset.
313 Reference< XSingleServiceFactory > xFac(
314 getConfigWriteAccess( OUString() ), UNO_QUERY );
315 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
316 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
318 OSL_ENSURE( xFac.is(),
319 "PropertySetRegistry::openPropertySet - "
320 "No factory!" );
322 OSL_ENSURE( xBatch.is(),
323 "PropertySetRegistry::openPropertySet - "
324 "No batch!" );
326 OSL_ENSURE( xContainer.is(),
327 "PropertySetRegistry::openPropertySet - "
328 "No container!" );
330 if ( xFac.is() && xBatch.is() && xContainer.is() )
334 // Create new "Properties" config item.
335 Reference< XNameReplace > xNameReplace(
336 xFac->createInstance(), UNO_QUERY );
338 if ( xNameReplace.is() )
340 // Fill new item...
342 // Insert new item.
343 xContainer->insertByName(
344 key, makeAny( xNameReplace ) );
345 // Commit changes.
346 xBatch->commitChanges();
348 return Reference< XPersistentPropertySet >(
349 new PersistentPropertySet(
350 *this, key ) );
353 catch (const IllegalArgumentException&)
355 // insertByName
357 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
358 "caught IllegalArgumentException!" );
360 catch (const ElementExistException&)
362 // insertByName
364 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
365 "caught ElementExistException!" );
367 catch (const WrappedTargetException&)
369 // insertByName, commitChanges
371 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
372 "caught WrappedTargetException!" );
374 catch (const RuntimeException&)
376 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
377 "caught RuntimeException!" );
379 catch (const Exception&)
381 // createInstance
383 OSL_FAIL( "PropertySetRegistry::openPropertySet - "
384 "caught Exception!" );
388 else
390 // No entry. Fail, but no error.
391 return Reference< XPersistentPropertySet >();
395 SAL_WARN( "ucb", "no root access" );
399 return Reference< XPersistentPropertySet >();
403 // virtual
404 void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key )
406 if ( key.isEmpty() )
407 return;
409 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
411 Reference< XNameAccess > xRootNameAccess(
412 getRootConfigReadAccess(), UNO_QUERY );
413 if ( xRootNameAccess.is() )
415 // Propertyset in registry?
416 if ( !xRootNameAccess->hasByName( key ) )
417 return;
418 Reference< XChangesBatch > xBatch(
419 getConfigWriteAccess( OUString() ), UNO_QUERY );
420 Reference< XNameContainer > xContainer( xBatch, UNO_QUERY );
422 if ( xBatch.is() && xContainer.is() )
426 // Remove item.
427 xContainer->removeByName( key );
428 // Commit changes.
429 xBatch->commitChanges();
431 // Success.
432 return;
434 catch (const NoSuchElementException&)
436 // removeByName
438 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
439 "caught NoSuchElementException!" );
440 return;
442 catch (const WrappedTargetException&)
444 // commitChanges
446 OSL_FAIL( "PropertySetRegistry::removePropertySet - "
447 "caught WrappedTargetException!" );
448 return;
452 return;
455 SAL_WARN( "ucb", "no root access" );
459 // XElementAccess methods.
462 // virtual
463 css::uno::Type SAL_CALL PropertySetRegistry::getElementType()
465 return cppu::UnoType<XPersistentPropertySet>::get();
469 // virtual
470 sal_Bool SAL_CALL PropertySetRegistry::hasElements()
472 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
474 Reference< XElementAccess > xElemAccess(
475 getRootConfigReadAccess(), UNO_QUERY );
476 if ( xElemAccess.is() )
477 return xElemAccess->hasElements();
479 return false;
483 // XNameAccess methods.
486 // virtual
487 Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName )
489 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
491 Reference< XNameAccess > xNameAccess(
492 getRootConfigReadAccess(), UNO_QUERY );
493 if ( xNameAccess.is() )
498 return xNameAccess->getByName( aName );
500 catch (const NoSuchElementException&)
502 // getByName
504 catch (const WrappedTargetException&)
506 // getByName
510 return Any();
514 // virtual
515 Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames()
517 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
519 Reference< XNameAccess > xNameAccess(
520 getRootConfigReadAccess(), UNO_QUERY );
521 if ( xNameAccess.is() )
523 return xNameAccess->getElementNames();
525 return Sequence< OUString >( 0 );
529 // virtual
530 sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName )
532 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
534 Reference< XNameAccess > xNameAccess(
535 getRootConfigReadAccess(), UNO_QUERY );
536 if ( xNameAccess.is() )
538 return xNameAccess->hasByName( aName );
541 return false;
545 void PropertySetRegistry::add( PersistentPropertySet* pSet )
547 OUString key( pSet->getKey() );
549 if ( !key.isEmpty() )
551 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
552 m_pImpl->m_aPropSets[ key ] = pSet;
557 void PropertySetRegistry::remove( PersistentPropertySet* pSet )
559 OUString key( pSet->getKey() );
561 if ( !key.isEmpty() )
563 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
565 PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets;
567 PropertySetMap_Impl::iterator it = rSets.find( key );
568 if ( it != rSets.end() )
570 // Found.
571 rSets.erase( it );
577 void PropertySetRegistry::renamePropertySet( const OUString& rOldKey,
578 const OUString& rNewKey )
580 if ( rOldKey == rNewKey )
581 return;
583 Reference< XNameAccess > xRootNameAccess(
584 getConfigWriteAccess( OUString() ), UNO_QUERY );
585 if ( xRootNameAccess.is() )
587 // Old key present?
588 if ( xRootNameAccess->hasByName( rOldKey ) )
590 // New key not present?
591 if ( xRootNameAccess->hasByName( rNewKey ) )
593 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
594 "New key exists!" );
595 return;
597 Reference< XSingleServiceFactory > xFac(
598 xRootNameAccess, UNO_QUERY );
599 Reference< XChangesBatch > xBatch( xFac, UNO_QUERY );
600 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
602 OSL_ENSURE( xFac.is(),
603 "PropertySetRegistry::renamePropertySet - "
604 "No factory!" );
606 OSL_ENSURE( xBatch.is(),
607 "PropertySetRegistry::renamePropertySet - "
608 "No batch!" );
610 OSL_ENSURE( xContainer.is(),
611 "PropertySetRegistry::renamePropertySet - "
612 "No container!" );
614 if ( xFac.is() && xBatch.is() && xContainer.is() )
617 // Create new "Properties" config item.
622 Reference< XNameReplace > xNameReplace(
623 xFac->createInstance(), UNO_QUERY );
625 if ( xNameReplace.is() )
627 // Insert new item.
628 xContainer->insertByName(
629 rNewKey, makeAny( xNameReplace ) );
630 // Commit changes.
631 xBatch->commitChanges();
634 catch (const IllegalArgumentException&)
636 // insertByName
638 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
639 "caught IllegalArgumentException!" );
640 return;
642 catch (const ElementExistException&)
644 // insertByName
646 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
647 "caught ElementExistException!" );
648 return;
650 catch (const WrappedTargetException&)
652 // insertByName, commitChanges
654 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
655 "caught WrappedTargetException!" );
656 return;
658 catch (const RuntimeException&)
660 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
661 "caught RuntimeException!" );
662 return;
664 catch (const Exception&)
666 // createInstance
668 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
669 "caught Exception!" );
670 return;
674 // Copy data...
677 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
678 xRootNameAccess, UNO_QUERY );
679 if ( !xRootHierNameAccess.is() )
681 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
682 "No hierarchical name access!" );
683 return;
688 OUString aOldValuesKey
689 = makeHierarchalNameSegment( rOldKey );
690 aOldValuesKey += "/Values";
692 Reference< XNameAccess > xOldNameAccess;
693 xRootHierNameAccess->getByHierarchicalName(
694 aOldValuesKey )
695 >>= xOldNameAccess;
696 if ( !xOldNameAccess.is() )
698 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
699 "No old name access!" );
700 return;
703 // Obtain property names.
704 Sequence< OUString > aElems
705 = xOldNameAccess->getElementNames();
706 sal_Int32 nCount = aElems.getLength();
707 if ( nCount )
709 OUString aNewValuesKey
710 = makeHierarchalNameSegment( rNewKey );
711 aNewValuesKey += "/Values";
713 Reference< XSingleServiceFactory > xNewFac;
714 xRootHierNameAccess->getByHierarchicalName(
715 aNewValuesKey )
716 >>= xNewFac;
717 if ( !xNewFac.is() )
719 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
720 "No new factory!" );
721 return;
724 Reference< XNameContainer > xNewContainer(
725 xNewFac, UNO_QUERY );
726 if ( !xNewContainer.is() )
728 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
729 "No new container!" );
730 return;
733 aOldValuesKey += "/";
735 OUString const aHandleKey("/Handle");
736 OUString const aValueKey("/Value");
737 OUString const aStateKey("/State");
738 OUString const aAttrKey("/Attributes");
740 for ( sal_Int32 n = 0; n < nCount; ++n )
742 const OUString& rPropName = aElems[ n ];
744 // Create new item.
745 Reference< XNameReplace > xNewPropNameReplace(
746 xNewFac->createInstance(), UNO_QUERY );
748 if ( !xNewPropNameReplace.is() )
750 OSL_FAIL( "PersistentPropertySet::renamePropertySet - "
751 "No new prop name replace!" );
752 return;
755 // Fill new item...
757 // Set Values
758 OUString aKey = aOldValuesKey;
759 aKey += makeHierarchalNameSegment( rPropName );
761 // ... handle
762 OUString aNewKey1 = aKey + aHandleKey;
763 Any aAny =
764 xRootHierNameAccess->getByHierarchicalName(
765 aNewKey1 );
766 xNewPropNameReplace->replaceByName( "Handle", aAny );
768 // ... value
769 aNewKey1 = aKey + aValueKey;
770 aAny =
771 xRootHierNameAccess->getByHierarchicalName(
772 aNewKey1 );
773 xNewPropNameReplace->replaceByName( "Value", aAny );
775 // ... state
776 aNewKey1 = aKey + aStateKey;
777 aAny =
778 xRootHierNameAccess->getByHierarchicalName(
779 aNewKey1 );
780 xNewPropNameReplace->replaceByName( "State", aAny );
782 // ... attributes
783 aNewKey1 = aKey + aAttrKey;
784 aAny =
785 xRootHierNameAccess->getByHierarchicalName(
786 aNewKey1 );
787 xNewPropNameReplace->replaceByName( "Attributes", aAny );
789 // Insert new item.
790 xNewContainer->insertByName(
791 rPropName, makeAny( xNewPropNameReplace ) );
793 // Commit changes.
794 xBatch->commitChanges();
798 catch (const IllegalArgumentException&)
800 // insertByName, replaceByName
802 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
803 "caught IllegalArgumentException!" );
804 return;
806 catch (const ElementExistException&)
808 // insertByName
810 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
811 "caught ElementExistException!" );
812 return;
814 catch (const WrappedTargetException&)
816 // insertByName, replaceByName, commitChanges
818 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
819 "caught WrappedTargetException!" );
820 return;
822 catch (const NoSuchElementException&)
824 // getByHierarchicalName, replaceByName
826 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
827 "caught NoSuchElementException!" );
828 return;
830 catch (const RuntimeException&)
832 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
833 "caught RuntimeException!" );
834 return;
836 catch (const Exception&)
838 // createInstance
840 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
841 "caught Exception!" );
842 return;
846 // Remove old entry...
851 // Remove item.
852 xContainer->removeByName( rOldKey );
853 // Commit changes.
854 xBatch->commitChanges();
856 // Success.
857 return;
859 catch (const NoSuchElementException&)
861 // removeByName
863 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
864 "caught NoSuchElementException!" );
865 return;
867 catch (const WrappedTargetException&)
869 // commitChanges
871 OSL_FAIL( "PropertySetRegistry::renamePropertySet - "
872 "caught WrappedTargetException!" );
873 return;
879 OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" );
883 Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider()
885 if ( !m_pImpl->m_xConfigProvider.is() )
887 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
888 if ( !m_pImpl->m_xConfigProvider.is() )
890 const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs;
892 if ( rInitArgs.getLength() > 0 )
894 // Extract config provider from service init args.
895 rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider;
897 OSL_ENSURE( m_pImpl->m_xConfigProvider.is(),
898 "PropertySetRegistry::getConfigProvider - "
899 "No config provider!" );
901 else
905 m_pImpl->m_xConfigProvider = theDefaultProvider::get( m_xContext );
907 catch (const Exception&)
909 SAL_WARN( "ucb", "caught exception!" );
915 return m_pImpl->m_xConfigProvider;
919 Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess()
923 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
925 if ( !m_pImpl->m_xRootReadAccess.is() )
927 if ( m_pImpl->m_bTriedToGetRootReadAccess )
929 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - "
930 "Unable to read any config data! -> #82494#" );
931 return Reference< XInterface >();
934 getConfigProvider();
936 if ( m_pImpl->m_xConfigProvider.is() )
938 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
940 {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
941 }));
943 m_pImpl->m_bTriedToGetRootReadAccess = true;
945 m_pImpl->m_xRootReadAccess =
946 m_pImpl->m_xConfigProvider->createInstanceWithArguments(
947 "com.sun.star.configuration.ConfigurationAccess",
948 aArguments );
950 if ( m_pImpl->m_xRootReadAccess.is() )
951 return m_pImpl->m_xRootReadAccess;
954 else
955 return m_pImpl->m_xRootReadAccess;
957 catch (const RuntimeException&)
959 throw;
961 catch (const Exception&)
963 // createInstance, createInstanceWithArguments
965 OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - caught Exception!" );
966 return Reference< XInterface >();
969 SAL_WARN( "ucb", "Error!" );
970 return Reference< XInterface >();
974 Reference< XInterface > PropertySetRegistry::getConfigWriteAccess(
975 const OUString& rPath )
979 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
981 if ( !m_pImpl->m_xRootWriteAccess.is() )
983 if ( m_pImpl->m_bTriedToGetRootWriteAccess )
985 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
986 "Unable to write any config data! -> #82494#" );
987 return Reference< XInterface >();
990 getConfigProvider();
992 if ( m_pImpl->m_xConfigProvider.is() )
994 Sequence<Any> aArguments(comphelper::InitAnyPropertySequence(
996 {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))}
997 }));
999 m_pImpl->m_bTriedToGetRootWriteAccess = true;
1001 m_pImpl->m_xRootWriteAccess =
1002 m_pImpl->m_xConfigProvider->createInstanceWithArguments(
1003 "com.sun.star.configuration.ConfigurationUpdateAccess",
1004 aArguments );
1006 OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(),
1007 "PropertySetRegistry::getConfigWriteAccess - "
1008 "No config update access!" );
1012 if ( m_pImpl->m_xRootWriteAccess.is() )
1014 if ( !rPath.isEmpty() )
1016 Reference< XHierarchicalNameAccess > xNA(
1017 m_pImpl->m_xRootWriteAccess, UNO_QUERY );
1018 if ( xNA.is() )
1020 Reference< XInterface > xInterface;
1021 xNA->getByHierarchicalName( rPath ) >>= xInterface;
1023 if ( xInterface.is() )
1024 return xInterface;
1027 else
1028 return m_pImpl->m_xRootWriteAccess;
1031 catch (const RuntimeException&)
1033 throw;
1035 catch (const NoSuchElementException&)
1037 // getByHierarchicalName
1039 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1040 "caught NoSuchElementException!" );
1041 return Reference< XInterface >();
1043 catch (const Exception&)
1045 // createInstance, createInstanceWithArguments
1047 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - "
1048 "caught Exception!" );
1049 return Reference< XInterface >();
1052 OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" );
1053 return Reference< XInterface >();
1056 typedef OMultiTypeInterfaceContainerHelperVar<OUString> PropertyListeners_Impl;
1058 struct PersistentPropertySet_Impl
1060 rtl::Reference<PropertySetRegistry> m_pCreator;
1061 rtl::Reference<PropertySetInfo_Impl> m_pInfo;
1062 OUString const m_aKey;
1063 OUString m_aFullKey;
1064 osl::Mutex m_aMutex;
1065 std::unique_ptr<OInterfaceContainerHelper2> m_pDisposeEventListeners;
1066 std::unique_ptr<OInterfaceContainerHelper2> m_pPropSetChangeListeners;
1067 std::unique_ptr<PropertyListeners_Impl> m_pPropertyChangeListeners;
1069 PersistentPropertySet_Impl( PropertySetRegistry& rCreator,
1070 const OUString& rKey )
1071 : m_pCreator( &rCreator ), m_aKey( rKey )
1077 // PersistentPropertySet Implementation.
1080 PersistentPropertySet::PersistentPropertySet(
1081 PropertySetRegistry& rCreator,
1082 const OUString& rKey )
1083 : m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) )
1085 // register at creator.
1086 rCreator.add( this );
1090 // virtual
1091 PersistentPropertySet::~PersistentPropertySet()
1093 // deregister at creator.
1094 m_pImpl->m_pCreator->remove( this );
1097 // XServiceInfo methods.
1099 OUString SAL_CALL PersistentPropertySet::getImplementationName()
1101 return OUString( "com.sun.star.comp.ucb.PersistentPropertySet" );
1104 sal_Bool SAL_CALL PersistentPropertySet::supportsService( const OUString& ServiceName )
1106 return cppu::supportsService( this, ServiceName );
1109 css::uno::Sequence< OUString > SAL_CALL
1110 PersistentPropertySet::getSupportedServiceNames()
1112 return { PERS_PROPSET_SERVICE_NAME };
1116 // XComponent methods.
1119 // virtual
1120 void SAL_CALL PersistentPropertySet::dispose()
1122 if ( m_pImpl->m_pDisposeEventListeners &&
1123 m_pImpl->m_pDisposeEventListeners->getLength() )
1125 EventObject aEvt;
1126 aEvt.Source = static_cast< XComponent * >( this );
1127 m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
1130 if ( m_pImpl->m_pPropSetChangeListeners &&
1131 m_pImpl->m_pPropSetChangeListeners->getLength() )
1133 EventObject aEvt;
1134 aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this );
1135 m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
1138 if ( m_pImpl->m_pPropertyChangeListeners )
1140 EventObject aEvt;
1141 aEvt.Source = static_cast< XPropertySet * >( this );
1142 m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
1147 // virtual
1148 void SAL_CALL PersistentPropertySet::addEventListener(
1149 const Reference< XEventListener >& Listener )
1151 if ( !m_pImpl->m_pDisposeEventListeners )
1152 m_pImpl->m_pDisposeEventListeners.reset(
1153 new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) );
1155 m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
1159 // virtual
1160 void SAL_CALL PersistentPropertySet::removeEventListener(
1161 const Reference< XEventListener >& Listener )
1163 if ( m_pImpl->m_pDisposeEventListeners )
1164 m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
1166 // Note: Don't want to delete empty container here -> performance.
1170 // XPropertySet methods.
1173 // virtual
1174 Reference< XPropertySetInfo > SAL_CALL PersistentPropertySet::getPropertySetInfo()
1176 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1178 if ( !m_pImpl->m_pInfo.is() )
1180 m_pImpl->m_pInfo = new PropertySetInfo_Impl( this );
1182 return Reference< XPropertySetInfo >( m_pImpl->m_pInfo.get() );
1186 // virtual
1187 void SAL_CALL PersistentPropertySet::setPropertyValue( const OUString& aPropertyName,
1188 const Any& aValue )
1190 if ( aPropertyName.isEmpty() )
1191 throw UnknownPropertyException();
1193 osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1195 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1196 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1197 if ( xRootHierNameAccess.is() )
1199 OUString aFullPropName( getFullKey() );
1200 aFullPropName += "/";
1201 aFullPropName += makeHierarchalNameSegment( aPropertyName );
1203 // Does property exist?
1204 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1206 Reference< XNameReplace > xNameReplace(
1207 m_pImpl->m_pCreator->getConfigWriteAccess(
1208 aFullPropName ), UNO_QUERY );
1209 Reference< XChangesBatch > xBatch(
1210 m_pImpl->m_pCreator->getConfigWriteAccess(
1211 OUString() ), UNO_QUERY );
1213 if ( xNameReplace.is() && xBatch.is() )
1217 // Obtain old value
1218 OUString aValueName = aFullPropName;
1219 aValueName += "/Value";
1220 Any aOldValue
1221 = xRootHierNameAccess->getByHierarchicalName(
1222 aValueName );
1223 // Check value type.
1224 if ( aOldValue.getValueType() != aValue.getValueType() )
1226 aCGuard.clear();
1227 throw IllegalArgumentException();
1230 // Write value
1231 xNameReplace->replaceByName( "Value", aValue );
1233 // Write state ( Now it is a directly set value )
1234 xNameReplace->replaceByName(
1235 "State",
1236 makeAny(
1237 sal_Int32(
1238 PropertyState_DIRECT_VALUE ) ) );
1240 // Commit changes.
1241 xBatch->commitChanges();
1243 PropertyChangeEvent aEvt;
1244 if ( m_pImpl->m_pPropertyChangeListeners )
1246 // Obtain handle
1247 aValueName = aFullPropName;
1248 aValueName += "/Handle";
1249 sal_Int32 nHandle = -1;
1250 xRootHierNameAccess->getByHierarchicalName( aValueName )
1251 >>= nHandle;
1253 aEvt.Source = static_cast<OWeakObject*>(this);
1254 aEvt.PropertyName = aPropertyName;
1255 aEvt.PropertyHandle = nHandle;
1256 aEvt.Further = false;
1257 aEvt.OldValue = aOldValue;
1258 aEvt.NewValue = aValue;
1260 // Callback follows!
1261 aCGuard.clear();
1263 notifyPropertyChangeEvent( aEvt );
1265 return;
1267 catch (const IllegalArgumentException&)
1269 // replaceByName
1271 catch (const NoSuchElementException&)
1273 // getByHierarchicalName, replaceByName
1275 catch (const WrappedTargetException&)
1277 // replaceByName, commitChanges
1283 throw UnknownPropertyException();
1287 // virtual
1288 Any SAL_CALL PersistentPropertySet::getPropertyValue(
1289 const OUString& PropertyName )
1291 if ( PropertyName.isEmpty() )
1292 throw UnknownPropertyException();
1294 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1296 Reference< XHierarchicalNameAccess > xNameAccess(
1297 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1298 if ( xNameAccess.is() )
1300 OUString aFullPropName( getFullKey() );
1301 aFullPropName += "/";
1302 aFullPropName += makeHierarchalNameSegment( PropertyName );
1303 aFullPropName += "/Value";
1306 return xNameAccess->getByHierarchicalName( aFullPropName );
1308 catch (const NoSuchElementException&)
1310 throw UnknownPropertyException();
1314 throw UnknownPropertyException();
1318 // virtual
1319 void SAL_CALL PersistentPropertySet::addPropertyChangeListener(
1320 const OUString& aPropertyName,
1321 const Reference< XPropertyChangeListener >& xListener )
1323 // load();
1325 if ( !m_pImpl->m_pPropertyChangeListeners )
1326 m_pImpl->m_pPropertyChangeListeners.reset(
1327 new PropertyListeners_Impl( m_pImpl->m_aMutex ) );
1329 m_pImpl->m_pPropertyChangeListeners->addInterface(
1330 aPropertyName, xListener );
1334 // virtual
1335 void SAL_CALL PersistentPropertySet::removePropertyChangeListener(
1336 const OUString& aPropertyName,
1337 const Reference< XPropertyChangeListener >& aListener )
1339 // load();
1341 if ( m_pImpl->m_pPropertyChangeListeners )
1342 m_pImpl->m_pPropertyChangeListeners->removeInterface(
1343 aPropertyName, aListener );
1345 // Note: Don't want to delete empty container here -> performance.
1349 // virtual
1350 void SAL_CALL PersistentPropertySet::addVetoableChangeListener(
1351 const OUString&,
1352 const Reference< XVetoableChangeListener >& )
1354 // load();
1355 // OSL_FAIL( // "PersistentPropertySet::addVetoableChangeListener - N.Y.I." );
1359 // virtual
1360 void SAL_CALL PersistentPropertySet::removeVetoableChangeListener(
1361 const OUString&,
1362 const Reference< XVetoableChangeListener >& )
1364 // load();
1365 // OSL_FAIL( // "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." );
1369 // XPersistentPropertySet methods.
1372 // virtual
1373 Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry()
1375 return Reference< XPropertySetRegistry >( m_pImpl->m_pCreator.get() );
1379 // virtual
1380 OUString SAL_CALL PersistentPropertySet::getKey()
1382 return m_pImpl->m_aKey;
1386 // XNamed methods.
1389 // virtual
1390 OUString SAL_CALL PersistentPropertySet::getName()
1392 // same as getKey()
1393 return m_pImpl->m_aKey;
1397 // virtual
1398 void SAL_CALL PersistentPropertySet::setName( const OUString& aName )
1400 if ( aName != m_pImpl->m_aKey )
1401 m_pImpl->m_pCreator->renamePropertySet( m_pImpl->m_aKey, aName );
1405 // XPropertyContainer methods.
1408 // virtual
1409 void SAL_CALL PersistentPropertySet::addProperty(
1410 const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue )
1412 if ( Name.isEmpty() )
1413 throw IllegalArgumentException();
1415 // @@@ What other types can't be written to config server?
1417 // Check type class ( Not all types can be written to storage )
1418 TypeClass eTypeClass = DefaultValue.getValueTypeClass();
1419 if ( eTypeClass == TypeClass_INTERFACE )
1420 throw IllegalTypeException();
1422 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1424 // Property already in set?
1426 OUString aFullValuesName;
1428 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1429 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1430 if ( xRootHierNameAccess.is() )
1432 aFullValuesName = getFullKey();
1433 OUString aFullPropName = aFullValuesName;
1434 aFullPropName += "/";
1435 aFullPropName += makeHierarchalNameSegment( Name );
1437 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1439 // Already in set.
1440 throw PropertyExistException();
1444 // Property is always removable.
1445 Attributes |= PropertyAttribute::REMOVABLE;
1447 // Add property.
1449 Reference< XSingleServiceFactory > xFac(
1450 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1451 UNO_QUERY );
1452 Reference< XNameContainer > xContainer( xFac, UNO_QUERY );
1453 Reference< XChangesBatch > xBatch(
1454 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1455 UNO_QUERY );
1457 OSL_ENSURE( xFac.is(),
1458 "PersistentPropertySet::addProperty - No factory!" );
1460 OSL_ENSURE( xBatch.is(),
1461 "PersistentPropertySet::addProperty - No batch!" );
1463 OSL_ENSURE( xContainer.is(),
1464 "PersistentPropertySet::addProperty - No container!" );
1466 if ( xFac.is() && xBatch.is() && xContainer.is() )
1470 // Create new "PropertyValue" config item.
1471 Reference< XNameReplace > xNameReplace(
1472 xFac->createInstance(), UNO_QUERY );
1474 if ( xNameReplace.is() )
1476 // Fill new item...
1478 // Set handle
1479 xNameReplace->replaceByName(
1480 "Handle",
1481 makeAny( sal_Int32( -1 ) ) );
1483 // Set default value
1484 xNameReplace->replaceByName(
1485 "Value",
1486 DefaultValue );
1488 // Set state ( always "default" )
1489 xNameReplace->replaceByName(
1490 "State",
1491 makeAny(
1492 sal_Int32(
1493 PropertyState_DEFAULT_VALUE ) ) );
1495 // Set attributes
1496 xNameReplace->replaceByName(
1497 "Attributes",
1498 makeAny( sal_Int32( Attributes ) ) );
1500 // Insert new item.
1501 xContainer->insertByName( Name, makeAny( xNameReplace ) );
1503 // Commit changes.
1504 xBatch->commitChanges();
1506 // Property set info is invalid.
1507 if ( m_pImpl->m_pInfo.is() )
1508 m_pImpl->m_pInfo->reset();
1510 // Notify propertyset info change listeners.
1511 if ( m_pImpl->m_pPropSetChangeListeners &&
1512 m_pImpl->m_pPropSetChangeListeners->getLength() )
1514 PropertySetInfoChangeEvent evt(
1515 static_cast< OWeakObject * >( this ),
1516 Name,
1518 PropertySetInfoChange::PROPERTY_INSERTED );
1519 notifyPropertySetInfoChange( evt );
1522 // Success.
1523 return;
1526 catch (const IllegalArgumentException&)
1528 // insertByName
1530 OSL_FAIL( "PersistentPropertySet::addProperty - "
1531 "caught IllegalArgumentException!" );
1532 return;
1534 catch (const ElementExistException&)
1536 // insertByName
1538 OSL_FAIL( "PersistentPropertySet::addProperty - "
1539 "caught ElementExistException!" );
1540 return;
1542 catch (const WrappedTargetException&)
1544 // replaceByName, insertByName, commitChanges
1546 OSL_FAIL( "PersistentPropertySet::addProperty - "
1547 "caught WrappedTargetException!" );
1548 return;
1550 catch (const RuntimeException&)
1552 throw;
1554 catch (const Exception&)
1556 // createInstance
1558 OSL_FAIL( "PersistentPropertySet::addProperty - "
1559 "caught Exception!" );
1560 return;
1564 OSL_FAIL( "PersistentPropertySet::addProperty - Error!" );
1568 // virtual
1569 void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name )
1571 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1573 OUString aFullValuesName;
1574 OUString aFullPropName;
1576 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1577 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1578 if ( xRootHierNameAccess.is() )
1580 aFullValuesName = getFullKey();
1581 aFullPropName = aFullValuesName;
1582 aFullPropName += "/";
1583 aFullPropName += makeHierarchalNameSegment( Name );
1585 // Property in set?
1586 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1587 throw UnknownPropertyException();
1589 // Property removable?
1592 OUString aFullAttrName = aFullPropName;
1593 aFullAttrName += "/Attributes";
1595 sal_Int32 nAttribs = 0;
1596 if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName )
1597 >>= nAttribs )
1599 if ( !( nAttribs & PropertyAttribute::REMOVABLE ) )
1601 // Not removable!
1602 throw NotRemoveableException();
1605 else
1607 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1608 "No attributes!" );
1609 return;
1612 catch (const NoSuchElementException&)
1614 // getByHierarchicalName
1616 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1617 "caught NoSuchElementException!" );
1620 // Remove property...
1622 Reference< XNameContainer > xContainer(
1623 m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ),
1624 UNO_QUERY );
1625 Reference< XChangesBatch > xBatch(
1626 m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ),
1627 UNO_QUERY );
1629 OSL_ENSURE( xBatch.is(),
1630 "PersistentPropertySet::removeProperty - No batch!" );
1632 OSL_ENSURE( xContainer.is(),
1633 "PersistentPropertySet::removeProperty - No container!" );
1635 if ( xBatch.is() && xContainer.is() )
1639 sal_Int32 nHandle = -1;
1641 if ( m_pImpl->m_pPropSetChangeListeners &&
1642 m_pImpl->m_pPropSetChangeListeners->getLength() )
1644 // Obtain property handle ( needed for propertysetinfo
1645 // change event )...
1649 OUString aFullHandleName = aFullPropName;
1650 aFullHandleName
1651 += "/Handle";
1653 if ( ! ( xRootHierNameAccess->getByHierarchicalName(
1654 aFullHandleName ) >>= nHandle ) )
1655 nHandle = -1;
1658 catch (const NoSuchElementException&)
1660 // getByHierarchicalName
1662 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1663 "caught NoSuchElementException!" );
1664 nHandle = -1;
1668 xContainer->removeByName( Name );
1669 xBatch->commitChanges();
1671 // Property set info is invalid.
1672 if ( m_pImpl->m_pInfo.is() )
1673 m_pImpl->m_pInfo->reset();
1675 // Notify propertyset info change listeners.
1676 if ( m_pImpl->m_pPropSetChangeListeners &&
1677 m_pImpl->m_pPropSetChangeListeners->getLength() )
1679 PropertySetInfoChangeEvent evt(
1680 static_cast< OWeakObject * >( this ),
1681 Name,
1682 nHandle,
1683 PropertySetInfoChange::PROPERTY_REMOVED );
1684 notifyPropertySetInfoChange( evt );
1687 // Success.
1688 return;
1690 catch (const NoSuchElementException&)
1692 // removeByName
1694 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1695 "caught NoSuchElementException!" );
1696 return;
1698 catch (const WrappedTargetException&)
1700 // commitChanges
1702 OSL_FAIL( "PersistentPropertySet::removeProperty - "
1703 "caught WrappedTargetException!" );
1704 return;
1709 OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" );
1713 // XPropertySetInfoChangeNotifier methods.
1716 // virtual
1717 void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener(
1718 const Reference< XPropertySetInfoChangeListener >& Listener )
1720 if ( !m_pImpl->m_pPropSetChangeListeners )
1721 m_pImpl->m_pPropSetChangeListeners.reset(
1722 new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) );
1724 m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
1728 // virtual
1729 void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener(
1730 const Reference< XPropertySetInfoChangeListener >& Listener )
1732 if ( m_pImpl->m_pPropSetChangeListeners )
1733 m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
1737 // XPropertyAccess methods.
1740 // virtual
1741 Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues()
1743 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
1745 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1746 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1747 if ( xRootHierNameAccess.is() )
1751 Reference< XNameAccess > xNameAccess;
1752 xRootHierNameAccess->getByHierarchicalName(getFullKey())
1753 >>= xNameAccess;
1754 if ( xNameAccess.is() )
1756 // Obtain property names.
1758 Sequence< OUString > aElems = xNameAccess->getElementNames();
1760 sal_Int32 nCount = aElems.getLength();
1761 if ( nCount )
1763 Reference< XHierarchicalNameAccess > xHierNameAccess(
1764 xNameAccess, UNO_QUERY );
1766 OSL_ENSURE( xHierNameAccess.is(),
1767 "PersistentPropertySet::getPropertyValues - "
1768 "No hierarchical name access!" );
1770 if ( xHierNameAccess.is() )
1772 Sequence< PropertyValue > aValues( nCount );
1774 const OUString aHandleName("/Handle");
1775 const OUString aValueName("/Value");
1776 const OUString aStateName("/State");
1778 for ( sal_Int32 n = 0; n < nCount; ++n )
1780 PropertyValue& rValue = aValues[ n ];
1781 OUString rName = aElems[ n ];
1782 OUString aXMLName
1783 = makeHierarchalNameSegment( rName );
1785 // Set property name.
1787 rValue.Name = rName;
1791 // Obtain and set property handle
1792 OUString aHierName = aXMLName;
1793 aHierName += aHandleName;
1794 Any aKeyValue
1795 = xHierNameAccess->getByHierarchicalName(
1796 aHierName );
1798 if ( !( aKeyValue >>= rValue.Handle ) )
1799 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1800 "Error getting property handle!" );
1802 catch (const NoSuchElementException&)
1804 // getByHierarchicalName
1806 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1807 "NoSuchElementException!" );
1812 // Obtain and set property value
1813 OUString aHierName = aXMLName;
1814 aHierName += aValueName;
1815 rValue.Value
1816 = xHierNameAccess->getByHierarchicalName(
1817 aHierName );
1819 // Note: The value may be void if addProperty
1820 // was called with a default value
1821 // of type void.
1823 catch (const NoSuchElementException&)
1825 // getByHierarchicalName
1827 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1828 "NoSuchElementException!" );
1833 // Obtain and set property state
1834 OUString aHierName = aXMLName;
1835 aHierName += aStateName;
1836 Any aKeyValue
1837 = xHierNameAccess->getByHierarchicalName(
1838 aHierName );
1840 sal_Int32 nState = 0;
1841 if ( !( aKeyValue >>= nState ) )
1842 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1843 "Error getting property state!" );
1844 else
1845 rValue.State = PropertyState( nState );
1847 catch (const NoSuchElementException&)
1849 // getByHierarchicalName
1851 OSL_FAIL( "PersistentPropertySet::getPropertyValues - "
1852 "NoSuchElementException!" );
1856 return aValues;
1861 catch (const NoSuchElementException&)
1863 // getByHierarchicalName
1867 return Sequence< PropertyValue >( 0 );
1871 // virtual
1872 void SAL_CALL PersistentPropertySet::setPropertyValues(
1873 const Sequence< PropertyValue >& aProps )
1875 sal_Int32 nCount = aProps.getLength();
1876 if ( !nCount )
1877 return;
1879 osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex );
1881 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
1882 m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY );
1883 if ( xRootHierNameAccess.is() )
1885 const PropertyValue* pNewValues = aProps.getConstArray();
1887 std::vector< PropertyChangeEvent > aEvents;
1889 OUString aFullPropNamePrefix( getFullKey() );
1890 aFullPropNamePrefix += "/";
1892 // Iterate over given property value sequence.
1893 for ( sal_Int32 n = 0; n < nCount; ++n )
1895 const PropertyValue& rNewValue = pNewValues[ n ];
1896 const OUString& rName = rNewValue.Name;
1898 OUString aFullPropName = aFullPropNamePrefix;
1899 aFullPropName += makeHierarchalNameSegment( rName );
1901 // Does property exist?
1902 if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
1904 Reference< XNameReplace > xNameReplace(
1905 m_pImpl->m_pCreator->getConfigWriteAccess(
1906 aFullPropName ), UNO_QUERY );
1907 Reference< XChangesBatch > xBatch(
1908 m_pImpl->m_pCreator->getConfigWriteAccess(
1909 OUString() ), UNO_QUERY );
1911 if ( xNameReplace.is() && xBatch.is() )
1915 // Write handle
1916 xNameReplace->replaceByName(
1917 "Handle",
1918 makeAny( rNewValue.Handle ) );
1920 // Save old value
1921 OUString aValueName = aFullPropName;
1922 aValueName += "/Value";
1923 Any aOldValue
1924 = xRootHierNameAccess->getByHierarchicalName(
1925 aValueName );
1926 // Write value
1927 xNameReplace->replaceByName(
1928 "Value",
1929 rNewValue.Value );
1931 // Write state ( Now it is a directly set value )
1932 xNameReplace->replaceByName(
1933 "State",
1934 makeAny(
1935 sal_Int32(
1936 PropertyState_DIRECT_VALUE ) ) );
1938 // Commit changes.
1939 xBatch->commitChanges();
1941 if ( m_pImpl->m_pPropertyChangeListeners )
1943 PropertyChangeEvent aEvt;
1944 aEvt.Source = static_cast<OWeakObject*>(this);
1945 aEvt.PropertyName = rNewValue.Name;
1946 aEvt.PropertyHandle = rNewValue.Handle;
1947 aEvt.Further = false;
1948 aEvt.OldValue = aOldValue;
1949 aEvt.NewValue = rNewValue.Value;
1951 aEvents.push_back( aEvt );
1954 catch (const IllegalArgumentException&)
1956 // replaceByName
1958 catch (const NoSuchElementException&)
1960 // getByHierarchicalName, replaceByName
1962 catch (const WrappedTargetException&)
1964 // replaceByName, commitChanges
1970 // Callback follows!
1971 aCGuard.clear();
1973 if ( m_pImpl->m_pPropertyChangeListeners )
1975 // Notify property changes.
1976 for (auto const& event : aEvents)
1978 notifyPropertyChangeEvent( event );
1982 return;
1985 OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" );
1989 // Non-interface methods
1992 void PersistentPropertySet::notifyPropertyChangeEvent(
1993 const PropertyChangeEvent& rEvent ) const
1995 // Get "normal" listeners for the property.
1996 OInterfaceContainerHelper* pContainer =
1997 m_pImpl->m_pPropertyChangeListeners->getContainer(
1998 rEvent.PropertyName );
1999 if ( pContainer && pContainer->getLength() )
2001 OInterfaceIteratorHelper aIter( *pContainer );
2002 while ( aIter.hasMoreElements() )
2004 // Propagate event.
2005 Reference< XPropertyChangeListener > xListener(
2006 aIter.next(), UNO_QUERY );
2007 if ( xListener.is() )
2008 xListener->propertyChange( rEvent );
2012 // Get "normal" listeners for all properties.
2013 OInterfaceContainerHelper* pNoNameContainer =
2014 m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() );
2015 if ( pNoNameContainer && pNoNameContainer->getLength() )
2017 OInterfaceIteratorHelper aIter( *pNoNameContainer );
2018 while ( aIter.hasMoreElements() )
2020 // Propagate event.
2021 Reference< XPropertyChangeListener > xListener(
2022 aIter.next(), UNO_QUERY );
2023 if ( xListener.is() )
2024 xListener->propertyChange( rEvent );
2030 void PersistentPropertySet::notifyPropertySetInfoChange(
2031 const PropertySetInfoChangeEvent& evt ) const
2033 if ( !m_pImpl->m_pPropSetChangeListeners )
2034 return;
2036 // Notify event listeners.
2037 OInterfaceIteratorHelper2 aIter( *( m_pImpl->m_pPropSetChangeListeners ) );
2038 while ( aIter.hasMoreElements() )
2040 // Propagate event.
2041 Reference< XPropertySetInfoChangeListener >
2042 xListener( aIter.next(), UNO_QUERY );
2043 if ( xListener.is() )
2044 xListener->propertySetInfoChange( evt );
2049 const OUString& PersistentPropertySet::getFullKey()
2051 if ( m_pImpl->m_aFullKey.isEmpty() )
2053 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
2054 if ( m_pImpl->m_aFullKey.isEmpty() )
2056 m_pImpl->m_aFullKey
2057 = makeHierarchalNameSegment( m_pImpl->m_aKey );
2058 m_pImpl->m_aFullKey
2059 += "/Values";
2063 return m_pImpl->m_aFullKey;
2067 PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry()
2069 return *m_pImpl->m_pCreator;
2073 // PropertySetInfo_Impl Implementation.
2076 PropertySetInfo_Impl::PropertySetInfo_Impl(
2077 PersistentPropertySet* pOwner )
2078 : m_pOwner( pOwner )
2083 // XPropertySetInfo methods.
2086 // virtual
2087 Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties()
2089 if ( !m_pProps )
2091 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2092 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2093 UNO_QUERY );
2094 if ( xRootHierNameAccess.is() )
2098 Reference< XNameAccess > xNameAccess;
2099 xRootHierNameAccess->getByHierarchicalName(
2100 m_pOwner->getFullKey() )
2101 >>= xNameAccess;
2102 if ( xNameAccess.is() )
2104 // Obtain property names.
2106 Sequence< OUString > aElems
2107 = xNameAccess->getElementNames();
2109 sal_uInt32 nCount = aElems.getLength();
2110 Sequence< Property >* pPropSeq
2111 = new Sequence< Property >( nCount );
2113 if ( nCount )
2115 Reference< XHierarchicalNameAccess > xHierNameAccess(
2116 xNameAccess, UNO_QUERY );
2118 OSL_ENSURE( xHierNameAccess.is(),
2119 "PropertySetInfo_Impl::getProperties - "
2120 "No hierarchical name access!" );
2122 if ( xHierNameAccess.is() )
2124 const OUString aHandleName("/Handle");
2125 const OUString aValueName("/Value");
2126 const OUString aAttrName("/Attributes");
2128 Property* pProps = pPropSeq->getArray();
2130 for ( sal_uInt32 n = 0; n < nCount; ++n )
2132 Property& rProp = pProps[ n ];
2133 OUString rName = aElems[ n ];
2134 OUString aXMLName
2135 = makeHierarchalNameSegment( rName );
2137 // Set property name.
2139 rProp.Name = rName;
2143 // Obtain and set property handle
2144 OUString aHierName = aXMLName;
2145 aHierName += aHandleName;
2146 Any aKeyValue
2147 = xHierNameAccess->getByHierarchicalName(
2148 aHierName );
2150 if ( !( aKeyValue >>= rProp.Handle ) )
2151 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2152 "Error getting property handle!" );
2154 catch (const NoSuchElementException&)
2156 // getByHierarchicalName
2158 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2159 "NoSuchElementException!" );
2164 // Obtain and set property type
2165 OUString aHierName = aXMLName;
2166 aHierName += aValueName;
2167 Any aKeyValue
2168 = xHierNameAccess->getByHierarchicalName(
2169 aHierName );
2171 // Note: The type may be void if addProperty
2172 // was called with a default value
2173 // of type void.
2175 rProp.Type = aKeyValue.getValueType();
2177 catch (const NoSuchElementException&)
2179 // getByHierarchicalName
2181 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2182 "NoSuchElementException!" );
2187 // Obtain and set property attributes
2188 OUString aHierName = aXMLName;
2189 aHierName += aAttrName;
2190 Any aKeyValue
2191 = xHierNameAccess->getByHierarchicalName(
2192 aHierName );
2194 sal_Int32 nAttribs = 0;
2195 if ( aKeyValue >>= nAttribs )
2196 rProp.Attributes
2197 = sal_Int16( nAttribs );
2198 else
2199 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2200 "Error getting property attributes!" );
2202 catch (const NoSuchElementException&)
2204 // getByHierarchicalName
2206 OSL_FAIL( "PropertySetInfo_Impl::getProperties - "
2207 "NoSuchElementException!" );
2213 // Success.
2214 m_pProps.reset( pPropSeq );
2215 return *m_pProps;
2218 catch (const NoSuchElementException&)
2220 // getByHierarchicalName
2224 OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" );
2225 m_pProps.reset( new Sequence< Property >( 0 ) );
2228 return *m_pProps;
2232 // virtual
2233 Property SAL_CALL PropertySetInfo_Impl::getPropertyByName(
2234 const OUString& aName )
2236 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2237 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2238 UNO_QUERY );
2239 if ( xRootHierNameAccess.is() )
2241 OUString aFullPropName( m_pOwner->getFullKey() );
2242 aFullPropName += "/";
2243 aFullPropName += makeHierarchalNameSegment( aName );
2245 // Does property exist?
2246 if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) )
2247 throw UnknownPropertyException();
2251 Property aProp;
2253 // Obtain handle.
2254 OUString aKey = aFullPropName;
2255 aKey += "/Handle";
2257 if ( !( xRootHierNameAccess->getByHierarchicalName( aKey )
2258 >>= aProp.Handle ) )
2260 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2261 "No handle!" );
2262 return Property();
2265 // Obtain Value and extract type.
2266 aKey = aFullPropName;
2267 aKey += "/Value";
2269 Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey );
2270 if ( !aValue.hasValue() )
2272 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2273 "No Value!" );
2274 return Property();
2277 aProp.Type = aValue.getValueType();
2279 // Obtain Attributes.
2280 aKey = aFullPropName;
2281 aKey += "/Attributes";
2283 sal_Int32 nAttribs = 0;
2284 if ( xRootHierNameAccess->getByHierarchicalName( aKey )
2285 >>= nAttribs )
2286 aProp.Attributes = sal_Int16( nAttribs );
2287 else
2289 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2290 "No attributes!" );
2291 return Property();
2294 // set name.
2295 aProp.Name = aName;
2297 // Success.
2298 return aProp;
2300 catch (const NoSuchElementException&)
2302 // getByHierarchicalName
2304 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - "
2305 "caught NoSuchElementException!" );
2310 OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" );
2311 return Property();
2315 // virtual
2316 sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName(
2317 const OUString& Name )
2319 Reference< XHierarchicalNameAccess > xRootHierNameAccess(
2320 m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(),
2321 UNO_QUERY );
2322 if ( xRootHierNameAccess.is() )
2324 OUString aFullPropName( m_pOwner->getFullKey() );
2325 aFullPropName += "/";
2326 aFullPropName += makeHierarchalNameSegment( Name );
2328 return xRootHierNameAccess->hasByHierarchicalName( aFullPropName );
2331 return false;
2334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */