/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ /************************************************************************** TODO ************************************************************************** *************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ucbstore.hxx" using namespace com::sun::star::beans; using namespace com::sun::star::configuration; using namespace com::sun::star::container; using namespace com::sun::star::lang; using namespace com::sun::star::ucb; using namespace com::sun::star::uno; using namespace com::sun::star::util; using namespace comphelper; using namespace cppu; static OUString makeHierarchalNameSegment( const OUString & rIn ) { OUStringBuffer aBuffer; aBuffer.append( "['" ); sal_Int32 nCount = rIn.getLength(); for ( sal_Int32 n = 0; n < nCount; ++n ) { const sal_Unicode c = rIn[ n ]; switch ( c ) { case '&': aBuffer.append( "&" ); break; case '"': aBuffer.append( """ ); break; case '\'': aBuffer.append( "'" ); break; case '<': aBuffer.append( "<" ); break; case '>': aBuffer.append( ">" ); break; default: aBuffer.append( c ); break; } } aBuffer.append( "']" ); return aBuffer.makeStringAndClear(); } #define STORE_CONTENTPROPERTIES_KEY "/org.openoffice.ucb.Store/ContentProperties" // describe path of cfg entry #define CFGPROPERTY_NODEPATH "nodepath" // PropertySetMap_Impl. typedef std::unordered_map< OUString, PersistentPropertySet*> PropertySetMap_Impl; namespace { class PropertySetInfo_Impl : public cppu::WeakImplHelper < XPropertySetInfo > { std::unique_ptr> m_pProps; PersistentPropertySet* m_pOwner; public: explicit PropertySetInfo_Impl(PersistentPropertySet* pOwner); // XPropertySetInfo virtual Sequence< Property > SAL_CALL getProperties() override; virtual Property SAL_CALL getPropertyByName( const OUString& aName ) override; virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override; // Non-interface methods. void reset() { m_pProps.reset(); } }; } // UcbStore_Impl. struct UcbStore_Impl { osl::Mutex m_aMutex; Sequence< Any > m_aInitArgs; Reference< XPropertySetRegistry > m_xTheRegistry; }; // UcbStore Implementation. UcbStore::UcbStore( const Reference< XComponentContext >& xContext ) : m_xContext( xContext ), m_pImpl( new UcbStore_Impl ) { } // virtual UcbStore::~UcbStore() { } XSERVICEINFO_COMMOM_IMPL( UcbStore, "com.sun.star.comp.ucb.UcbStore" ) /// @throws css::uno::Exception static css::uno::Reference< css::uno::XInterface > UcbStore_CreateInstance( const css::uno::Reference< css::lang::XMultiServiceFactory> & rSMgr ) { return static_cast( new UcbStore(ucbhelper::getComponentContext(rSMgr))); } css::uno::Sequence< OUString > UcbStore::getSupportedServiceNames_Static() { css::uno::Sequence< OUString > aSNS { STORE_SERVICE_NAME }; return aSNS; } // Service factory implementation. ONE_INSTANCE_SERVICE_FACTORY_IMPL( UcbStore ); // XPropertySetRegistryFactory methods. // virtual Reference< XPropertySetRegistry > SAL_CALL UcbStore::createPropertySetRegistry( const OUString& ) { // The URL parameter is ignored by this interface implementation. It always // uses the configuration server as storage medium. if ( !m_pImpl->m_xTheRegistry.is() ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); if ( !m_pImpl->m_xTheRegistry.is() ) m_pImpl->m_xTheRegistry = new PropertySetRegistry( m_xContext, m_pImpl->m_aInitArgs ); } return m_pImpl->m_xTheRegistry; } // XInitialization methods. // virtual void SAL_CALL UcbStore::initialize( const Sequence< Any >& aArguments ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); m_pImpl->m_aInitArgs = aArguments; } // PropertySetRegistry_Impl. struct PropertySetRegistry_Impl { const Sequence< Any > m_aInitArgs; PropertySetMap_Impl m_aPropSets; Reference< XMultiServiceFactory > m_xConfigProvider; Reference< XInterface > m_xRootReadAccess; Reference< XInterface > m_xRootWriteAccess; osl::Mutex m_aMutex; bool m_bTriedToGetRootReadAccess; bool m_bTriedToGetRootWriteAccess; explicit PropertySetRegistry_Impl(const Sequence &rInitArgs) : m_aInitArgs(rInitArgs) , m_bTriedToGetRootReadAccess(false) , m_bTriedToGetRootWriteAccess(false) { } }; // PropertySetRegistry Implementation. PropertySetRegistry::PropertySetRegistry( const Reference< XComponentContext >& xContext, const Sequence< Any > &rInitArgs ) : m_xContext( xContext ), m_pImpl( new PropertySetRegistry_Impl( rInitArgs ) ) { } // virtual PropertySetRegistry::~PropertySetRegistry() { } // XServiceInfo methods. OUString SAL_CALL PropertySetRegistry::getImplementationName() { return "com.sun.star.comp.ucb.PropertySetRegistry"; } sal_Bool SAL_CALL PropertySetRegistry::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } css::uno::Sequence< OUString > SAL_CALL PropertySetRegistry::getSupportedServiceNames() { return { PROPSET_REG_SERVICE_NAME }; } // XPropertySetRegistry methods. // virtual Reference< XPersistentPropertySet > SAL_CALL PropertySetRegistry::openPropertySet( const OUString& key, sal_Bool create ) { if ( !key.isEmpty() ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets; PropertySetMap_Impl::const_iterator it = rSets.find( key ); if ( it != rSets.end() ) { // Already instantiated. return Reference< XPersistentPropertySet >( (*it).second ); } else { // Create new instance. Reference< XNameAccess > xRootNameAccess( getRootConfigReadAccess(), UNO_QUERY ); if ( xRootNameAccess.is() ) { // Propertyset in registry? if ( xRootNameAccess->hasByName( key ) ) { // Yep! return Reference< XPersistentPropertySet >( new PersistentPropertySet( *this, key ) ); } else if ( create ) { // No. Create entry for propertyset. Reference< XSingleServiceFactory > xFac( getConfigWriteAccess( OUString() ), UNO_QUERY ); Reference< XChangesBatch > xBatch( xFac, UNO_QUERY ); Reference< XNameContainer > xContainer( xFac, UNO_QUERY ); OSL_ENSURE( xFac.is(), "PropertySetRegistry::openPropertySet - " "No factory!" ); OSL_ENSURE( xBatch.is(), "PropertySetRegistry::openPropertySet - " "No batch!" ); OSL_ENSURE( xContainer.is(), "PropertySetRegistry::openPropertySet - " "No container!" ); if ( xFac.is() && xBatch.is() && xContainer.is() ) { try { // Create new "Properties" config item. Reference< XNameReplace > xNameReplace( xFac->createInstance(), UNO_QUERY ); if ( xNameReplace.is() ) { // Fill new item... // Insert new item. xContainer->insertByName( key, makeAny( xNameReplace ) ); // Commit changes. xBatch->commitChanges(); return Reference< XPersistentPropertySet >( new PersistentPropertySet( *this, key ) ); } } catch (const IllegalArgumentException&) { // insertByName OSL_FAIL( "PropertySetRegistry::openPropertySet - " "caught IllegalArgumentException!" ); } catch (const ElementExistException&) { // insertByName OSL_FAIL( "PropertySetRegistry::openPropertySet - " "caught ElementExistException!" ); } catch (const WrappedTargetException&) { // insertByName, commitChanges OSL_FAIL( "PropertySetRegistry::openPropertySet - " "caught WrappedTargetException!" ); } catch (const RuntimeException&) { OSL_FAIL( "PropertySetRegistry::openPropertySet - " "caught RuntimeException!" ); } catch (const Exception&) { // createInstance OSL_FAIL( "PropertySetRegistry::openPropertySet - " "caught Exception!" ); } } } else { // No entry. Fail, but no error. return Reference< XPersistentPropertySet >(); } } SAL_WARN( "ucb", "no root access" ); } } return Reference< XPersistentPropertySet >(); } // virtual void SAL_CALL PropertySetRegistry::removePropertySet( const OUString& key ) { if ( key.isEmpty() ) return; osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); Reference< XNameAccess > xRootNameAccess( getRootConfigReadAccess(), UNO_QUERY ); if ( xRootNameAccess.is() ) { // Propertyset in registry? if ( !xRootNameAccess->hasByName( key ) ) return; Reference< XChangesBatch > xBatch( getConfigWriteAccess( OUString() ), UNO_QUERY ); Reference< XNameContainer > xContainer( xBatch, UNO_QUERY ); if ( xBatch.is() && xContainer.is() ) { try { // Remove item. xContainer->removeByName( key ); // Commit changes. xBatch->commitChanges(); // Success. return; } catch (const NoSuchElementException&) { // removeByName OSL_FAIL( "PropertySetRegistry::removePropertySet - " "caught NoSuchElementException!" ); return; } catch (const WrappedTargetException&) { // commitChanges OSL_FAIL( "PropertySetRegistry::removePropertySet - " "caught WrappedTargetException!" ); return; } } return; } SAL_WARN( "ucb", "no root access" ); } // XElementAccess methods. // virtual css::uno::Type SAL_CALL PropertySetRegistry::getElementType() { return cppu::UnoType::get(); } // virtual sal_Bool SAL_CALL PropertySetRegistry::hasElements() { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); Reference< XElementAccess > xElemAccess( getRootConfigReadAccess(), UNO_QUERY ); if ( xElemAccess.is() ) return xElemAccess->hasElements(); return false; } // XNameAccess methods. // virtual Any SAL_CALL PropertySetRegistry::getByName( const OUString& aName ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); Reference< XNameAccess > xNameAccess( getRootConfigReadAccess(), UNO_QUERY ); if ( xNameAccess.is() ) { try { return xNameAccess->getByName( aName ); } catch (const NoSuchElementException&) { // getByName } catch (const WrappedTargetException&) { // getByName } } return Any(); } // virtual Sequence< OUString > SAL_CALL PropertySetRegistry::getElementNames() { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); Reference< XNameAccess > xNameAccess( getRootConfigReadAccess(), UNO_QUERY ); if ( xNameAccess.is() ) { return xNameAccess->getElementNames(); } return Sequence< OUString >( 0 ); } // virtual sal_Bool SAL_CALL PropertySetRegistry::hasByName( const OUString& aName ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); Reference< XNameAccess > xNameAccess( getRootConfigReadAccess(), UNO_QUERY ); if ( xNameAccess.is() ) { return xNameAccess->hasByName( aName ); } return false; } void PropertySetRegistry::add( PersistentPropertySet* pSet ) { OUString key( pSet->getKey() ); if ( !key.isEmpty() ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); m_pImpl->m_aPropSets[ key ] = pSet; } } void PropertySetRegistry::remove( PersistentPropertySet* pSet ) { OUString key( pSet->getKey() ); if ( !key.isEmpty() ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); PropertySetMap_Impl& rSets = m_pImpl->m_aPropSets; PropertySetMap_Impl::iterator it = rSets.find( key ); if ( it != rSets.end() ) { // Found. rSets.erase( it ); } } } void PropertySetRegistry::renamePropertySet( const OUString& rOldKey, const OUString& rNewKey ) { if ( rOldKey == rNewKey ) return; Reference< XNameAccess > xRootNameAccess( getConfigWriteAccess( OUString() ), UNO_QUERY ); if ( xRootNameAccess.is() ) { // Old key present? if ( xRootNameAccess->hasByName( rOldKey ) ) { // New key not present? if ( xRootNameAccess->hasByName( rNewKey ) ) { OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "New key exists!" ); return; } Reference< XSingleServiceFactory > xFac( xRootNameAccess, UNO_QUERY ); Reference< XChangesBatch > xBatch( xFac, UNO_QUERY ); Reference< XNameContainer > xContainer( xFac, UNO_QUERY ); OSL_ENSURE( xFac.is(), "PropertySetRegistry::renamePropertySet - " "No factory!" ); OSL_ENSURE( xBatch.is(), "PropertySetRegistry::renamePropertySet - " "No batch!" ); OSL_ENSURE( xContainer.is(), "PropertySetRegistry::renamePropertySet - " "No container!" ); if ( xFac.is() && xBatch.is() && xContainer.is() ) { // Create new "Properties" config item. try { Reference< XNameReplace > xNameReplace( xFac->createInstance(), UNO_QUERY ); if ( xNameReplace.is() ) { // Insert new item. xContainer->insertByName( rNewKey, makeAny( xNameReplace ) ); // Commit changes. xBatch->commitChanges(); } } catch (const IllegalArgumentException&) { // insertByName OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught IllegalArgumentException!" ); return; } catch (const ElementExistException&) { // insertByName OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught ElementExistException!" ); return; } catch (const WrappedTargetException&) { // insertByName, commitChanges OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught WrappedTargetException!" ); return; } catch (const RuntimeException&) { OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught RuntimeException!" ); return; } catch (const Exception&) { // createInstance OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught Exception!" ); return; } // Copy data... Reference< XHierarchicalNameAccess > xRootHierNameAccess( xRootNameAccess, UNO_QUERY ); if ( !xRootHierNameAccess.is() ) { OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "No hierarchical name access!" ); return; } try { OUString aOldValuesKey = makeHierarchalNameSegment( rOldKey ) + "/Values"; Reference< XNameAccess > xOldNameAccess; xRootHierNameAccess->getByHierarchicalName( aOldValuesKey ) >>= xOldNameAccess; if ( !xOldNameAccess.is() ) { OSL_FAIL( "PersistentPropertySet::renamePropertySet - " "No old name access!" ); return; } // Obtain property names. const Sequence< OUString > aElems = xOldNameAccess->getElementNames(); if ( aElems.hasElements() ) { OUString aNewValuesKey = makeHierarchalNameSegment( rNewKey ) + "/Values"; Reference< XSingleServiceFactory > xNewFac; xRootHierNameAccess->getByHierarchicalName( aNewValuesKey ) >>= xNewFac; if ( !xNewFac.is() ) { OSL_FAIL( "PersistentPropertySet::renamePropertySet - " "No new factory!" ); return; } Reference< XNameContainer > xNewContainer( xNewFac, UNO_QUERY ); if ( !xNewContainer.is() ) { OSL_FAIL( "PersistentPropertySet::renamePropertySet - " "No new container!" ); return; } aOldValuesKey += "/"; OUString const aHandleKey("/Handle"); OUString const aValueKey("/Value"); OUString const aStateKey("/State"); OUString const aAttrKey("/Attributes"); for ( const OUString& rPropName : aElems ) { // Create new item. Reference< XNameReplace > xNewPropNameReplace( xNewFac->createInstance(), UNO_QUERY ); if ( !xNewPropNameReplace.is() ) { OSL_FAIL( "PersistentPropertySet::renamePropertySet - " "No new prop name replace!" ); return; } // Fill new item... // Set Values OUString aKey = aOldValuesKey; aKey += makeHierarchalNameSegment( rPropName ); // ... handle OUString aNewKey1 = aKey + aHandleKey; Any aAny = xRootHierNameAccess->getByHierarchicalName( aNewKey1 ); xNewPropNameReplace->replaceByName( "Handle", aAny ); // ... value aNewKey1 = aKey + aValueKey; aAny = xRootHierNameAccess->getByHierarchicalName( aNewKey1 ); xNewPropNameReplace->replaceByName( "Value", aAny ); // ... state aNewKey1 = aKey + aStateKey; aAny = xRootHierNameAccess->getByHierarchicalName( aNewKey1 ); xNewPropNameReplace->replaceByName( "State", aAny ); // ... attributes aNewKey1 = aKey + aAttrKey; aAny = xRootHierNameAccess->getByHierarchicalName( aNewKey1 ); xNewPropNameReplace->replaceByName( "Attributes", aAny ); // Insert new item. xNewContainer->insertByName( rPropName, makeAny( xNewPropNameReplace ) ); // Commit changes. xBatch->commitChanges(); } } } catch (const IllegalArgumentException&) { // insertByName, replaceByName OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught IllegalArgumentException!" ); return; } catch (const ElementExistException&) { // insertByName OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught ElementExistException!" ); return; } catch (const WrappedTargetException&) { // insertByName, replaceByName, commitChanges OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught WrappedTargetException!" ); return; } catch (const NoSuchElementException&) { // getByHierarchicalName, replaceByName OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught NoSuchElementException!" ); return; } catch (const RuntimeException&) { OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught RuntimeException!" ); return; } catch (const Exception&) { // createInstance OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught Exception!" ); return; } // Remove old entry... try { // Remove item. xContainer->removeByName( rOldKey ); // Commit changes. xBatch->commitChanges(); // Success. return; } catch (const NoSuchElementException&) { // removeByName OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught NoSuchElementException!" ); return; } catch (const WrappedTargetException&) { // commitChanges OSL_FAIL( "PropertySetRegistry::renamePropertySet - " "caught WrappedTargetException!" ); return; } } } } OSL_FAIL( "PropertySetRegistry::renamePropertySet - Error!" ); } Reference< XMultiServiceFactory > PropertySetRegistry::getConfigProvider() { if ( !m_pImpl->m_xConfigProvider.is() ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); if ( !m_pImpl->m_xConfigProvider.is() ) { const Sequence< Any >& rInitArgs = m_pImpl->m_aInitArgs; if ( rInitArgs.hasElements() ) { // Extract config provider from service init args. rInitArgs[ 0 ] >>= m_pImpl->m_xConfigProvider; OSL_ENSURE( m_pImpl->m_xConfigProvider.is(), "PropertySetRegistry::getConfigProvider - " "No config provider!" ); } else { try { m_pImpl->m_xConfigProvider = theDefaultProvider::get( m_xContext ); } catch (const Exception&) { TOOLS_WARN_EXCEPTION( "ucb", ""); } } } } return m_pImpl->m_xConfigProvider; } Reference< XInterface > PropertySetRegistry::getRootConfigReadAccess() { try { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); if ( !m_pImpl->m_xRootReadAccess.is() ) { if ( m_pImpl->m_bTriedToGetRootReadAccess ) { OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - " "Unable to read any config data! -> #82494#" ); return Reference< XInterface >(); } getConfigProvider(); if ( m_pImpl->m_xConfigProvider.is() ) { Sequence aArguments(comphelper::InitAnyPropertySequence( { {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))} })); m_pImpl->m_bTriedToGetRootReadAccess = true; m_pImpl->m_xRootReadAccess = m_pImpl->m_xConfigProvider->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", aArguments ); if ( m_pImpl->m_xRootReadAccess.is() ) return m_pImpl->m_xRootReadAccess; } } else return m_pImpl->m_xRootReadAccess; } catch (const RuntimeException&) { throw; } catch (const Exception&) { // createInstance, createInstanceWithArguments OSL_FAIL( "PropertySetRegistry::getRootConfigReadAccess - caught Exception!" ); return Reference< XInterface >(); } SAL_WARN( "ucb", "Error!" ); return Reference< XInterface >(); } Reference< XInterface > PropertySetRegistry::getConfigWriteAccess( const OUString& rPath ) { try { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); if ( !m_pImpl->m_xRootWriteAccess.is() ) { if ( m_pImpl->m_bTriedToGetRootWriteAccess ) { OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - " "Unable to write any config data! -> #82494#" ); return Reference< XInterface >(); } getConfigProvider(); if ( m_pImpl->m_xConfigProvider.is() ) { Sequence aArguments(comphelper::InitAnyPropertySequence( { {CFGPROPERTY_NODEPATH, Any(OUString( STORE_CONTENTPROPERTIES_KEY ))} })); m_pImpl->m_bTriedToGetRootWriteAccess = true; m_pImpl->m_xRootWriteAccess = m_pImpl->m_xConfigProvider->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationUpdateAccess", aArguments ); OSL_ENSURE( m_pImpl->m_xRootWriteAccess.is(), "PropertySetRegistry::getConfigWriteAccess - " "No config update access!" ); } } if ( m_pImpl->m_xRootWriteAccess.is() ) { if ( !rPath.isEmpty() ) { Reference< XHierarchicalNameAccess > xNA( m_pImpl->m_xRootWriteAccess, UNO_QUERY ); if ( xNA.is() ) { Reference< XInterface > xInterface; xNA->getByHierarchicalName( rPath ) >>= xInterface; if ( xInterface.is() ) return xInterface; } } else return m_pImpl->m_xRootWriteAccess; } } catch (const RuntimeException&) { throw; } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - " "caught NoSuchElementException!" ); return Reference< XInterface >(); } catch (const Exception&) { // createInstance, createInstanceWithArguments OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - " "caught Exception!" ); return Reference< XInterface >(); } OSL_FAIL( "PropertySetRegistry::getConfigWriteAccess - Error!" ); return Reference< XInterface >(); } typedef OMultiTypeInterfaceContainerHelperVar PropertyListeners_Impl; struct PersistentPropertySet_Impl { rtl::Reference m_pCreator; rtl::Reference m_pInfo; OUString m_aKey; OUString m_aFullKey; osl::Mutex m_aMutex; std::unique_ptr m_pDisposeEventListeners; std::unique_ptr m_pPropSetChangeListeners; std::unique_ptr m_pPropertyChangeListeners; PersistentPropertySet_Impl( PropertySetRegistry& rCreator, const OUString& rKey ) : m_pCreator( &rCreator ), m_aKey( rKey ) { } }; // PersistentPropertySet Implementation. PersistentPropertySet::PersistentPropertySet( PropertySetRegistry& rCreator, const OUString& rKey ) : m_pImpl( new PersistentPropertySet_Impl( rCreator, rKey ) ) { // register at creator. rCreator.add( this ); } // virtual PersistentPropertySet::~PersistentPropertySet() { // deregister at creator. m_pImpl->m_pCreator->remove( this ); } // XServiceInfo methods. OUString SAL_CALL PersistentPropertySet::getImplementationName() { return "com.sun.star.comp.ucb.PersistentPropertySet"; } sal_Bool SAL_CALL PersistentPropertySet::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } css::uno::Sequence< OUString > SAL_CALL PersistentPropertySet::getSupportedServiceNames() { return { PERS_PROPSET_SERVICE_NAME }; } // XComponent methods. // virtual void SAL_CALL PersistentPropertySet::dispose() { if ( m_pImpl->m_pDisposeEventListeners && m_pImpl->m_pDisposeEventListeners->getLength() ) { EventObject aEvt; aEvt.Source = static_cast< XComponent * >( this ); m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt ); } if ( m_pImpl->m_pPropSetChangeListeners && m_pImpl->m_pPropSetChangeListeners->getLength() ) { EventObject aEvt; aEvt.Source = static_cast< XPropertySetInfoChangeNotifier * >( this ); m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt ); } if ( m_pImpl->m_pPropertyChangeListeners ) { EventObject aEvt; aEvt.Source = static_cast< XPropertySet * >( this ); m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt ); } } // virtual void SAL_CALL PersistentPropertySet::addEventListener( const Reference< XEventListener >& Listener ) { if ( !m_pImpl->m_pDisposeEventListeners ) m_pImpl->m_pDisposeEventListeners.reset( new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) ); m_pImpl->m_pDisposeEventListeners->addInterface( Listener ); } // virtual void SAL_CALL PersistentPropertySet::removeEventListener( const Reference< XEventListener >& Listener ) { if ( m_pImpl->m_pDisposeEventListeners ) m_pImpl->m_pDisposeEventListeners->removeInterface( Listener ); // Note: Don't want to delete empty container here -> performance. } // XPropertySet methods. // virtual Reference< XPropertySetInfo > SAL_CALL PersistentPropertySet::getPropertySetInfo() { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); if ( !m_pImpl->m_pInfo.is() ) { m_pImpl->m_pInfo = new PropertySetInfo_Impl( this ); } return Reference< XPropertySetInfo >( m_pImpl->m_pInfo.get() ); } // virtual void SAL_CALL PersistentPropertySet::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) { osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex ); Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { OUString aFullPropName( getFullKey() + "/" ); aFullPropName += makeHierarchalNameSegment( aPropertyName ); // Does property exist? if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) { Reference< XNameReplace > xNameReplace( m_pImpl->m_pCreator->getConfigWriteAccess( aFullPropName ), UNO_QUERY ); Reference< XChangesBatch > xBatch( m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ), UNO_QUERY ); if ( xNameReplace.is() && xBatch.is() ) { try { // Obtain old value OUString aValueName = aFullPropName + "/Value"; Any aOldValue = xRootHierNameAccess->getByHierarchicalName( aValueName ); // Check value type. if ( aOldValue.getValueType() != aValue.getValueType() ) { aCGuard.clear(); throw IllegalArgumentException(); } // Write value xNameReplace->replaceByName( "Value", aValue ); // Write state ( Now it is a directly set value ) xNameReplace->replaceByName( "State", makeAny( sal_Int32( PropertyState_DIRECT_VALUE ) ) ); // Commit changes. xBatch->commitChanges(); PropertyChangeEvent aEvt; if ( m_pImpl->m_pPropertyChangeListeners ) { // Obtain handle aValueName = aFullPropName + "/Handle"; sal_Int32 nHandle = -1; xRootHierNameAccess->getByHierarchicalName( aValueName ) >>= nHandle; aEvt.Source = static_cast(this); aEvt.PropertyName = aPropertyName; aEvt.PropertyHandle = nHandle; aEvt.Further = false; aEvt.OldValue = aOldValue; aEvt.NewValue = aValue; // Callback follows! aCGuard.clear(); notifyPropertyChangeEvent( aEvt ); } return; } catch (const IllegalArgumentException&) { // replaceByName } catch (const NoSuchElementException&) { // getByHierarchicalName, replaceByName } catch (const WrappedTargetException&) { // replaceByName, commitChanges } } } } throw UnknownPropertyException(aPropertyName); } // virtual Any SAL_CALL PersistentPropertySet::getPropertyValue( const OUString& PropertyName ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); Reference< XHierarchicalNameAccess > xNameAccess( m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); if ( xNameAccess.is() ) { OUString aFullPropName( getFullKey() + "/" ); aFullPropName += makeHierarchalNameSegment( PropertyName ) + "/Value"; try { return xNameAccess->getByHierarchicalName( aFullPropName ); } catch (const NoSuchElementException&) { throw UnknownPropertyException(aFullPropName); } } throw UnknownPropertyException(PropertyName); } // virtual void SAL_CALL PersistentPropertySet::addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) { // load(); if ( !m_pImpl->m_pPropertyChangeListeners ) m_pImpl->m_pPropertyChangeListeners.reset( new PropertyListeners_Impl( m_pImpl->m_aMutex ) ); m_pImpl->m_pPropertyChangeListeners->addInterface( aPropertyName, xListener ); } // virtual void SAL_CALL PersistentPropertySet::removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) { // load(); if ( m_pImpl->m_pPropertyChangeListeners ) m_pImpl->m_pPropertyChangeListeners->removeInterface( aPropertyName, aListener ); // Note: Don't want to delete empty container here -> performance. } // virtual void SAL_CALL PersistentPropertySet::addVetoableChangeListener( const OUString&, const Reference< XVetoableChangeListener >& ) { // load(); // OSL_FAIL( // "PersistentPropertySet::addVetoableChangeListener - N.Y.I." ); } // virtual void SAL_CALL PersistentPropertySet::removeVetoableChangeListener( const OUString&, const Reference< XVetoableChangeListener >& ) { // load(); // OSL_FAIL( // "PersistentPropertySet::removeVetoableChangeListener - N.Y.I." ); } // XPersistentPropertySet methods. // virtual Reference< XPropertySetRegistry > SAL_CALL PersistentPropertySet::getRegistry() { return Reference< XPropertySetRegistry >( m_pImpl->m_pCreator.get() ); } // virtual OUString SAL_CALL PersistentPropertySet::getKey() { return m_pImpl->m_aKey; } // XNamed methods. // virtual OUString SAL_CALL PersistentPropertySet::getName() { // same as getKey() return m_pImpl->m_aKey; } // virtual void SAL_CALL PersistentPropertySet::setName( const OUString& aName ) { if ( aName != m_pImpl->m_aKey ) m_pImpl->m_pCreator->renamePropertySet( m_pImpl->m_aKey, aName ); } // XPropertyContainer methods. // virtual void SAL_CALL PersistentPropertySet::addProperty( const OUString& Name, sal_Int16 Attributes, const Any& DefaultValue ) { if ( Name.isEmpty() ) throw IllegalArgumentException(); // @@@ What other types can't be written to config server? // Check type class ( Not all types can be written to storage ) TypeClass eTypeClass = DefaultValue.getValueTypeClass(); if ( eTypeClass == TypeClass_INTERFACE ) throw IllegalTypeException(); osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); // Property already in set? OUString aFullValuesName; Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { aFullValuesName = getFullKey(); OUString aFullPropName = aFullValuesName + "/"; aFullPropName += makeHierarchalNameSegment( Name ); if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) { // Already in set. throw PropertyExistException(); } } // Property is always removable. Attributes |= PropertyAttribute::REMOVABLE; // Add property. Reference< XSingleServiceFactory > xFac( m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ), UNO_QUERY ); Reference< XNameContainer > xContainer( xFac, UNO_QUERY ); Reference< XChangesBatch > xBatch( m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ), UNO_QUERY ); OSL_ENSURE( xFac.is(), "PersistentPropertySet::addProperty - No factory!" ); OSL_ENSURE( xBatch.is(), "PersistentPropertySet::addProperty - No batch!" ); OSL_ENSURE( xContainer.is(), "PersistentPropertySet::addProperty - No container!" ); if ( xFac.is() && xBatch.is() && xContainer.is() ) { try { // Create new "PropertyValue" config item. Reference< XNameReplace > xNameReplace( xFac->createInstance(), UNO_QUERY ); if ( xNameReplace.is() ) { // Fill new item... // Set handle xNameReplace->replaceByName( "Handle", makeAny( sal_Int32( -1 ) ) ); // Set default value xNameReplace->replaceByName( "Value", DefaultValue ); // Set state ( always "default" ) xNameReplace->replaceByName( "State", makeAny( sal_Int32( PropertyState_DEFAULT_VALUE ) ) ); // Set attributes xNameReplace->replaceByName( "Attributes", makeAny( sal_Int32( Attributes ) ) ); // Insert new item. xContainer->insertByName( Name, makeAny( xNameReplace ) ); // Commit changes. xBatch->commitChanges(); // Property set info is invalid. if ( m_pImpl->m_pInfo.is() ) m_pImpl->m_pInfo->reset(); // Notify propertyset info change listeners. if ( m_pImpl->m_pPropSetChangeListeners && m_pImpl->m_pPropSetChangeListeners->getLength() ) { PropertySetInfoChangeEvent evt( static_cast< OWeakObject * >( this ), Name, -1, PropertySetInfoChange::PROPERTY_INSERTED ); notifyPropertySetInfoChange( evt ); } // Success. return; } } catch (const IllegalArgumentException&) { // insertByName OSL_FAIL( "PersistentPropertySet::addProperty - " "caught IllegalArgumentException!" ); return; } catch (const ElementExistException&) { // insertByName OSL_FAIL( "PersistentPropertySet::addProperty - " "caught ElementExistException!" ); return; } catch (const WrappedTargetException&) { // replaceByName, insertByName, commitChanges OSL_FAIL( "PersistentPropertySet::addProperty - " "caught WrappedTargetException!" ); return; } catch (const RuntimeException&) { throw; } catch (const Exception&) { // createInstance OSL_FAIL( "PersistentPropertySet::addProperty - " "caught Exception!" ); return; } } OSL_FAIL( "PersistentPropertySet::addProperty - Error!" ); } // virtual void SAL_CALL PersistentPropertySet::removeProperty( const OUString& Name ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); OUString aFullValuesName; OUString aFullPropName; Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { aFullValuesName = getFullKey(); aFullPropName = aFullValuesName + "/"; aFullPropName += makeHierarchalNameSegment( Name ); // Property in set? if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) throw UnknownPropertyException(aFullPropName); // Property removable? try { OUString aFullAttrName = aFullPropName + "/Attributes"; sal_Int32 nAttribs = 0; if ( xRootHierNameAccess->getByHierarchicalName( aFullAttrName ) >>= nAttribs ) { if ( !( nAttribs & PropertyAttribute::REMOVABLE ) ) { // Not removable! throw NotRemoveableException(); } } else { OSL_FAIL( "PersistentPropertySet::removeProperty - " "No attributes!" ); return; } } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PersistentPropertySet::removeProperty - " "caught NoSuchElementException!" ); } // Remove property... Reference< XNameContainer > xContainer( m_pImpl->m_pCreator->getConfigWriteAccess( aFullValuesName ), UNO_QUERY ); Reference< XChangesBatch > xBatch( m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ), UNO_QUERY ); OSL_ENSURE( xBatch.is(), "PersistentPropertySet::removeProperty - No batch!" ); OSL_ENSURE( xContainer.is(), "PersistentPropertySet::removeProperty - No container!" ); if ( xBatch.is() && xContainer.is() ) { try { sal_Int32 nHandle = -1; if ( m_pImpl->m_pPropSetChangeListeners && m_pImpl->m_pPropSetChangeListeners->getLength() ) { // Obtain property handle ( needed for propertysetinfo // change event )... try { OUString aFullHandleName = aFullPropName + "/Handle"; if ( ! ( xRootHierNameAccess->getByHierarchicalName( aFullHandleName ) >>= nHandle ) ) nHandle = -1; } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PersistentPropertySet::removeProperty - " "caught NoSuchElementException!" ); nHandle = -1; } } xContainer->removeByName( Name ); xBatch->commitChanges(); // Property set info is invalid. if ( m_pImpl->m_pInfo.is() ) m_pImpl->m_pInfo->reset(); // Notify propertyset info change listeners. if ( m_pImpl->m_pPropSetChangeListeners && m_pImpl->m_pPropSetChangeListeners->getLength() ) { PropertySetInfoChangeEvent evt( static_cast< OWeakObject * >( this ), Name, nHandle, PropertySetInfoChange::PROPERTY_REMOVED ); notifyPropertySetInfoChange( evt ); } // Success. return; } catch (const NoSuchElementException&) { // removeByName OSL_FAIL( "PersistentPropertySet::removeProperty - " "caught NoSuchElementException!" ); return; } catch (const WrappedTargetException&) { // commitChanges OSL_FAIL( "PersistentPropertySet::removeProperty - " "caught WrappedTargetException!" ); return; } } } OSL_FAIL( "PersistentPropertySet::removeProperty - Error!" ); } // XPropertySetInfoChangeNotifier methods. // virtual void SAL_CALL PersistentPropertySet::addPropertySetInfoChangeListener( const Reference< XPropertySetInfoChangeListener >& Listener ) { if ( !m_pImpl->m_pPropSetChangeListeners ) m_pImpl->m_pPropSetChangeListeners.reset( new OInterfaceContainerHelper2( m_pImpl->m_aMutex ) ); m_pImpl->m_pPropSetChangeListeners->addInterface( Listener ); } // virtual void SAL_CALL PersistentPropertySet::removePropertySetInfoChangeListener( const Reference< XPropertySetInfoChangeListener >& Listener ) { if ( m_pImpl->m_pPropSetChangeListeners ) m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener ); } // XPropertyAccess methods. // virtual Sequence< PropertyValue > SAL_CALL PersistentPropertySet::getPropertyValues() { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { try { Reference< XNameAccess > xNameAccess; xRootHierNameAccess->getByHierarchicalName(getFullKey()) >>= xNameAccess; if ( xNameAccess.is() ) { // Obtain property names. Sequence< OUString > aElems = xNameAccess->getElementNames(); sal_Int32 nCount = aElems.getLength(); if ( nCount ) { Reference< XHierarchicalNameAccess > xHierNameAccess( xNameAccess, UNO_QUERY ); OSL_ENSURE( xHierNameAccess.is(), "PersistentPropertySet::getPropertyValues - " "No hierarchical name access!" ); if ( xHierNameAccess.is() ) { Sequence< PropertyValue > aValues( nCount ); const OUString aHandleName("/Handle"); const OUString aValueName("/Value"); const OUString aStateName("/State"); for ( sal_Int32 n = 0; n < nCount; ++n ) { PropertyValue& rValue = aValues[ n ]; OUString rName = aElems[ n ]; OUString aXMLName = makeHierarchalNameSegment( rName ); // Set property name. rValue.Name = rName; try { // Obtain and set property handle OUString aHierName = aXMLName + aHandleName; Any aKeyValue = xHierNameAccess->getByHierarchicalName( aHierName ); if ( !( aKeyValue >>= rValue.Handle ) ) OSL_FAIL( "PersistentPropertySet::getPropertyValues - " "Error getting property handle!" ); } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PersistentPropertySet::getPropertyValues - " "NoSuchElementException!" ); } try { // Obtain and set property value OUString aHierName = aXMLName + aValueName; rValue.Value = xHierNameAccess->getByHierarchicalName( aHierName ); // Note: The value may be void if addProperty // was called with a default value // of type void. } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PersistentPropertySet::getPropertyValues - " "NoSuchElementException!" ); } try { // Obtain and set property state OUString aHierName = aXMLName +aStateName; Any aKeyValue = xHierNameAccess->getByHierarchicalName( aHierName ); sal_Int32 nState = 0; if ( !( aKeyValue >>= nState ) ) OSL_FAIL( "PersistentPropertySet::getPropertyValues - " "Error getting property state!" ); else rValue.State = PropertyState( nState ); } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PersistentPropertySet::getPropertyValues - " "NoSuchElementException!" ); } } return aValues; } } } } catch (const NoSuchElementException&) { // getByHierarchicalName } } return Sequence< PropertyValue >( 0 ); } // virtual void SAL_CALL PersistentPropertySet::setPropertyValues( const Sequence< PropertyValue >& aProps ) { if ( !aProps.hasElements() ) return; osl::ClearableGuard< osl::Mutex > aCGuard( m_pImpl->m_aMutex ); Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pImpl->m_pCreator->getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { std::vector< PropertyChangeEvent > aEvents; OUString aFullPropNamePrefix( getFullKey() + "/" ); // Iterate over given property value sequence. for ( const PropertyValue& rNewValue : aProps ) { const OUString& rName = rNewValue.Name; OUString aFullPropName = aFullPropNamePrefix; aFullPropName += makeHierarchalNameSegment( rName ); // Does property exist? if ( xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) { Reference< XNameReplace > xNameReplace( m_pImpl->m_pCreator->getConfigWriteAccess( aFullPropName ), UNO_QUERY ); Reference< XChangesBatch > xBatch( m_pImpl->m_pCreator->getConfigWriteAccess( OUString() ), UNO_QUERY ); if ( xNameReplace.is() && xBatch.is() ) { try { // Write handle xNameReplace->replaceByName( "Handle", makeAny( rNewValue.Handle ) ); // Save old value OUString aValueName = aFullPropName +"/Value"; Any aOldValue = xRootHierNameAccess->getByHierarchicalName( aValueName ); // Write value xNameReplace->replaceByName( "Value", rNewValue.Value ); // Write state ( Now it is a directly set value ) xNameReplace->replaceByName( "State", makeAny( sal_Int32( PropertyState_DIRECT_VALUE ) ) ); // Commit changes. xBatch->commitChanges(); if ( m_pImpl->m_pPropertyChangeListeners ) { PropertyChangeEvent aEvt; aEvt.Source = static_cast(this); aEvt.PropertyName = rNewValue.Name; aEvt.PropertyHandle = rNewValue.Handle; aEvt.Further = false; aEvt.OldValue = aOldValue; aEvt.NewValue = rNewValue.Value; aEvents.push_back( aEvt ); } } catch (const IllegalArgumentException&) { // replaceByName } catch (const NoSuchElementException&) { // getByHierarchicalName, replaceByName } catch (const WrappedTargetException&) { // replaceByName, commitChanges } } } } // Callback follows! aCGuard.clear(); if ( m_pImpl->m_pPropertyChangeListeners ) { // Notify property changes. for (auto const& event : aEvents) { notifyPropertyChangeEvent( event ); } } return; } OSL_FAIL( "PersistentPropertySet::setPropertyValues - Nothing set!" ); } // Non-interface methods void PersistentPropertySet::notifyPropertyChangeEvent( const PropertyChangeEvent& rEvent ) const { // Get "normal" listeners for the property. OInterfaceContainerHelper* pContainer = m_pImpl->m_pPropertyChangeListeners->getContainer( rEvent.PropertyName ); if ( pContainer && pContainer->getLength() ) { OInterfaceIteratorHelper aIter( *pContainer ); while ( aIter.hasMoreElements() ) { // Propagate event. Reference< XPropertyChangeListener > xListener( aIter.next(), UNO_QUERY ); if ( xListener.is() ) xListener->propertyChange( rEvent ); } } // Get "normal" listeners for all properties. OInterfaceContainerHelper* pNoNameContainer = m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() ); if ( pNoNameContainer && pNoNameContainer->getLength() ) { OInterfaceIteratorHelper aIter( *pNoNameContainer ); while ( aIter.hasMoreElements() ) { // Propagate event. Reference< XPropertyChangeListener > xListener( aIter.next(), UNO_QUERY ); if ( xListener.is() ) xListener->propertyChange( rEvent ); } } } void PersistentPropertySet::notifyPropertySetInfoChange( const PropertySetInfoChangeEvent& evt ) const { if ( !m_pImpl->m_pPropSetChangeListeners ) return; // Notify event listeners. OInterfaceIteratorHelper2 aIter( *( m_pImpl->m_pPropSetChangeListeners ) ); while ( aIter.hasMoreElements() ) { // Propagate event. Reference< XPropertySetInfoChangeListener > xListener( aIter.next(), UNO_QUERY ); if ( xListener.is() ) xListener->propertySetInfoChange( evt ); } } const OUString& PersistentPropertySet::getFullKey() { if ( m_pImpl->m_aFullKey.isEmpty() ) { osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); if ( m_pImpl->m_aFullKey.isEmpty() ) { m_pImpl->m_aFullKey = makeHierarchalNameSegment( m_pImpl->m_aKey ); m_pImpl->m_aFullKey += "/Values"; } } return m_pImpl->m_aFullKey; } PropertySetRegistry& PersistentPropertySet::getPropertySetRegistry() { return *m_pImpl->m_pCreator; } // PropertySetInfo_Impl Implementation. PropertySetInfo_Impl::PropertySetInfo_Impl( PersistentPropertySet* pOwner ) : m_pOwner( pOwner ) { } // XPropertySetInfo methods. // virtual Sequence< Property > SAL_CALL PropertySetInfo_Impl::getProperties() { if ( !m_pProps ) { Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { try { Reference< XNameAccess > xNameAccess; xRootHierNameAccess->getByHierarchicalName( m_pOwner->getFullKey() ) >>= xNameAccess; if ( xNameAccess.is() ) { // Obtain property names. Sequence< OUString > aElems = xNameAccess->getElementNames(); sal_uInt32 nCount = aElems.getLength(); Sequence< Property >* pPropSeq = new Sequence< Property >( nCount ); if ( nCount ) { Reference< XHierarchicalNameAccess > xHierNameAccess( xNameAccess, UNO_QUERY ); OSL_ENSURE( xHierNameAccess.is(), "PropertySetInfo_Impl::getProperties - " "No hierarchical name access!" ); if ( xHierNameAccess.is() ) { const OUString aHandleName("/Handle"); const OUString aValueName("/Value"); const OUString aAttrName("/Attributes"); Property* pProps = pPropSeq->getArray(); for ( sal_uInt32 n = 0; n < nCount; ++n ) { Property& rProp = pProps[ n ]; OUString rName = aElems[ n ]; OUString aXMLName = makeHierarchalNameSegment( rName ); // Set property name. rProp.Name = rName; try { // Obtain and set property handle OUString aHierName = aXMLName + aHandleName; Any aKeyValue = xHierNameAccess->getByHierarchicalName( aHierName ); if ( !( aKeyValue >>= rProp.Handle ) ) OSL_FAIL( "PropertySetInfo_Impl::getProperties - " "Error getting property handle!" ); } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PropertySetInfo_Impl::getProperties - " "NoSuchElementException!" ); } try { // Obtain and set property type OUString aHierName = aXMLName + aValueName; Any aKeyValue = xHierNameAccess->getByHierarchicalName( aHierName ); // Note: The type may be void if addProperty // was called with a default value // of type void. rProp.Type = aKeyValue.getValueType(); } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PropertySetInfo_Impl::getProperties - " "NoSuchElementException!" ); } try { // Obtain and set property attributes OUString aHierName = aXMLName + aAttrName; Any aKeyValue = xHierNameAccess->getByHierarchicalName( aHierName ); sal_Int32 nAttribs = 0; if ( aKeyValue >>= nAttribs ) rProp.Attributes = sal_Int16( nAttribs ); else OSL_FAIL( "PropertySetInfo_Impl::getProperties - " "Error getting property attributes!" ); } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PropertySetInfo_Impl::getProperties - " "NoSuchElementException!" ); } } } } // Success. m_pProps.reset( pPropSeq ); return *m_pProps; } } catch (const NoSuchElementException&) { // getByHierarchicalName } } OSL_FAIL( "PropertySetInfo_Impl::getProperties - Error!" ); m_pProps.reset( new Sequence< Property >( 0 ) ); } return *m_pProps; } // virtual Property SAL_CALL PropertySetInfo_Impl::getPropertyByName( const OUString& aName ) { Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { OUString aFullPropName( m_pOwner->getFullKey() + "/" ); aFullPropName += makeHierarchalNameSegment( aName ); // Does property exist? if ( !xRootHierNameAccess->hasByHierarchicalName( aFullPropName ) ) throw UnknownPropertyException(aFullPropName); try { Property aProp; // Obtain handle. OUString aKey = aFullPropName + "/Handle"; if ( !( xRootHierNameAccess->getByHierarchicalName( aKey ) >>= aProp.Handle ) ) { OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - " "No handle!" ); return Property(); } // Obtain Value and extract type. aKey = aFullPropName + "/Value"; Any aValue = xRootHierNameAccess->getByHierarchicalName( aKey ); if ( !aValue.hasValue() ) { OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - " "No Value!" ); return Property(); } aProp.Type = aValue.getValueType(); // Obtain Attributes. aKey = aFullPropName + "/Attributes"; sal_Int32 nAttribs = 0; if ( xRootHierNameAccess->getByHierarchicalName( aKey ) >>= nAttribs ) aProp.Attributes = sal_Int16( nAttribs ); else { OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - " "No attributes!" ); return Property(); } // set name. aProp.Name = aName; // Success. return aProp; } catch (const NoSuchElementException&) { // getByHierarchicalName OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - " "caught NoSuchElementException!" ); } } OSL_FAIL( "PropertySetInfo_Impl::getPropertyByName - Error!" ); return Property(); } // virtual sal_Bool SAL_CALL PropertySetInfo_Impl::hasPropertyByName( const OUString& Name ) { Reference< XHierarchicalNameAccess > xRootHierNameAccess( m_pOwner->getPropertySetRegistry().getRootConfigReadAccess(), UNO_QUERY ); if ( xRootHierNameAccess.is() ) { OUString aFullPropName( m_pOwner->getFullKey() + "/" ); aFullPropName += makeHierarchalNameSegment( Name ); return xRootHierNameAccess->hasByHierarchicalName( aFullPropName ); } return false; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */